mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
wip
This commit is contained in:
@@ -136,8 +136,13 @@ impl<'a, 'fnc> ExpressionCompiler<'a, 'fnc> {
|
||||
}
|
||||
Arrow(arrow) => self.arrow_expression(arrow, target_register),
|
||||
Class(class_exp) => {
|
||||
self.todo(class_exp.span(), "Class expression");
|
||||
CompiledExpression::empty()
|
||||
// TODO: Handle captures
|
||||
let p = self
|
||||
.fnc
|
||||
.mc
|
||||
.compile_class(None, class_exp.ident.as_ref(), &class_exp.class);
|
||||
|
||||
CompiledExpression::new(Value::Pointer(p), vec![])
|
||||
}
|
||||
Yield(yield_expr) => self.yield_expr(yield_expr, target_register),
|
||||
MetaProp(meta_prop) => {
|
||||
|
||||
@@ -275,7 +275,11 @@ impl<'a> FunctionCompiler<'a> {
|
||||
Some(block) => {
|
||||
self.handle_block_body(block);
|
||||
}
|
||||
None => self.todo(constructor.span(), "constructor without body"),
|
||||
|
||||
// This case is constructed artificially when there is no explicit constructor but there
|
||||
// are member initializer expressions which need to be compiled into a constructor. I'm
|
||||
// not sure whether SWC ever produces this case.
|
||||
None => {}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1113,7 +1117,12 @@ impl<'a> FunctionCompiler<'a> {
|
||||
use swc_ecma_ast::Decl::*;
|
||||
|
||||
match decl {
|
||||
Class(class) => self.todo(class.span(), "Class declaration"),
|
||||
Class(class) => {
|
||||
// TODO: Handle captures
|
||||
self
|
||||
.mc
|
||||
.compile_class(None, Some(&class.ident), &class.class);
|
||||
}
|
||||
Fn(fn_decl) => {
|
||||
let p = match self.lookup_value(&Ident::from_swc_ident(&fn_decl.ident)) {
|
||||
Some(Value::Pointer(p)) => p,
|
||||
|
||||
@@ -7,8 +7,8 @@ use swc_ecma_ast::EsVersion;
|
||||
use swc_ecma_parser::{Syntax, TsConfig};
|
||||
|
||||
use crate::asm::{
|
||||
Class, Definition, DefinitionContent, FnLine, Function, Instruction, Lazy, Module, Number,
|
||||
Object, Pointer, Register, Value,
|
||||
Class, Definition, DefinitionContent, FnLine, Instruction, Lazy, Module, Number, Object, Pointer,
|
||||
Register, Value,
|
||||
};
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticContainer, DiagnosticReporter};
|
||||
use crate::expression_compiler::{CompiledExpression, ExpressionCompiler};
|
||||
@@ -769,39 +769,34 @@ impl ModuleCompiler {
|
||||
let mut member_initializers_assembly = Vec::<FnLine>::new();
|
||||
member_initializers_assembly.append(&mut mi_fnc.fn_.body);
|
||||
|
||||
let mut has_constructor = false;
|
||||
let mut ctor = swc_ecma_ast::Constructor {
|
||||
span: class.span,
|
||||
key: swc_ecma_ast::PropName::Str(swc_ecma_ast::Str {
|
||||
span: class.span,
|
||||
value: swc_atoms::JsWord::from(""),
|
||||
raw: None,
|
||||
}),
|
||||
params: vec![],
|
||||
body: None,
|
||||
accessibility: None,
|
||||
is_optional: false,
|
||||
};
|
||||
|
||||
for class_member in &class.body {
|
||||
if let swc_ecma_ast::ClassMember::Constructor(ctor) = class_member {
|
||||
has_constructor = true;
|
||||
|
||||
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", defn_name.name));
|
||||
|
||||
self.compile_fn(
|
||||
ctor_defn_name.clone(),
|
||||
Functionish::Constructor(
|
||||
member_initializers_assembly.clone(),
|
||||
class.span,
|
||||
ctor.clone(),
|
||||
),
|
||||
);
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name);
|
||||
if let swc_ecma_ast::ClassMember::Constructor(concrete_ctor) = class_member {
|
||||
ctor = concrete_ctor.clone();
|
||||
}
|
||||
}
|
||||
|
||||
if !member_initializers_assembly.is_empty() && !has_constructor {
|
||||
if !member_initializers_assembly.is_empty() || ctor.body.is_some() {
|
||||
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", defn_name.name));
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name.clone());
|
||||
self.module.definitions.push(Definition {
|
||||
pointer: ctor_defn_name,
|
||||
content: DefinitionContent::Function(Function {
|
||||
is_generator: false,
|
||||
parameters: vec![],
|
||||
body: member_initializers_assembly,
|
||||
}),
|
||||
});
|
||||
self.compile_fn(
|
||||
ctor_defn_name.clone(),
|
||||
Functionish::Constructor(member_initializers_assembly.clone(), class.span, ctor),
|
||||
);
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name);
|
||||
}
|
||||
|
||||
for class_member in &class.body {
|
||||
@@ -855,15 +850,19 @@ impl ModuleCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
let class_value = Value::Class(Box::new(Class {
|
||||
constructor,
|
||||
prototype: Value::Object(Box::new(prototype)),
|
||||
static_: Value::Object(Box::new(static_)),
|
||||
}));
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer: defn_name.clone(),
|
||||
content: DefinitionContent::Value(Value::Class(Box::new(Class {
|
||||
constructor,
|
||||
prototype: Value::Object(Box::new(prototype)),
|
||||
static_: Value::Object(Box::new(static_)),
|
||||
}))),
|
||||
content: DefinitionContent::Value(class_value.clone()),
|
||||
});
|
||||
|
||||
self.constants_map.insert(defn_name.clone(), class_value);
|
||||
|
||||
defn_name
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::collections::BTreeSet;
|
||||
|
||||
use crate::asm::{Pointer, Register};
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Clone, Debug)]
|
||||
pub struct NameAllocator {
|
||||
used_names: BTreeSet<String>,
|
||||
released_names: Vec<String>,
|
||||
@@ -102,7 +102,7 @@ pub fn ident_from_str(str: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct PointerAllocator {
|
||||
alloc: NameAllocator,
|
||||
}
|
||||
@@ -115,7 +115,7 @@ impl PointerAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RegAllocator {
|
||||
pub alloc: NameAllocator,
|
||||
}
|
||||
|
||||
@@ -61,7 +61,14 @@ pub fn shake_tree(module: &mut Module) {
|
||||
|
||||
for pointer in &ordered_pointers {
|
||||
if required_pointers.contains(pointer) {
|
||||
let defn = new_definitions_map.get_mut(pointer).unwrap();
|
||||
let defn = match new_definitions_map.get_mut(pointer) {
|
||||
Some(defn) => defn,
|
||||
None => {
|
||||
// This can happen due to errors in the input program. Ideally we should ensure there are
|
||||
// error diagnostics when we hit this case (TODO).
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// First include pointers that are allowed to be circular
|
||||
match &defn.content {
|
||||
@@ -75,7 +82,14 @@ pub fn shake_tree(module: &mut Module) {
|
||||
|
||||
for pointer in ordered_pointers {
|
||||
if required_pointers.contains(&pointer) {
|
||||
let defn = new_definitions_map.get_mut(&pointer).unwrap();
|
||||
let defn = match new_definitions_map.get_mut(&pointer) {
|
||||
Some(defn) => defn,
|
||||
None => {
|
||||
// This can happen due to errors in the input program. Ideally we should ensure there are
|
||||
// error diagnostics when we hit this case (TODO).
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if defn.pointer.name.is_empty() {
|
||||
// "" isn't a valid pointer name - this happens when `take` has already been used on the
|
||||
|
||||
@@ -62,7 +62,7 @@ pub struct Ref {
|
||||
pub span: swc_common::Span,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ScopeAnalysis {
|
||||
pub names: HashMap<NameId, Name>,
|
||||
pub owners: HashMap<OwnerId, HashSet<swc_common::Span>>,
|
||||
|
||||
Reference in New Issue
Block a user