Use asm::Pointer during compilation

This commit is contained in:
Andrew Morris
2023-03-06 14:02:27 +11:00
parent 6734567c89
commit 3093016344
5 changed files with 145 additions and 136 deletions

View File

@@ -1,8 +1,8 @@
use std::collections::HashSet;
use crate::scope::scope_reg;
use crate::{asm::Pointer, scope::scope_reg};
use super::scope::{MappedName, Scope, ScopeTrait};
use super::scope::{MappedName, Scope};
pub struct CaptureFinder {
outside_scope: Scope,
@@ -222,7 +222,12 @@ impl CaptureFinder {
Fn(fn_) => {
let fn_name = fn_.ident.sym.to_string();
scope.set(fn_name.clone(), MappedName::Definition("".to_string()));
scope.set(
fn_name.clone(),
MappedName::Definition(Pointer {
name: "".to_string(),
}),
);
}
Var(var_decl) => self.populate_block_scope_var_decl(scope, var_decl),
TsInterface(_) => {}

View File

@@ -7,11 +7,13 @@ use swc_common::{errors::Handler, FileName, SourceMap, Spanned};
use swc_ecma_ast::EsVersion;
use swc_ecma_parser::{Syntax, TsConfig};
use crate::asm::Pointer;
use super::diagnostic::{Diagnostic, DiagnosticLevel};
use super::expression_compiler::{string_literal, CompiledExpression, ExpressionCompiler};
use super::function_compiler::{FunctionCompiler, Functionish};
use super::name_allocator::NameAllocator;
use super::scope::{init_std_scope, MappedName, Scope, ScopeTrait};
use super::scope::{init_std_scope, MappedName, Scope};
use super::scope_analysis::ScopeAnalysis;
struct DiagnosticCollector {
@@ -112,6 +114,28 @@ struct Compiler {
}
impl Compiler {
fn allocate_defn(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate(&name.to_string());
Pointer {
name: allocated_name,
}
}
fn allocate_defn_numbered(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate_numbered(&name.to_string());
Pointer {
name: allocated_name,
}
}
fn compile_program(&mut self, program: &swc_ecma_ast::Program) {
use swc_ecma_ast::Program::*;
@@ -137,7 +161,7 @@ impl Compiler {
use swc_ecma_ast::ModuleItem;
use swc_ecma_ast::Stmt;
let mut default_export_name = None;
let mut default_export_pointer = None;
// Populate scope with top-level declarations
for module_item in &module.body {
@@ -169,22 +193,14 @@ impl Compiler {
swc_ecma_ast::DefaultDecl::Fn(fn_) => {
match &fn_.ident {
Some(id) => {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate(&id.sym.to_string());
let allocated_name = self.allocate_defn(&id.sym.to_string());
default_export_name = Some(allocated_name.clone());
default_export_pointer = Some(allocated_name.clone());
scope.set(id.sym.to_string(), MappedName::Definition(allocated_name));
}
None => {
default_export_name = Some(
self
.definition_allocator
.borrow_mut()
.allocate_numbered(&"_anon".to_string()),
);
default_export_pointer = Some(self.allocate_defn_numbered("_anon"));
}
};
}
@@ -365,23 +381,13 @@ impl Compiler {
Decl::Class(class) => {
scope.set(
class.ident.sym.to_string(),
MappedName::Definition(
self
.definition_allocator
.borrow_mut()
.allocate(&class.ident.sym.to_string()),
),
MappedName::Definition(self.allocate_defn(&class.ident.sym.to_string())),
);
}
Decl::Fn(fn_) => {
scope.set(
fn_.ident.sym.to_string(),
MappedName::Definition(
self
.definition_allocator
.borrow_mut()
.allocate(&fn_.ident.sym.to_string()),
),
MappedName::Definition(self.allocate_defn(&fn_.ident.sym.to_string())),
);
}
Decl::Var(var_decl) => {
@@ -423,15 +429,15 @@ impl Compiler {
}
// First compile default
match default_export_name {
Some(default_export_name) => {
match default_export_pointer {
Some(default_export_pointer) => {
for module_item in &module.body {
match module_item {
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(edd)) => self
.compile_export_default_decl(
edd,
// FIXME: clone() shouldn't be necessary here (we want to move)
default_export_name.clone(),
default_export_pointer.name.clone(),
&scope,
),
_ => {}
@@ -625,7 +631,7 @@ impl Compiler {
use swc_ecma_ast::Decl::*;
match decl {
Class(class) => self.compile_class_decl(class, self.definition_allocator.clone(), scope),
Class(class) => self.compile_class_decl(class, scope),
Fn(fn_) => {
let fn_name = fn_.ident.sym.to_string();
@@ -646,7 +652,6 @@ impl Compiler {
defn,
Some(fn_.ident.sym.to_string()),
Functionish::Fn(fn_.function.clone()),
self.definition_allocator.clone(),
scope,
)
}
@@ -705,7 +710,6 @@ impl Compiler {
defn,
Some(fn_name),
Functionish::Fn(fn_.function.clone()),
self.definition_allocator.clone(),
scope,
);
}
@@ -721,17 +725,16 @@ impl Compiler {
fn compile_fn(
&mut self,
defn_name: String,
defn_pointer: Pointer,
fn_name: Option<String>,
functionish: Functionish,
definition_allocator: Rc<RefCell<NameAllocator>>,
parent_scope: &Scope,
) {
let (defn, mut diagnostics) = FunctionCompiler::compile(
defn_name,
defn_pointer,
fn_name,
functionish,
definition_allocator,
self.definition_allocator.clone(),
parent_scope,
);
@@ -739,12 +742,7 @@ impl Compiler {
self.diagnostics.append(&mut diagnostics);
}
fn compile_class_decl(
&mut self,
class_decl: &swc_ecma_ast::ClassDecl,
definition_allocator: Rc<RefCell<NameAllocator>>,
parent_scope: &Scope,
) {
fn compile_class_decl(&mut self, class_decl: &swc_ecma_ast::ClassDecl, parent_scope: &Scope) {
let mut defn = Vec::<String>::new();
let class_name = class_decl.ident.sym.to_string();
@@ -762,9 +760,9 @@ impl Compiler {
}
};
let mut constructor_defn_name: Option<String> = None;
let mut constructor_defn_name: Option<Pointer> = None;
let mut member_initializers_fnc = FunctionCompiler::new(definition_allocator.clone());
let mut member_initializers_fnc = FunctionCompiler::new(self.definition_allocator.clone());
for class_member in &class_decl.class.body {
match class_member {
@@ -829,15 +827,12 @@ impl Compiler {
swc_ecma_ast::ClassMember::Constructor(constructor) => {
has_constructor = true;
let ctor_defn_name = definition_allocator
.borrow_mut()
.allocate(&format!("{}_constructor", class_name));
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", class_name));
self.compile_fn(
ctor_defn_name.clone(),
None,
Functionish::Constructor(member_initializers_assembly.clone(), constructor.clone()),
definition_allocator.clone(),
parent_scope,
);
@@ -848,11 +843,9 @@ impl Compiler {
}
if member_initializers_assembly.len() > 0 && !has_constructor {
let ctor_defn_name = definition_allocator
.borrow_mut()
.allocate(&format!("{}_constructor", class_name));
let ctor_defn_name = self.allocate_defn(&format!("{}_constructor", class_name));
defn.push(format!("@{} = function() {{", &ctor_defn_name));
defn.push(format!("{} = function() {{", ctor_defn_name));
for line in member_initializers_assembly {
defn.push(line.clone());
@@ -865,11 +858,11 @@ impl Compiler {
}
defn.push(format!(
"@{} = class({}, {{",
"{} = class({}, {{",
defn_name,
match constructor_defn_name {
None => "void".to_string(),
Some(d) => format!("@{}", d),
Some(d) => format!("{}", d),
},
));
@@ -892,20 +885,17 @@ impl Compiler {
}
};
let method_defn_name = definition_allocator
.borrow_mut()
.allocate(&format!("{}_{}", defn_name, name));
let method_defn_name = self.allocate_defn(&format!("{}_{}", defn_name.name, name));
self.compile_fn(
method_defn_name.clone(),
None,
Functionish::Fn(method.function.clone()),
definition_allocator.clone(),
parent_scope,
);
defn.push(format!(
" {}: @{},",
" {}: {},",
string_literal(&name),
method_defn_name,
));

View File

@@ -2,12 +2,12 @@ use queues::*;
use swc_common::Spanned;
use crate::asm::Register;
use crate::asm::{Pointer, Register};
use super::capture_finder::CaptureFinder;
use super::diagnostic::{Diagnostic, DiagnosticLevel};
use super::function_compiler::{FunctionCompiler, Functionish, QueuedFunction};
use super::scope::{init_std_scope, MappedName, Scope, ScopeTrait};
use super::scope::{init_std_scope, MappedName, Scope};
pub struct CompiledExpression {
/** It is usually better to access this via functionCompiler.use_ */
@@ -1058,13 +1058,9 @@ impl<'a> ExpressionCompiler<'a> {
.clone()
.and_then(|ident| Some(ident.sym.to_string()));
let definition_name = match &fn_name {
Some(name) => self.fnc.definition_allocator.borrow_mut().allocate(&name),
None => self
.fnc
.definition_allocator
.borrow_mut()
.allocate_numbered(&"_anon".to_string()),
let definition_pointer = match &fn_name {
Some(name) => self.fnc.allocate_defn(&name),
None => self.fnc.allocate_defn_numbered(&"_anon".to_string()),
};
let mut cf = CaptureFinder::new(self.scope.clone());
@@ -1074,7 +1070,7 @@ impl<'a> ExpressionCompiler<'a> {
.fnc
.queue
.add(QueuedFunction {
definition_name: definition_name.clone(),
definition_pointer: definition_pointer.clone(),
fn_name: fn_name.clone(),
capture_params: cf.ordered_names.clone(),
functionish: Functionish::Fn(fn_.function.clone()),
@@ -1082,13 +1078,13 @@ impl<'a> ExpressionCompiler<'a> {
.expect("Failed to queue function");
if cf.ordered_names.len() == 0 {
return self.inline(format!("@{}", definition_name), target_register);
return self.inline(format!("{}", definition_pointer), target_register);
}
return self.capturing_fn_ref(
fn_name,
fn_.ident.span(),
&definition_name,
&definition_pointer,
&cf.ordered_names,
target_register,
);
@@ -1099,11 +1095,7 @@ impl<'a> ExpressionCompiler<'a> {
arrow_expr: &swc_ecma_ast::ArrowExpr,
target_register: Option<Register>,
) -> CompiledExpression {
let definition_name = self
.fnc
.definition_allocator
.borrow_mut()
.allocate_numbered(&"_anon".to_string());
let definition_pointer = self.fnc.allocate_defn_numbered(&"_anon".to_string());
let mut cf = CaptureFinder::new(self.scope.clone());
cf.arrow_expr(&init_std_scope(), arrow_expr);
@@ -1112,7 +1104,7 @@ impl<'a> ExpressionCompiler<'a> {
.fnc
.queue
.add(QueuedFunction {
definition_name: definition_name.clone(),
definition_pointer: definition_pointer.clone(),
fn_name: None,
capture_params: cf.ordered_names.clone(),
functionish: Functionish::Arrow(arrow_expr.clone()),
@@ -1120,13 +1112,13 @@ impl<'a> ExpressionCompiler<'a> {
.expect("Failed to queue function");
if cf.ordered_names.len() == 0 {
return self.inline(format!("@{}", definition_name), target_register);
return self.inline(format!("{}", definition_pointer), target_register);
}
return self.capturing_fn_ref(
None,
arrow_expr.span(),
&definition_name,
&definition_pointer,
&cf.ordered_names,
target_register,
);
@@ -1136,7 +1128,7 @@ impl<'a> ExpressionCompiler<'a> {
&mut self,
fn_name: Option<String>,
span: swc_common::Span,
definition_name: &String,
definition_pointer: &Pointer,
captures: &Vec<String>,
target_register: Option<Register>,
) -> CompiledExpression {
@@ -1157,7 +1149,7 @@ impl<'a> ExpressionCompiler<'a> {
Some(tr) => tr.clone(),
};
let mut bind_instr = format!(" bind @{} [", definition_name);
let mut bind_instr = format!(" bind {} [", definition_pointer);
for i in 0..captures.len() {
let captured_name = &captures[i];
@@ -1208,7 +1200,7 @@ impl<'a> ExpressionCompiler<'a> {
Functionish::Arrow(arrow) => arrow.span,
Functionish::Constructor(_, constructor) => constructor.span,
},
&qfn.definition_name,
&qfn.definition_pointer,
&qfn.capture_params,
None,
);
@@ -1360,7 +1352,7 @@ impl<'a> ExpressionCompiler<'a> {
return match mapped {
MappedName::Register(reg) => self.inline(format!("{}", reg), target_register),
MappedName::Definition(def) => self.inline("@".to_string() + &def, target_register),
MappedName::Definition(def) => self.inline(format!("{}", def), target_register),
MappedName::QueuedFunction(qfn) => self.capturing_fn_ref(
qfn.fn_name.clone(),
match &qfn.functionish {
@@ -1368,7 +1360,7 @@ impl<'a> ExpressionCompiler<'a> {
Functionish::Arrow(arrow) => arrow.span,
Functionish::Constructor(_, constructor) => constructor.span,
},
&qfn.definition_name,
&qfn.definition_pointer,
&qfn.capture_params,
target_register,
),

View File

@@ -5,7 +5,7 @@ use std::rc::Rc;
use swc_common::Spanned;
use crate::asm::Register;
use crate::asm::{Pointer, Register};
use crate::scope::scope_reg;
use super::capture_finder::CaptureFinder;
@@ -13,7 +13,7 @@ use super::diagnostic::{Diagnostic, DiagnosticLevel};
use super::expression_compiler::CompiledExpression;
use super::expression_compiler::ExpressionCompiler;
use super::name_allocator::NameAllocator;
use super::scope::{init_std_scope, MappedName, Scope, ScopeTrait};
use super::scope::{init_std_scope, MappedName, Scope};
#[derive(Clone, Debug)]
pub enum Functionish {
@@ -24,7 +24,7 @@ pub enum Functionish {
#[derive(Clone, Debug)]
pub struct QueuedFunction {
pub definition_name: String,
pub definition_pointer: Pointer,
pub fn_name: Option<String>,
pub capture_params: Vec<String>,
pub functionish: Functionish,
@@ -71,6 +71,28 @@ impl FunctionCompiler {
});
}
pub fn allocate_defn(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate(&name.to_string());
Pointer {
name: allocated_name,
}
}
pub fn allocate_defn_numbered(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate_numbered(&name.to_string());
Pointer {
name: allocated_name,
}
}
pub fn allocate_tmp(&mut self) -> Register {
return Register::Named(self.reg_allocator.allocate(&"_tmp".to_string()));
}
@@ -99,7 +121,7 @@ impl FunctionCompiler {
}
pub fn compile(
definition_name: String,
definition_pointer: Pointer,
fn_name: Option<String>,
functionish: Functionish,
definition_allocator: Rc<RefCell<NameAllocator>>,
@@ -110,7 +132,7 @@ impl FunctionCompiler {
self_
.queue
.add(QueuedFunction {
definition_name: definition_name.clone(),
definition_pointer: definition_pointer.clone(),
fn_name,
capture_params: Vec::new(),
functionish,
@@ -126,7 +148,7 @@ impl FunctionCompiler {
loop {
match self.queue.remove() {
Ok(qfn) => self.compile_functionish(
qfn.definition_name,
qfn.definition_pointer,
qfn.fn_name,
qfn.capture_params,
&qfn.functionish,
@@ -141,7 +163,7 @@ impl FunctionCompiler {
fn compile_functionish(
&mut self,
definition_name: String,
definition_pointer: Pointer,
fn_name: Option<String>,
capture_params: Vec<String>,
functionish: &Functionish,
@@ -154,13 +176,11 @@ impl FunctionCompiler {
match fn_name {
// TODO: Capture propagation when using this name recursively
Some(fn_name_) => scope.set(fn_name_, MappedName::Definition(definition_name.clone())),
Some(fn_name_) => scope.set(fn_name_, MappedName::Definition(definition_pointer.clone())),
None => {}
}
let mut heading = "@".to_string();
heading += &definition_name;
heading += " = function(";
let mut heading = format!("{} = function(", definition_pointer);
let mut param_count = 0;
@@ -640,10 +660,10 @@ impl FunctionCompiler {
let fn_name = fn_.ident.sym.to_string();
let definition_name = self.definition_allocator.borrow_mut().allocate(&fn_name);
let definition_pointer = self.allocate_defn(&fn_name);
let qf = QueuedFunction {
definition_name: definition_name,
definition_pointer,
fn_name: Some(fn_name.clone()),
capture_params: full_captures,
functionish: Functionish::Fn(fn_.function.clone()),
@@ -677,7 +697,7 @@ impl FunctionCompiler {
self.statement(stmt, false, &block_scope);
}
for mapping in block_scope.borrow().name_map.values() {
for mapping in block_scope.rc.borrow().name_map.values() {
match mapping {
MappedName::Register(reg) => {
self.release_reg(reg);

View File

@@ -2,7 +2,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use crate::asm;
use crate::asm::{Pointer, Register};
use super::function_compiler::QueuedFunction;
@@ -23,8 +23,8 @@ impl std::fmt::Display for Builtin {
#[derive(Clone, Debug)]
pub enum MappedName {
Register(asm::Register),
Definition(String),
Register(Register),
Definition(Pointer),
QueuedFunction(QueuedFunction),
Builtin(Builtin),
}
@@ -34,35 +34,31 @@ pub fn scope_reg(name: String) -> MappedName {
std::panic!("Invalid register name (use Register enum)");
}
MappedName::Register(asm::Register::Named(name))
MappedName::Register(Register::Named(name))
}
pub struct ScopeData {
pub name_map: HashMap<String, MappedName>,
pub parent: Option<Rc<RefCell<ScopeData>>>,
pub parent: Option<Scope>,
}
pub type Scope = Rc<RefCell<ScopeData>>;
pub trait ScopeTrait {
fn get(&self, name: &String) -> Option<MappedName>;
fn get_defn(&self, name: &String) -> Option<String>;
fn set(&self, name: String, mapped_name: MappedName);
fn nest(&self) -> Rc<RefCell<ScopeData>>;
#[derive(Clone)]
pub struct Scope {
pub rc: Rc<RefCell<ScopeData>>,
}
impl ScopeTrait for Scope {
fn get(&self, name: &String) -> Option<MappedName> {
match self.borrow().name_map.get(name) {
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.borrow().parent {
None => match &self.rc.borrow().parent {
Some(parent) => parent.get(name),
None => None,
},
}
}
fn get_defn(&self, name: &String) -> Option<String> {
pub fn get_defn(&self, name: &String) -> Option<Pointer> {
let get_result = self.get(name);
return match get_result {
@@ -71,36 +67,42 @@ impl ScopeTrait for Scope {
};
}
fn set(&self, name: String, mapped_name: MappedName) {
let old_mapping = self.borrow_mut().name_map.insert(name, mapped_name);
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)");
}
}
fn nest(&self) -> Rc<RefCell<ScopeData>> {
return Rc::new(RefCell::new(ScopeData {
name_map: Default::default(),
parent: Some(self.clone()),
}));
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 Rc::new(RefCell::new(ScopeData {
name_map: Default::default(),
parent: None,
}));
return Scope {
rc: Rc::new(RefCell::new(ScopeData {
name_map: Default::default(),
parent: None,
})),
};
}
pub fn init_std_scope() -> Scope {
return Rc::new(RefCell::new(ScopeData {
name_map: HashMap::from([
("Math".to_string(), MappedName::Builtin(Builtin::Math)),
("Debug".to_string(), MappedName::Builtin(Builtin::Debug)),
]),
parent: None,
}))
.nest();
Scope {
rc: Rc::new(RefCell::new(ScopeData {
name_map: HashMap::from([
("Math".to_string(), MappedName::Builtin(Builtin::Math)),
("Debug".to_string(), MappedName::Builtin(Builtin::Debug)),
]),
parent: None,
})),
}
.nest()
}