feat: class 私有成员语义(字段/方法/访问器 + brand 检查 + 契约修复)
This commit is contained in:
@@ -207,12 +207,15 @@ impl Emitter {
|
||||
}
|
||||
let obj_reg = self.emit_expression(&member.object, ctx)?;
|
||||
let val_reg = self.emit_expression(&assign.right, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SET_PRIVATE,
|
||||
let name = member.field.name.as_str();
|
||||
let (brand_reg, brand_id) = self.private_access_brand(obj_reg, name, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(name, ctx)?;
|
||||
ctx.inst(Inst::set_private(
|
||||
Operand::Reg(obj_reg),
|
||||
Operand::Reg(val_reg),
|
||||
Operand::Reg(key_reg),
|
||||
brand_reg,
|
||||
brand_id,
|
||||
));
|
||||
Ok(val_reg)
|
||||
} else if let oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(id_ref) = &assign.left {
|
||||
|
||||
@@ -39,13 +39,16 @@ impl Emitter {
|
||||
let (callee_reg, this_reg) = match &call.callee {
|
||||
Expression::PrivateFieldExpression(member) => {
|
||||
let obj_reg = self.emit_expression(&member.object, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
|
||||
let name = member.field.name.as_str();
|
||||
let (brand_reg, brand_id) = self.private_access_brand(obj_reg, name, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(name, ctx)?;
|
||||
let callee_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::GET_PRIVATE,
|
||||
ctx.inst(Inst::get_private(
|
||||
Operand::Reg(callee_reg),
|
||||
Operand::Reg(obj_reg),
|
||||
Operand::Reg(key_reg),
|
||||
brand_reg,
|
||||
brand_id,
|
||||
));
|
||||
(callee_reg, obj_reg)
|
||||
}
|
||||
|
||||
@@ -54,12 +54,7 @@ impl Emitter {
|
||||
ctx.inst(Inst::load_const(Operand::Reg(key_reg), key_idx));
|
||||
|
||||
let has_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::IN,
|
||||
Operand::Reg(has_reg),
|
||||
Operand::Reg(key_reg),
|
||||
Operand::Reg(obj_reg),
|
||||
));
|
||||
ctx.inst(Inst::new(OpCode::IN, Operand::Reg(has_reg), Operand::Reg(key_reg), Operand::Reg(obj_reg)));
|
||||
|
||||
let fallback_label = ctx.next_label_id();
|
||||
let end_label = ctx.next_label_id();
|
||||
@@ -101,12 +96,7 @@ impl Emitter {
|
||||
));
|
||||
}
|
||||
} else if let Some(reg) = ctx.scopes.symbols.lookup_any(name) {
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::LOAD_VAR,
|
||||
Operand::Reg(result_reg),
|
||||
Operand::Reg(reg),
|
||||
Operand::None,
|
||||
));
|
||||
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(reg), Operand::None));
|
||||
} else {
|
||||
let undef_idx = ctx.add_constant(Constant::Undefined);
|
||||
ctx.inst(Inst::load_const(Operand::Reg(result_reg), undef_idx));
|
||||
@@ -164,12 +154,7 @@ impl Emitter {
|
||||
ctx.inst(Inst::load_const(Operand::Reg(key_reg), key_idx));
|
||||
|
||||
let has_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::IN,
|
||||
Operand::Reg(has_reg),
|
||||
Operand::Reg(key_reg),
|
||||
Operand::Reg(obj_reg),
|
||||
));
|
||||
ctx.inst(Inst::new(OpCode::IN, Operand::Reg(has_reg), Operand::Reg(key_reg), Operand::Reg(obj_reg)));
|
||||
|
||||
let fallback_label = ctx.next_label_id();
|
||||
let end_label = ctx.next_label_id();
|
||||
|
||||
@@ -70,9 +70,7 @@ impl Emitter {
|
||||
// 非法正则字面量须在编译期报 SyntaxError(负面测试期望编译失败)。
|
||||
// 用 regress(ECMAScript 语法)校验,避免误报 backreference/lookaround 等合法模式。
|
||||
if regress::Regex::with_flags(&pattern, flags.as_str()).is_err() {
|
||||
return Err(format!(
|
||||
"SyntaxError: Invalid regular expression: /{pattern}/{flags}"
|
||||
));
|
||||
return Err(format!("SyntaxError: Invalid regular expression: /{pattern}/{flags}"));
|
||||
}
|
||||
let pat_ci = ctx.add_constant(Constant::String(pattern));
|
||||
let pat_reg = ctx.alloc_reg();
|
||||
@@ -96,5 +94,3 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,13 +60,16 @@ impl Emitter {
|
||||
&self, member: &oxide_parser::PrivateFieldExpression, ctx: &mut CompileCtx,
|
||||
) -> Result<u32, String> {
|
||||
let obj_reg = self.emit_expression(&member.object, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
|
||||
let name = member.field.name.as_str();
|
||||
let (brand_reg, brand_id) = self.private_access_brand(obj_reg, name, ctx)?;
|
||||
let key_reg = self.emit_private_id_reg(name, ctx)?;
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::GET_PRIVATE,
|
||||
ctx.inst(Inst::get_private(
|
||||
Operand::Reg(r),
|
||||
Operand::Reg(obj_reg),
|
||||
Operand::Reg(key_reg),
|
||||
brand_reg,
|
||||
brand_id,
|
||||
));
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
@@ -343,12 +343,7 @@ impl Emitter {
|
||||
} else {
|
||||
OpCode::SUB
|
||||
};
|
||||
ctx.inst(Inst::new(
|
||||
op,
|
||||
Operand::Reg(new_reg),
|
||||
Operand::Reg(old_reg),
|
||||
Operand::Reg(one_reg),
|
||||
));
|
||||
ctx.inst(Inst::new(op, Operand::Reg(new_reg), Operand::Reg(old_reg), Operand::Reg(one_reg)));
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::SET_PROP_DYNAMIC,
|
||||
Operand::Reg(obj_reg),
|
||||
|
||||
Reference in New Issue
Block a user