fix(emit): 默认参数/解构默认值函数名推断(SetFunctionName)
This commit is contained in:
@@ -811,7 +811,7 @@ impl Emitter {
|
|||||||
ParamSpec::Pattern { synthetic_name, pattern, initializer } => {
|
ParamSpec::Pattern { synthetic_name, pattern, initializer } => {
|
||||||
let src_reg = ctx.lookup(synthetic_name)?;
|
let src_reg = ctx.lookup(synthetic_name)?;
|
||||||
let src_reg = if let Some(init) = initializer {
|
let src_reg = if let Some(init) = initializer {
|
||||||
self.emit_default_if_undefined(src_reg, init, ctx)?
|
self.emit_default_if_undefined(src_reg, init, Some(synthetic_name), ctx)?
|
||||||
} else {
|
} else {
|
||||||
src_reg
|
src_reg
|
||||||
};
|
};
|
||||||
@@ -821,7 +821,7 @@ impl Emitter {
|
|||||||
if let Some(init) = initializer {
|
if let Some(init) = initializer {
|
||||||
// 默认参数:实参为 undefined 时用默认值。
|
// 默认参数:实参为 undefined 时用默认值。
|
||||||
let reg = ctx.lookup(name)?;
|
let reg = ctx.lookup(name)?;
|
||||||
self.emit_default_if_undefined(reg, init, ctx)?;
|
self.emit_default_if_undefined(reg, init, Some(name), ctx)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use oxide_parser::{
|
|||||||
|
|
||||||
impl Emitter {
|
impl Emitter {
|
||||||
pub(crate) fn emit_default_if_undefined(
|
pub(crate) fn emit_default_if_undefined(
|
||||||
&self, val_reg: u32, default_expr: &Expression, ctx: &mut CompileCtx,
|
&self, val_reg: u32, default_expr: &Expression, name: Option<&str>, ctx: &mut CompileCtx,
|
||||||
) -> Result<u32, String> {
|
) -> Result<u32, String> {
|
||||||
let undef_reg = self.emit_undefined(ctx);
|
let undef_reg = self.emit_undefined(ctx);
|
||||||
let eq_reg = ctx.alloc_reg();
|
let eq_reg = ctx.alloc_reg();
|
||||||
@@ -28,6 +28,21 @@ impl Emitter {
|
|||||||
let end_label = ctx.next_label_id();
|
let end_label = ctx.next_label_id();
|
||||||
ctx.inst(Inst::jmp_if_false(eq_reg, end_label));
|
ctx.inst(Inst::jmp_if_false(eq_reg, end_label));
|
||||||
let default_reg = self.emit_expression(default_expr, ctx)?;
|
let default_reg = self.emit_expression(default_expr, ctx)?;
|
||||||
|
// 默认值表达式是匿名函数/箭头/class 时按绑定名推断 name(SetFunctionName)。
|
||||||
|
if let Some(name) = name {
|
||||||
|
if matches!(
|
||||||
|
default_expr,
|
||||||
|
Expression::ArrowFunctionExpression(_)
|
||||||
|
| Expression::FunctionExpression(_)
|
||||||
|
| Expression::ClassExpression(_)
|
||||||
|
) {
|
||||||
|
if let Some(sub_mod) = ctx.nested.last_mut() {
|
||||||
|
if sub_mod.function_name.is_none() {
|
||||||
|
sub_mod.function_name = Some(name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ctx.inst(Inst::new(
|
ctx.inst(Inst::new(
|
||||||
OpCode::LOAD_VAR,
|
OpCode::LOAD_VAR,
|
||||||
Operand::Reg(val_reg),
|
Operand::Reg(val_reg),
|
||||||
@@ -110,7 +125,12 @@ impl Emitter {
|
|||||||
BindingPattern::ArrayPattern(ap) => self.emit_array_binding(ap, src_reg, kind, is_const, ctx),
|
BindingPattern::ArrayPattern(ap) => self.emit_array_binding(ap, src_reg, kind, is_const, ctx),
|
||||||
BindingPattern::ObjectPattern(op) => self.emit_object_binding(op, src_reg, kind, is_const, ctx),
|
BindingPattern::ObjectPattern(op) => self.emit_object_binding(op, src_reg, kind, is_const, ctx),
|
||||||
BindingPattern::AssignmentPattern(ap) => {
|
BindingPattern::AssignmentPattern(ap) => {
|
||||||
let val_reg = self.emit_default_if_undefined(src_reg, &ap.right, ctx)?;
|
// `[x = fn]`:默认值函数按绑定名推断 name。
|
||||||
|
let name = match &ap.left {
|
||||||
|
BindingPattern::BindingIdentifier(bi) => Some(bi.name.as_str()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let val_reg = self.emit_default_if_undefined(src_reg, &ap.right, name, ctx)?;
|
||||||
self.emit_binding_pattern(&ap.left, val_reg, kind, is_const, ctx)
|
self.emit_binding_pattern(&ap.left, val_reg, kind, is_const, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +214,11 @@ impl Emitter {
|
|||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
match target {
|
match target {
|
||||||
AssignmentTargetMaybeDefault::AssignmentTargetWithDefault(default) => {
|
AssignmentTargetMaybeDefault::AssignmentTargetWithDefault(default) => {
|
||||||
let val_reg = self.emit_default_if_undefined(src_reg, &default.init, ctx)?;
|
let name = match &default.binding {
|
||||||
|
AssignmentTarget::AssignmentTargetIdentifier(id) => Some(id.name.as_str()),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let val_reg = self.emit_default_if_undefined(src_reg, &default.init, name, ctx)?;
|
||||||
self.emit_assign_target(&default.binding, val_reg, ctx)
|
self.emit_assign_target(&default.binding, val_reg, ctx)
|
||||||
}
|
}
|
||||||
AssignmentTargetMaybeDefault::ArrayAssignmentTarget(ap) => self.emit_array_assignment(ap, src_reg, ctx),
|
AssignmentTargetMaybeDefault::ArrayAssignmentTarget(ap) => self.emit_array_assignment(ap, src_reg, ctx),
|
||||||
@@ -246,7 +270,8 @@ impl Emitter {
|
|||||||
excluded.push(key.clone());
|
excluded.push(key.clone());
|
||||||
let mut prop_reg = self.emit_object_property_read(src_reg, &key, ctx);
|
let mut prop_reg = self.emit_object_property_read(src_reg, &key, ctx);
|
||||||
if let Some(default_expr) = &id.init {
|
if let Some(default_expr) = &id.init {
|
||||||
prop_reg = self.emit_default_if_undefined(prop_reg, default_expr, ctx)?;
|
let name = id.binding.name.as_str();
|
||||||
|
prop_reg = self.emit_default_if_undefined(prop_reg, default_expr, Some(name), ctx)?;
|
||||||
}
|
}
|
||||||
let name = id.binding.name.as_str();
|
let name = id.binding.name.as_str();
|
||||||
let var_reg = ctx.lookup_or_global(name);
|
let var_reg = ctx.lookup_or_global(name);
|
||||||
|
|||||||
Reference in New Issue
Block a user