Skip to content

Commit

Permalink
Partial support for module constants
Browse files Browse the repository at this point in the history
  • Loading branch information
voltrevo committed Jun 23, 2023
1 parent 9135181 commit 50369d1
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 6 deletions.
11 changes: 11 additions & 0 deletions valuescript_compiler/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ pub struct Definition {
pub content: DefinitionContent,
}

impl Default for Definition {
fn default() -> Self {
Definition {
pointer: Pointer {
name: "".to_string(),
},
content: DefinitionContent::Value(Value::Void),
}
}
}

impl std::fmt::Display for Definition {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{} = {}", self.pointer, self.content)
Expand Down
15 changes: 13 additions & 2 deletions valuescript_compiler/src/link_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ fn shake_tree(module: &mut Module) {
pointers_included.insert(pointer.clone());

if let Some(dependencies) = dependency_graph.get(pointer) {
// TODO: Avoid randomness caused by HashSet iteration
for dependency in dependencies {
if !pointers_included.contains(dependency) {
pointers_to_include.push(dependency.clone());
Expand All @@ -462,11 +463,21 @@ fn shake_tree(module: &mut Module) {
}

let previous_definitions = std::mem::take(&mut module.definitions);
let mut new_definitions = Vec::<Definition>::new();
let mut new_definitions_map = HashMap::<Pointer, Definition>::new();

for definition in previous_definitions {
if pointers_included.contains(&definition.pointer) {
new_definitions.push(definition);
new_definitions_map.insert(definition.pointer.clone(), definition);
}
}

let mut new_definitions = Vec::<Definition>::new();

for pointer in pointers_to_include {
let defn = take(new_definitions_map.get_mut(&pointer).unwrap());

if defn.pointer.name != "" {
new_definitions.push(defn);
}
}

Expand Down
82 changes: 79 additions & 3 deletions valuescript_compiler/src/module_compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl ModuleCompiler {
For(for_) => self.not_supported(for_.span, "module level For statement"),
ForIn(for_in) => self.not_supported(for_in.span, "module level ForIn statement"),
ForOf(for_of) => self.not_supported(for_of.span, "module level ForOf statement"),
Expr(expr) => self.todo(expr.span, "module level Expr statement"),
Expr(expr) => self.not_supported(expr.span, "module level Expr statement"),
};
}

Expand All @@ -244,8 +244,84 @@ impl ModuleCompiler {
}
Fn(fn_) => self.compile_fn_decl(false, fn_),
Var(var_decl) => {
if !var_decl.declare {
self.todo(var_decl.span, "non-declare module level var declaration");
if var_decl.declare {
// Uses the `declare` typescript keyword. Nothing needed to support this.
return;
}

if var_decl.kind != swc_ecma_ast::VarDeclKind::Const {
// Only `const` variables in the global area. They cannot be mutated, so might as well
// insist they are `const` for clarity.
self.not_supported(var_decl.span, "non-const module level variable");
}

for decl in &var_decl.decls {
let ident = match &decl.name {
swc_ecma_ast::Pat::Ident(bi) => Some(&bi.id),
_ => {
self.todo(decl.name.span(), "Module level destructuring");
None
}
};

let init = match &decl.init {
Some(_) => &decl.init,
_ => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::Error,
message: format!("const variable without initializer"),
span: decl.init.span(),
});

&None
}
};

match (ident, init) {
(Some(ident), Some(init)) => {
let value = match static_eval_expr(init) {
Some(value) => value,
None => {
self.todo(
init.span(),
"Determine whether initializer can be statically evaluated",
);

continue;
}
};

let pointer = match self.scope_analysis.lookup(ident) {
Some(name) => match &name.value {
Value::Pointer(p) => p.clone(),
_ => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
message: "Expected pointer for module constant".to_string(),
span: ident.span(),
});

continue;
}
},
None => {
self.diagnostics.push(Diagnostic {
level: DiagnosticLevel::InternalError,
message: "Failed to lookup name".to_string(),
span: ident.span(),
});

continue;
}
};

self.module.definitions.push(Definition {
pointer,
content: DefinitionContent::Value(value),
});
}
_ => {}
}
}
}
TsInterface(_) => {}
Expand Down
7 changes: 6 additions & 1 deletion valuescript_compiler/src/scope_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,12 @@ impl ScopeAnalysis {

for decl in &var_decl.decls {
for ident in self.get_pat_idents(&decl.name) {
self.insert_reg_name(scope, name_type, &ident, Some(decl.span.hi));
let owner_id = scope.borrow().owner_id.clone();

match owner_id {
OwnerId::Span(..) => self.insert_reg_name(scope, name_type, &ident, Some(decl.span.hi)),
OwnerId::Module => self.insert_pointer_name(scope, name_type, &ident),
}
}
}
}
Expand Down

0 comments on commit 50369d1

Please sign in to comment.