diff --git a/crates/oxide_emit/src/emit.rs b/crates/oxide_emit/src/emit.rs index 6495acef..3d11b951 100644 --- a/crates/oxide_emit/src/emit.rs +++ b/crates/oxide_emit/src/emit.rs @@ -6,10 +6,9 @@ use std::collections::HashSet; -use oxide_bytecode::module::UpvalueCapture; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; -use oxide_ir::operand::{LabelId, Operand}; +use oxide_ir::operand::Operand; use oxide_ir::IRFunction; /// 是否为匿名函数定义(剥括号):函数/箭头/class 表达式。 @@ -23,8 +22,7 @@ pub fn is_anonymous_function_definition(expr: &oxide_parser::Expression) -> bool } } -use crate::compile_ctx::{CompileCtx, FieldBuffer}; -use crate::symbol_table::{Binding, ScopeKind}; +use crate::compile_ctx::CompileCtx; /// 常量池项(bytecode module 类型)re-export,供调用方构造常量。 pub use oxide_bytecode::module::Constant; @@ -148,44 +146,6 @@ pub(crate) const BUILTIN_GLOBALS: &[&str] = &[ /// (writable:true),标识符写须双写全局属性(见 targets_writable_builtin)。 pub(crate) const NON_WRITABLE_GLOBAL_BUILTINS: &[&str] = &["undefined", "NaN", "Infinity"]; -/// 函数体编译上下文:决定 `this`/`super` 绑定与参数前导(prologue)形态。 -#[derive(Clone, Copy)] -pub enum FunctionBodyContext { - /// 普通函数:自身 `this`、独立作用域。 - Ordinary, - /// 箭头函数:词法捕获外层 `this`,不生成参数前导。 - Arrow, - /// 类元素方法:按类语义处理 `super` 与 home object。 - ClassElement, -} - -/// 参数规格:普通形参为标识符(可带默认值 initializer),解构形参用合成名 + 原始 pattern, -/// rest 形参为数组(无默认值,只能是最末形参)。 -pub enum ParamSpec<'a> { - Identifier { - name: String, - initializer: Option<&'a Expression<'a>>, - }, - Pattern { - synthetic_name: String, - pattern: &'a oxide_parser::BindingPattern<'a>, - initializer: Option<&'a Expression<'a>>, - }, - Rest { - name: String, - }, -} - -impl ParamSpec<'_> { - pub(crate) fn register_name(&self) -> &str { - match self { - Self::Identifier { name, .. } => name, - Self::Pattern { synthetic_name, .. } => synthetic_name, - Self::Rest { name } => name, - } - } -} - impl Emitter { /// 构造空 `Emitter`(静态编译口径:源文本为良形 UTF-8,无注入 marker)。 pub fn new() -> Self { @@ -199,655 +159,6 @@ impl Emitter { self } - /// 遍历解构 pattern 收集内嵌默认值表达式(AssignmentPattern.right)与 - /// 计算键表达式(`{[k]: a}` 的键,运行时求值)——二者都会在参数绑定期被 - /// 内部闭包引用,须一并纳入捕获分析。 - fn collect_pattern_default_exprs<'a>( - &self, pattern: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec<&'a oxide_parser::Expression<'a>>, - ) { - use oxide_parser::BindingPattern; - match pattern { - BindingPattern::AssignmentPattern(ap) => { - out.push(&ap.right); - self.collect_pattern_default_exprs(&ap.left, out); - } - BindingPattern::ArrayPattern(ap) => { - for p in ap.elements.iter().flatten() { - self.collect_pattern_default_exprs(p, out); - } - if let Some(rest) = &ap.rest { - self.collect_pattern_default_exprs(&rest.argument, out); - } - } - BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - if prop.computed { - out.push(prop.key.to_expression()); - } - self.collect_pattern_default_exprs(&prop.value, out); - } - if let Some(rest) = &op.rest { - self.collect_pattern_default_exprs(&rest.argument, out); - } - } - _ => {} - } - } - - // ── 闭包捕获分析(AST 级,时序无关)── - - /// 把 rest 形参的绑定模式追加为 `ParamSpec::Rest`:仅支持标识符形态(解构 rest 未支持)。 - pub(crate) fn push_rest_param<'a>( - &self, argument: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec>, - ) -> Result<(), String> { - match argument { - oxide_parser::BindingPattern::BindingIdentifier(bi) => { - out.push(ParamSpec::Rest { name: bi.name.to_string() }); - } - _ => return Err("rest parameters with destructuring patterns not yet supported".into()), - } - Ok(()) - } - - /// 收集函数参数的绑定名(BindingIdentifier 形态)。 - pub(crate) fn extract_function_parts<'a>( - &self, function: &'a oxide_parser::Function<'a>, - ) -> Result<(Vec>, &'a [Statement<'a>]), String> { - let mut param_specs = Vec::new(); - for (idx, param) in function.params.items.iter().enumerate() { - match ¶m.pattern { - oxide_parser::BindingPattern::BindingIdentifier(bi) => { - param_specs.push(ParamSpec::Identifier { - name: bi.name.to_string(), - initializer: param.initializer.as_deref(), - }); - } - pattern => { - param_specs.push(ParamSpec::Pattern { - synthetic_name: format!("@@param_{idx}"), - pattern, - initializer: param.initializer.as_deref(), - }); - } - } - } - if let Some(rest) = &function.params.rest { - self.push_rest_param(&rest.rest.argument, &mut param_specs)?; - } - let body_stmts: &[Statement] = if let Some(body) = &function.body { &body.statements } else { &[] }; - Ok((param_specs, body_stmts)) - } - - /// 编译函数体(函数声明/函数表达式/箭头函数共用),单 pass 完成发码。 - /// - /// `is_expression_body` 为 true(箭头表达式体)时返回最后一个表达式的值, - /// 否则返回 undefined。`is_arrow` 控制 super 相关标志的继承:箭头函数词法 - /// 继承外层 super,普通函数重置 super 作用域。 - pub(crate) fn compile_function_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, own_strict: bool, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - is_arrow, - false, - false, - own_strict, - ) - } - - /// 编译函数体并显式指定生成器标志(`function*` 走此入口)。 - pub(crate) fn compile_generator_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - false, - false, - true, - false, - own_strict, - ) - } - - /// 编译异步生成器函数体(`async function*` / async 生成器表达式走此入口): - /// 同时标记 `is_generator` 与 `is_async`,VM 调用时按异步生成器协议执行 - /// (next 返回 Promise,yield 挂起与 await 挂起共存)。 - pub(crate) fn compile_async_generator_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, - ) -> Result { - self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, true, own_strict) - } - - /// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使 - /// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。 - pub(crate) fn compile_async_body<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, own_strict: bool, - ) -> Result { - self.compile_function_body_with_flags( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - is_arrow, - false, - true, - own_strict, - ) - } - - #[allow(clippy::too_many_arguments)] - fn compile_function_body_with_flags<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool, own_strict: bool, - ) -> Result { - let body_context = if is_arrow { - FunctionBodyContext::Arrow - } else { - FunctionBodyContext::Ordinary - }; - self.compile_function_body_with_bindings_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - &[], - body_context, - is_generator, - is_async, - own_strict, - ) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_bindings_gen<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - is_generator: bool, is_async: bool, own_strict: bool, - ) -> Result { - self.compile_function_body_with_field_hooks_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - extra_bindings, - body_context, - None:: Result<(), String>>, - false, - &[], - &[], - is_generator, - is_async, - own_strict, - ) - } - - /// 预注册 builtin 引用并编译函数体(普通/箭头/类元素方法共用入口)。 - /// - /// 本函数体内任意位置(表达式、成员对象、调用实参、类字段等)引用的内置全局 - /// 标识符,其寄存器槽都先于任何临时寄存器登记。 - /// - /// vreg 化后临时值不复用(独立 vreg),但 builtin 槽预注册仍保证分配序稳定: - /// builtin 槽先于临时值池,嵌套函数继承边界不受扰。 - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_field_hooks<'a, E>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], - extra_upvalue_names: &[(&str, u8)], own_strict: bool, - ) -> Result - where - E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, - { - self.compile_function_body_with_field_hooks_gen( - param_specs, - body_stmts, - parent_ctx, - is_expression_body, - extra_bindings, - body_context, - emit_fields, - fields_after_super, - extra_capture_exprs, - extra_upvalue_names, - false, - false, - own_strict, - ) - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn compile_function_body_with_field_hooks_gen<'a, E>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, - mut emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], - extra_upvalue_names: &[(&str, u8)], is_generator: bool, is_async: bool, own_strict: bool, - ) -> Result - where - E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, - { - let mut ctx = CompileCtx::new(); - ctx.is_generator = is_generator; - ctx.is_async = is_async; - // 函数 strict = 自身 directive ‖ 外层严格(规范不可解除); - // 类元素方法/构造器恒 strict(ClassBody 是严格模式代码)。 - ctx.is_strict = own_strict || matches!(body_context, FunctionBodyContext::ClassElement) || parent_ctx.is_strict; - - // 形参名集(含解构叶子与 rest):块级函数名同名的 web-compat 守卫查此集。 - let mut param_names = HashSet::new(); - for spec in param_specs { - param_names.insert(spec.register_name().to_string()); - if let ParamSpec::Pattern { pattern, .. } = spec { - self.collect_binding_pattern_names(pattern, &mut param_names); - } - } - ctx.param_names = param_names; - - // length = 第一个带默认值形参之前的形参数(解构默认与标识符默认同规则); - // rest 参数不计入 length(以 0 结尾即止)。 - ctx.function_length = param_specs - .iter() - .take_while(|spec| match spec { - ParamSpec::Identifier { initializer, .. } => initializer.is_none(), - ParamSpec::Pattern { initializer, .. } => initializer.is_none(), - ParamSpec::Rest { .. } => false, - }) - .count() as u32; - - // 继承父内置寄存器映射:子模块寄存器文件中,内置标识符(Math、Object 等) - // 解析到父预先分配的槽位。 - ctx.scopes.builtin_reg_map = parent_ctx.scopes.builtin_reg_map.clone(); - ctx.scopes.private_name_map = parent_ctx.scopes.private_name_map.clone(); - ctx.scopes.private_element_kinds = parent_ctx.scopes.private_element_kinds.clone(); - ctx.scopes.private_brand_id = parent_ctx.scopes.private_brand_id; - ctx.scopes.next_private_name_id = parent_ctx.scopes.next_private_name_id; - // 标签模板 site 序号继承:整棵编译树全局唯一(跨嵌套函数递增), - // 运行时以 (flat_id, site_no) 缓存模板对象,跨函数不冲突。 - ctx.next_template_site = parent_ctx.next_template_site; - - // 传递 enclosing_this_reg:嵌套箭头函数捕获正确的 `this`。 - ctx.enclosing_this_reg = parent_ctx.enclosing_this_reg; - // 编码源口径是整棵编译树属性(嵌套函数仍在同一编码源内)。 - ctx.source_encoded = parent_ctx.source_encoded; - - // 箭头函数词法继承 super;类方法体顶层编译也需要类提供的 super 上下文。 - if matches!(body_context, FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement) { - ctx.in_derived_constructor = parent_ctx.in_derived_constructor; - ctx.in_instance_method = parent_ctx.in_instance_method; - ctx.in_static_method = parent_ctx.in_static_method; - } else { - ctx.in_derived_constructor = false; - ctx.in_instance_method = false; - ctx.in_static_method = false; - } - - // 继承父全局作用域条目:先前声明的函数名在函数体内可见。 - let mut inherited_reg_start = 1u32.max(ctx.builtin_reg_floor()); - for (name, binding) in &parent_ctx.scopes.symbols.scopes[0].bindings { - ctx.scopes.symbols.scopes[0].bindings.insert( - name.clone(), - Binding { - reg: binding.reg, - initialized: binding.initialized, - is_const: binding.is_const, - predeclared: false, - }, - ); - inherited_reg_start = inherited_reg_start.max(binding.reg.saturating_add(1)); - } - // 隐式全局登记集合随继承绑定传入:父层未声明名已登记全局作用域,子层解析 - // 命中继承绑定时须同样补全局对象属性写(或严格模式抛错)。读写两侧登记 - // 一并继承——读侧登记的全局槽与写侧同属一个槽,写判定跨嵌套函数一致。 - ctx.implicit_global_writes = parent_ctx.implicit_global_writes.clone(); - ctx.implicit_global_reads = parent_ctx.implicit_global_reads.clone(); - // 顶层已声明 var 名集随作用域继承:嵌套函数裸读/写顶层 var 直连全局对象 - // (经继承的 scope-0 绑定 + 作用域索引判定,不被局部同名遮蔽误判)。 - ctx.global_tier_names = parent_ctx.global_tier_names.clone(); - for (name, reg) in extra_bindings { - ctx.scopes.symbols.scopes[0].bindings.insert( - (*name).to_string(), - Binding { - reg: *reg, - initialized: true, - is_const: true, - predeclared: false, - }, - ); - inherited_reg_start = inherited_reg_start.max(reg.saturating_add(1)); - } - ctx.reserved_reg_start = inherited_reg_start.max(1); - - // 让 next_reg 与 builtin 槽位对齐,参数在 builtin 槽之后分配。 - ctx.reset_regs(); - - let param_base = self.emit_params_prologue( - param_specs, - body_stmts, - parent_ctx, - &mut ctx, - body_context, - extra_capture_exprs, - extra_upvalue_names, - )?; - // 实例字段 computed key 数组所在 upvalue 下标,供字段初始化 emit 定位。 - ctx.field_keys_uv = ctx - .current_upvalue_captures - .iter() - .position(|u| u.name == "@@field_keys") - .map(|i| i as u8); - - self.predeclare_function_declarations(body_stmts, &mut ctx); - - // 预注册 builtin 引用(先于任何临时寄存器),builtin 槽不与被复用的临时值冲突。 - self.pre_register_builtin_references(body_stmts, &mut ctx); - - // 预声明 `var` 名,使首个 sub-pass 中提升的函数声明能解析其闭包引用的外层 var。 - self.predeclare_var_declarations(body_stmts, &mut ctx); - - // 预声明 body 级 `let`/`const`/`class`(未初始化 TDZ 占位), - // 使声明点前读取可编译为运行时 ReferenceError。函数体 lexical 声明是 - // 局部绑定,不做受限全局名检查;重复声明错在 emit 期报。 - let _ = self.predeclare_lexical_declarations(body_stmts, &mut ctx, false); - - // 块级函数名 web-compat 外层 var 绑定(sloppy):块内函数声明名在实例化 - // 期于函数作用域建外层 var 绑定——无同名绑定则新建 var 槽;名在抑制集 - // (形参/词法声明同名,该形退化为纯块作用域)则不建。求值期声明点把 - // 函数对象写回此绑定(见函数声明 emit)。 - if !ctx.is_strict { - ctx.block_fn_suppressed = self.collect_block_fn_suppressed_names(body_stmts, &ctx.param_names); - for name in self.collect_block_function_names(body_stmts) { - if !ctx.block_fn_suppressed.contains(&name) { - self.predeclare_var_name(&name, &mut ctx); - } - } - } - - // 生成器:body 起点标记——调用时参数初始化(emit_params_prologue)结束后挂起于此, - // 参数副作用/异常在 `g()` 调用时刻生效,首次 next() 从这继续执行 body。 - if is_generator { - ctx.inst(Inst::suspend_body()); - } - - if let Some(emit) = emit_fields.as_mut() { - if fields_after_super { - let mut parent_insts = Vec::new(); - let mut parent_label_pos = Vec::new(); - std::mem::swap(&mut ctx.insts, &mut parent_insts); - std::mem::swap(&mut ctx.labels.label_pos, &mut parent_label_pos); - emit(self, &mut ctx)?; - let field_buffer = FieldBuffer { - insts: std::mem::take(&mut ctx.insts), - labels: std::mem::take(&mut ctx.labels.label_pos) - .into_iter() - .enumerate() - .filter_map(|(id, pos)| pos.map(|p| (id as LabelId, p))) - .collect(), - }; - ctx.insts = parent_insts; - ctx.labels.label_pos = parent_label_pos; - ctx.field_buffer = Some(field_buffer); - } else { - emit(self, &mut ctx)?; - } - } - - // 发 body 语句(先函数声明 hoisting,再其余)。 - let last_result_reg = self.emit_body_stmts(body_stmts, &mut ctx)?; - - // 隐式 RETURN:表达式体返回最后表达式,语句体返回 undefined。 - // 函数尾词法上不在任何循环内,迭代器逃出计数恒 0。 - if is_expression_body { - if let Some(reg) = last_result_reg { - ctx.inst(Inst::ret(Operand::Reg(reg), 0, 0)); - } else { - let undef_idx = ctx.add_constant(Constant::Undefined); - let undef_reg = ctx.alloc_reg(); - ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx)); - ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0)); - } - } else { - let undef_idx = ctx.add_constant(Constant::Undefined); - let undef_reg = ctx.alloc_reg(); - ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx)); - ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0)); - } - - // 调用契约参数段只含固定形参:rest 是函数体内普通变量,不在 VM 实参传递区。 - let fixed_count = param_specs - .iter() - .filter(|spec| !matches!(spec, ParamSpec::Rest { .. })) - .count() as u32; - let ir = ctx.assemble_ir( - oxide_ir::ParamLayout { - base: param_base, - count: fixed_count, - }, - Some(parent_ctx), - ); - Ok(ir) - } - - /// 参数 prologue:函数作用域 + 参数声明/解构 + 闭包捕获与 upvalue 分析。返回 param_base。 - #[allow(clippy::too_many_arguments)] - fn emit_params_prologue<'a>( - &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, - ctx: &mut CompileCtx, body_context: FunctionBodyContext, extra_capture_exprs: &[&'a Expression<'a>], - extra_upvalue_names: &[(&str, u8)], - ) -> Result { - ctx.push_scope_with_kind(ScopeKind::FunctionScope); - let param_base = ctx.next_reg; - - // 发参数声明(分配寄存器;分析用 register_name 引用)。 - for spec in param_specs { - let name = spec.register_name(); - let reg = ctx.alloc_reg(); - ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false)?; - } - - // 闭包捕获分析(AST 级,emit 前确定):须在参数默认值 emit 之前, - // 否则默认值内嵌套函数(IIFE)编译时父分析为空 → upvalue 捕获丢失。 - let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect(); - let mut param_defaults: Vec<&oxide_parser::Expression> = Vec::new(); - for spec in param_specs { - match spec { - ParamSpec::Identifier { initializer, .. } => { - if let Some(init) = initializer { - param_defaults.push(init); - } - } - ParamSpec::Pattern { pattern, initializer, .. } => { - if let Some(init) = initializer { - param_defaults.push(init); - } - // 模式内嵌默认值(`[x = expr]` 的 AssignmentPattern.right)也会被 - // 内部闭包引用,需纳入捕获分析。 - self.collect_pattern_default_exprs(pattern, &mut param_defaults); - } - ParamSpec::Rest { .. } => {} - } - } - ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); - for spec in param_specs { - if let ParamSpec::Pattern { pattern, .. } = spec { - self.collect_binding_pattern_names(pattern, &mut ctx.own_bindings); - } - } - - // 自动声明 arguments 绑定(非箭头函数,且用户未显式声明同名标识符)。 - // 先登记符号并纳入 own_bindings,使嵌套箭头引用 arguments 被识别为本函数 - // 绑定(否则被当自由变量 → 子模块 upvalue 解析错位)。 - let mut arguments_reg = None; - if !matches!(body_context, FunctionBodyContext::Arrow) && !ctx.own_bindings.contains("arguments") { - let reg = ctx.alloc_reg(); - ctx.declare_initialized("arguments", reg, VariableDeclarationKind::Var, false)?; - ctx.own_bindings.insert("arguments".to_string()); - arguments_reg = Some(reg); - } - - // 字段初始化表达式(值表达式)与参数默认值一并纳入捕获分析。 - let mut capture_exprs: Vec<&oxide_parser::Expression> = param_defaults.clone(); - capture_exprs.extend_from_slice(extra_capture_exprs); - ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings); - // 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。 - if matches!( - body_context, - FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement - ) { - ctx.current_upvalue_captures = self.collect_upvalue_names( - body_stmts, - &capture_exprs, - &parent_ctx.captured_bindings, - &parent_ctx.current_upvalue_captures, - &ctx.own_bindings, - ); - // 捕获 const 信息快照:父作用域符号表此时完整(预声明已完成), - // 直接查绑定 is_const(不依赖初始化状态,TDZ 中 const 也须拦截)。 - ctx.upvalue_const_flags = ctx - .current_upvalue_captures - .iter() - .filter(|u| u.parent_uv_idx.is_none()) - .filter(|u| { - parent_ctx - .scopes - .symbols - .lookup_any_binding(u.name.as_str()) - .map(|(b, _)| b.is_const) - .unwrap_or(false) - }) - .map(|u| u.name.clone()) - .collect(); - // 类字段 computed key 数组等合成捕获:直接追加 upvalue(cell_idx 由父分配)。 - for (name, cell_idx) in extra_upvalue_names { - if !ctx.own_bindings.contains(*name) && !ctx.current_upvalue_captures.iter().any(|u| u.name == *name) { - ctx.current_upvalue_captures.push(UpvalueCapture { - name: (*name).to_string(), - enclosing_reg: 0, - cell_idx: *cell_idx, - parent_uv_idx: None, - }); - } - } - } - - // 创建 arguments 对象:指令须在默认参数求值前发出(默认参数可引用 arguments)。 - if let Some(reg) = arguments_reg { - ctx.inst(Inst::create_arguments(Operand::Reg(reg))); - } - - for spec in param_specs { - match spec { - ParamSpec::Pattern { - synthetic_name, - pattern, - initializer, - } => { - let src_reg = ctx.lookup(synthetic_name)?; - let src_reg = if let Some(init) = initializer { - self.emit_default_if_undefined(src_reg, init, Some(synthetic_name), ctx)? - } else { - src_reg - }; - self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, false, ctx)?; - } - ParamSpec::Identifier { name, initializer } => { - if let Some(init) = initializer { - // 默认参数:实参为 undefined 时用默认值。 - let reg = ctx.lookup(name)?; - self.emit_default_if_undefined(reg, init, Some(name), ctx)?; - } - } - ParamSpec::Rest { name } => { - // rest 数组:从实参区收集固定形参之后的实参,绑定为普通变量。 - let reg = ctx.lookup(name)?; - let fixed_count = - param_specs.iter().filter(|s| !matches!(s, ParamSpec::Rest { .. })).count() as u32; - ctx.inst(Inst::create_rest_array(Operand::Reg(reg), fixed_count)); - } - } - } - - // 被捕获的参数也必须建 cell(MAKE_CELL):否则子函数经 lazy upvalue 路径读 - // 自身寄存器(依赖调用者寄存器残留),vreg 化/RegAlloc 移动寄存器后读到垃圾。 - // 与 var/let/const 的 MAKE_CELL 语义一致(binding.rs:50)。须在默认值之后 - // (默认值 emit 会读参数寄存器)。 - for spec in param_specs { - let name = spec.register_name(); - if let Some(&cell_idx) = ctx.captured_bindings.get(name) { - let reg = ctx.lookup(name)?; - ctx.inst(Inst::new( - OpCode::MAKE_CELL, - Operand::Reg(reg), - Operand::Imm(cell_idx as u16), - Operand::None, - )); - } - } - - // 被捕获的 arguments 绑定同样建 cell(与参数一致,须在默认值之后)。 - if let (Some(reg), Some(&cell_idx)) = (arguments_reg, ctx.captured_bindings.get("arguments")) { - ctx.inst(Inst::new( - OpCode::MAKE_CELL, - Operand::Reg(reg), - Operand::Imm(cell_idx as u16), - Operand::None, - )); - } - - // var 绑定函数入口实例化:被捕获的 var 名统一 MAKE_CELL(undefined)。 - // 规范上 var 在函数入口即初始化为 undefined(HoistDeclaration),声明语句 - // 只是赋值;否则声明语句前创建的闭包读取占位 cell → TDZ 误报。参数与 - // arguments 已在上方初始化(跳过以免覆盖参数值);let/const/class 保持 - // TDZ 语义不动。声明语句的 MAKE_CELL 按占位更新语义覆盖此初值。 - let var_names: Vec = self - .collect_var_binding_names(body_stmts) - .into_iter() - .filter(|n| !param_names.contains(&n.as_str()) && n != "arguments") - .filter(|n| ctx.captured_bindings.contains_key(n)) - .collect(); - if !var_names.is_empty() { - let undef_reg = self.emit_undefined(ctx); - for name in var_names { - if let Some(&cell_idx) = ctx.captured_bindings.get(&name) { - ctx.inst(Inst::new( - OpCode::MAKE_CELL, - Operand::Reg(undef_reg), - Operand::Imm(cell_idx as u16), - Operand::None, - )); - } - } - } - - Ok(param_base) - } - - /// 双 sub-pass emit body:先函数声明(hoisting),再其余语句。返回最后结果寄存器。 - fn emit_body_stmts(&self, body_stmts: &[Statement], ctx: &mut CompileCtx) -> Result, String> { - let mut last_result_reg = None; - for stmt in body_stmts { - if matches!(stmt, Statement::FunctionDeclaration(_)) { - if let Some(reg) = self.emit_statement(stmt, ctx)? { - last_result_reg = Some(reg); - } - } - } - for stmt in body_stmts { - if matches!(stmt, Statement::FunctionDeclaration(_)) { - continue; - } - if let Some(reg) = self.emit_statement(stmt, ctx)? { - last_result_reg = Some(reg); - } - } - Ok(last_result_reg) - } - pub(crate) fn emit_statement(&self, stmt: &Statement, ctx: &mut CompileCtx) -> Result, String> { match stmt { Statement::ExpressionStatement(_) | Statement::ReturnStatement(_) | Statement::EmptyStatement(_) => { diff --git a/crates/oxide_emit/src/function_body.rs b/crates/oxide_emit/src/function_body.rs new file mode 100644 index 00000000..490538cd --- /dev/null +++ b/crates/oxide_emit/src/function_body.rs @@ -0,0 +1,705 @@ +//! 函数体编译域:`FunctionBodyContext` / `ParamSpec` 类型与函数体编译链 +//! (参数 prologue、参数默认值与闭包捕获分析、双 sub-pass 语句发射)。 +//! +//! 两类型经 lib.rs 重导出供各语法域构造实参;编译链为 `Emitter` 方法, +//! 捕获分析经 `self.*` 调用 closure 族,与所在文件无关。 + +use std::collections::HashSet; + +use oxide_bytecode::module::{Constant, UpvalueCapture}; +use oxide_bytecode::opcode::OpCode; +use oxide_ir::inst::Inst; +use oxide_ir::operand::{LabelId, Operand}; +use oxide_ir::IRFunction; +use oxide_parser::{Expression, Statement, VariableDeclarationKind}; + +use crate::compile_ctx::{CompileCtx, FieldBuffer}; +use crate::symbol_table::{Binding, ScopeKind}; +use crate::Emitter; + +/// 函数体编译上下文:决定 `this`/`super` 绑定与参数前导(prologue)形态。 +#[derive(Clone, Copy)] +pub enum FunctionBodyContext { + /// 普通函数:自身 `this`、独立作用域。 + Ordinary, + /// 箭头函数:词法捕获外层 `this`,不生成参数前导。 + Arrow, + /// 类元素方法:按类语义处理 `super` 与 home object。 + ClassElement, +} + +/// 参数规格:普通形参为标识符(可带默认值 initializer),解构形参用合成名 + 原始 pattern, +/// rest 形参为数组(无默认值,只能是最末形参)。 +pub enum ParamSpec<'a> { + Identifier { + name: String, + initializer: Option<&'a Expression<'a>>, + }, + Pattern { + synthetic_name: String, + pattern: &'a oxide_parser::BindingPattern<'a>, + initializer: Option<&'a Expression<'a>>, + }, + Rest { + name: String, + }, +} + +impl ParamSpec<'_> { + pub(crate) fn register_name(&self) -> &str { + match self { + Self::Identifier { name, .. } => name, + Self::Pattern { synthetic_name, .. } => synthetic_name, + Self::Rest { name } => name, + } + } +} + +impl Emitter { + /// 遍历解构 pattern 收集内嵌默认值表达式(AssignmentPattern.right)与 + /// 计算键表达式(`{[k]: a}` 的键,运行时求值)——二者都会在参数绑定期被 + /// 内部闭包引用,须一并纳入捕获分析。 + fn collect_pattern_default_exprs<'a>( + &self, pattern: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec<&'a oxide_parser::Expression<'a>>, + ) { + use oxide_parser::BindingPattern; + match pattern { + BindingPattern::AssignmentPattern(ap) => { + out.push(&ap.right); + self.collect_pattern_default_exprs(&ap.left, out); + } + BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + self.collect_pattern_default_exprs(p, out); + } + if let Some(rest) = &ap.rest { + self.collect_pattern_default_exprs(&rest.argument, out); + } + } + BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + if prop.computed { + out.push(prop.key.to_expression()); + } + self.collect_pattern_default_exprs(&prop.value, out); + } + if let Some(rest) = &op.rest { + self.collect_pattern_default_exprs(&rest.argument, out); + } + } + _ => {} + } + } + + /// 把 rest 形参的绑定模式追加为 `ParamSpec::Rest`:仅支持标识符形态(解构 rest 未支持)。 + pub(crate) fn push_rest_param<'a>( + &self, argument: &'a oxide_parser::BindingPattern<'a>, out: &mut Vec>, + ) -> Result<(), String> { + match argument { + oxide_parser::BindingPattern::BindingIdentifier(bi) => { + out.push(ParamSpec::Rest { name: bi.name.to_string() }); + } + _ => return Err("rest parameters with destructuring patterns not yet supported".into()), + } + Ok(()) + } + + /// 收集函数参数的绑定名(BindingIdentifier 形态)。 + pub(crate) fn extract_function_parts<'a>( + &self, function: &'a oxide_parser::Function<'a>, + ) -> Result<(Vec>, &'a [Statement<'a>]), String> { + let mut param_specs = Vec::new(); + for (idx, param) in function.params.items.iter().enumerate() { + match ¶m.pattern { + oxide_parser::BindingPattern::BindingIdentifier(bi) => { + param_specs.push(ParamSpec::Identifier { + name: bi.name.to_string(), + initializer: param.initializer.as_deref(), + }); + } + pattern => { + param_specs.push(ParamSpec::Pattern { + synthetic_name: format!("@@param_{idx}"), + pattern, + initializer: param.initializer.as_deref(), + }); + } + } + } + if let Some(rest) = &function.params.rest { + self.push_rest_param(&rest.rest.argument, &mut param_specs)?; + } + let body_stmts: &[Statement] = if let Some(body) = &function.body { &body.statements } else { &[] }; + Ok((param_specs, body_stmts)) + } + + /// 编译函数体(函数声明/函数表达式/箭头函数共用),单 pass 完成发码。 + /// + /// `is_expression_body` 为 true(箭头表达式体)时返回最后一个表达式的值, + /// 否则返回 undefined。`is_arrow` 控制 super 相关标志的继承:箭头函数词法 + /// 继承外层 super,普通函数重置 super 作用域。 + pub(crate) fn compile_function_body<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, is_arrow: bool, own_strict: bool, + ) -> Result { + self.compile_function_body_with_flags( + param_specs, + body_stmts, + parent_ctx, + is_expression_body, + is_arrow, + false, + false, + own_strict, + ) + } + + /// 编译函数体并显式指定生成器标志(`function*` 走此入口)。 + pub(crate) fn compile_generator_body<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, + ) -> Result { + self.compile_function_body_with_flags( + param_specs, + body_stmts, + parent_ctx, + false, + false, + true, + false, + own_strict, + ) + } + + /// 编译异步生成器函数体(`async function*` / async 生成器表达式走此入口): + /// 同时标记 `is_generator` 与 `is_async`,VM 调用时按异步生成器协议执行 + /// (next 返回 Promise,yield 挂起与 await 挂起共存)。 + pub(crate) fn compile_async_generator_body<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, own_strict: bool, + ) -> Result { + self.compile_function_body_with_flags(param_specs, body_stmts, parent_ctx, false, false, true, true, own_strict) + } + + /// 编译异步函数体(`async function` / async 箭头走此入口):`is_async` 使 + /// `assemble_ir` 标记模块,VM 调用时按异步函数协议执行。 + pub(crate) fn compile_async_body<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, is_arrow: bool, own_strict: bool, + ) -> Result { + self.compile_function_body_with_flags( + param_specs, + body_stmts, + parent_ctx, + is_expression_body, + is_arrow, + false, + true, + own_strict, + ) + } + + #[allow(clippy::too_many_arguments)] + fn compile_function_body_with_flags<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, is_arrow: bool, is_generator: bool, is_async: bool, own_strict: bool, + ) -> Result { + let body_context = if is_arrow { + FunctionBodyContext::Arrow + } else { + FunctionBodyContext::Ordinary + }; + self.compile_function_body_with_bindings_gen( + param_specs, + body_stmts, + parent_ctx, + is_expression_body, + &[], + body_context, + is_generator, + is_async, + own_strict, + ) + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn compile_function_body_with_bindings_gen<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, + is_generator: bool, is_async: bool, own_strict: bool, + ) -> Result { + self.compile_function_body_with_field_hooks_gen( + param_specs, + body_stmts, + parent_ctx, + is_expression_body, + extra_bindings, + body_context, + None:: Result<(), String>>, + false, + &[], + &[], + is_generator, + is_async, + own_strict, + ) + } + + /// 预注册 builtin 引用并编译函数体(普通/箭头/类元素方法共用入口)。 + /// + /// 本函数体内任意位置(表达式、成员对象、调用实参、类字段等)引用的内置全局 + /// 标识符,其寄存器槽都先于任何临时寄存器登记。 + /// + /// vreg 化后临时值不复用(独立 vreg),但 builtin 槽预注册仍保证分配序稳定: + /// builtin 槽先于临时值池,嵌套函数继承边界不受扰。 + #[allow(clippy::too_many_arguments)] + pub(crate) fn compile_function_body_with_field_hooks<'a, E>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, + emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], + extra_upvalue_names: &[(&str, u8)], own_strict: bool, + ) -> Result + where + E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, + { + self.compile_function_body_with_field_hooks_gen( + param_specs, + body_stmts, + parent_ctx, + is_expression_body, + extra_bindings, + body_context, + emit_fields, + fields_after_super, + extra_capture_exprs, + extra_upvalue_names, + false, + false, + own_strict, + ) + } + + #[allow(clippy::too_many_arguments)] + pub(crate) fn compile_function_body_with_field_hooks_gen<'a, E>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + is_expression_body: bool, extra_bindings: &[(&str, u32)], body_context: FunctionBodyContext, + mut emit_fields: Option, fields_after_super: bool, extra_capture_exprs: &[&'a Expression<'a>], + extra_upvalue_names: &[(&str, u8)], is_generator: bool, is_async: bool, own_strict: bool, + ) -> Result + where + E: FnMut(&Emitter, &mut CompileCtx) -> Result<(), String>, + { + let mut ctx = CompileCtx::new(); + ctx.is_generator = is_generator; + ctx.is_async = is_async; + // 函数 strict = 自身 directive ‖ 外层严格(规范不可解除); + // 类元素方法/构造器恒 strict(ClassBody 是严格模式代码)。 + ctx.is_strict = own_strict || matches!(body_context, FunctionBodyContext::ClassElement) || parent_ctx.is_strict; + + // 形参名集(含解构叶子与 rest):块级函数名同名的 web-compat 守卫查此集。 + let mut param_names = HashSet::new(); + for spec in param_specs { + param_names.insert(spec.register_name().to_string()); + if let ParamSpec::Pattern { pattern, .. } = spec { + self.collect_binding_pattern_names(pattern, &mut param_names); + } + } + ctx.param_names = param_names; + + // length = 第一个带默认值形参之前的形参数(解构默认与标识符默认同规则); + // rest 参数不计入 length(以 0 结尾即止)。 + ctx.function_length = param_specs + .iter() + .take_while(|spec| match spec { + ParamSpec::Identifier { initializer, .. } => initializer.is_none(), + ParamSpec::Pattern { initializer, .. } => initializer.is_none(), + ParamSpec::Rest { .. } => false, + }) + .count() as u32; + + // 继承父内置寄存器映射:子模块寄存器文件中,内置标识符(Math、Object 等) + // 解析到父预先分配的槽位。 + ctx.scopes.builtin_reg_map = parent_ctx.scopes.builtin_reg_map.clone(); + ctx.scopes.private_name_map = parent_ctx.scopes.private_name_map.clone(); + ctx.scopes.private_element_kinds = parent_ctx.scopes.private_element_kinds.clone(); + ctx.scopes.private_brand_id = parent_ctx.scopes.private_brand_id; + ctx.scopes.next_private_name_id = parent_ctx.scopes.next_private_name_id; + // 标签模板 site 序号继承:整棵编译树全局唯一(跨嵌套函数递增), + // 运行时以 (flat_id, site_no) 缓存模板对象,跨函数不冲突。 + ctx.next_template_site = parent_ctx.next_template_site; + + // 传递 enclosing_this_reg:嵌套箭头函数捕获正确的 `this`。 + ctx.enclosing_this_reg = parent_ctx.enclosing_this_reg; + // 编码源口径是整棵编译树属性(嵌套函数仍在同一编码源内)。 + ctx.source_encoded = parent_ctx.source_encoded; + + // 箭头函数词法继承 super;类方法体顶层编译也需要类提供的 super 上下文。 + if matches!(body_context, FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement) { + ctx.in_derived_constructor = parent_ctx.in_derived_constructor; + ctx.in_instance_method = parent_ctx.in_instance_method; + ctx.in_static_method = parent_ctx.in_static_method; + } else { + ctx.in_derived_constructor = false; + ctx.in_instance_method = false; + ctx.in_static_method = false; + } + + // 继承父全局作用域条目:先前声明的函数名在函数体内可见。 + let mut inherited_reg_start = 1u32.max(ctx.builtin_reg_floor()); + for (name, binding) in &parent_ctx.scopes.symbols.scopes[0].bindings { + ctx.scopes.symbols.scopes[0].bindings.insert( + name.clone(), + Binding { + reg: binding.reg, + initialized: binding.initialized, + is_const: binding.is_const, + predeclared: false, + }, + ); + inherited_reg_start = inherited_reg_start.max(binding.reg.saturating_add(1)); + } + // 隐式全局登记集合随继承绑定传入:父层未声明名已登记全局作用域,子层解析 + // 命中继承绑定时须同样补全局对象属性写(或严格模式抛错)。读写两侧登记 + // 一并继承——读侧登记的全局槽与写侧同属一个槽,写判定跨嵌套函数一致。 + ctx.implicit_global_writes = parent_ctx.implicit_global_writes.clone(); + ctx.implicit_global_reads = parent_ctx.implicit_global_reads.clone(); + // 顶层已声明 var 名集随作用域继承:嵌套函数裸读/写顶层 var 直连全局对象 + // (经继承的 scope-0 绑定 + 作用域索引判定,不被局部同名遮蔽误判)。 + ctx.global_tier_names = parent_ctx.global_tier_names.clone(); + for (name, reg) in extra_bindings { + ctx.scopes.symbols.scopes[0].bindings.insert( + (*name).to_string(), + Binding { + reg: *reg, + initialized: true, + is_const: true, + predeclared: false, + }, + ); + inherited_reg_start = inherited_reg_start.max(reg.saturating_add(1)); + } + ctx.reserved_reg_start = inherited_reg_start.max(1); + + // 让 next_reg 与 builtin 槽位对齐,参数在 builtin 槽之后分配。 + ctx.reset_regs(); + + let param_base = self.emit_params_prologue( + param_specs, + body_stmts, + parent_ctx, + &mut ctx, + body_context, + extra_capture_exprs, + extra_upvalue_names, + )?; + // 实例字段 computed key 数组所在 upvalue 下标,供字段初始化 emit 定位。 + ctx.field_keys_uv = ctx + .current_upvalue_captures + .iter() + .position(|u| u.name == "@@field_keys") + .map(|i| i as u8); + + self.predeclare_function_declarations(body_stmts, &mut ctx); + + // 预注册 builtin 引用(先于任何临时寄存器),builtin 槽不与被复用的临时值冲突。 + self.pre_register_builtin_references(body_stmts, &mut ctx); + + // 预声明 `var` 名,使首个 sub-pass 中提升的函数声明能解析其闭包引用的外层 var。 + self.predeclare_var_declarations(body_stmts, &mut ctx); + + // 预声明 body 级 `let`/`const`/`class`(未初始化 TDZ 占位), + // 使声明点前读取可编译为运行时 ReferenceError。函数体 lexical 声明是 + // 局部绑定,不做受限全局名检查;重复声明错在 emit 期报。 + let _ = self.predeclare_lexical_declarations(body_stmts, &mut ctx, false); + + // 块级函数名 web-compat 外层 var 绑定(sloppy):块内函数声明名在实例化 + // 期于函数作用域建外层 var 绑定——无同名绑定则新建 var 槽;名在抑制集 + // (形参/词法声明同名,该形退化为纯块作用域)则不建。求值期声明点把 + // 函数对象写回此绑定(见函数声明 emit)。 + if !ctx.is_strict { + ctx.block_fn_suppressed = self.collect_block_fn_suppressed_names(body_stmts, &ctx.param_names); + for name in self.collect_block_function_names(body_stmts) { + if !ctx.block_fn_suppressed.contains(&name) { + self.predeclare_var_name(&name, &mut ctx); + } + } + } + + // 生成器:body 起点标记——调用时参数初始化(emit_params_prologue)结束后挂起于此, + // 参数副作用/异常在 `g()` 调用时刻生效,首次 next() 从这继续执行 body。 + if is_generator { + ctx.inst(Inst::suspend_body()); + } + + if let Some(emit) = emit_fields.as_mut() { + if fields_after_super { + let mut parent_insts = Vec::new(); + let mut parent_label_pos = Vec::new(); + std::mem::swap(&mut ctx.insts, &mut parent_insts); + std::mem::swap(&mut ctx.labels.label_pos, &mut parent_label_pos); + emit(self, &mut ctx)?; + let field_buffer = FieldBuffer { + insts: std::mem::take(&mut ctx.insts), + labels: std::mem::take(&mut ctx.labels.label_pos) + .into_iter() + .enumerate() + .filter_map(|(id, pos)| pos.map(|p| (id as LabelId, p))) + .collect(), + }; + ctx.insts = parent_insts; + ctx.labels.label_pos = parent_label_pos; + ctx.field_buffer = Some(field_buffer); + } else { + emit(self, &mut ctx)?; + } + } + + // 发 body 语句(先函数声明 hoisting,再其余)。 + let last_result_reg = self.emit_body_stmts(body_stmts, &mut ctx)?; + + // 隐式 RETURN:表达式体返回最后表达式,语句体返回 undefined。 + // 函数尾词法上不在任何循环内,迭代器逃出计数恒 0。 + if is_expression_body { + if let Some(reg) = last_result_reg { + ctx.inst(Inst::ret(Operand::Reg(reg), 0, 0)); + } else { + let undef_idx = ctx.add_constant(Constant::Undefined); + let undef_reg = ctx.alloc_reg(); + ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx)); + ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0)); + } + } else { + let undef_idx = ctx.add_constant(Constant::Undefined); + let undef_reg = ctx.alloc_reg(); + ctx.inst(Inst::load_const(Operand::Reg(undef_reg), undef_idx)); + ctx.inst(Inst::ret(Operand::Reg(undef_reg), 0, 0)); + } + + // 调用契约参数段只含固定形参:rest 是函数体内普通变量,不在 VM 实参传递区。 + let fixed_count = param_specs + .iter() + .filter(|spec| !matches!(spec, ParamSpec::Rest { .. })) + .count() as u32; + let ir = ctx.assemble_ir( + oxide_ir::ParamLayout { + base: param_base, + count: fixed_count, + }, + Some(parent_ctx), + ); + Ok(ir) + } + + /// 参数 prologue:函数作用域 + 参数声明/解构 + 闭包捕获与 upvalue 分析。返回 param_base。 + #[allow(clippy::too_many_arguments)] + fn emit_params_prologue<'a>( + &self, param_specs: &[ParamSpec<'a>], body_stmts: &[Statement<'a>], parent_ctx: &CompileCtx, + ctx: &mut CompileCtx, body_context: FunctionBodyContext, extra_capture_exprs: &[&'a Expression<'a>], + extra_upvalue_names: &[(&str, u8)], + ) -> Result { + ctx.push_scope_with_kind(ScopeKind::FunctionScope); + let param_base = ctx.next_reg; + + // 发参数声明(分配寄存器;分析用 register_name 引用)。 + for spec in param_specs { + let name = spec.register_name(); + let reg = ctx.alloc_reg(); + ctx.declare_initialized(name, reg, VariableDeclarationKind::Var, false)?; + } + + // 闭包捕获分析(AST 级,emit 前确定):须在参数默认值 emit 之前, + // 否则默认值内嵌套函数(IIFE)编译时父分析为空 → upvalue 捕获丢失。 + let param_names: Vec<&str> = param_specs.iter().map(|s| s.register_name()).collect(); + let mut param_defaults: Vec<&oxide_parser::Expression> = Vec::new(); + for spec in param_specs { + match spec { + ParamSpec::Identifier { initializer, .. } => { + if let Some(init) = initializer { + param_defaults.push(init); + } + } + ParamSpec::Pattern { pattern, initializer, .. } => { + if let Some(init) = initializer { + param_defaults.push(init); + } + // 模式内嵌默认值(`[x = expr]` 的 AssignmentPattern.right)也会被 + // 内部闭包引用,需纳入捕获分析。 + self.collect_pattern_default_exprs(pattern, &mut param_defaults); + } + ParamSpec::Rest { .. } => {} + } + } + ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); + for spec in param_specs { + if let ParamSpec::Pattern { pattern, .. } = spec { + self.collect_binding_pattern_names(pattern, &mut ctx.own_bindings); + } + } + + // 自动声明 arguments 绑定(非箭头函数,且用户未显式声明同名标识符)。 + // 先登记符号并纳入 own_bindings,使嵌套箭头引用 arguments 被识别为本函数 + // 绑定(否则被当自由变量 → 子模块 upvalue 解析错位)。 + let mut arguments_reg = None; + if !matches!(body_context, FunctionBodyContext::Arrow) && !ctx.own_bindings.contains("arguments") { + let reg = ctx.alloc_reg(); + ctx.declare_initialized("arguments", reg, VariableDeclarationKind::Var, false)?; + ctx.own_bindings.insert("arguments".to_string()); + arguments_reg = Some(reg); + } + + // 字段初始化表达式(值表达式)与参数默认值一并纳入捕获分析。 + let mut capture_exprs: Vec<&oxide_parser::Expression> = param_defaults.clone(); + capture_exprs.extend_from_slice(extra_capture_exprs); + ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings); + // 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。 + if matches!( + body_context, + FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement + ) { + ctx.current_upvalue_captures = self.collect_upvalue_names( + body_stmts, + &capture_exprs, + &parent_ctx.captured_bindings, + &parent_ctx.current_upvalue_captures, + &ctx.own_bindings, + ); + // 捕获 const 信息快照:父作用域符号表此时完整(预声明已完成), + // 直接查绑定 is_const(不依赖初始化状态,TDZ 中 const 也须拦截)。 + ctx.upvalue_const_flags = ctx + .current_upvalue_captures + .iter() + .filter(|u| u.parent_uv_idx.is_none()) + .filter(|u| { + parent_ctx + .scopes + .symbols + .lookup_any_binding(u.name.as_str()) + .map(|(b, _)| b.is_const) + .unwrap_or(false) + }) + .map(|u| u.name.clone()) + .collect(); + // 类字段 computed key 数组等合成捕获:直接追加 upvalue(cell_idx 由父分配)。 + for (name, cell_idx) in extra_upvalue_names { + if !ctx.own_bindings.contains(*name) && !ctx.current_upvalue_captures.iter().any(|u| u.name == *name) { + ctx.current_upvalue_captures.push(UpvalueCapture { + name: (*name).to_string(), + enclosing_reg: 0, + cell_idx: *cell_idx, + parent_uv_idx: None, + }); + } + } + } + + // 创建 arguments 对象:指令须在默认参数求值前发出(默认参数可引用 arguments)。 + if let Some(reg) = arguments_reg { + ctx.inst(Inst::create_arguments(Operand::Reg(reg))); + } + + for spec in param_specs { + match spec { + ParamSpec::Pattern { + synthetic_name, + pattern, + initializer, + } => { + let src_reg = ctx.lookup(synthetic_name)?; + let src_reg = if let Some(init) = initializer { + self.emit_default_if_undefined(src_reg, init, Some(synthetic_name), ctx)? + } else { + src_reg + }; + self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, false, ctx)?; + } + ParamSpec::Identifier { name, initializer } => { + if let Some(init) = initializer { + // 默认参数:实参为 undefined 时用默认值。 + let reg = ctx.lookup(name)?; + self.emit_default_if_undefined(reg, init, Some(name), ctx)?; + } + } + ParamSpec::Rest { name } => { + // rest 数组:从实参区收集固定形参之后的实参,绑定为普通变量。 + let reg = ctx.lookup(name)?; + let fixed_count = + param_specs.iter().filter(|s| !matches!(s, ParamSpec::Rest { .. })).count() as u32; + ctx.inst(Inst::create_rest_array(Operand::Reg(reg), fixed_count)); + } + } + } + + // 被捕获的参数也必须建 cell(MAKE_CELL):否则子函数经 lazy upvalue 路径读 + // 自身寄存器(依赖调用者寄存器残留),vreg 化/RegAlloc 移动寄存器后读到垃圾。 + // 与 var/let/const 的 MAKE_CELL 语义一致(binding.rs:50)。须在默认值之后 + // (默认值 emit 会读参数寄存器)。 + for spec in param_specs { + let name = spec.register_name(); + if let Some(&cell_idx) = ctx.captured_bindings.get(name) { + let reg = ctx.lookup(name)?; + ctx.inst(Inst::new( + OpCode::MAKE_CELL, + Operand::Reg(reg), + Operand::Imm(cell_idx as u16), + Operand::None, + )); + } + } + + // 被捕获的 arguments 绑定同样建 cell(与参数一致,须在默认值之后)。 + if let (Some(reg), Some(&cell_idx)) = (arguments_reg, ctx.captured_bindings.get("arguments")) { + ctx.inst(Inst::new( + OpCode::MAKE_CELL, + Operand::Reg(reg), + Operand::Imm(cell_idx as u16), + Operand::None, + )); + } + + // var 绑定函数入口实例化:被捕获的 var 名统一 MAKE_CELL(undefined)。 + // 规范上 var 在函数入口即初始化为 undefined(HoistDeclaration),声明语句 + // 只是赋值;否则声明语句前创建的闭包读取占位 cell → TDZ 误报。参数与 + // arguments 已在上方初始化(跳过以免覆盖参数值);let/const/class 保持 + // TDZ 语义不动。声明语句的 MAKE_CELL 按占位更新语义覆盖此初值。 + let var_names: Vec = self + .collect_var_binding_names(body_stmts) + .into_iter() + .filter(|n| !param_names.contains(&n.as_str()) && n != "arguments") + .filter(|n| ctx.captured_bindings.contains_key(n)) + .collect(); + if !var_names.is_empty() { + let undef_reg = self.emit_undefined(ctx); + for name in var_names { + if let Some(&cell_idx) = ctx.captured_bindings.get(&name) { + ctx.inst(Inst::new( + OpCode::MAKE_CELL, + Operand::Reg(undef_reg), + Operand::Imm(cell_idx as u16), + Operand::None, + )); + } + } + } + + Ok(param_base) + } + + /// 双 sub-pass emit body:先函数声明(hoisting),再其余语句。返回最后结果寄存器。 + fn emit_body_stmts(&self, body_stmts: &[Statement], ctx: &mut CompileCtx) -> Result, String> { + let mut last_result_reg = None; + for stmt in body_stmts { + if matches!(stmt, Statement::FunctionDeclaration(_)) { + if let Some(reg) = self.emit_statement(stmt, ctx)? { + last_result_reg = Some(reg); + } + } + } + for stmt in body_stmts { + if matches!(stmt, Statement::FunctionDeclaration(_)) { + continue; + } + if let Some(reg) = self.emit_statement(stmt, ctx)? { + last_result_reg = Some(reg); + } + } + Ok(last_result_reg) + } +} diff --git a/crates/oxide_emit/src/lib.rs b/crates/oxide_emit/src/lib.rs index 26e3bd09..a968be97 100644 --- a/crates/oxide_emit/src/lib.rs +++ b/crates/oxide_emit/src/lib.rs @@ -13,6 +13,7 @@ pub mod emit_ctx; mod emit_log; mod errors; pub mod expr; +mod function_body; pub mod module; pub mod prepass; pub mod shared; @@ -20,8 +21,9 @@ pub mod stmt; pub mod symbol_table; pub use compile_ctx::CompileCtx; +pub use emit::Emitter; pub use emit::{is_anonymous_function_definition, is_int_literal, is_side_effect_free}; -pub use emit::{Emitter, FunctionBodyContext, ParamSpec}; pub use emit_ctx::LabelScope; +pub use function_body::{FunctionBodyContext, ParamSpec}; pub use oxide_bytecode::module::Constant; pub use oxide_parser::{AssignmentOperator, BinaryOperator, UnaryOperator};