Files
OxideJS-New/crates/oxide_emit/src/stmt/iteration/do_while.rs
T
pjh123 744899aae9 fix: for-of/for-in 提前退出时按规范顺序完成 IteratorClose
return/break/continue 逃出 for-of 时此前完全不执行 IteratorClose:
BREAK/CONTINUE/RETURN 指令现在经 ext 字携带词法逃出的迭代器层数
(for-of + for-in 各 16 位),运行时在全部 finally 穿越之后、真正
跳转/返回之前按 LIFO 关闭——与规范 §13.7.5.4(循环体完成值已含
内部 try-finally 处理,IteratorClose 在后)顺序一致。

- emit 词法:LabelCtx 增加 for-of/for-in 深度计数,loop/switch/label
  打开时快照,break/continue/return 按当前深度减目标深度计算逃出层数
  (switch 内 break 以 switch 打开点为基准,目标循环自身不计入)
- 指令编码:brk/cont/ret 三参构造,lower 跳转路径补发 ext 字
- 运行时:dispatch_break/continue/return 读取逃出计数,无 finally 时
  直接关闭后跳转/返回,有 finally 时随 Completion 悬挂由 TRY_FINALLY_END
  在穿越完成后消费;生成器 .return()/.throw() 注入经 complete_generator_return
  全关快照栈迭代器;return() 抛错经 unwind 替代完成值并关闭剩余迭代器
- 顺带:for-in 逃出残留(无 return() 语义,仅弹栈);for-await-of 的
  异步迭代器不做同步关闭(return() promise 须 await,走异步机制)
- 新增 15 项回归测试:return/labeled break/continue/switch/while/finally
  顺序/抛错优先/生成器注入/for-in/for-await-of 嵌套
2026-08-16 09:31:39 +08:00

28 lines
1.0 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! do-while 语句 emit:`emit_do_while_statement` 先执行体后测条件。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_parser::Statement;
impl Emitter {
pub(crate) fn emit_do_while_statement(
&self, stmt: &Statement, ctx: &mut CompileCtx,
) -> Result<Option<u32>, String> {
let Statement::DoWhileStatement(dw) = stmt else {
return Ok(None);
};
let start_label = ctx.next_label_id();
let end_label = ctx.next_label_id();
ctx.labels.set_label_pos(start_label, ctx.insts.len());
ctx.push_loop(end_label, start_label, crate::emit_ctx::LoopKind::Plain);
let n_labeled = ctx.take_pending_loop_labels(end_label, start_label);
self.emit_statement(&dw.body, ctx)?;
let test_reg = self.emit_expression(&dw.test, ctx)?;
ctx.inst(Inst::jmp_if_true(test_reg, start_label));
ctx.labels.set_label_pos(end_label, ctx.insts.len());
ctx.pop_label_scopes(n_labeled);
ctx.pop_loop();
Ok(None)
}
}