feat(iter): 迭代协议支持对象字面量 computed key 与 upvalue 捕获

This commit is contained in:
爱特每羊队
2026-08-07 10:49:24 +08:00
parent d1675c217d
commit dd291250e2
4 changed files with 118 additions and 17 deletions
@@ -5,7 +5,7 @@ use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::{Expression, ObjectPropertyKind, PropertyKey, PropertyKind};
use oxide_parser::{Expression, ObjectPropertyKind, PropertyKind};
impl Emitter {
pub(crate) fn emit_object_expression(
@@ -17,13 +17,17 @@ impl Emitter {
let ObjectPropertyKind::ObjectProperty(p) = prop else {
return Err("spread properties not yet supported".into());
};
let prop_name = match &p.key {
PropertyKey::StaticIdentifier(ident) => ident.name.as_str().to_string(),
PropertyKey::StringLiteral(s) => s.value.to_string(),
_ => return Err("unsupported object property key type".into()),
let computed = p.computed;
let prop_name = if computed {
"<computed>".to_string()
} else {
self.class_property_name(&p.key)?
};
match p.kind {
PropertyKind::Get | PropertyKind::Set => {
if computed {
return Err("computed object accessors not yet supported".into());
}
let accessor_reg = self.emit_expression(&p.value, ctx)?;
if let Some(sub_mod) = ctx.nested.last_mut() {
sub_mod.function_name = Some(prop_name.to_string());
@@ -43,20 +47,31 @@ impl Emitter {
));
}
_ => {
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));
let key_reg = if computed {
self.emit_expression(p.key.to_expression(), ctx)?
} else {
let idx = ctx.add_constant(Constant::String(prop_name.to_string()));
let reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(reg), idx));
reg
};
let val_reg = self.emit_expression(&p.value, ctx)?;
if matches!(&p.value, Expression::ArrowFunctionExpression(_)) {
if let Some(sub_mod) = ctx.nested.last_mut() {
sub_mod.function_name = Some(prop_name.to_string());
}
}
let op = if computed { OpCode::SET_PROP_DYNAMIC } else { OpCode::SET_PROP };
let operands = if computed {
(Operand::Reg(key_reg), Operand::Reg(val_reg))
} else {
(Operand::Reg(val_reg), Operand::Reg(key_reg))
};
ctx.inst(Inst::new(
OpCode::SET_PROP,
op,
Operand::Reg(obj_reg),
Operand::Reg(val_reg),
Operand::Reg(key_reg),
operands.0,
operands.1,
));
}
}
+8 -6
View File
@@ -261,11 +261,12 @@ impl Emitter {
let uv_idx = ctx.current_upvalue_captures.iter().position(|u| u.name == name);
let captured_cell = ctx.captured_bindings.get(name).copied();
if let Some(uv) = uv_idx {
// upvalue:LOAD_UPVALUE + 常量 1 + ADD/SUB + STORE_UPVALUE
let val_reg = ctx.alloc_reg();
// upvalue:LOAD_UPVALUE + 常量 1 + ADD/SUB + STORE_UPVALUE;
// 后缀形式返回旧值(前缀返回新值)。
let old_reg = ctx.alloc_reg();
ctx.inst(Inst::new(
OpCode::LOAD_UPVALUE,
Operand::Reg(val_reg),
Operand::Reg(old_reg),
Operand::Imm(uv as u16),
Operand::None,
));
@@ -277,14 +278,15 @@ impl Emitter {
} else {
OpCode::SUB
};
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(val_reg), Operand::Reg(one_reg)));
let new_reg = ctx.alloc_reg();
ctx.inst(Inst::new(op, Operand::Reg(new_reg), Operand::Reg(old_reg), Operand::Reg(one_reg)));
ctx.inst(Inst::new(
OpCode::STORE_UPVALUE,
Operand::None,
Operand::Reg(val_reg),
Operand::Reg(new_reg),
Operand::Imm(uv as u16),
));
Ok(val_reg)
Ok(if update.prefix { new_reg } else { old_reg })
} else if let Some(cell_idx) = captured_cell {
// 被捕获 cell:CELL_GET + 常量 1 + ADD/SUB + CELL_SET
let val_reg = ctx.alloc_reg();