mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 10:41:11 +08:00
feat: super 属性写新建 SUPER_PUT_PROP 指令
This commit is contained in:
@@ -6,7 +6,7 @@ use oxide_bytecode::module::Constant;
|
||||
use oxide_bytecode::opcode::OpCode;
|
||||
use oxide_ir::inst::Inst;
|
||||
use oxide_ir::operand::Operand;
|
||||
use oxide_parser::AssignmentOperator;
|
||||
use oxide_parser::{AssignmentOperator, Expression};
|
||||
|
||||
impl Emitter {
|
||||
/// 标识符复合赋值的静态路径:upvalue / 被捕获 cell 走显式读取-运算-写回
|
||||
@@ -168,10 +168,63 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
|
||||
/// 复合赋值运算符映射到二元运算指令(super 属性写与计算成员动态路径共用)。
|
||||
fn super_compound_op(&self, op: AssignmentOperator) -> Result<OpCode, String> {
|
||||
Ok(match op {
|
||||
AssignmentOperator::Addition => OpCode::ADD,
|
||||
AssignmentOperator::Subtraction => OpCode::SUB,
|
||||
AssignmentOperator::Multiplication => OpCode::MUL,
|
||||
AssignmentOperator::Division => OpCode::DIV,
|
||||
AssignmentOperator::Remainder => OpCode::MOD,
|
||||
AssignmentOperator::Exponential => OpCode::COMPOUND_EXP,
|
||||
AssignmentOperator::BitwiseAnd => OpCode::BIT_AND,
|
||||
AssignmentOperator::BitwiseOR => OpCode::BIT_OR,
|
||||
AssignmentOperator::BitwiseXOR => OpCode::BIT_XOR,
|
||||
AssignmentOperator::ShiftLeft => OpCode::SHL,
|
||||
AssignmentOperator::ShiftRight => OpCode::SHR,
|
||||
AssignmentOperator::ShiftRightZeroFill => OpCode::USHR,
|
||||
_ => return Err(format!("compound assignment operator {:?} not supported", op)),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn emit_assignment_expression(
|
||||
&self, assign: &oxide_parser::AssignmentExpression, ctx: &mut CompileCtx,
|
||||
) -> Result<u32, String> {
|
||||
if let oxide_parser::AssignmentTarget::StaticMemberExpression(member) = &assign.left {
|
||||
// super 属性写:this 先装载(GetThisBinding),键常量装载,后发 SUPER_PUT_PROP
|
||||
// (运行期 GetSuperBase 先于 ToPropertyKey,步序与 super 读对齐)。
|
||||
if matches!(&member.object, Expression::Super(_)) {
|
||||
if assign.operator.to_logical_operator().is_some() {
|
||||
return Err("logical assignment to super property not supported".into());
|
||||
}
|
||||
let this_reg = self.emit_super_this(ctx)?;
|
||||
let prop_name = member.property.name.as_str();
|
||||
let idx = ctx.add_constant(Constant::String(prop_name.to_string()));
|
||||
let key_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(key_reg), idx));
|
||||
if assign.operator != AssignmentOperator::Assign {
|
||||
// 复合赋值:先读旧值(SUPER_GET_PROP),求值 RHS,运算,后写回。
|
||||
let val_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SUPER_GET_PROP,
|
||||
Operand::Reg(val_reg),
|
||||
Operand::Reg(this_reg),
|
||||
Operand::Reg(key_reg),
|
||||
));
|
||||
let rhs = self.emit_expression(&assign.right, ctx)?;
|
||||
let op = self.super_compound_op(assign.operator)?;
|
||||
if assign.operator == AssignmentOperator::Exponential {
|
||||
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(rhs), Operand::None));
|
||||
} else {
|
||||
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(val_reg), Operand::Reg(rhs)));
|
||||
}
|
||||
self.emit_super_put(this_reg, key_reg, val_reg, ctx);
|
||||
return Ok(val_reg);
|
||||
}
|
||||
let val_reg = self.emit_expression(&assign.right, ctx)?;
|
||||
self.emit_super_put(this_reg, key_reg, val_reg, ctx);
|
||||
return Ok(val_reg);
|
||||
}
|
||||
if let Some(logical_op) = assign.operator.to_logical_operator() {
|
||||
let store_label = ctx.next_label_id();
|
||||
let end_label = ctx.next_label_id();
|
||||
@@ -232,6 +285,37 @@ impl Emitter {
|
||||
Ok(val_reg)
|
||||
}
|
||||
} else if let oxide_parser::AssignmentTarget::ComputedMemberExpression(member) = &assign.left {
|
||||
// super 计算成员写:this 先装载(GetThisBinding),键表达式后求值,
|
||||
// 后发 SUPER_PUT_PROP(运行期 GetSuperBase 先于 ToPropertyKey)。
|
||||
if matches!(&member.object, Expression::Super(_)) {
|
||||
if assign.operator.to_logical_operator().is_some() {
|
||||
return Err("logical assignment to super property not supported".into());
|
||||
}
|
||||
let this_reg = self.emit_super_this(ctx)?;
|
||||
let key_reg = self.emit_expression(&member.expression, ctx)?;
|
||||
if assign.operator != AssignmentOperator::Assign {
|
||||
// 复合赋值:先读旧值(SUPER_GET_PROP),求值 RHS,运算,后写回。
|
||||
let val_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SUPER_GET_PROP,
|
||||
Operand::Reg(val_reg),
|
||||
Operand::Reg(this_reg),
|
||||
Operand::Reg(key_reg),
|
||||
));
|
||||
let rhs = self.emit_expression(&assign.right, ctx)?;
|
||||
let op = self.super_compound_op(assign.operator)?;
|
||||
if assign.operator == AssignmentOperator::Exponential {
|
||||
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(rhs), Operand::None));
|
||||
} else {
|
||||
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(val_reg), Operand::Reg(rhs)));
|
||||
}
|
||||
self.emit_super_put(this_reg, key_reg, val_reg, ctx);
|
||||
return Ok(val_reg);
|
||||
}
|
||||
let val_reg = self.emit_expression(&assign.right, ctx)?;
|
||||
self.emit_super_put(this_reg, key_reg, val_reg, ctx);
|
||||
return Ok(val_reg);
|
||||
}
|
||||
// 常量字符串键折叠为 IC 静态路径,与 StaticMemberExpression 分支同构。
|
||||
if let Some(key) = crate::expr::member::computed_const_key(&member.expression) {
|
||||
if let Some(logical_op) = assign.operator.to_logical_operator() {
|
||||
|
||||
@@ -37,6 +37,18 @@ impl Emitter {
|
||||
result_reg
|
||||
}
|
||||
|
||||
/// super 属性写:给定 this 寄存器、键寄存器与值寄存器,发 `SUPER_PUT_PROP`
|
||||
/// (GetSuperBase + RequireObjectCoercible + ToPropertyKey + Set 在运行期完成,
|
||||
/// 步序与 super 读对齐)。
|
||||
pub(crate) fn emit_super_put(&self, this_reg: u32, key_reg: u32, val_reg: u32, ctx: &mut CompileCtx) {
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SUPER_PUT_PROP,
|
||||
Operand::Reg(val_reg),
|
||||
Operand::Reg(this_reg),
|
||||
Operand::Reg(key_reg),
|
||||
));
|
||||
}
|
||||
|
||||
fn emit_static_member_expression(
|
||||
&self, member: &oxide_parser::StaticMemberExpression, ctx: &mut CompileCtx,
|
||||
) -> Result<u32, String> {
|
||||
|
||||
@@ -579,6 +579,41 @@ impl Emitter {
|
||||
self.emit_identifier_update_static(name, update, ctx)
|
||||
}
|
||||
SimpleAssignmentTarget::StaticMemberExpression(member) => {
|
||||
// super 属性自增/自减:this 先装载(GetThisBinding),键常量装载,
|
||||
// 读旧值(SUPER_GET_PROP),运算,写回(SUPER_PUT_PROP)。
|
||||
if matches!(&member.object, Expression::Super(_)) {
|
||||
let this_reg = self.emit_super_this(ctx)?;
|
||||
let prop_name = member.property.name.as_str();
|
||||
let key_idx = ctx.add_constant(Constant::String(prop_name.to_string()));
|
||||
let key_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(key_reg), key_idx));
|
||||
let old_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SUPER_GET_PROP,
|
||||
Operand::Reg(old_reg),
|
||||
Operand::Reg(this_reg),
|
||||
Operand::Reg(key_reg),
|
||||
));
|
||||
let one_idx = ctx.add_constant(Constant::Int(1));
|
||||
let one_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(one_reg), one_idx));
|
||||
let new_reg = ctx.alloc_reg();
|
||||
let op = if update.operator == UpdateOperator::Increment {
|
||||
OpCode::ADD
|
||||
} else {
|
||||
OpCode::SUB
|
||||
};
|
||||
ctx.inst(Inst::new(op, Operand::Reg(new_reg), Operand::Reg(old_reg), Operand::Reg(one_reg)));
|
||||
self.emit_super_put(this_reg, key_reg, new_reg, ctx);
|
||||
let result_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::LOAD_VAR,
|
||||
Operand::Reg(result_reg),
|
||||
Operand::Reg(if update.prefix { new_reg } else { old_reg }),
|
||||
Operand::None,
|
||||
));
|
||||
return Ok(result_reg);
|
||||
}
|
||||
let obj_reg = self.emit_expression(&member.object, ctx)?;
|
||||
let prop_name = member.property.name.as_str();
|
||||
let key_idx = ctx.add_constant(Constant::String(prop_name.to_string()));
|
||||
@@ -601,6 +636,38 @@ impl Emitter {
|
||||
Ok(val_reg)
|
||||
}
|
||||
SimpleAssignmentTarget::ComputedMemberExpression(member) => {
|
||||
// super 计算成员自增/自减:this 先装载(GetThisBinding),键表达式
|
||||
// 后求值,读旧值(SUPER_GET_PROP),运算,写回(SUPER_PUT_PROP)。
|
||||
if matches!(&member.object, Expression::Super(_)) {
|
||||
let this_reg = self.emit_super_this(ctx)?;
|
||||
let key_reg = self.emit_expression(&member.expression, ctx)?;
|
||||
let old_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SUPER_GET_PROP,
|
||||
Operand::Reg(old_reg),
|
||||
Operand::Reg(this_reg),
|
||||
Operand::Reg(key_reg),
|
||||
));
|
||||
let one_idx = ctx.add_constant(Constant::Int(1));
|
||||
let one_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(one_reg), one_idx));
|
||||
let new_reg = ctx.alloc_reg();
|
||||
let op = if update.operator == UpdateOperator::Increment {
|
||||
OpCode::ADD
|
||||
} else {
|
||||
OpCode::SUB
|
||||
};
|
||||
ctx.inst(Inst::new(op, Operand::Reg(new_reg), Operand::Reg(old_reg), Operand::Reg(one_reg)));
|
||||
self.emit_super_put(this_reg, key_reg, new_reg, ctx);
|
||||
let result_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::LOAD_VAR,
|
||||
Operand::Reg(result_reg),
|
||||
Operand::Reg(if update.prefix { new_reg } else { old_reg }),
|
||||
Operand::None,
|
||||
));
|
||||
return Ok(result_reg);
|
||||
}
|
||||
let obj_reg = self.emit_expression(&member.object, ctx)?;
|
||||
// 常量字符串键折叠为 IC 静态路径:MEMBER_INC/DEC 携带 IC 扩展字。
|
||||
if let Some(key) = crate::expr::member::computed_const_key(&member.expression) {
|
||||
|
||||
Reference in New Issue
Block a user