mirror of
https://github.com/voltrevo/ValueScript.git
synced 2026-04-18 03:00:27 -04:00
wiiiip
This commit is contained in:
@@ -1024,7 +1024,8 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
.fnc
|
||||
.scope_analysis
|
||||
.captures
|
||||
.get(&OwnerId::Span(fn_.function.span));
|
||||
.get(&OwnerId::Span(fn_.function.span))
|
||||
.cloned();
|
||||
|
||||
self
|
||||
.fnc
|
||||
@@ -1040,9 +1041,8 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
None => self.inline(Value::Pointer(definition_pointer), target_register),
|
||||
Some(capture_params) => self.capturing_fn_ref(
|
||||
fn_name,
|
||||
fn_.ident.span(),
|
||||
&definition_pointer,
|
||||
capture_params,
|
||||
&capture_params,
|
||||
target_register,
|
||||
),
|
||||
}
|
||||
@@ -1059,7 +1059,8 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
.fnc
|
||||
.scope_analysis
|
||||
.captures
|
||||
.get(&OwnerId::Span(arrow_expr.span));
|
||||
.get(&OwnerId::Span(arrow_expr.span))
|
||||
.cloned();
|
||||
|
||||
self
|
||||
.fnc
|
||||
@@ -1073,26 +1074,20 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
|
||||
match capture_params {
|
||||
None => self.inline(Value::Pointer(definition_pointer), target_register),
|
||||
Some(capture_params) => self.capturing_fn_ref(
|
||||
None,
|
||||
arrow_expr.span(),
|
||||
&definition_pointer,
|
||||
capture_params,
|
||||
target_register,
|
||||
),
|
||||
Some(capture_params) => {
|
||||
self.capturing_fn_ref(None, &definition_pointer, &capture_params, target_register)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn capturing_fn_ref(
|
||||
&mut self,
|
||||
fn_name: Option<String>,
|
||||
span: swc_common::Span,
|
||||
definition_pointer: &Pointer,
|
||||
captures: &HashSet<NameId>,
|
||||
target_register: Option<Register>,
|
||||
) -> CompiledExpression {
|
||||
let mut nested_registers = Vec::<Register>::new();
|
||||
let mut sub_nested_registers = Vec::<Register>::new();
|
||||
|
||||
let reg = match target_register {
|
||||
None => {
|
||||
@@ -1120,10 +1115,6 @@ impl<'a> ExpressionCompiler<'a> {
|
||||
reg.clone(),
|
||||
));
|
||||
|
||||
for reg in sub_nested_registers {
|
||||
self.fnc.release_reg(®);
|
||||
}
|
||||
|
||||
return CompiledExpression::new(Value::Register(reg), nested_registers);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,7 @@ impl FunctionCompiler {
|
||||
pub fn process_queue(&mut self) {
|
||||
loop {
|
||||
match self.queue.remove() {
|
||||
Ok(qfn) => self.compile_functionish(qfn.definition_pointer, qfn.fn_name, &qfn.functionish),
|
||||
Ok(qfn) => self.compile_functionish(qfn.definition_pointer, &qfn.functionish),
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
@@ -216,12 +216,7 @@ impl FunctionCompiler {
|
||||
}
|
||||
}
|
||||
|
||||
fn compile_functionish(
|
||||
&mut self,
|
||||
definition_pointer: Pointer,
|
||||
fn_name: Option<String>,
|
||||
functionish: &Functionish,
|
||||
) {
|
||||
fn compile_functionish(&mut self, definition_pointer: Pointer, functionish: &Functionish) {
|
||||
// TODO: Use a new FunctionCompiler per function instead of this hack
|
||||
self.reg_allocator = self
|
||||
.scope_analysis
|
||||
|
||||
@@ -12,7 +12,6 @@ mod link_module;
|
||||
mod module_compiler;
|
||||
mod name_allocator;
|
||||
mod resolve_path;
|
||||
mod scope;
|
||||
mod scope_analysis;
|
||||
|
||||
pub use assembler::assemble;
|
||||
|
||||
@@ -11,14 +11,12 @@ use crate::asm::{
|
||||
Class, Definition, DefinitionContent, Function, Instruction, InstructionOrLabel, Lazy, Module,
|
||||
Object, Pointer, Register, Value,
|
||||
};
|
||||
use crate::diagnostic::{Diagnostic, DiagnosticLevel};
|
||||
use crate::expression_compiler::{CompiledExpression, ExpressionCompiler};
|
||||
use crate::function_compiler::{FunctionCompiler, Functionish};
|
||||
use crate::name_allocator::NameAllocator;
|
||||
use crate::scope_analysis::OwnerId;
|
||||
|
||||
use super::diagnostic::{Diagnostic, DiagnosticLevel};
|
||||
use super::expression_compiler::{CompiledExpression, ExpressionCompiler};
|
||||
use super::function_compiler::{FunctionCompiler, Functionish};
|
||||
use super::name_allocator::NameAllocator;
|
||||
use super::scope::{init_std_scope, MappedName, Scope};
|
||||
use super::scope_analysis::ScopeAnalysis;
|
||||
use crate::scope_analysis::ScopeAnalysis;
|
||||
|
||||
struct DiagnosticCollector {
|
||||
diagnostics: Arc<Mutex<Vec<Diagnostic>>>,
|
||||
@@ -174,7 +172,6 @@ impl ModuleCompiler {
|
||||
fn compile_module(&mut self, module: &swc_ecma_ast::Module) {
|
||||
let mut scope_analysis = ScopeAnalysis::run(module);
|
||||
self.diagnostics.append(&mut scope_analysis.diagnostics);
|
||||
let scope = init_std_scope();
|
||||
|
||||
for module_item in &module.body {
|
||||
self.compile_module_item(module_item);
|
||||
@@ -239,7 +236,7 @@ impl ModuleCompiler {
|
||||
|
||||
match decl {
|
||||
Class(class) => {
|
||||
self.compile_class(None, Some(class.ident.sym.to_string()), &class.class);
|
||||
self.compile_class(None, Some(&class.ident), &class.class);
|
||||
}
|
||||
Fn(fn_) => self.compile_fn_decl(false, fn_),
|
||||
Var(var_decl) => {
|
||||
@@ -291,12 +288,7 @@ impl ModuleCompiler {
|
||||
|
||||
match &edd.decl {
|
||||
DefaultDecl::Class(class) => {
|
||||
let class_name = match &class.ident {
|
||||
Some(ident) => Some(ident.sym.to_string()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
let pointer = self.compile_class(None, class_name, &class.class);
|
||||
let pointer = self.compile_class(None, class.ident.as_ref(), &class.class);
|
||||
self.module.export_default = Value::Pointer(pointer);
|
||||
}
|
||||
DefaultDecl::Fn(fn_) => {
|
||||
@@ -340,7 +332,7 @@ impl ModuleCompiler {
|
||||
match &ed.decl {
|
||||
Decl::Class(class) => {
|
||||
let class_name = class.ident.sym.to_string();
|
||||
self.compile_class(Some(class_name.clone()), Some(class_name), &class.class);
|
||||
self.compile_class(Some(class_name.clone()), Some(&class.ident), &class.class);
|
||||
}
|
||||
Decl::Fn(fn_) => self.compile_fn_decl(true, fn_),
|
||||
Decl::Var(var_decl) => {
|
||||
@@ -366,7 +358,7 @@ impl ModuleCompiler {
|
||||
match specifier {
|
||||
Named(named) => {
|
||||
let orig_name = match &named.orig {
|
||||
ModuleExportName::Ident(ident) => ident.sym.to_string(),
|
||||
ModuleExportName::Ident(ident) => ident,
|
||||
ModuleExportName::Str(_) => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
@@ -374,7 +366,7 @@ impl ModuleCompiler {
|
||||
span: named.span,
|
||||
});
|
||||
|
||||
"_todo_export_non_ident".to_string()
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -384,7 +376,7 @@ impl ModuleCompiler {
|
||||
self.todo(str_.span, "exporting a non-identifier");
|
||||
"_todo_export_non_ident".to_string()
|
||||
}
|
||||
None => orig_name.clone(),
|
||||
None => orig_name.sym.to_string(),
|
||||
};
|
||||
|
||||
let defn = match &en.src {
|
||||
@@ -394,7 +386,7 @@ impl ModuleCompiler {
|
||||
self.module.definitions.push(Definition {
|
||||
pointer: defn.clone(),
|
||||
content: DefinitionContent::Lazy(Lazy {
|
||||
body: match orig_name == "default" {
|
||||
body: match orig_name.sym.to_string() == "default" {
|
||||
true => vec![InstructionOrLabel::Instruction(Instruction::Import(
|
||||
Value::String(src.value.to_string()),
|
||||
Register::Return,
|
||||
@@ -406,7 +398,7 @@ impl ModuleCompiler {
|
||||
)),
|
||||
InstructionOrLabel::Instruction(Instruction::Sub(
|
||||
Value::Register(Register::Return),
|
||||
Value::String(orig_name.clone()),
|
||||
Value::String(orig_name.sym.to_string()),
|
||||
Register::Return,
|
||||
)),
|
||||
],
|
||||
@@ -416,9 +408,9 @@ impl ModuleCompiler {
|
||||
|
||||
Some(defn)
|
||||
}
|
||||
None => match scope.get_defn(&orig_name) {
|
||||
Some(found_defn) => Some(found_defn),
|
||||
None => {
|
||||
None => match self.scope_analysis.lookup(&OwnerId::Module, &orig_name) {
|
||||
Value::Pointer(p) => Some(p),
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("Definition for {} should have been in scope", orig_name),
|
||||
@@ -525,9 +517,18 @@ impl ModuleCompiler {
|
||||
None => local_name.clone(),
|
||||
};
|
||||
|
||||
let pointer = scope
|
||||
.get_defn(&local_name)
|
||||
.expect("imported name should have been in scope");
|
||||
let pointer = match self.scope_analysis.lookup(&OwnerId::Module, &named.local) {
|
||||
Value::Pointer(pointer) => pointer,
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("Imported name {} should have been a pointer", local_name),
|
||||
span: named.span,
|
||||
});
|
||||
|
||||
self.allocate_defn(local_name.as_str())
|
||||
}
|
||||
};
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer,
|
||||
@@ -549,9 +550,18 @@ impl ModuleCompiler {
|
||||
Default(default) => {
|
||||
let local_name = default.local.sym.to_string();
|
||||
|
||||
let pointer = scope
|
||||
.get_defn(&local_name)
|
||||
.expect("imported name should have been in scope");
|
||||
let pointer = match self.scope_analysis.lookup(&OwnerId::Module, &default.local) {
|
||||
Value::Pointer(pointer) => pointer,
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("Imported name {} should have been a pointer", local_name),
|
||||
span: default.span,
|
||||
});
|
||||
|
||||
self.allocate_defn(local_name.as_str())
|
||||
}
|
||||
};
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer,
|
||||
@@ -566,9 +576,21 @@ impl ModuleCompiler {
|
||||
Namespace(namespace) => {
|
||||
let local_name = namespace.local.sym.to_string();
|
||||
|
||||
let pointer = scope
|
||||
.get_defn(&local_name)
|
||||
.expect("imported name should have been in scope");
|
||||
let pointer = match self
|
||||
.scope_analysis
|
||||
.lookup(&OwnerId::Module, &namespace.local)
|
||||
{
|
||||
Value::Pointer(pointer) => pointer,
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("Imported name {} should have been a pointer", local_name),
|
||||
span: namespace.span,
|
||||
});
|
||||
|
||||
self.allocate_defn(local_name.as_str())
|
||||
}
|
||||
};
|
||||
|
||||
self.module.definitions.push(Definition {
|
||||
pointer,
|
||||
@@ -606,31 +628,27 @@ impl ModuleCompiler {
|
||||
fn compile_class(
|
||||
&mut self,
|
||||
export_name: Option<String>,
|
||||
class_name: Option<String>,
|
||||
ident: Option<&swc_ecma_ast::Ident>,
|
||||
class: &swc_ecma_ast::Class,
|
||||
) -> Pointer {
|
||||
let mut constructor: Value = Value::Void;
|
||||
let mut methods: Object = Object::default();
|
||||
let mut dependent_definitions: Vec<Definition>;
|
||||
|
||||
let defn_name = 'block: {
|
||||
let class_name = match class_name {
|
||||
Some(class_name) => class_name,
|
||||
None => break 'block self.allocate_defn_numbered("_anon"),
|
||||
};
|
||||
|
||||
match parent_scope.get(&class_name) {
|
||||
Some(MappedName::Definition(d)) => d,
|
||||
let defn_name = match ident {
|
||||
Some(ident) => match self.scope_analysis.lookup(&OwnerId::Module, ident) {
|
||||
Value::Pointer(p) => p,
|
||||
_ => {
|
||||
self.diagnostics.push(Diagnostic {
|
||||
level: DiagnosticLevel::InternalError,
|
||||
message: format!("Definition for {} should have been in scope", class_name),
|
||||
message: format!("Definition for {} should have been in scope", ident.sym),
|
||||
span: class.span, // FIXME: make class_name ident and use that span
|
||||
});
|
||||
|
||||
return self.allocate_defn_numbered("_scope_error");
|
||||
self.allocate_defn_numbered("_scope_error")
|
||||
}
|
||||
}
|
||||
},
|
||||
None => self.allocate_defn_numbered("_anon"),
|
||||
};
|
||||
|
||||
if let Some(export_name) = export_name {
|
||||
@@ -656,7 +674,6 @@ impl ModuleCompiler {
|
||||
}
|
||||
|
||||
let mut ec = ExpressionCompiler {
|
||||
scope: parent_scope,
|
||||
fnc: &mut member_initializers_fnc,
|
||||
};
|
||||
|
||||
@@ -684,7 +701,7 @@ impl ModuleCompiler {
|
||||
member_initializers_assembly.append(&mut member_initializers_fnc.current.body);
|
||||
|
||||
// Include any other definitions that were created by the member initializers
|
||||
member_initializers_fnc.process_queue(parent_scope);
|
||||
member_initializers_fnc.process_queue();
|
||||
dependent_definitions = std::mem::take(&mut member_initializers_fnc.definitions);
|
||||
|
||||
let mut has_constructor = false;
|
||||
@@ -704,7 +721,6 @@ impl ModuleCompiler {
|
||||
class.span,
|
||||
ctor.clone(),
|
||||
),
|
||||
parent_scope,
|
||||
));
|
||||
|
||||
constructor = Value::Pointer(ctor_defn_name);
|
||||
@@ -746,7 +762,6 @@ impl ModuleCompiler {
|
||||
method_defn_name.clone(),
|
||||
None,
|
||||
Functionish::Fn(method.function.clone()),
|
||||
parent_scope,
|
||||
));
|
||||
|
||||
methods
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use valuescript_common::BUILTIN_NAMES;
|
||||
|
||||
use crate::{
|
||||
asm::{Builtin, Pointer, Register, Value},
|
||||
constants::CONSTANTS,
|
||||
};
|
||||
|
||||
use super::function_compiler::QueuedFunction;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum MappedName {
|
||||
Register(Register),
|
||||
Definition(Pointer),
|
||||
QueuedFunction(QueuedFunction),
|
||||
Builtin(Builtin),
|
||||
Constant(Value),
|
||||
}
|
||||
|
||||
pub fn scope_reg(name: String) -> MappedName {
|
||||
if name == "return" || name == "this" || name == "ignore" {
|
||||
std::panic!("Invalid register name (use Register enum)");
|
||||
}
|
||||
|
||||
MappedName::Register(Register::Named(name))
|
||||
}
|
||||
|
||||
pub struct ScopeData {
|
||||
pub name_map: HashMap<String, MappedName>,
|
||||
pub parent: Option<Scope>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Scope {
|
||||
pub rc: Rc<RefCell<ScopeData>>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
pub fn get(&self, name: &String) -> Option<MappedName> {
|
||||
match self.rc.borrow().name_map.get(name) {
|
||||
Some(mapped_name) => Some(mapped_name.clone()),
|
||||
None => match &self.rc.borrow().parent {
|
||||
Some(parent) => parent.get(name),
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_defn(&self, name: &String) -> Option<Pointer> {
|
||||
let get_result = self.get(name);
|
||||
|
||||
return match get_result {
|
||||
Some(MappedName::Definition(d)) => Some(d.clone()),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set(&self, name: String, mapped_name: MappedName) {
|
||||
let old_mapping = self.rc.borrow_mut().name_map.insert(name, mapped_name);
|
||||
|
||||
if old_mapping.is_some() {
|
||||
std::panic!("Scope overwrite occurred (not implemented: being permissive about this)");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nest(&self) -> Scope {
|
||||
return Scope {
|
||||
rc: Rc::new(RefCell::new(ScopeData {
|
||||
name_map: Default::default(),
|
||||
parent: Some(self.clone()),
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn _init_scope() -> Scope {
|
||||
return Scope {
|
||||
rc: Rc::new(RefCell::new(ScopeData {
|
||||
name_map: Default::default(),
|
||||
parent: None,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn init_std_scope() -> Scope {
|
||||
let mut name_map: HashMap<String, MappedName> = Default::default();
|
||||
|
||||
for name in BUILTIN_NAMES {
|
||||
name_map.insert(
|
||||
name.to_string(),
|
||||
MappedName::Builtin(Builtin {
|
||||
name: name.to_string(),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
for (name, value) in CONSTANTS {
|
||||
name_map.insert(name.to_string(), MappedName::Constant(value.clone()));
|
||||
}
|
||||
|
||||
Scope {
|
||||
rc: Rc::new(RefCell::new(ScopeData {
|
||||
name_map,
|
||||
parent: None,
|
||||
})),
|
||||
}
|
||||
.nest()
|
||||
}
|
||||
Reference in New Issue
Block a user