fix: 修复嵌套函数调用并接通闭包捕获链路

This commit is contained in:
2026-06-30 21:52:18 +08:00
parent 9af91aada3
commit 77a52bf7e8
5 changed files with 50 additions and 27 deletions
+14 -8
View File
@@ -1089,10 +1089,13 @@ impl Compiler {
is_class_constructor: false,
is_derived_constructor: false,
needs_home_object: false,
upvalue_captures: Vec::new(),
cells_needed: ctx.scopes.symbols.scopes[0]
.bindings
.values()
upvalue_captures: ctx.current_upvalue_captures.clone(),
cells_needed: ctx
.scopes
.symbols
.scopes
.iter()
.flat_map(|s| s.bindings.values())
.filter(|b| b.is_captured.get())
.count() as u8,
})
@@ -1193,10 +1196,13 @@ impl Compiler {
is_class_constructor: false,
is_derived_constructor: false,
needs_home_object: false,
upvalue_captures: Vec::new(),
cells_needed: ctx.scopes.symbols.scopes[0]
.bindings
.values()
upvalue_captures: ctx.current_upvalue_captures.clone(),
cells_needed: ctx
.scopes
.symbols
.scopes
.iter()
.flat_map(|s| s.bindings.values())
.filter(|b| b.is_captured.get())
.count() as u8,
})
+7 -4
View File
@@ -356,9 +356,6 @@ impl Compiler {
) -> Result<(), String> {
let var_reg = ctx.alloc_reg();
let target_reg = if matches!(kind, VariableDeclarationKind::Var) {
// `var` is hoisted, so the count pass already registered the name. A redeclare
// here reuses that existing register instead of erroring; the freshly allocated
// reg matches it (count/emit allocate in lock-step) so either resolves the same.
match ctx.declare(name, var_reg, kind, is_const) {
Ok(()) => var_reg,
Err(_) => ctx.lookup(name).unwrap_or(var_reg),
@@ -367,7 +364,13 @@ impl Compiler {
ctx.declare(name, var_reg, kind, is_const)?;
var_reg
};
ctx.emit(opcode::encode(OpCode::STORE_VAR, target_reg, src_reg, if is_const { 1 } else { 0 }));
if ctx.scopes.symbols.lookup_is_captured(name) {
let cell_idx = ctx.scopes.cell_registry.len() as u8;
ctx.scopes.cell_registry.push((name.to_string(), cell_idx));
ctx.emit(opcode::encode(OpCode::MAKE_CELL, src_reg, cell_idx, 0));
} else {
ctx.emit(opcode::encode(OpCode::STORE_VAR, target_reg, src_reg, if is_const { 1 } else { 0 }));
}
ctx.init_var(name);
Ok(())
}
@@ -37,7 +37,7 @@ impl Compiler {
if is_captured {
let cell_idx = ctx.scopes.cell_registry.len() as u8;
ctx.scopes.cell_registry.push((bi.name.to_string(), cell_idx));
ctx.emit(opcode::encode(OpCode::MAKE_CELL, var_reg, cell_idx, 0));
ctx.emit(opcode::encode(OpCode::MAKE_CELL, tmp, cell_idx, 0));
} else {
ctx.emit(opcode::encode(OpCode::STORE_VAR, var_reg, tmp, 0));
}