From 04a6aa10f724111640aa54b610ebad54cdd6e5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=88=B1=E7=89=B9=E6=AF=8F=E7=BE=8A=E9=98=9F?= Date: Fri, 7 Aug 2026 15:26:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(emit):=20=E5=AE=9E=E7=8E=B0=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=8F=82=E6=95=B0=EF=BC=88=E5=BD=A2=E5=8F=82=20initia?= =?UTF-8?q?lizer=20=E4=B8=8E=E8=A7=A3=E6=9E=84=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_emit/src/emit.rs | 37 +++++++++++++++---- crates/oxide_emit/src/expr/function/mod.rs | 13 ++++++- crates/oxide_emit/src/shared/binding.rs | 2 +- .../src/stmt/declaration/function_decl.rs | 13 +++++-- 4 files changed, 51 insertions(+), 14 deletions(-) diff --git a/crates/oxide_emit/src/emit.rs b/crates/oxide_emit/src/emit.rs index 4e52cfd..c3328c6 100644 --- a/crates/oxide_emit/src/emit.rs +++ b/crates/oxide_emit/src/emit.rs @@ -174,19 +174,23 @@ pub enum FunctionBodyContext { ClassElement, } -/// 参数规格:普通形参为标识符,解构形参用合成名 + 原始 pattern。 +/// 参数规格:普通形参为标识符(可带默认值 initializer),解构形参用合成名 + 原始 pattern。 pub enum ParamSpec<'a> { - Identifier(String), + Identifier { + name: String, + initializer: Option<&'a Expression<'a>>, + }, Pattern { synthetic_name: String, pattern: &'a oxide_parser::BindingPattern<'a>, + initializer: Option<&'a Expression<'a>>, }, } impl ParamSpec<'_> { pub(crate) fn register_name(&self) -> &str { match self { - Self::Identifier(name) => name, + Self::Identifier { name, .. } => name, Self::Pattern { synthetic_name, .. } => synthetic_name, } } @@ -529,12 +533,16 @@ impl Emitter { for (idx, param) in function.params.items.iter().enumerate() { match ¶m.pattern { oxide_parser::BindingPattern::BindingIdentifier(bi) => { - param_specs.push(ParamSpec::Identifier(bi.name.to_string())); + 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(), }); } } @@ -729,9 +737,23 @@ impl Emitter { } for spec in param_specs { - if let ParamSpec::Pattern { synthetic_name, pattern } = spec { - let src_reg = ctx.lookup(synthetic_name)?; - self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, ctx)?; + 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, ctx)? + } else { + src_reg + }; + self.emit_binding_pattern(pattern, src_reg, VariableDeclarationKind::Var, false, ctx)?; + } + ParamSpec::Identifier { name, initializer } => { + if let Some(init) = initializer { + // 默认参数:实参为 undefined 时用默认值。 + let reg = ctx.lookup(name)?; + self.emit_default_if_undefined(reg, init, ctx)?; + } + } } } @@ -910,3 +932,4 @@ impl Default for Emitter { Self::new() } } + diff --git a/crates/oxide_emit/src/expr/function/mod.rs b/crates/oxide_emit/src/expr/function/mod.rs index 22a8e24..c1d3da3 100644 --- a/crates/oxide_emit/src/expr/function/mod.rs +++ b/crates/oxide_emit/src/expr/function/mod.rs @@ -21,12 +21,16 @@ impl Emitter { for (idx, param) in arrow.params.items.iter().enumerate() { match ¶m.pattern { oxide_parser::BindingPattern::BindingIdentifier(bi) => { - param_names.push(ParamSpec::Identifier(bi.name.to_string())); + 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(), }); } } @@ -54,12 +58,16 @@ impl Emitter { for (idx, param) in fe.params.items.iter().enumerate() { match ¶m.pattern { oxide_parser::BindingPattern::BindingIdentifier(bi) => { - param_names.push(ParamSpec::Identifier(bi.name.to_string())); + 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(), }); } } @@ -113,3 +121,4 @@ impl Emitter { } } } + diff --git a/crates/oxide_emit/src/shared/binding.rs b/crates/oxide_emit/src/shared/binding.rs index b520daf..f14e2cb 100644 --- a/crates/oxide_emit/src/shared/binding.rs +++ b/crates/oxide_emit/src/shared/binding.rs @@ -13,7 +13,7 @@ use oxide_parser::{ }; impl Emitter { - fn emit_default_if_undefined( + pub(crate) fn emit_default_if_undefined( &self, val_reg: u32, default_expr: &Expression, ctx: &mut CompileCtx, ) -> Result { let undef_reg = self.emit_undefined(ctx); diff --git a/crates/oxide_emit/src/stmt/declaration/function_decl.rs b/crates/oxide_emit/src/stmt/declaration/function_decl.rs index 287a475..237e0fb 100644 --- a/crates/oxide_emit/src/stmt/declaration/function_decl.rs +++ b/crates/oxide_emit/src/stmt/declaration/function_decl.rs @@ -22,12 +22,16 @@ impl Emitter { for (idx, param) in fd.params.items.iter().enumerate() { match ¶m.pattern { oxide_parser::BindingPattern::BindingIdentifier(bi) => { - param_names.push(ParamSpec::Identifier(bi.name.to_string())) + 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, - }), + synthetic_name: format!("@@param_{idx}"), + pattern, + initializer: param.initializer.as_deref(), + }), } } let body_stmts: &[Statement] = if let Some(body) = &fd.body { &body.statements } else { &[] }; @@ -50,3 +54,4 @@ impl Emitter { Ok(None) } } +