Skip to content

Commit 72d9bb7

Browse files
committed
update
1 parent ade94fe commit 72d9bb7

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

crates/luars/src/compiler/stmt.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,10 @@ fn compile_if_stat(c: &mut Compiler, stat: &LuaIfStat) -> Result<(), String> {
10731073
fn compile_while_stat(c: &mut Compiler, stat: &LuaWhileStat) -> Result<(), String> {
10741074
// Structure: while <condition> do <block> end
10751075

1076-
// Begin loop
1076+
// Begin scope for the loop body (to track locals for CLOSE)
1077+
begin_scope(c);
1078+
1079+
// Begin loop - record first_reg for break CLOSE
10771080
begin_loop(c);
10781081

10791082
// Mark loop start
@@ -1116,6 +1119,31 @@ fn compile_while_stat(c: &mut Compiler, stat: &LuaWhileStat) -> Result<(), Strin
11161119
compile_block(c, &body)?;
11171120
}
11181121

1122+
// Before jumping back, emit CLOSE if any local in the loop body was captured
1123+
{
1124+
let loop_info = c.loop_stack.last().unwrap();
1125+
let loop_scope_depth = loop_info.scope_depth;
1126+
let first_reg = loop_info.first_local_register;
1127+
1128+
let scope = c.scope_chain.borrow();
1129+
let mut min_close_reg: Option<u32> = None;
1130+
for local in scope.locals.iter().rev() {
1131+
if local.depth < loop_scope_depth {
1132+
break;
1133+
}
1134+
if local.needs_close && local.register >= first_reg {
1135+
min_close_reg = Some(match min_close_reg {
1136+
None => local.register,
1137+
Some(min_reg) => min_reg.min(local.register),
1138+
});
1139+
}
1140+
}
1141+
drop(scope);
1142+
if let Some(reg) = min_close_reg {
1143+
emit(c, Instruction::encode_abc(OpCode::Close, reg, 0, 0));
1144+
}
1145+
}
1146+
11191147
// Jump back to loop start
11201148
let jump_offset = (c.chunk.code.len() - loop_start) as i32 + 1;
11211149
emit(c, Instruction::create_sj(OpCode::Jmp, -jump_offset));
@@ -1127,6 +1155,9 @@ fn compile_while_stat(c: &mut Compiler, stat: &LuaWhileStat) -> Result<(), Strin
11271155

11281156
// End loop (patches all break statements)
11291157
end_loop(c);
1158+
1159+
// End scope
1160+
end_scope(c);
11301161

11311162
Ok(())
11321163
}

0 commit comments

Comments
 (0)