From b93847564e41ec796ad484d5bd68105f7379e450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Wed, 5 Aug 2026 19:29:02 +0800 Subject: [PATCH] =?UTF-8?q?refactor(compiler):=20=E6=8B=86=E5=88=86?= =?UTF-8?q?=E9=97=AD=E5=8C=85=E5=88=86=E6=9E=90=E4=B8=8E=E9=A2=84=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E6=A8=A1=E5=9D=97=EF=BC=8C=E6=8B=86=E5=88=86=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=BD=93=E7=BC=96=E8=AF=91=E5=AD=90=E6=AD=A5=E9=AA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_compiler/src/closure.rs | 518 ++++++++++++++ crates/oxide_compiler/src/compiler.rs | 950 ++------------------------ crates/oxide_compiler/src/lib.rs | 2 + crates/oxide_compiler/src/prepass.rs | 343 ++++++++++ 4 files changed, 923 insertions(+), 890 deletions(-) create mode 100644 crates/oxide_compiler/src/closure.rs create mode 100644 crates/oxide_compiler/src/prepass.rs diff --git a/crates/oxide_compiler/src/closure.rs b/crates/oxide_compiler/src/closure.rs new file mode 100644 index 0000000..59d99e6 --- /dev/null +++ b/crates/oxide_compiler/src/closure.rs @@ -0,0 +1,518 @@ +use std::collections::{BTreeMap, HashSet}; + +use oxide_bytecode::module::UpvalueCapture; +use oxide_parser::{Expression, Statement}; + +use crate::compiler::Compiler; + +impl Compiler { + + fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet { + let mut names = HashSet::new(); + for p in ¶ms.items { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &p.pattern { + names.insert(bi.name.to_string()); + } + } + names + } + + /// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。 + pub(crate) fn collect_own_binding_names(&self, param_names: &[&str], stmts: &[Statement]) -> HashSet { + let mut names = HashSet::new(); + for p in param_names { + names.insert(p.to_string()); + } + self.collect_decl_names_stmt(stmts, &mut names); + names + } + + fn collect_decl_names_stmt(&self, stmts: &[Statement], out: &mut HashSet) { + for stmt in stmts { + match stmt { + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + out.insert(bi.name.to_string()); + } + } + } + Statement::FunctionDeclaration(fd) => { + if let Some(id) = &fd.id { + out.insert(id.name.to_string()); + } + } + Statement::BlockStatement(b) => self.collect_decl_names_stmt(&b.body, out), + Statement::IfStatement(is) => { + self.collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out); + if let Some(alt) = &is.alternate { + self.collect_decl_names_stmt(std::slice::from_ref(alt), out); + } + } + Statement::WhileStatement(w) => self.collect_decl_names_stmt(std::slice::from_ref(&w.body), out), + Statement::DoWhileStatement(d) => self.collect_decl_names_stmt(std::slice::from_ref(&d.body), out), + Statement::ForStatement(f) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { + for d in &vd.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + out.insert(bi.name.to_string()); + } + } + } + self.collect_decl_names_stmt(std::slice::from_ref(&f.body), out); + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + self.collect_decl_names_stmt(&case.consequent, out); + } + } + Statement::TryStatement(ts) => { + self.collect_decl_names_stmt(&ts.block.body, out); + if let Some(h) = &ts.handler { + self.collect_decl_names_stmt(&h.body.body, out); + } + if let Some(f) = &ts.finalizer { + self.collect_decl_names_stmt(&f.body, out); + } + } + Statement::LabeledStatement(ls) => self.collect_decl_names_stmt(std::slice::from_ref(&ls.body), out), + _ => {} + } + } + } + + /// 扫描 stmts 内(含任意深度嵌套函数)对 `ref_set` 的引用,写入 out。 + /// 递归进入嵌套函数时累加其局部绑定为遮蔽集,避免把内层局部误判为捕获。 + fn collect_capture_names(&self, stmts: &[Statement], ref_set: &HashSet, out: &mut HashSet) { + let shadow = HashSet::new(); + self.collect_capture_names_shadowed(stmts, ref_set, &shadow, out); + } + + fn collect_capture_names_shadowed( + &self, stmts: &[Statement], ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, + ) { + for stmt in stmts { + self.collect_capture_names_stmt(stmt, ref_set, shadow, out); + } + } + + fn collect_capture_names_stmt( + &self, stmt: &Statement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, + ) { + match stmt { + Statement::ExpressionStatement(es) => self.collect_capture_names_expr(&es.expression, ref_set, shadow, out), + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + self.collect_capture_names_expr(a, ref_set, shadow, out); + } + } + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + if let Some(init) = &d.init { + self.collect_capture_names_expr(init, ref_set, shadow, out); + } + } + } + Statement::FunctionDeclaration(fd) => { + let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(self.collect_fn_param_names(&fd.params)); + inner.extend(self.collect_own_binding_names(&[], body)); + self.collect_capture_names_shadowed(body, ref_set, &inner, out); + } + Statement::IfStatement(is) => { + self.collect_capture_names_expr(&is.test, ref_set, shadow, out); + self.collect_capture_names_stmt(&is.consequent, ref_set, shadow, out); + if let Some(alt) = &is.alternate { + self.collect_capture_names_stmt(alt, ref_set, shadow, out); + } + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { + for d in &vd.declarations { + if let Some(i) = &d.init { + self.collect_capture_names_expr(i, ref_set, shadow, out); + } + } + } + } + if let Some(t) = &fs.test { + self.collect_capture_names_expr(t, ref_set, shadow, out); + } + if let Some(u) = &fs.update { + self.collect_capture_names_expr(u, ref_set, shadow, out); + } + self.collect_capture_names_stmt(&fs.body, ref_set, shadow, out); + } + Statement::WhileStatement(w) => { + self.collect_capture_names_expr(&w.test, ref_set, shadow, out); + self.collect_capture_names_stmt(&w.body, ref_set, shadow, out); + } + Statement::DoWhileStatement(d) => { + self.collect_capture_names_stmt(&d.body, ref_set, shadow, out); + self.collect_capture_names_expr(&d.test, ref_set, shadow, out); + } + Statement::ForInStatement(fi) => { + self.collect_capture_names_expr(&fi.right, ref_set, shadow, out); + self.collect_capture_names_stmt(&fi.body, ref_set, shadow, out); + } + Statement::ForOfStatement(fo) => { + self.collect_capture_names_expr(&fo.right, ref_set, shadow, out); + self.collect_capture_names_stmt(&fo.body, ref_set, shadow, out); + } + Statement::BlockStatement(b) => self.collect_capture_names_shadowed(&b.body, ref_set, shadow, out), + Statement::TryStatement(ts) => { + for s in &ts.block.body { + self.collect_capture_names_stmt(s, ref_set, shadow, out); + } + if let Some(h) = &ts.handler { + for s in &h.body.body { + self.collect_capture_names_stmt(s, ref_set, shadow, out); + } + } + if let Some(f) = &ts.finalizer { + for s in &f.body { + self.collect_capture_names_stmt(s, ref_set, shadow, out); + } + } + } + Statement::ThrowStatement(ts) => self.collect_capture_names_expr(&ts.argument, ref_set, shadow, out), + Statement::SwitchStatement(sw) => { + self.collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out); + for case in &sw.cases { + for s in &case.consequent { + self.collect_capture_names_stmt(s, ref_set, shadow, out); + } + } + } + Statement::LabeledStatement(ls) => self.collect_capture_names_stmt(&ls.body, ref_set, shadow, out), + _ => {} + } + } + + fn collect_capture_names_expr( + &self, expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, + ) { + match expr { + Expression::Identifier(id) => { + let name = id.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(id.name.to_string()); + } + } + Expression::AssignmentExpression(ae) => { + if let oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) = &ae.left { + let name = ati.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(ati.name.to_string()); + } + } + self.collect_capture_names_expr(&ae.right, ref_set, shadow, out); + } + Expression::UpdateExpression(ue) => { + if let oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(ati) = &ue.argument { + let name = ati.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(ati.name.to_string()); + } + } + } + Expression::FunctionExpression(fe) => { + let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(self.collect_fn_param_names(&fe.params)); + inner.extend(self.collect_own_binding_names(&[], body)); + self.collect_capture_names_shadowed(body, ref_set, &inner, out); + } + Expression::ArrowFunctionExpression(ae) => { + let mut inner = shadow.clone(); + inner.extend(self.collect_fn_param_names(&ae.params)); + inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); + self.collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out); + } + Expression::BinaryExpression(be) => { + self.collect_capture_names_expr(&be.left, ref_set, shadow, out); + self.collect_capture_names_expr(&be.right, ref_set, shadow, out); + } + Expression::UnaryExpression(ue) => self.collect_capture_names_expr(&ue.argument, ref_set, shadow, out), + Expression::CallExpression(ce) => { + self.collect_capture_names_expr(&ce.callee, ref_set, shadow, out); + for a in &ce.arguments { + if let Some(e) = a.as_expression() { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + } + Expression::NewExpression(ne) => { + self.collect_capture_names_expr(&ne.callee, ref_set, shadow, out); + for a in &ne.arguments { + if let Some(e) = a.as_expression() { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + } + Expression::SequenceExpression(se) => { + for e in &se.expressions { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::ConditionalExpression(ce) => { + self.collect_capture_names_expr(&ce.test, ref_set, shadow, out); + self.collect_capture_names_expr(&ce.consequent, ref_set, shadow, out); + self.collect_capture_names_expr(&ce.alternate, ref_set, shadow, out); + } + Expression::ArrayExpression(ae) => { + for e in &ae.elements { + if let Some(e) = e.as_expression() { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + } + Expression::LogicalExpression(le) => { + self.collect_capture_names_expr(&le.left, ref_set, shadow, out); + self.collect_capture_names_expr(&le.right, ref_set, shadow, out); + } + Expression::ComputedMemberExpression(m) => { + self.collect_capture_names_expr(&m.object, ref_set, shadow, out); + self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + Expression::StaticMemberExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), + Expression::PrivateFieldExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), + Expression::ParenthesizedExpression(p) => self.collect_capture_names_expr(&p.expression, ref_set, shadow, out), + Expression::TemplateLiteral(tl) => { + for e in &tl.expressions { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::TaggedTemplateExpression(tt) => { + self.collect_capture_names_expr(&tt.tag, ref_set, shadow, out); + for e in &tt.quasi.expressions { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::ObjectExpression(o) => { + for prop in &o.properties { + if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop { + self.collect_capture_names_expr(&p.value, ref_set, shadow, out); + } + } + } + Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out), + _ => {} + } + } + + fn collect_capture_names_chain( + &self, element: &oxide_parser::ChainElement, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, + ) { + match element { + oxide_parser::ChainElement::StaticMemberExpression(m) => { + self.collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::ChainElement::ComputedMemberExpression(m) => { + self.collect_capture_names_expr(&m.object, ref_set, shadow, out); + self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + oxide_parser::ChainElement::PrivateFieldExpression(m) => { + self.collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::ChainElement::CallExpression(call) => { + self.collect_capture_names_expr(&call.callee, ref_set, shadow, out); + for a in &call.arguments { + if let Some(e) = a.as_expression() { + self.collect_capture_names_expr(e, ref_set, shadow, out); + } + } + } + _ => {} + } + } + + /// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 + pub(crate) fn collect_captured_bindings(&self, stmts: &[Statement], own: &HashSet) -> BTreeMap { + let mut names = HashSet::new(); + for stmt in stmts { + self.collect_captured_stmt(stmt, own, &mut names); + } + // 名字排序分配 cell_idx(稳定跨 run,父 MAKE_CELL 与子 upvalue 统一引用) + let mut sorted: Vec = names.into_iter().collect(); + sorted.sort(); + sorted + .into_iter() + .enumerate() + .map(|(i, n)| (n, i as u8)) + .collect() + } + + /// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 + fn collect_captured_stmt(&self, stmt: &Statement, own: &HashSet, out: &mut HashSet) { + match stmt { + Statement::FunctionDeclaration(fd) => { + let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + self.collect_capture_names(body, own, out); + } + Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out), + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + self.collect_captured_expr(a, own, out); + } + } + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + if let Some(init) = &d.init { + self.collect_captured_expr(init, own, out); + } + } + } + Statement::IfStatement(is) => { + self.collect_captured_expr(&is.test, own, out); + self.collect_captured_stmt(&is.consequent, own, out); + if let Some(alt) = &is.alternate { + self.collect_captured_stmt(alt, own, out); + } + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + self.collect_captured_expr(e, own, out); + } + } + if let Some(t) = &fs.test { + self.collect_captured_expr(t, own, out); + } + if let Some(u) = &fs.update { + self.collect_captured_expr(u, own, out); + } + self.collect_captured_stmt(&fs.body, own, out); + } + Statement::WhileStatement(w) => { + self.collect_captured_expr(&w.test, own, out); + self.collect_captured_stmt(&w.body, own, out); + } + Statement::DoWhileStatement(d) => { + self.collect_captured_stmt(&d.body, own, out); + self.collect_captured_expr(&d.test, own, out); + } + Statement::ForInStatement(fi) => { + self.collect_captured_expr(&fi.right, own, out); + self.collect_captured_stmt(&fi.body, own, out); + } + Statement::ForOfStatement(fo) => { + self.collect_captured_expr(&fo.right, own, out); + self.collect_captured_stmt(&fo.body, own, out); + } + Statement::BlockStatement(b) => { + for s in &b.body { + self.collect_captured_stmt(s, own, out); + } + } + Statement::TryStatement(ts) => { + for s in &ts.block.body { + self.collect_captured_stmt(s, own, out); + } + if let Some(h) = &ts.handler { + for s in &h.body.body { + self.collect_captured_stmt(s, own, out); + } + } + if let Some(f) = &ts.finalizer { + for s in &f.body { + self.collect_captured_stmt(s, own, out); + } + } + } + Statement::ThrowStatement(ts) => self.collect_captured_expr(&ts.argument, own, out), + Statement::SwitchStatement(sw) => { + self.collect_captured_expr(&sw.discriminant, own, out); + for case in &sw.cases { + for s in &case.consequent { + self.collect_captured_stmt(s, own, out); + } + } + } + Statement::LabeledStatement(ls) => self.collect_captured_stmt(&ls.body, own, out), + _ => {} + } + } + + fn collect_captured_expr(&self, expr: &Expression, own: &HashSet, out: &mut HashSet) { + match expr { + Expression::FunctionExpression(fe) => { + let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = self.collect_fn_param_names(&fe.params); + inner.extend(self.collect_own_binding_names(&[], body)); + self.collect_capture_names_shadowed(body, own, &inner, out); + } + Expression::ArrowFunctionExpression(ae) => { + let mut inner = self.collect_fn_param_names(&ae.params); + inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); + self.collect_capture_names_shadowed(&ae.body.statements, own, &inner, out); + } + Expression::CallExpression(ce) => { + self.collect_captured_expr(&ce.callee, own, out); + for a in &ce.arguments { + if let Some(e) = a.as_expression() { + self.collect_captured_expr(e, own, out); + } + } + } + Expression::BinaryExpression(be) => { + self.collect_captured_expr(&be.left, own, out); + self.collect_captured_expr(&be.right, own, out); + } + Expression::UnaryExpression(ue) => self.collect_captured_expr(&ue.argument, own, out), + Expression::LogicalExpression(le) => { + self.collect_captured_expr(&le.left, own, out); + self.collect_captured_expr(&le.right, own, out); + } + Expression::ConditionalExpression(ce) => { + self.collect_captured_expr(&ce.test, own, out); + self.collect_captured_expr(&ce.consequent, own, out); + self.collect_captured_expr(&ce.alternate, own, out); + } + Expression::SequenceExpression(se) => { + for e in &se.expressions { + self.collect_captured_expr(e, own, out); + } + } + Expression::AssignmentExpression(ae) => self.collect_captured_expr(&ae.right, own, out), + Expression::ArrayExpression(ae) => { + for e in &ae.elements { + if let Some(e) = e.as_expression() { + self.collect_captured_expr(e, own, out); + } + } + } + _ => {} + } + } + + /// 分析子函数 body:引用父级绑定的名字 → upvalue_captures(enclosing_reg 由父 emit 完成后填充)。 + /// 分析子函数 body:引用父级被捕获绑定的名字 → upvalue_captures。 + /// cell_idx 直接取父 captured_bindings 映射(父 emit 前已确定,索引一致); + /// enclosing_reg 由父 emit 完成后填充(assemble_ir)。 + pub(crate) fn collect_upvalue_names( + &self, body_stmts: &[Statement], parent_captured: &BTreeMap, sub_own: &HashSet, + ) -> Vec { + let parent_names: HashSet = parent_captured.keys().cloned().collect(); + let mut names = HashSet::new(); + self.collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names); + names + .into_iter() + .map(|name| { + let cell_idx = parent_captured.get(&name).copied().unwrap_or(0); + UpvalueCapture { + name, + enclosing_reg: 0, // assemble_ir 时从父符号表填充 + cell_idx, + } + }) + .collect() + } +} + diff --git a/crates/oxide_compiler/src/compiler.rs b/crates/oxide_compiler/src/compiler.rs index 010f398..e091524 100644 --- a/crates/oxide_compiler/src/compiler.rs +++ b/crates/oxide_compiler/src/compiler.rs @@ -523,513 +523,6 @@ impl Compiler { // ── 闭包捕获分析(AST 级,时序无关)── /// 收集函数参数的绑定名(BindingIdentifier 形态)。 - fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet { - let mut names = HashSet::new(); - for p in ¶ms.items { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &p.pattern { - names.insert(bi.name.to_string()); - } - } - names - } - - /// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。 - fn collect_own_binding_names(&self, param_names: &[&str], stmts: &[Statement]) -> HashSet { - let mut names = HashSet::new(); - for p in param_names { - names.insert(p.to_string()); - } - self.collect_decl_names_stmt(stmts, &mut names); - names - } - - fn collect_decl_names_stmt(&self, stmts: &[Statement], out: &mut HashSet) { - for stmt in stmts { - match stmt { - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - out.insert(bi.name.to_string()); - } - } - } - Statement::FunctionDeclaration(fd) => { - if let Some(id) = &fd.id { - out.insert(id.name.to_string()); - } - } - Statement::BlockStatement(b) => self.collect_decl_names_stmt(&b.body, out), - Statement::IfStatement(is) => { - self.collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out); - if let Some(alt) = &is.alternate { - self.collect_decl_names_stmt(std::slice::from_ref(alt), out); - } - } - Statement::WhileStatement(w) => self.collect_decl_names_stmt(std::slice::from_ref(&w.body), out), - Statement::DoWhileStatement(d) => self.collect_decl_names_stmt(std::slice::from_ref(&d.body), out), - Statement::ForStatement(f) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { - for d in &vd.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - out.insert(bi.name.to_string()); - } - } - } - self.collect_decl_names_stmt(std::slice::from_ref(&f.body), out); - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.collect_decl_names_stmt(&case.consequent, out); - } - } - Statement::TryStatement(ts) => { - self.collect_decl_names_stmt(&ts.block.body, out); - if let Some(h) = &ts.handler { - self.collect_decl_names_stmt(&h.body.body, out); - } - if let Some(f) = &ts.finalizer { - self.collect_decl_names_stmt(&f.body, out); - } - } - Statement::LabeledStatement(ls) => self.collect_decl_names_stmt(std::slice::from_ref(&ls.body), out), - _ => {} - } - } - } - - /// 扫描 stmts 内(含任意深度嵌套函数)对 `ref_set` 的引用,写入 out。 - /// 递归进入嵌套函数时累加其局部绑定为遮蔽集,避免把内层局部误判为捕获。 - fn collect_capture_names(&self, stmts: &[Statement], ref_set: &HashSet, out: &mut HashSet) { - let shadow = HashSet::new(); - self.collect_capture_names_shadowed(stmts, ref_set, &shadow, out); - } - - fn collect_capture_names_shadowed( - &self, stmts: &[Statement], ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - for stmt in stmts { - self.collect_capture_names_stmt(stmt, ref_set, shadow, out); - } - } - - fn collect_capture_names_stmt( - &self, stmt: &Statement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - match stmt { - Statement::ExpressionStatement(es) => self.collect_capture_names_expr(&es.expression, ref_set, shadow, out), - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.collect_capture_names_expr(a, ref_set, shadow, out); - } - } - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - if let Some(init) = &d.init { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - } - } - Statement::FunctionDeclaration(fd) => { - let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fd.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - Statement::IfStatement(is) => { - self.collect_capture_names_expr(&is.test, ref_set, shadow, out); - self.collect_capture_names_stmt(&is.consequent, ref_set, shadow, out); - if let Some(alt) = &is.alternate { - self.collect_capture_names_stmt(alt, ref_set, shadow, out); - } - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { - for d in &vd.declarations { - if let Some(i) = &d.init { - self.collect_capture_names_expr(i, ref_set, shadow, out); - } - } - } - } - if let Some(t) = &fs.test { - self.collect_capture_names_expr(t, ref_set, shadow, out); - } - if let Some(u) = &fs.update { - self.collect_capture_names_expr(u, ref_set, shadow, out); - } - self.collect_capture_names_stmt(&fs.body, ref_set, shadow, out); - } - Statement::WhileStatement(w) => { - self.collect_capture_names_expr(&w.test, ref_set, shadow, out); - self.collect_capture_names_stmt(&w.body, ref_set, shadow, out); - } - Statement::DoWhileStatement(d) => { - self.collect_capture_names_stmt(&d.body, ref_set, shadow, out); - self.collect_capture_names_expr(&d.test, ref_set, shadow, out); - } - Statement::ForInStatement(fi) => { - self.collect_capture_names_expr(&fi.right, ref_set, shadow, out); - self.collect_capture_names_stmt(&fi.body, ref_set, shadow, out); - } - Statement::ForOfStatement(fo) => { - self.collect_capture_names_expr(&fo.right, ref_set, shadow, out); - self.collect_capture_names_stmt(&fo.body, ref_set, shadow, out); - } - Statement::BlockStatement(b) => self.collect_capture_names_shadowed(&b.body, ref_set, shadow, out), - Statement::TryStatement(ts) => { - for s in &ts.block.body { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - if let Some(h) = &ts.handler { - for s in &h.body.body { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - } - if let Some(f) = &ts.finalizer { - for s in &f.body { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - } - } - Statement::ThrowStatement(ts) => self.collect_capture_names_expr(&ts.argument, ref_set, shadow, out), - Statement::SwitchStatement(sw) => { - self.collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out); - for case in &sw.cases { - for s in &case.consequent { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - } - } - Statement::LabeledStatement(ls) => self.collect_capture_names_stmt(&ls.body, ref_set, shadow, out), - _ => {} - } - } - - fn collect_capture_names_expr( - &self, expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - match expr { - Expression::Identifier(id) => { - let name = id.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(id.name.to_string()); - } - } - Expression::AssignmentExpression(ae) => { - if let oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) = &ae.left { - let name = ati.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(ati.name.to_string()); - } - } - self.collect_capture_names_expr(&ae.right, ref_set, shadow, out); - } - Expression::UpdateExpression(ue) => { - if let oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(ati) = &ue.argument { - let name = ati.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(ati.name.to_string()); - } - } - } - Expression::FunctionExpression(fe) => { - let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fe.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - Expression::ArrowFunctionExpression(ae) => { - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&ae.params)); - inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); - self.collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out); - } - Expression::BinaryExpression(be) => { - self.collect_capture_names_expr(&be.left, ref_set, shadow, out); - self.collect_capture_names_expr(&be.right, ref_set, shadow, out); - } - Expression::UnaryExpression(ue) => self.collect_capture_names_expr(&ue.argument, ref_set, shadow, out), - Expression::CallExpression(ce) => { - self.collect_capture_names_expr(&ce.callee, ref_set, shadow, out); - for a in &ce.arguments { - if let Some(e) = a.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - } - Expression::NewExpression(ne) => { - self.collect_capture_names_expr(&ne.callee, ref_set, shadow, out); - for a in &ne.arguments { - if let Some(e) = a.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - } - Expression::SequenceExpression(se) => { - for e in &se.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::ConditionalExpression(ce) => { - self.collect_capture_names_expr(&ce.test, ref_set, shadow, out); - self.collect_capture_names_expr(&ce.consequent, ref_set, shadow, out); - self.collect_capture_names_expr(&ce.alternate, ref_set, shadow, out); - } - Expression::ArrayExpression(ae) => { - for e in &ae.elements { - if let Some(e) = e.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - } - Expression::LogicalExpression(le) => { - self.collect_capture_names_expr(&le.left, ref_set, shadow, out); - self.collect_capture_names_expr(&le.right, ref_set, shadow, out); - } - Expression::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - Expression::StaticMemberExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), - Expression::PrivateFieldExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), - Expression::ParenthesizedExpression(p) => self.collect_capture_names_expr(&p.expression, ref_set, shadow, out), - Expression::TemplateLiteral(tl) => { - for e in &tl.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::TaggedTemplateExpression(tt) => { - self.collect_capture_names_expr(&tt.tag, ref_set, shadow, out); - for e in &tt.quasi.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::ObjectExpression(o) => { - for prop in &o.properties { - if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop { - self.collect_capture_names_expr(&p.value, ref_set, shadow, out); - } - } - } - Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out), - _ => {} - } - } - - fn collect_capture_names_chain( - &self, element: &oxide_parser::ChainElement, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - match element { - oxide_parser::ChainElement::StaticMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::ChainElement::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - oxide_parser::ChainElement::PrivateFieldExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::ChainElement::CallExpression(call) => { - self.collect_capture_names_expr(&call.callee, ref_set, shadow, out); - for a in &call.arguments { - if let Some(e) = a.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - } - _ => {} - } - } - - /// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 - fn collect_captured_bindings(&self, stmts: &[Statement], own: &HashSet) -> BTreeMap { - let mut names = HashSet::new(); - for stmt in stmts { - self.collect_captured_stmt(stmt, own, &mut names); - } - // 名字排序分配 cell_idx(稳定跨 run,父 MAKE_CELL 与子 upvalue 统一引用) - let mut sorted: Vec = names.into_iter().collect(); - sorted.sort(); - sorted - .into_iter() - .enumerate() - .map(|(i, n)| (n, i as u8)) - .collect() - } - - /// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 - fn collect_captured_stmt(&self, stmt: &Statement, own: &HashSet, out: &mut HashSet) { - match stmt { - Statement::FunctionDeclaration(fd) => { - let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - self.collect_capture_names(body, own, out); - } - Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out), - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.collect_captured_expr(a, own, out); - } - } - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - if let Some(init) = &d.init { - self.collect_captured_expr(init, own, out); - } - } - } - Statement::IfStatement(is) => { - self.collect_captured_expr(&is.test, own, out); - self.collect_captured_stmt(&is.consequent, own, out); - if let Some(alt) = &is.alternate { - self.collect_captured_stmt(alt, own, out); - } - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.collect_captured_expr(e, own, out); - } - } - if let Some(t) = &fs.test { - self.collect_captured_expr(t, own, out); - } - if let Some(u) = &fs.update { - self.collect_captured_expr(u, own, out); - } - self.collect_captured_stmt(&fs.body, own, out); - } - Statement::WhileStatement(w) => { - self.collect_captured_expr(&w.test, own, out); - self.collect_captured_stmt(&w.body, own, out); - } - Statement::DoWhileStatement(d) => { - self.collect_captured_stmt(&d.body, own, out); - self.collect_captured_expr(&d.test, own, out); - } - Statement::ForInStatement(fi) => { - self.collect_captured_expr(&fi.right, own, out); - self.collect_captured_stmt(&fi.body, own, out); - } - Statement::ForOfStatement(fo) => { - self.collect_captured_expr(&fo.right, own, out); - self.collect_captured_stmt(&fo.body, own, out); - } - Statement::BlockStatement(b) => { - for s in &b.body { - self.collect_captured_stmt(s, own, out); - } - } - Statement::TryStatement(ts) => { - for s in &ts.block.body { - self.collect_captured_stmt(s, own, out); - } - if let Some(h) = &ts.handler { - for s in &h.body.body { - self.collect_captured_stmt(s, own, out); - } - } - if let Some(f) = &ts.finalizer { - for s in &f.body { - self.collect_captured_stmt(s, own, out); - } - } - } - Statement::ThrowStatement(ts) => self.collect_captured_expr(&ts.argument, own, out), - Statement::SwitchStatement(sw) => { - self.collect_captured_expr(&sw.discriminant, own, out); - for case in &sw.cases { - for s in &case.consequent { - self.collect_captured_stmt(s, own, out); - } - } - } - Statement::LabeledStatement(ls) => self.collect_captured_stmt(&ls.body, own, out), - _ => {} - } - } - - fn collect_captured_expr(&self, expr: &Expression, own: &HashSet, out: &mut HashSet) { - match expr { - Expression::FunctionExpression(fe) => { - let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = self.collect_fn_param_names(&fe.params); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_capture_names_shadowed(body, own, &inner, out); - } - Expression::ArrowFunctionExpression(ae) => { - let mut inner = self.collect_fn_param_names(&ae.params); - inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); - self.collect_capture_names_shadowed(&ae.body.statements, own, &inner, out); - } - Expression::CallExpression(ce) => { - self.collect_captured_expr(&ce.callee, own, out); - for a in &ce.arguments { - if let Some(e) = a.as_expression() { - self.collect_captured_expr(e, own, out); - } - } - } - Expression::BinaryExpression(be) => { - self.collect_captured_expr(&be.left, own, out); - self.collect_captured_expr(&be.right, own, out); - } - Expression::UnaryExpression(ue) => self.collect_captured_expr(&ue.argument, own, out), - Expression::LogicalExpression(le) => { - self.collect_captured_expr(&le.left, own, out); - self.collect_captured_expr(&le.right, own, out); - } - Expression::ConditionalExpression(ce) => { - self.collect_captured_expr(&ce.test, own, out); - self.collect_captured_expr(&ce.consequent, own, out); - self.collect_captured_expr(&ce.alternate, own, out); - } - Expression::SequenceExpression(se) => { - for e in &se.expressions { - self.collect_captured_expr(e, own, out); - } - } - Expression::AssignmentExpression(ae) => self.collect_captured_expr(&ae.right, own, out), - Expression::ArrayExpression(ae) => { - for e in &ae.elements { - if let Some(e) = e.as_expression() { - self.collect_captured_expr(e, own, out); - } - } - } - _ => {} - } - } - - /// 分析子函数 body:引用父级绑定的名字 → upvalue_captures(enclosing_reg 由父 emit 完成后填充)。 - /// 分析子函数 body:引用父级被捕获绑定的名字 → upvalue_captures。 - /// cell_idx 直接取父 captured_bindings 映射(父 emit 前已确定,索引一致); - /// enclosing_reg 由父 emit 完成后填充(assemble_ir)。 - fn collect_upvalue_names( - &self, body_stmts: &[Statement], parent_captured: &BTreeMap, sub_own: &HashSet, - ) -> Vec { - let parent_names: HashSet = parent_captured.keys().cloned().collect(); - let mut names = HashSet::new(); - self.collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names); - names - .into_iter() - .map(|name| { - let cell_idx = parent_captured.get(&name).copied().unwrap_or(0); - UpvalueCapture { - name, - enclosing_reg: 0, // assemble_ir 时从父符号表填充 - cell_idx, - } - }) - .collect() - } pub(crate) fn extract_function_parts<'a>( @@ -1104,341 +597,6 @@ impl Compiler { /// `lookup_or_builtin` at first use, which can collide with a temporary /// register already reused by `restore_reg_checkpoint`. Pre-scanning moves /// builtin slot allocation ahead of the temporary register pool. - pub(crate) fn pre_register_builtin_references(&self, stmts: &[Statement], ctx: &mut CompileCtx) { - for stmt in stmts { - self.pre_scan_builtin_stmt(stmt, ctx); - } - } - - fn pre_scan_builtin_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) { - match stmt { - Statement::ExpressionStatement(es) => self.pre_scan_builtin_expr(&es.expression, ctx), - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - if let Some(init) = &d.init { - self.pre_scan_builtin_expr(init, ctx); - } - } - } - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.pre_scan_builtin_expr(a, ctx); - } - } - Statement::IfStatement(is) => { - self.pre_scan_builtin_expr(&is.test, ctx); - self.pre_scan_builtin_stmt(&is.consequent, ctx); - if let Some(alt) = &is.alternate { - self.pre_scan_builtin_stmt(alt, ctx); - } - } - Statement::WhileStatement(wh) => { - self.pre_scan_builtin_expr(&wh.test, ctx); - self.pre_scan_builtin_stmt(&wh.body, ctx); - } - Statement::DoWhileStatement(dw) => { - self.pre_scan_builtin_stmt(&dw.body, ctx); - self.pre_scan_builtin_expr(&dw.test, ctx); - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } else if let oxide_parser::ForStatementInit::VariableDeclaration(decl) = init { - for d in &decl.declarations { - if let Some(init_expr) = &d.init { - self.pre_scan_builtin_expr(init_expr, ctx); - } - } - } - } - if let Some(t) = &fs.test { - self.pre_scan_builtin_expr(t, ctx); - } - if let Some(u) = &fs.update { - self.pre_scan_builtin_expr(u, ctx); - } - self.pre_scan_builtin_stmt(&fs.body, ctx); - } - Statement::ForInStatement(fi) => { - self.pre_scan_builtin_expr(&fi.right, ctx); - self.pre_scan_builtin_stmt(&fi.body, ctx); - } - Statement::ForOfStatement(fo) => { - self.pre_scan_builtin_expr(&fo.right, ctx); - self.pre_scan_builtin_stmt(&fo.body, ctx); - } - Statement::SwitchStatement(sw) => { - self.pre_scan_builtin_expr(&sw.discriminant, ctx); - for case in &sw.cases { - if let Some(test) = &case.test { - self.pre_scan_builtin_expr(test, ctx); - } - for s in &case.consequent { - self.pre_scan_builtin_stmt(s, ctx); - } - } - } - Statement::ThrowStatement(ts) => { - self.pre_scan_builtin_expr(&ts.argument, ctx); - } - Statement::TryStatement(ts) => { - for s in &ts.block.body { - self.pre_scan_builtin_stmt(s, ctx); - } - if let Some(handler) = &ts.handler { - for s in &handler.body.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - if let Some(finalizer) = &ts.finalizer { - for s in &finalizer.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - } - Statement::BlockStatement(bs) => { - for s in &bs.body { - self.pre_scan_builtin_stmt(s, ctx); - } - } - Statement::LabeledStatement(ls) => self.pre_scan_builtin_stmt(&ls.body, ctx), - Statement::ClassDeclaration(cd) => { - if let Some(super_class) = &cd.super_class { - self.pre_scan_builtin_expr(super_class, ctx); - } - } - Statement::FunctionDeclaration(_) | Statement::BreakStatement(_) | Statement::ContinueStatement(_) => {} - _ => {} - } - } - - fn pre_scan_builtin_expr(&self, expr: &Expression, ctx: &mut CompileCtx) { - match expr { - Expression::Identifier(ident) => { - if CompileCtx::is_known_builtin(ident.name.as_str()) { - let _ = ctx.lookup_or_builtin(ident.name.as_str()); - } - } - Expression::BinaryExpression(bin) => { - self.pre_scan_builtin_expr(&bin.left, ctx); - self.pre_scan_builtin_expr(&bin.right, ctx); - } - Expression::UnaryExpression(un) => { - self.pre_scan_builtin_expr(&un.argument, ctx); - } - Expression::CallExpression(call) => { - self.pre_scan_builtin_expr(&call.callee, ctx); - for arg in &call.arguments { - if let Some(e) = arg.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - } - Expression::NewExpression(ne) => { - self.pre_scan_builtin_expr(&ne.callee, ctx); - for arg in &ne.arguments { - if let Some(e) = arg.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - } - Expression::LogicalExpression(log) => { - self.pre_scan_builtin_expr(&log.left, ctx); - self.pre_scan_builtin_expr(&log.right, ctx); - } - Expression::ConditionalExpression(cond) => { - self.pre_scan_builtin_expr(&cond.test, ctx); - self.pre_scan_builtin_expr(&cond.consequent, ctx); - self.pre_scan_builtin_expr(&cond.alternate, ctx); - } - Expression::PrivateInExpression(pin) => { - self.pre_scan_builtin_expr(&pin.right, ctx); - } - Expression::SequenceExpression(seq) => { - for e in &seq.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::AssignmentExpression(assign) => { - if let Some(target) = assign.left.as_simple_assignment_target() { - self.pre_scan_builtin_target(target, ctx); - } - self.pre_scan_builtin_expr(&assign.right, ctx); - } - Expression::UpdateExpression(update) => { - self.pre_scan_builtin_target(&update.argument, ctx); - } - Expression::TemplateLiteral(tl) => { - for e in &tl.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::TaggedTemplateExpression(tt) => { - self.pre_scan_builtin_expr(&tt.tag, ctx); - for e in &tt.quasi.expressions { - self.pre_scan_builtin_expr(e, ctx); - } - } - Expression::ObjectExpression(obj) => { - for prop in &obj.properties { - if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop { - if p.computed { - self.pre_scan_builtin_expr(p.key.to_expression(), ctx); - } - self.pre_scan_builtin_expr(&p.value, ctx); - } - } - } - Expression::ArrayExpression(arr) => { - for e in &arr.elements { - if let Some(e) = e.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - } - Expression::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - Expression::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - Expression::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - Expression::ChainExpression(chain) => { - self.pre_scan_builtin_chain(&chain.expression, ctx); - } - Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx), - Expression::ArrowFunctionExpression(_) - | Expression::FunctionExpression(_) - | Expression::ClassExpression(_) => {} - _ => {} - } - } - - fn pre_scan_builtin_target(&self, target: &oxide_parser::SimpleAssignmentTarget, ctx: &mut CompileCtx) { - match target { - oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - oxide_parser::SimpleAssignmentTarget::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - _ => {} - } - } - - fn pre_scan_builtin_chain(&self, element: &oxide_parser::ChainElement, ctx: &mut CompileCtx) { - match element { - oxide_parser::ChainElement::StaticMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::ChainElement::ComputedMemberExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - self.pre_scan_builtin_expr(&member.expression, ctx); - } - oxide_parser::ChainElement::PrivateFieldExpression(member) => { - self.pre_scan_builtin_expr(&member.object, ctx); - } - oxide_parser::ChainElement::CallExpression(call) => { - self.pre_scan_builtin_expr(&call.callee, ctx); - for arg in &call.arguments { - if let Some(e) = arg.as_expression() { - self.pre_scan_builtin_expr(e, ctx); - } - } - } - _ => {} - } - } - - - fn predeclare_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { - for statement in statements { - let Statement::FunctionDeclaration(function) = statement else { - continue; - }; - let Some(identifier) = &function.id else { - continue; - }; - let reg = ctx.alloc_reg(); - let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Var, false); - } - } - - /// Pre-declare all `var` bindings in this statement list so hoisted function - /// declarations emitted earlier can resolve them. Mirrors the removed count - /// pass behavior (see fe8bd86): top-level `var` names must be visible while - /// compiling function bodies that close over them. - fn predeclare_var_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { - for statement in statements { - match statement { - Statement::VariableDeclaration(decl) => { - if !matches!(decl.kind, VariableDeclarationKind::Var) { - continue; - } - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - let reg = ctx.alloc_reg(); - let _ = ctx.declare_initialized(bi.name.as_str(), reg, VariableDeclarationKind::Var, false); - } - } - } - Statement::BlockStatement(bs) => self.predeclare_var_declarations(&bs.body, ctx), - Statement::IfStatement(is) => { - self.predeclare_var_declarations(std::slice::from_ref(&is.consequent), ctx); - if let Some(alt) = &is.alternate { - self.predeclare_var_declarations(std::slice::from_ref(alt), ctx); - } - } - Statement::WhileStatement(wh) => { - self.predeclare_var_declarations(std::slice::from_ref(&wh.body), ctx); - } - Statement::DoWhileStatement(dw) => { - self.predeclare_var_declarations(std::slice::from_ref(&dw.body), ctx); - } - Statement::ForStatement(fs) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { - if matches!(decl.kind, VariableDeclarationKind::Var) { - for d in &decl.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - let reg = ctx.alloc_reg(); - let _ = - ctx.declare_initialized(bi.name.as_str(), reg, VariableDeclarationKind::Var, false); - } - } - } - } - self.predeclare_var_declarations(std::slice::from_ref(&fs.body), ctx); - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.predeclare_var_declarations(&case.consequent, ctx); - } - } - Statement::TryStatement(ts) => { - self.predeclare_var_declarations(&ts.block.body, ctx); - if let Some(handler) = &ts.handler { - self.predeclare_var_declarations(&handler.body.body, ctx); - } - if let Some(finalizer) = &ts.finalizer { - self.predeclare_var_declarations(&finalizer.body, ctx); - } - } - Statement::LabeledStatement(ls) => { - self.predeclare_var_declarations(std::slice::from_ref(&ls.body), ctx); - } - _ => {} - } - } - } - #[allow(clippy::too_many_arguments)] pub(crate) fn compile_function_body_with_field_hooks<'a, E>( &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, @@ -1501,35 +659,7 @@ impl Compiler { // same register offset (params go after builtin slots). ctx.reset_regs(); - // Function body scope - params and local vars - ctx.push_scope_with_kind(ScopeKind::FunctionScope); - - let param_base = ctx.next_reg; - - // Emit parameters and destructuring prologue. - for spec in param_specs { - let name = spec.register_name(); - let reg = ctx.alloc_reg(); - ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false)?; - } - - for spec in param_specs { - if let ParamSpec::Pattern { synthetic_name, pattern } = spec { - let src_reg = ctx.lookup(synthetic_name)?; - self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, &mut ctx)?; - } - } - - // 闭包捕获分析(AST 级,emit 前确定,时序无关) - let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect(); - ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); - ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &ctx.own_bindings); - - // Free variable analysis for upvalue capture (Ordinary + Arrow functions only) - if matches!(body_context, FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow) { - ctx.current_upvalue_captures = - self.collect_upvalue_names(body_stmts, &parent_ctx.captured_bindings, &ctx.own_bindings); - } + let param_base = self.emit_params_prologue(param_specs, body_stmts, parent_ctx, &mut ctx, body_context)?; self.predeclare_function_declarations(body_stmts, &mut ctx); @@ -1564,25 +694,8 @@ impl Compiler { } } - // Emit body statements. - // First sub-pass: emit function declarations (hoisting + marks parent captures) - let mut last_result_reg = None; - for stmt in body_stmts { - if matches!(stmt, Statement::FunctionDeclaration(_)) { - if let Some(reg) = self.emit_statement(stmt, &mut ctx)? { - last_result_reg = Some(reg); - } - } - } - // Second sub-pass: emit all other statements - for stmt in body_stmts { - if matches!(stmt, Statement::FunctionDeclaration(_)) { - continue; - } - if let Some(reg) = self.emit_statement(stmt, &mut ctx)? { - last_result_reg = Some(reg); - } - } + // Emit body statements(先函数声明 hoisting,再其余)。 + let last_result_reg = self.emit_body_stmts(body_stmts, &mut ctx)?; // Emit implicit RETURN: expression body returns the last expression, // statement body returns undefined. @@ -1612,6 +725,63 @@ impl Compiler { Ok(ir) } + /// 参数 prologue:函数作用域 + 参数声明/解构 + 闭包捕获与 upvalue 分析。返回 param_base。 + fn emit_params_prologue<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + ctx: &mut CompileCtx, body_context: FunctionBodyContext, + ) -> Result { + ctx.push_scope_with_kind(ScopeKind::FunctionScope); + let param_base = ctx.next_reg; + + // Emit parameters and destructuring prologue. + for spec in param_specs { + let name = spec.register_name(); + let reg = ctx.alloc_reg(); + ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false)?; + } + + for spec in param_specs { + if let ParamSpec::Pattern { synthetic_name, pattern } = spec { + let src_reg = ctx.lookup(synthetic_name)?; + self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, ctx)?; + } + } + + // 闭包捕获分析(AST 级,emit 前确定,时序无关) + let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect(); + ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); + ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &ctx.own_bindings); + + // Free variable analysis for upvalue capture (Ordinary + Arrow functions only) + if matches!(body_context, FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow) { + ctx.current_upvalue_captures = + self.collect_upvalue_names(body_stmts, &parent_ctx.captured_bindings, &ctx.own_bindings); + } + + Ok(param_base) + } + + /// 双 sub-pass emit body:先函数声明(hoisting),再其余语句。返回最后结果寄存器。 + fn emit_body_stmts(&self, body_stmts: &[Statement], ctx: &mut CompileCtx) -> Result, String> { + let mut last_result_reg = None; + for stmt in body_stmts { + if matches!(stmt, Statement::FunctionDeclaration(_)) { + if let Some(reg) = self.emit_statement(stmt, ctx)? { + last_result_reg = Some(reg); + } + } + } + for stmt in body_stmts { + if matches!(stmt, Statement::FunctionDeclaration(_)) { + continue; + } + if let Some(reg) = self.emit_statement(stmt, ctx)? { + last_result_reg = Some(reg); + } + } + Ok(last_result_reg) + } + pub(crate) fn emit_statement(&self, stmt: &Statement, ctx: &mut CompileCtx) -> Result, String> { match stmt { Statement::ExpressionStatement(_) | Statement::ReturnStatement(_) | Statement::EmptyStatement(_) => { diff --git a/crates/oxide_compiler/src/lib.rs b/crates/oxide_compiler/src/lib.rs index 8bcd418..c88ae0b 100644 --- a/crates/oxide_compiler/src/lib.rs +++ b/crates/oxide_compiler/src/lib.rs @@ -1,12 +1,14 @@ #![doc = "OxideJS - AST to bytecode compiler"] pub mod class; +pub mod closure; pub mod compiler; pub mod compiler_log; pub mod emit_ctx; pub mod expr; pub mod hash; pub mod ir; +pub mod prepass; pub mod shared; pub mod stmt; pub mod symbol_table; diff --git a/crates/oxide_compiler/src/prepass.rs b/crates/oxide_compiler/src/prepass.rs new file mode 100644 index 0000000..93f7bd7 --- /dev/null +++ b/crates/oxide_compiler/src/prepass.rs @@ -0,0 +1,343 @@ +use crate::compiler::{CompileCtx, Compiler}; +use oxide_parser::{Expression, Statement, VariableDeclarationKind}; + +impl Compiler { + + /// builtin slot allocation ahead of the temporary register pool. + pub(crate) fn pre_register_builtin_references(&self, stmts: &[Statement], ctx: &mut CompileCtx) { + for stmt in stmts { + self.pre_scan_builtin_stmt(stmt, ctx); + } + } + + fn pre_scan_builtin_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) { + match stmt { + Statement::ExpressionStatement(es) => self.pre_scan_builtin_expr(&es.expression, ctx), + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + if let Some(init) = &d.init { + self.pre_scan_builtin_expr(init, ctx); + } + } + } + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + self.pre_scan_builtin_expr(a, ctx); + } + } + Statement::IfStatement(is) => { + self.pre_scan_builtin_expr(&is.test, ctx); + self.pre_scan_builtin_stmt(&is.consequent, ctx); + if let Some(alt) = &is.alternate { + self.pre_scan_builtin_stmt(alt, ctx); + } + } + Statement::WhileStatement(wh) => { + self.pre_scan_builtin_expr(&wh.test, ctx); + self.pre_scan_builtin_stmt(&wh.body, ctx); + } + Statement::DoWhileStatement(dw) => { + self.pre_scan_builtin_stmt(&dw.body, ctx); + self.pre_scan_builtin_expr(&dw.test, ctx); + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } else if let oxide_parser::ForStatementInit::VariableDeclaration(decl) = init { + for d in &decl.declarations { + if let Some(init_expr) = &d.init { + self.pre_scan_builtin_expr(init_expr, ctx); + } + } + } + } + if let Some(t) = &fs.test { + self.pre_scan_builtin_expr(t, ctx); + } + if let Some(u) = &fs.update { + self.pre_scan_builtin_expr(u, ctx); + } + self.pre_scan_builtin_stmt(&fs.body, ctx); + } + Statement::ForInStatement(fi) => { + self.pre_scan_builtin_expr(&fi.right, ctx); + self.pre_scan_builtin_stmt(&fi.body, ctx); + } + Statement::ForOfStatement(fo) => { + self.pre_scan_builtin_expr(&fo.right, ctx); + self.pre_scan_builtin_stmt(&fo.body, ctx); + } + Statement::SwitchStatement(sw) => { + self.pre_scan_builtin_expr(&sw.discriminant, ctx); + for case in &sw.cases { + if let Some(test) = &case.test { + self.pre_scan_builtin_expr(test, ctx); + } + for s in &case.consequent { + self.pre_scan_builtin_stmt(s, ctx); + } + } + } + Statement::ThrowStatement(ts) => { + self.pre_scan_builtin_expr(&ts.argument, ctx); + } + Statement::TryStatement(ts) => { + for s in &ts.block.body { + self.pre_scan_builtin_stmt(s, ctx); + } + if let Some(handler) = &ts.handler { + for s in &handler.body.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + if let Some(finalizer) = &ts.finalizer { + for s in &finalizer.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + } + Statement::BlockStatement(bs) => { + for s in &bs.body { + self.pre_scan_builtin_stmt(s, ctx); + } + } + Statement::LabeledStatement(ls) => self.pre_scan_builtin_stmt(&ls.body, ctx), + Statement::ClassDeclaration(cd) => { + if let Some(super_class) = &cd.super_class { + self.pre_scan_builtin_expr(super_class, ctx); + } + } + Statement::FunctionDeclaration(_) | Statement::BreakStatement(_) | Statement::ContinueStatement(_) => {} + _ => {} + } + } + + fn pre_scan_builtin_expr(&self, expr: &Expression, ctx: &mut CompileCtx) { + match expr { + Expression::Identifier(ident) => { + if CompileCtx::is_known_builtin(ident.name.as_str()) { + let _ = ctx.lookup_or_builtin(ident.name.as_str()); + } + } + Expression::BinaryExpression(bin) => { + self.pre_scan_builtin_expr(&bin.left, ctx); + self.pre_scan_builtin_expr(&bin.right, ctx); + } + Expression::UnaryExpression(un) => { + self.pre_scan_builtin_expr(&un.argument, ctx); + } + Expression::CallExpression(call) => { + self.pre_scan_builtin_expr(&call.callee, ctx); + for arg in &call.arguments { + if let Some(e) = arg.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + } + Expression::NewExpression(ne) => { + self.pre_scan_builtin_expr(&ne.callee, ctx); + for arg in &ne.arguments { + if let Some(e) = arg.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + } + Expression::LogicalExpression(log) => { + self.pre_scan_builtin_expr(&log.left, ctx); + self.pre_scan_builtin_expr(&log.right, ctx); + } + Expression::ConditionalExpression(cond) => { + self.pre_scan_builtin_expr(&cond.test, ctx); + self.pre_scan_builtin_expr(&cond.consequent, ctx); + self.pre_scan_builtin_expr(&cond.alternate, ctx); + } + Expression::PrivateInExpression(pin) => { + self.pre_scan_builtin_expr(&pin.right, ctx); + } + Expression::SequenceExpression(seq) => { + for e in &seq.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::AssignmentExpression(assign) => { + if let Some(target) = assign.left.as_simple_assignment_target() { + self.pre_scan_builtin_target(target, ctx); + } + self.pre_scan_builtin_expr(&assign.right, ctx); + } + Expression::UpdateExpression(update) => { + self.pre_scan_builtin_target(&update.argument, ctx); + } + Expression::TemplateLiteral(tl) => { + for e in &tl.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::TaggedTemplateExpression(tt) => { + self.pre_scan_builtin_expr(&tt.tag, ctx); + for e in &tt.quasi.expressions { + self.pre_scan_builtin_expr(e, ctx); + } + } + Expression::ObjectExpression(obj) => { + for prop in &obj.properties { + if let oxide_parser::ObjectPropertyKind::ObjectProperty(p) = prop { + if p.computed { + self.pre_scan_builtin_expr(p.key.to_expression(), ctx); + } + self.pre_scan_builtin_expr(&p.value, ctx); + } + } + } + Expression::ArrayExpression(arr) => { + for e in &arr.elements { + if let Some(e) = e.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + } + Expression::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + Expression::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + Expression::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + Expression::ChainExpression(chain) => { + self.pre_scan_builtin_chain(&chain.expression, ctx); + } + Expression::ParenthesizedExpression(p) => self.pre_scan_builtin_expr(&p.expression, ctx), + Expression::ArrowFunctionExpression(_) + | Expression::FunctionExpression(_) + | Expression::ClassExpression(_) => {} + _ => {} + } + } + + fn pre_scan_builtin_target(&self, target: &oxide_parser::SimpleAssignmentTarget, ctx: &mut CompileCtx) { + match target { + oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + oxide_parser::SimpleAssignmentTarget::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + _ => {} + } + } + + fn pre_scan_builtin_chain(&self, element: &oxide_parser::ChainElement, ctx: &mut CompileCtx) { + match element { + oxide_parser::ChainElement::StaticMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::ChainElement::ComputedMemberExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + self.pre_scan_builtin_expr(&member.expression, ctx); + } + oxide_parser::ChainElement::PrivateFieldExpression(member) => { + self.pre_scan_builtin_expr(&member.object, ctx); + } + oxide_parser::ChainElement::CallExpression(call) => { + self.pre_scan_builtin_expr(&call.callee, ctx); + for arg in &call.arguments { + if let Some(e) = arg.as_expression() { + self.pre_scan_builtin_expr(e, ctx); + } + } + } + _ => {} + } + } + + + pub(crate) fn predeclare_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { + for statement in statements { + let Statement::FunctionDeclaration(function) = statement else { + continue; + }; + let Some(identifier) = &function.id else { + continue; + }; + let reg = ctx.alloc_reg(); + let _ = ctx.declare_initialized(identifier.name.as_str(), reg, VariableDeclarationKind::Var, false); + } + } + + /// Pre-declare all `var` bindings in this statement list so hoisted function + /// declarations emitted earlier can resolve them. Mirrors the removed count + /// pass behavior (see fe8bd86): top-level `var` names must be visible while + /// compiling function bodies that close over them. + pub(crate) fn predeclare_var_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) { + for statement in statements { + match statement { + Statement::VariableDeclaration(decl) => { + if !matches!(decl.kind, VariableDeclarationKind::Var) { + continue; + } + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + let reg = ctx.alloc_reg(); + let _ = ctx.declare_initialized(bi.name.as_str(), reg, VariableDeclarationKind::Var, false); + } + } + } + Statement::BlockStatement(bs) => self.predeclare_var_declarations(&bs.body, ctx), + Statement::IfStatement(is) => { + self.predeclare_var_declarations(std::slice::from_ref(&is.consequent), ctx); + if let Some(alt) = &is.alternate { + self.predeclare_var_declarations(std::slice::from_ref(alt), ctx); + } + } + Statement::WhileStatement(wh) => { + self.predeclare_var_declarations(std::slice::from_ref(&wh.body), ctx); + } + Statement::DoWhileStatement(dw) => { + self.predeclare_var_declarations(std::slice::from_ref(&dw.body), ctx); + } + Statement::ForStatement(fs) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { + if matches!(decl.kind, VariableDeclarationKind::Var) { + for d in &decl.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + let reg = ctx.alloc_reg(); + let _ = + ctx.declare_initialized(bi.name.as_str(), reg, VariableDeclarationKind::Var, false); + } + } + } + } + self.predeclare_var_declarations(std::slice::from_ref(&fs.body), ctx); + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + self.predeclare_var_declarations(&case.consequent, ctx); + } + } + Statement::TryStatement(ts) => { + self.predeclare_var_declarations(&ts.block.body, ctx); + if let Some(handler) = &ts.handler { + self.predeclare_var_declarations(&handler.body.body, ctx); + } + if let Some(finalizer) = &ts.finalizer { + self.predeclare_var_declarations(&finalizer.body, ctx); + } + } + Statement::LabeledStatement(ls) => { + self.predeclare_var_declarations(std::slice::from_ref(&ls.body), ctx); + } + _ => {} + } + } + } + +} +