Partial support for module constants

This commit is contained in:
Andrew Morris
2023-06-23 15:41:16 +10:00
parent 9135181634
commit 50369d18f3
4 changed files with 109 additions and 6 deletions

View File

@@ -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)

View File

@@ -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());
@@ -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);
}
}

View File

@@ -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"),
};
}
@@ -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(_) => {}

View File

@@ -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),
}
}
}
}