fix(emit): 参数默认值 emit 前完成捕获分析 + 类方法支持 upvalue 捕获
This commit is contained in:
@@ -762,13 +762,50 @@ impl Emitter {
|
||||
ctx.push_scope_with_kind(ScopeKind::FunctionScope);
|
||||
let param_base = ctx.next_reg;
|
||||
|
||||
// 发参数与解构 prologue。
|
||||
// 发参数声明(分配寄存器;分析用 register_name 引用)。
|
||||
for spec in param_specs {
|
||||
let name = spec.register_name();
|
||||
let reg = ctx.alloc_reg();
|
||||
ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false)?;
|
||||
}
|
||||
|
||||
// 闭包捕获分析(AST 级,emit 前确定):须在参数默认值 emit 之前,
|
||||
// 否则默认值内嵌套函数(IIFE)编译时父分析为空 → upvalue 捕获丢失。
|
||||
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, ¶m_defaults, &ctx.own_bindings);
|
||||
// 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。
|
||||
if matches!(
|
||||
body_context,
|
||||
FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement
|
||||
) {
|
||||
ctx.current_upvalue_captures = self.collect_upvalue_names(
|
||||
body_stmts,
|
||||
¶m_defaults,
|
||||
&parent_ctx.captured_bindings,
|
||||
&parent_ctx.current_upvalue_captures,
|
||||
&ctx.own_bindings,
|
||||
);
|
||||
}
|
||||
|
||||
for spec in param_specs {
|
||||
match spec {
|
||||
ParamSpec::Pattern { synthetic_name, pattern, initializer } => {
|
||||
@@ -790,32 +827,10 @@ 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, ¶m_defaults, &ctx.own_bindings);
|
||||
|
||||
// 被捕获的参数也必须建 cell(MAKE_CELL):否则子函数经 lazy upvalue 路径读
|
||||
// 自身寄存器(依赖调用者寄存器残留),vreg 化/RegAlloc 移动寄存器后读到垃圾。
|
||||
// 与 var/let/const 的 MAKE_CELL 语义一致(binding.rs:50)。
|
||||
// 与 var/let/const 的 MAKE_CELL 语义一致(binding.rs:50)。须在默认值之后
|
||||
// (默认值 emit 会读参数寄存器)。
|
||||
for spec in param_specs {
|
||||
let name = spec.register_name();
|
||||
if let Some(&cell_idx) = ctx.captured_bindings.get(name) {
|
||||
@@ -829,17 +844,6 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
|
||||
// 自由变量分析(仅普通/箭头函数):收集 upvalue 捕获。
|
||||
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,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(param_base)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user