diff --git a/crates/oxide_emit/src/capture/captured.rs b/crates/oxide_emit/src/capture/captured.rs index 6fddf4dc..d406ecd1 100644 --- a/crates/oxide_emit/src/capture/captured.rs +++ b/crates/oxide_emit/src/capture/captured.rs @@ -1,5 +1,6 @@ //! 闭包捕获分析,父层捕获分析:本函数哪些绑定被任意深度嵌套函数捕获 -//! → BTreeMap(cell_idx 按名字序,稳定跨 run)。 +//! → BTreeMap(cell_idx 按名字排序分配,同一程序重编译得到相同索引, +//! 父 MAKE_CELL 与子函数 upvalue 引用同一 cell)。 use std::collections::{BTreeMap, HashSet}; @@ -10,6 +11,9 @@ use super::names::collect_own_binding_names; use super::scanner::{collect_capture_names_expr, collect_capture_names_shadowed, collect_class_capture_names}; /// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 +/// +/// 本族以本函数 own 绑定集为过滤条件做捕获集的最终判定;`scanner.rs` 的 +/// `collect_capture_names_*` 族带显式 `ref_set`/`shadow`,按过滤条件收集引用名。 pub(crate) fn collect_captured_bindings( stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet, ) -> BTreeMap { @@ -17,8 +21,9 @@ pub(crate) fn collect_captured_bindings( for stmt in stmts { collect_captured_stmt(stmt, own, &mut names); } - // 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获, - // 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。 + // 参数默认值表达式里的引用同样纳入捕获分析:默认值位于函数体之外,其中的 + // 嵌套函数引用全局或外层变量时,若未登记进捕获集,发射期会走 LOAD_VAR 读到 + // 寄存器残留值。 for expr in extra_exprs { collect_captured_expr(expr, own, &mut names); } @@ -279,6 +284,9 @@ pub(crate) fn collect_captured_binding_keys( } } +/// 以本函数 own 绑定集为过滤条件,判定表达式内嵌套函数捕获了哪些父绑定。与 +/// `scanner.rs` 的 `collect_capture_names_expr` 相比,本函数以 own 为过滤条件做 +/// 捕获最终判定,不接收显式 `ref_set`/`shadow`。 pub(crate) fn collect_captured_expr(expr: &Expression, own: &HashSet, out: &mut HashSet) { match expr { Expression::FunctionExpression(fe) => { @@ -390,6 +398,7 @@ pub(crate) fn collect_captured_expr(expr: &Expression, own: &HashSet, ou } } +/// 遍历可选链元素,判定链上表达式对父绑定的捕获。 pub(crate) fn collect_captured_chain( element: &oxide_parser::ChainElement, own: &HashSet, out: &mut HashSet, ) { diff --git a/crates/oxide_emit/src/capture/mod.rs b/crates/oxide_emit/src/capture/mod.rs index c2f6a52a..83b18bff 100644 --- a/crates/oxide_emit/src/capture/mod.rs +++ b/crates/oxide_emit/src/capture/mod.rs @@ -1,7 +1,8 @@ //! 闭包捕获分析(AST 级,emit 前完成,时序无关)。 //! //! 收集本函数绑定的名字(own_bindings)与被嵌套函数捕获的名字 -//! (captured_bindings → cell_idx,按名排序稳定跨 run),为 MAKE_CELL / +//! (captured_bindings → cell_idx;cell_idx 按名字排序分配,同一程序重编译得到 +//! 相同索引,保证父 MAKE_CELL 与子函数 upvalue 引用同一 cell),为 MAKE_CELL / //! CELL_GET / CELL_SET 与子函数 upvalue cell_idx 提供统一依据。 //! //! 五区严格单向分层(本文件 ← names ← scanner ← captured ← upvalues): @@ -21,6 +22,7 @@ pub(crate) use names::collect_top_level_function_names_ordered; pub(crate) use names::collect_var_binding_names; pub(crate) use upvalues::collect_upvalue_names; +/// 收集形参(含 rest)绑定的名字集,作为本函数作用域的遮蔽集。 pub(crate) fn collect_fn_param_names(params: &oxide_parser::FormalParameters) -> HashSet { let mut names = HashSet::new(); for p in ¶ms.items { diff --git a/crates/oxide_emit/src/capture/names.rs b/crates/oxide_emit/src/capture/names.rs index ae7d6275..4ffc2760 100644 --- a/crates/oxide_emit/src/capture/names.rs +++ b/crates/oxide_emit/src/capture/names.rs @@ -16,6 +16,7 @@ pub(crate) fn collect_var_binding_names(stmts: &[Statement]) -> HashSet names } +/// 递归遍历语句树收集 `var` 声明名(函数/程序级提升目标),含嵌套块与控制流各分支。 pub(crate) fn collect_var_names_stmt(stmts: &[Statement], out: &mut HashSet) { for stmt in stmts { match stmt { @@ -109,7 +110,8 @@ pub(crate) fn collect_top_level_function_names(stmts: &[Statement]) -> HashSet Vec { let mut names = Vec::new(); for stmt in stmts { @@ -132,6 +134,8 @@ pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement names } +/// 递归遍历语句树收集当前函数作用域声明的绑定名(变量/函数/类/import/export, +/// 含嵌套块,不进嵌套函数体)。 pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet) { for stmt in stmts { match stmt { diff --git a/crates/oxide_emit/src/capture/scanner.rs b/crates/oxide_emit/src/capture/scanner.rs index dd5700aa..4da26c85 100644 --- a/crates/oxide_emit/src/capture/scanner.rs +++ b/crates/oxide_emit/src/capture/scanner.rs @@ -9,6 +9,10 @@ use oxide_parser::{ClassBody, ClassElement, Expression, Statement}; use super::names::collect_own_binding_names; use super::{collect_fn_param_names, collect_for_left_decl_names}; +/// 以 `ref_set`(关注名集)× `shadow`(遮蔽名集)双集驱动,收集被任意深度嵌套 +/// 函数引用、且未被遮蔽的名字写入 `out`。本族带显式 `ref_set`/`shadow` 参数,按 +/// 过滤条件收集引用名;`captured.rs` 的 `collect_captured_*` 族则以本函数 own 绑定集 +/// 为过滤条件做捕获最终判定。 pub(crate) fn collect_capture_names_shadowed( stmts: &[Statement], ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, ) { @@ -17,6 +21,7 @@ pub(crate) fn collect_capture_names_shadowed( } } +/// 按语句类型递归扫描引用;进入嵌套函数/类/for 头/catch 时逐层扩充遮蔽集。 pub(crate) fn collect_capture_names_stmt( stmt: &Statement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, ) { @@ -448,6 +453,9 @@ pub(crate) fn collect_fn_default_names( } } +/// 按表达式类型递归扫描引用;进入嵌套函数体时以形参 + 体内声明扩充遮蔽集。与 +/// `captured.rs` 的 `collect_captured_expr` 相比,本函数带显式 `ref_set`/`shadow` +/// 收集引用名,不做捕获最终判定。 pub(crate) fn collect_capture_names_expr( expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, ) { @@ -577,6 +585,7 @@ pub(crate) fn collect_capture_names_expr( } } +/// 遍历可选链元素,扫描链上成员访问、调用与实参中的引用。 pub(crate) fn collect_capture_names_chain( element: &oxide_parser::ChainElement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet,