mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 03:31:12 +08:00
fix: switch 语句补 case 块作用域与函数预声明
This commit is contained in:
@@ -48,7 +48,13 @@ impl Emitter {
|
||||
/// # 副作用
|
||||
/// - 当前指令流在块入口发 CREATE_CLOSURE(及 MAKE_CELL / STORE_VAR);
|
||||
/// 物化登记写入 `block_fn_entry_mats` 栈顶帧。
|
||||
fn emit_block_fn_entry_init_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) -> Result<(), String> {
|
||||
///
|
||||
/// # 注意事项
|
||||
/// - 同名重复的直接子声明只登记首个节点:该名任一直接子声明点都复用块槽
|
||||
/// (取其当前值),而非重编本节点闭包——块绑定入口值按源序末次物化,
|
||||
/// 复用槽才与外层 var 写回后的块槽值一致(仅登记末次会让较早声明点把
|
||||
/// 本节点闭包写回外层 var,与规范的块绑定写回口径不符)。
|
||||
pub(crate) fn emit_block_fn_entry_init_stmt(&self, stmt: &Statement, ctx: &mut CompileCtx) -> Result<(), String> {
|
||||
match stmt {
|
||||
Statement::FunctionDeclaration(fd) => {
|
||||
let Some(id) = &fd.id else {
|
||||
@@ -61,7 +67,8 @@ impl Emitter {
|
||||
ctx.block_fn_entry_mats
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.insert(name, &**fd as *const _ as *const ());
|
||||
.entry(name)
|
||||
.or_insert_with(|| &**fd as *const _ as *const ());
|
||||
Ok(())
|
||||
}
|
||||
Statement::LabeledStatement(ls) => self.emit_block_fn_entry_init_stmt(&ls.body, ctx),
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
//! switch 语句 emit:case 匹配链 + 穿落(fallthrough)与 default,见 `emit_switch_statement`。
|
||||
//! CaseBlock 有独立块作用域:case 选择表达式与全部 case 体共享同一环境,case 内
|
||||
//! 函数/词法声明不泄漏到 switch 外。
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{CompileCtx, Emitter};
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
@@ -13,8 +17,25 @@ impl Emitter {
|
||||
};
|
||||
let end_label = ctx.next_label_id();
|
||||
ctx.push_switch(end_label);
|
||||
// 判别式在 switch 外层词法环境求值,CaseBlock 环境尚未建立。
|
||||
let disc_reg = self.emit_expression(&sw.discriminant, ctx)?;
|
||||
let cases = &sw.cases;
|
||||
// CaseBlock 环境:case 选择表达式与全部 case 体同处一个块作用域。
|
||||
// 块函数预声明先于 lexical,使 `case 0: let g; function g(){}` 的 lexical
|
||||
// 占位命中已存在的函数绑定,报重复声明错。
|
||||
ctx.push_scope();
|
||||
for case in cases.iter() {
|
||||
self.predeclare_block_function_declarations(&case.consequent, ctx, false);
|
||||
self.predeclare_lexical_declarations(&case.consequent, ctx, false)?;
|
||||
}
|
||||
// case 内函数声明的块入口初始化:同名重复声明按源序物化,末次声明成为
|
||||
// 入口值;声明点复用块槽写回外层 var(见 emit_function_declaration)。
|
||||
ctx.block_fn_entry_mats.push(HashMap::new());
|
||||
for case in cases.iter() {
|
||||
for s in &case.consequent {
|
||||
self.emit_block_fn_entry_init_stmt(s, ctx)?;
|
||||
}
|
||||
}
|
||||
let mut case_labels = Vec::with_capacity(cases.len());
|
||||
for case in cases.iter() {
|
||||
let case_label = ctx.next_label_id();
|
||||
@@ -45,7 +66,9 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.block_fn_entry_mats.pop();
|
||||
ctx.labels.set_label_pos(end_label, ctx.insts.len());
|
||||
ctx.pop_scope();
|
||||
ctx.pop_switch();
|
||||
// switch 完成值 = 已执行 case 链最后一次非空完成值(源序最后非空语句的
|
||||
// 收敛寄存器:命中后穿落到 break/尾即为其值,无命中则该寄存器不被写入而
|
||||
|
||||
Reference in New Issue
Block a user