diff --git a/crates/oxide_emit/src/closure.rs b/crates/oxide_emit/src/closure.rs index 2c52a384..24539e66 100644 --- a/crates/oxide_emit/src/closure.rs +++ b/crates/oxide_emit/src/closure.rs @@ -123,6 +123,7 @@ impl Emitter { let mut inner = shadow.clone(); inner.extend(self.collect_fn_param_names(&fd.params)); inner.extend(self.collect_own_binding_names(&[], body)); + self.collect_fn_default_names(&fd.params, ref_set, shadow, out); self.collect_capture_names_shadowed(body, ref_set, &inner, out); } Statement::IfStatement(is) => { @@ -240,6 +241,20 @@ impl Emitter { } } + /// 收集函数参数默认值表达式里的引用(子层 upvalue 判定;参数名遮蔽)。 + fn collect_fn_default_names( + &self, params: &oxide_parser::FormalParameters, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, + ) { + for p in ¶ms.items { + if let Some(init) = &p.initializer { + self.collect_capture_names_expr(init, ref_set, shadow, out); + } + let mut param_shadow = shadow.clone(); + self.collect_capture_names_binding_pattern(&p.pattern, ref_set, shadow, out, &mut param_shadow); + } + } + fn collect_capture_names_expr( &self, expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, ) { @@ -272,12 +287,14 @@ impl Emitter { let mut inner = shadow.clone(); inner.extend(self.collect_fn_param_names(&fe.params)); inner.extend(self.collect_own_binding_names(&[], body)); + self.collect_fn_default_names(&fe.params, ref_set, shadow, out); 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_fn_default_names(&ae.params, ref_set, shadow, out); self.collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out); } Expression::BinaryExpression(be) => { @@ -382,21 +399,41 @@ impl Emitter { } /// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 - pub(crate) fn collect_captured_bindings(&self, stmts: &[Statement], own: &HashSet) -> BTreeMap { + pub(crate) fn collect_captured_bindings( + &self, stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet, + ) -> BTreeMap { let mut names = HashSet::new(); for stmt in stmts { self.collect_captured_stmt(stmt, own, &mut names); } + // 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获, + // 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。 + for expr in extra_exprs { + self.collect_captured_expr(expr, 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() } + /// 收集函数参数默认值表达式里的嵌套函数引用(父层 captured/子层 upvalue 判定)。 + fn collect_fn_default_captured( + &self, params: &oxide_parser::FormalParameters, own: &HashSet, out: &mut HashSet, + ) { + for p in ¶ms.items { + if let Some(init) = &p.initializer { + self.collect_captured_expr(init, own, out); + } + self.collect_captured_binding_pattern(&p.pattern, own, out); + } + } + /// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 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_fn_default_captured(&fd.params, own, out); self.collect_capture_names(body, own, out); } Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out), @@ -523,11 +560,13 @@ impl Emitter { 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_fn_default_captured(&fe.params, own, out); 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_fn_default_captured(&ae.params, own, out); self.collect_capture_names_shadowed(&ae.body.statements, own, &inner, out); } Expression::CallExpression(ce) => { @@ -634,7 +673,7 @@ impl Emitter { /// 若在父 `upvalue_captures`(父自身从更外层捕获)则链式标记 `parent_uv_idx`, /// 运行时从父闭包 upvalues 取 cell。enclosing_reg 由父 emit 完成后填充。 pub(crate) fn collect_upvalue_names( - &self, body_stmts: &[Statement], parent_captured: &BTreeMap, + &self, body_stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], parent_captured: &BTreeMap, parent_upvalues: &[UpvalueCapture], sub_own: &HashSet, ) -> Vec { let mut parent_names: HashSet = parent_captured.keys().cloned().collect(); @@ -643,6 +682,10 @@ impl Emitter { } let mut names = HashSet::new(); self.collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names); + // 参数默认值表达式(不在 body_stmts)里的嵌套函数引用也会捕获父变量。 + for expr in extra_exprs { + self.collect_capture_names_expr(expr, &parent_names, sub_own, &mut names); + } // HashSet 迭代序带随机种子(进程级非确定),必须排序使 upvalue_captures 的顺序与 // 父 captured_bindings 的 cell_idx(BTreeMap 名字序)对齐——否则 LOAD_UPVALUE 的 // a 槽 uv_idx 编码与 cell_idx 错位,读错 upvalue。 diff --git a/crates/oxide_emit/src/emit.rs b/crates/oxide_emit/src/emit.rs index fa443296..f5e2e42a 100644 --- a/crates/oxide_emit/src/emit.rs +++ b/crates/oxide_emit/src/emit.rs @@ -523,6 +523,39 @@ impl Emitter { Self } + /// 遍历解构 pattern 收集内嵌默认值表达式(AssignmentPattern.right)。 + fn collect_pattern_default_exprs<'a>( + &self, pattern: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec<&'a oxide_parser::Expression<'a>>, + ) { + use oxide_parser::BindingPattern; + match pattern { + BindingPattern::AssignmentPattern(ap) => { + out.push(&ap.right); + self.collect_pattern_default_exprs(&ap.left, out); + } + BindingPattern::ArrayPattern(ap) => { + for elem in &ap.elements { + if let Some(p) = elem { + self.collect_pattern_default_exprs(p, out); + } + } + if let Some(rest) = &ap.rest { + self.collect_pattern_default_exprs(&rest.argument, out); + } + } + BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + self.collect_pattern_default_exprs(&prop.value, out); + } + if let Some(rest) = &op.rest { + self.collect_pattern_default_exprs(&rest.argument, out); + } + } + _ => {} + } + } + + // ── 闭包捕获分析(AST 级,时序无关)── /// 收集函数参数的绑定名(BindingIdentifier 形态)。 @@ -759,8 +792,26 @@ impl Emitter { // 闭包捕获分析(AST 级,emit 前确定,时序无关) let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect(); + let mut param_defaults: Vec<&oxide_parser::Expression> = Vec::new(); + for spec in param_specs { + match spec { + ParamSpec::Identifier { initializer, .. } => { + if let Some(init) = initializer { + param_defaults.push(init); + } + } + ParamSpec::Pattern { pattern, initializer, .. } => { + if let Some(init) = initializer { + param_defaults.push(init); + } + // 模式内嵌默认值(`[x = expr]` 的 AssignmentPattern.right)也会被 + // 内部闭包引用,需纳入捕获分析。 + self.collect_pattern_default_exprs(pattern, &mut param_defaults); + } + } + } ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); - ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &ctx.own_bindings); + ctx.captured_bindings = self.collect_captured_bindings(body_stmts, ¶m_defaults, &ctx.own_bindings); // 被捕获的参数也必须建 cell(MAKE_CELL):否则子函数经 lazy upvalue 路径读 // 自身寄存器(依赖调用者寄存器残留),vreg 化/RegAlloc 移动寄存器后读到垃圾。 @@ -782,6 +833,7 @@ impl Emitter { if matches!(body_context, FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow) { ctx.current_upvalue_captures = self.collect_upvalue_names( body_stmts, + ¶m_defaults, &parent_ctx.captured_bindings, &parent_ctx.current_upvalue_captures, &ctx.own_bindings, @@ -888,7 +940,7 @@ impl Emitter { // 闭包捕获分析(AST 级,emit 前确定) ctx.own_bindings = self.collect_own_binding_names(&[], &program.body); - ctx.captured_bindings = self.collect_captured_bindings(&program.body, &ctx.own_bindings); + ctx.captured_bindings = self.collect_captured_bindings(&program.body, &[], &ctx.own_bindings); // 首个 sub-pass:发函数声明(hoisting),保证任何代码运行前函数对象已就绪。 for stmt in &program.body {