Use compile-time borrowing of module compiler to simplify fnc, ec

This commit is contained in:
Andrew Morris
2023-07-24 11:16:38 +10:00
parent e81eb6d1e2
commit 1a12e57435
3 changed files with 53 additions and 93 deletions

View File

@@ -61,11 +61,11 @@ impl Drop for ReleaseChecker {
}
}
pub struct ExpressionCompiler<'a> {
pub fnc: &'a mut FunctionCompiler,
pub struct ExpressionCompiler<'a, 'fnc> {
pub fnc: &'a mut FunctionCompiler<'fnc>,
}
impl<'a> ExpressionCompiler<'a> {
impl<'a, 'fnc> ExpressionCompiler<'a, 'fnc> {
pub fn compile_top_level(
&mut self,
expr: &swc_ecma_ast::Expr,
@@ -952,6 +952,7 @@ impl<'a> ExpressionCompiler<'a> {
let capture_params = self
.fnc
.mc
.scope_analysis
.get_register_captures(&fn_to_owner_id(&fn_.ident, &fn_.function));
@@ -989,6 +990,7 @@ impl<'a> ExpressionCompiler<'a> {
let capture_params = self
.fnc
.mc
.scope_analysis
.get_register_captures(&OwnerId::Span(arrow_expr.span));
@@ -1075,6 +1077,7 @@ impl<'a> ExpressionCompiler<'a> {
if !is_param {
let cap_name = self
.fnc
.mc
.scope_analysis
.names
.get(cap)
@@ -1232,7 +1235,7 @@ impl<'a> ExpressionCompiler<'a> {
ident: &CrateIdent,
target_register: Option<Register>,
) -> CompiledExpression {
let fn_as_owner_id = match self.fnc.scope_analysis.lookup(ident) {
let fn_as_owner_id = match self.fnc.mc.scope_analysis.lookup(ident) {
Some(name) => match name.type_ == NameType::Function {
true => match name.id {
// TODO: This is a bit of a hack, it might break...
@@ -1265,7 +1268,7 @@ impl<'a> ExpressionCompiler<'a> {
match fn_as_owner_id {
Some(owner_id) => {
let capture_params = self.fnc.scope_analysis.get_register_captures(&owner_id);
let capture_params = self.fnc.mc.scope_analysis.get_register_captures(&owner_id);
match capture_params.len() {
0 => value.to_ce(),

View File

@@ -1,8 +1,6 @@
use queues::*;
use std::cell::RefCell;
use std::collections::{BTreeSet, HashMap};
use std::collections::BTreeSet;
use std::mem::take;
use std::rc::Rc;
use swc_common::Spanned;
@@ -15,9 +13,10 @@ use crate::diagnostic::{Diagnostic, DiagnosticLevel};
use crate::expression_compiler::CompiledExpression;
use crate::expression_compiler::ExpressionCompiler;
use crate::ident::Ident;
use crate::module_compiler::ModuleCompiler;
use crate::name_allocator::{NameAllocator, RegAllocator};
use crate::scope::{NameId, OwnerId};
use crate::scope_analysis::{fn_to_owner_id, Name, ScopeAnalysis};
use crate::scope_analysis::{fn_to_owner_id, Name};
#[derive(Clone, Debug)]
pub enum Functionish {
@@ -62,13 +61,11 @@ pub struct CatchSetting {
pub reg: Register,
}
pub struct FunctionCompiler {
pub struct FunctionCompiler<'a> {
pub mc: &'a mut ModuleCompiler,
pub current: Function,
pub definitions: Vec<Definition>,
pub owner_id: OwnerId,
pub scope_analysis: Rc<ScopeAnalysis>,
pub constants_map: Rc<RefCell<HashMap<Pointer, Value>>>,
pub definition_allocator: Rc<RefCell<NameAllocator>>,
pub reg_allocator: RegAllocator,
pub label_allocator: NameAllocator,
pub queue: Queue<QueuedFunction>,
@@ -81,25 +78,18 @@ pub struct FunctionCompiler {
pub diagnostics: Vec<Diagnostic>,
}
impl FunctionCompiler {
pub fn new(
scope_analysis: &Rc<ScopeAnalysis>,
constants_map: &Rc<RefCell<HashMap<Pointer, Value>>>,
owner_id: OwnerId,
definition_allocator: Rc<RefCell<NameAllocator>>,
) -> FunctionCompiler {
let reg_allocator = match scope_analysis.reg_allocators.get(&owner_id) {
impl<'a> FunctionCompiler<'a> {
pub fn new(mc: &'a mut ModuleCompiler, owner_id: OwnerId) -> Self {
let reg_allocator = match mc.scope_analysis.reg_allocators.get(&owner_id) {
Some(reg_allocator) => reg_allocator.clone(),
None => RegAllocator::default(),
};
FunctionCompiler {
mc,
current: Function::default(),
definitions: vec![],
owner_id,
scope_analysis: scope_analysis.clone(),
constants_map: constants_map.clone(),
definition_allocator,
reg_allocator,
label_allocator: NameAllocator::default(),
queue: Queue::new(),
@@ -134,7 +124,7 @@ impl FunctionCompiler {
}
pub fn lookup(&mut self, ident: &Ident) -> Option<&Name> {
let name = self.scope_analysis.lookup(ident);
let name = self.mc.scope_analysis.lookup(ident);
if name.is_none() {
self.diagnostics.push(Diagnostic {
@@ -148,11 +138,12 @@ impl FunctionCompiler {
}
pub fn lookup_value(&self, ident: &Ident) -> Option<Value> {
self.scope_analysis.lookup_value(&self.owner_id, ident)
self.mc.scope_analysis.lookup_value(&self.owner_id, ident)
}
pub fn lookup_by_name_id(&self, name_id: &NameId) -> Option<Value> {
self
.mc
.scope_analysis
.lookup_by_name_id(&self.owner_id, name_id)
}
@@ -182,10 +173,7 @@ impl FunctionCompiler {
}
pub fn allocate_defn(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate(&name.to_string());
let allocated_name = self.mc.definition_allocator.allocate(&name.to_string());
Pointer {
name: allocated_name,
@@ -193,10 +181,7 @@ impl FunctionCompiler {
}
pub fn allocate_defn_numbered(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate_numbered(name);
let allocated_name = self.mc.definition_allocator.allocate_numbered(name);
Pointer {
name: allocated_name,
@@ -240,19 +225,12 @@ impl FunctionCompiler {
}
pub fn compile(
mc: &'a mut ModuleCompiler,
definition_pointer: Pointer,
fn_name: Option<String>,
functionish: Functionish,
scope_analysis: &Rc<ScopeAnalysis>,
constants_map: &Rc<RefCell<HashMap<Pointer, Value>>>,
definition_allocator: Rc<RefCell<NameAllocator>>,
) -> (Vec<Definition>, Vec<Diagnostic>) {
let mut self_ = FunctionCompiler::new(
scope_analysis,
constants_map,
functionish.owner_id(),
definition_allocator,
);
let mut self_ = FunctionCompiler::new(mc, functionish.owner_id());
self_
.queue
@@ -287,6 +265,7 @@ impl FunctionCompiler {
// TODO: Use a new FunctionCompiler per function instead of this hack
self.reg_allocator = match self
.mc
.scope_analysis
.reg_allocators
.get(&functionish.owner_id())
@@ -298,11 +277,13 @@ impl FunctionCompiler {
self.owner_id = functionish.owner_id();
let capture_params = self
.mc
.scope_analysis
.get_register_captures(&functionish.owner_id());
for cap_param in capture_params {
let reg = match self
.mc
.scope_analysis
.lookup_capture(&self.owner_id, &cap_param)
{
@@ -454,7 +435,7 @@ impl FunctionCompiler {
}
pub fn get_variable_register(&mut self, ident: &Ident) -> Register {
match self.scope_analysis.lookup_value(&self.owner_id, ident) {
match self.mc.scope_analysis.lookup_value(&self.owner_id, ident) {
Some(Value::Register(reg)) => reg,
lookup_result => {
self.diagnostics.push(Diagnostic {
@@ -1243,6 +1224,7 @@ impl FunctionCompiler {
TsTypeAlias(_) => {}
TsEnum(ts_enum) => {
let pointer = match self
.mc
.scope_analysis
.lookup_value(&OwnerId::Module, &Ident::from_swc_ident(&ts_enum.id))
{
@@ -1259,8 +1241,8 @@ impl FunctionCompiler {
};
let enum_value = compile_enum_value(
&self.scope_analysis,
&self.constants_map.borrow(),
&self.mc.scope_analysis,
&self.mc.constants_map,
ts_enum,
&mut self.diagnostics,
);
@@ -1333,7 +1315,7 @@ impl FunctionCompiler {
let mut mutated_registers = BTreeSet::<Register>::new();
for (_span, mutated_name_id) in self.scope_analysis.mutations.range(start..end) {
for (_span, mutated_name_id) in self.mc.scope_analysis.mutations.range(start..end) {
if let Some(Value::Register(reg)) = self.lookup_by_name_id(mutated_name_id) {
mutated_registers.insert(reg);
}
@@ -1342,7 +1324,7 @@ impl FunctionCompiler {
// TODO: Avoid doing this. This is a workaround to include mutations of variables that are
// supposed to be const, because we don't yet protect these variables from mutation that occurs
// via method calls. Once that is implemented, this shouldn't be needed.
for (_span, mutated_name_id) in self.scope_analysis.optional_mutations.range(start..end) {
for (_span, mutated_name_id) in self.mc.scope_analysis.optional_mutations.range(start..end) {
if let Some(Value::Register(reg)) = self.lookup_by_name_id(mutated_name_id) {
mutated_registers.insert(reg);
}

View File

@@ -1,6 +1,4 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use swc_common::errors::{DiagnosticBuilder, Emitter};
@@ -96,12 +94,12 @@ pub fn compile_module(source: &str) -> CompilerOutput {
}
#[derive(Default)]
struct ModuleCompiler {
diagnostics: Vec<Diagnostic>,
definition_allocator: Rc<RefCell<NameAllocator>>,
scope_analysis: Rc<ScopeAnalysis>,
constants_map: Rc<RefCell<HashMap<Pointer, Value>>>,
module: Module,
pub struct ModuleCompiler {
pub diagnostics: Vec<Diagnostic>,
pub definition_allocator: NameAllocator,
pub scope_analysis: ScopeAnalysis,
pub constants_map: HashMap<Pointer, Value>,
pub module: Module,
}
impl ModuleCompiler {
@@ -122,10 +120,7 @@ impl ModuleCompiler {
}
fn allocate_defn(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate(&name.to_string());
let allocated_name = self.definition_allocator.allocate(&name.to_string());
Pointer {
name: allocated_name,
@@ -133,10 +128,7 @@ impl ModuleCompiler {
}
fn allocate_defn_numbered(&mut self, name: &str) -> Pointer {
let allocated_name = self
.definition_allocator
.borrow_mut()
.allocate_numbered(name);
let allocated_name = self.definition_allocator.allocate_numbered(name);
Pointer {
name: allocated_name,
@@ -169,7 +161,7 @@ impl ModuleCompiler {
);
let mut self_ = Self {
scope_analysis: Rc::new(scope_analysis),
scope_analysis,
diagnostics: scope_analysis_diagnostics,
..Default::default()
};
@@ -208,7 +200,7 @@ impl ModuleCompiler {
.scope_analysis
.lookup(&Ident::from_swc_ident(ident))
.map(|name| name.value.clone()),
expr => static_eval_expr(&self.scope_analysis, &self.constants_map.borrow(), expr),
expr => static_eval_expr(&self.scope_analysis, &self.constants_map, expr),
};
match value {
@@ -311,7 +303,7 @@ impl ModuleCompiler {
};
if let (Some(ident), Some(init)) = (ident, init) {
let value_opt = static_eval_expr(&self.scope_analysis, &self.constants_map.borrow(), init);
let value_opt = static_eval_expr(&self.scope_analysis, &self.constants_map, init);
let value = match value_opt {
Some(value) => value,
@@ -349,10 +341,7 @@ impl ModuleCompiler {
}
};
self
.constants_map
.borrow_mut()
.insert(pointer.clone(), value.clone());
self.constants_map.insert(pointer.clone(), value.clone());
self.module.definitions.push(Definition {
pointer: pointer.clone(),
@@ -430,7 +419,7 @@ impl ModuleCompiler {
let enum_value = compile_enum_value(
&self.scope_analysis,
&self.constants_map.borrow(),
&self.constants_map,
ts_enum,
&mut self.diagnostics,
);
@@ -797,14 +786,8 @@ impl ModuleCompiler {
fn_name: Option<String>,
functionish: Functionish,
) -> Vec<Definition> {
let (defn, mut diagnostics) = FunctionCompiler::compile(
defn_pointer,
fn_name,
functionish,
&self.scope_analysis,
&self.constants_map,
self.definition_allocator.clone(),
);
let (defn, mut diagnostics) =
FunctionCompiler::compile(self, defn_pointer, fn_name, functionish);
self.diagnostics.append(&mut diagnostics);
@@ -848,18 +831,13 @@ impl ModuleCompiler {
));
}
let mut member_initializers_fnc = FunctionCompiler::new(
&self.scope_analysis,
&self.constants_map,
OwnerId::Span(class.span),
self.definition_allocator.clone(),
);
let mut member_initializers_fnc = FunctionCompiler::new(self, OwnerId::Span(class.span));
for class_member in &class.body {
match class_member {
swc_ecma_ast::ClassMember::ClassProp(class_prop) => {
if class_prop.is_static {
self.todo(class_prop.span, "static props");
member_initializers_fnc.todo(class_prop.span, "static props");
continue;
}
@@ -885,7 +863,7 @@ impl ModuleCompiler {
ec.fnc.release_ce(compiled_value);
}
swc_ecma_ast::ClassMember::PrivateProp(private_prop) => {
self.todo(private_prop.span, "private props")
member_initializers_fnc.todo(private_prop.span, "private props")
}
_ => {}
}
@@ -943,11 +921,8 @@ impl ModuleCompiler {
let name = match &method.key {
swc_ecma_ast::PropName::Ident(ident) => Value::String(ident.sym.to_string()),
swc_ecma_ast::PropName::Computed(computed) => {
let value_opt = static_eval_expr(
&self.scope_analysis,
&self.constants_map.borrow(),
&computed.expr,
);
let value_opt =
static_eval_expr(&self.scope_analysis, &self.constants_map, &computed.expr);
match value_opt {
None => {