mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
Partial support for module constants
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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(_) => {}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user