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,
));
}
}