//! 函数声明语句 emit:`emit_function_declaration_statement` 创建闭包并绑定函数名。 use crate::{CompileCtx, Emitter, ParamSpec}; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; use oxide_ir::operand::Operand; use oxide_parser::Statement; impl Emitter { pub(crate) fn emit_function_declaration_statement( &self, stmt: &Statement, ctx: &mut CompileCtx, ) -> Result, String> { let Statement::FunctionDeclaration(fd) = stmt else { return Err("FunctionDeclaration without name".into()); }; self.emit_function_declaration(fd, ctx) } /// 函数声明本体:供 export 声明复用(导出声明先按普通声明 emit,再就地注册导出值)。 pub(crate) fn emit_function_declaration( &self, fd: &oxide_parser::Function, ctx: &mut CompileCtx, ) -> Result, String> { let name = if let Some(id) = &fd.id { id.name.to_string() } else { return Err("FunctionDeclaration without name".into()); }; let mut param_names = Vec::new(); for (idx, param) in fd.params.items.iter().enumerate() { match ¶m.pattern { oxide_parser::BindingPattern::BindingIdentifier(bi) => param_names.push(ParamSpec::Identifier { name: bi.name.to_string(), initializer: param.initializer.as_deref(), }), pattern => param_names.push(ParamSpec::Pattern { synthetic_name: format!("@@param_{idx}"), pattern, initializer: param.initializer.as_deref(), }), } } if let Some(rest) = &fd.params.rest { self.push_rest_param(&rest.rest.argument, &mut param_names)?; } let body_stmts: &[Statement] = if let Some(body) = &fd.body { &body.statements } else { &[] }; let own_strict = fd.has_use_strict_directive(); let mut sub_module = if fd.generator && fd.r#async { self.compile_async_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fd.generator { self.compile_generator_body(¶m_names, body_stmts, ctx, own_strict)? } else if fd.r#async { self.compile_async_body(¶m_names, body_stmts, ctx, false, false, own_strict)? } else { self.compile_function_body(¶m_names, body_stmts, ctx, false, false, own_strict)? }; sub_module.function_name = Some(name.clone()); ctx.nested.push(sub_module); let var_reg = ctx.lookup(&name)?; ctx.reserve_reg(var_reg); ctx.inst(Inst::create_closure(Operand::Reg(var_reg), ctx.nested.len() as u16)); if let Some(&cell_idx) = ctx.captured_bindings.get(&name) { ctx.inst(Inst::new( OpCode::MAKE_CELL, Operand::Reg(var_reg), Operand::Imm(cell_idx as u16), Operand::None, )); } else { ctx.inst(Inst::new(OpCode::STORE_VAR, Operand::Reg(var_reg), Operand::Reg(var_reg), Operand::None)); } // 脚本顶层(非块内)函数声明:同步写全局对象,使 globalThis 可反射函数名。 // 块内函数声明是块级绑定,不得落全局对象(作用域隔离,块外不可见)。 // 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不落全局对象:抑制 A // 侧写(局部绑定读面未暴露),同时避免不可写全局内置在 0x98 上误抛 strict。 if ctx.is_global_scope && ctx.scopes.symbols.scopes.len() == 1 && !(ctx.is_eval_script && ctx.is_strict) { self.emit_global_prop_write(&name, var_reg, ctx); } Ok(None) } }