feat: class 私有成员语义(字段/方法/访问器 + brand 检查 + 契约修复)

This commit is contained in:
2026-08-09 11:08:36 +08:00
parent 088b3bc976
commit 6c79dbb21c
41 changed files with 573 additions and 216 deletions
+33 -7
View File
@@ -5,14 +5,14 @@ use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::{Expression, PropertyKey};
use oxide_parser::{Expression, MethodDefinitionKind, PropertyKey};
impl Emitter {
/// 实例字段初始化:define 语义(不触发原型 setter)。
/// 非计算键用字符串常量;计算键从 `@@field_keys` upvalue 数组按 `key_slot` 取(类定义期求值一次)。
pub(crate) fn emit_public_field_init(
&self, target: Operand, key: &PropertyKey, computed: bool, value: Option<&Expression>,
key_slot: Option<u8>, ctx: &mut CompileCtx,
&self, target: Operand, key: &PropertyKey, computed: bool, value: Option<&Expression>, key_slot: Option<u8>,
ctx: &mut CompileCtx,
) -> Result<(), String> {
let key_reg = if computed {
self.emit_instance_field_key(key_slot, ctx)?
@@ -28,7 +28,12 @@ impl Emitter {
fn emit_instance_field_key(&self, key_slot: Option<u8>, ctx: &mut CompileCtx) -> Result<u32, String> {
let uv = ctx.field_keys_uv.expect("computed instance field without field keys upvalue");
let arr_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_UPVALUE, Operand::Reg(arr_reg), Operand::Imm(uv as u16), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_UPVALUE,
Operand::Reg(arr_reg),
Operand::Imm(uv as u16),
Operand::None,
));
let idx_reg = ctx.alloc_reg();
let idx = ctx.add_constant(Constant::Int(key_slot.unwrap_or(0) as i32));
ctx.inst(Inst::load_const(Operand::Reg(idx_reg), idx));
@@ -56,7 +61,7 @@ impl Emitter {
) -> Result<(), String> {
let key_reg = self.emit_private_id_reg(name, ctx)?;
let value_reg = self.emit_field_value(value, ctx)?;
ctx.inst(Inst::new(OpCode::INIT_PRIVATE, target, Operand::Reg(value_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::init_private(target, Operand::Reg(value_reg), Operand::Reg(key_reg), false));
Ok(())
}
@@ -67,9 +72,30 @@ impl Emitter {
return Err("expected private method key".into());
};
let name = private.name.as_str();
let key_reg = self.emit_private_id_reg(name, ctx)?;
let method_reg = self.emit_class_method_function(method, name, home_reg, ctx, &[])?;
ctx.inst(Inst::new(OpCode::INIT_PRIVATE, target, Operand::Reg(method_reg), Operand::Reg(key_reg)));
match method.kind {
MethodDefinitionKind::Method => {
let key_reg = self.emit_private_id_reg(name, ctx)?;
ctx.inst(Inst::init_private(target, Operand::Reg(method_reg), Operand::Reg(key_reg), true));
}
MethodDefinitionKind::Get | MethodDefinitionKind::Set => {
let id = self.private_name_id(name, ctx)?;
let key_idx = ctx.add_constant(Constant::Int(id as i32));
let undef_reg = self.emit_undefined(ctx);
let (get_reg, set_reg) = if method.kind == MethodDefinitionKind::Get {
(method_reg, undef_reg)
} else {
(undef_reg, method_reg)
};
ctx.inst(Inst::define_accessor(
target,
Operand::Reg(get_reg),
Operand::Reg(set_reg),
key_idx as u32,
));
}
MethodDefinitionKind::Constructor => return Err("constructor cannot be private".into()),
}
Ok(())
}
}