docs: 补充注释与格式化

This commit is contained in:
爱特每羊队
2026-08-06 23:10:27 +08:00
parent 4e0fd762c2
commit 328b8a3ddc
156 changed files with 2393 additions and 1687 deletions
+82 -17
View File
@@ -2,10 +2,10 @@
//! 函数:`emit_assignment_expression`。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::AssignmentOperator;
impl Emitter {
@@ -22,13 +22,23 @@ impl Emitter {
let key_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(key_reg), idx));
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(obj_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(obj_reg),
Operand::None,
));
ctx.inst(Inst::ic_get(Operand::Reg(result_reg), Operand::Reg(key_reg)));
self.emit_logical_assign_test(logical_op, result_reg, store_label, end_label, ctx)?;
ctx.labels.set_label_pos(store_label, ctx.insts.len());
let val_reg = self.emit_expression(&assign.right, ctx)?;
ctx.inst(Inst::ic_set(Operand::Reg(obj_reg), Operand::Reg(val_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(val_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(val_reg),
Operand::None,
));
ctx.labels.set_label_pos(end_label, ctx.insts.len());
return Ok(result_reg);
}
@@ -63,19 +73,39 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_expression(&member.expression, ctx)?;
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::GET_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(key_reg), Operand::Reg(result_reg)));
ctx.inst(Inst::new(
OpCode::GET_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
Operand::Reg(result_reg),
));
self.emit_logical_assign_test(logical_op, result_reg, store_label, end_label, ctx)?;
ctx.labels.set_label_pos(store_label, ctx.insts.len());
let val_reg = self.emit_expression(&assign.right, ctx)?;
ctx.inst(Inst::new(OpCode::SET_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(key_reg), Operand::Reg(val_reg)));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(val_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::SET_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
Operand::Reg(val_reg),
));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(val_reg),
Operand::None,
));
ctx.labels.set_label_pos(end_label, ctx.insts.len());
return Ok(result_reg);
}
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_expression(&member.expression, ctx)?;
let val_reg = self.emit_expression(&assign.right, ctx)?;
ctx.inst(Inst::new(OpCode::SET_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(key_reg), Operand::Reg(val_reg)));
ctx.inst(Inst::new(
OpCode::SET_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
Operand::Reg(val_reg),
));
Ok(val_reg)
} else if let oxide_parser::AssignmentTarget::PrivateFieldExpression(member) = &assign.left {
if assign.operator != AssignmentOperator::Assign {
@@ -84,7 +114,12 @@ 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, Operand::Reg(obj_reg), Operand::Reg(val_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::SET_PRIVATE,
Operand::Reg(obj_reg),
Operand::Reg(val_reg),
Operand::Reg(key_reg),
));
Ok(val_reg)
} else if let oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(id_ref) = &assign.left {
if assign.operator != AssignmentOperator::Assign {
@@ -94,14 +129,29 @@ impl Emitter {
let name = id_ref.name.as_str();
let var_reg = ctx.lookup_or_global(name);
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(var_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(var_reg),
Operand::None,
));
self.emit_logical_assign_test(logical_op, result_reg, store_label, end_label, ctx)?;
ctx.labels.set_label_pos(store_label, ctx.insts.len());
let val_reg = self.emit_expression(&assign.right, ctx)?;
let is_const = ctx.lookup_const_flag(name);
let const_flag = if is_const { 1 } else { 0 };
ctx.inst(Inst::new(OpCode::STORE_VAR, Operand::Reg(var_reg), Operand::Reg(val_reg), Operand::Imm(const_flag)));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(val_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::STORE_VAR,
Operand::Reg(var_reg),
Operand::Reg(val_reg),
Operand::Imm(const_flag),
));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(val_reg),
Operand::None,
));
ctx.labels.set_label_pos(end_label, ctx.insts.len());
Ok(result_reg)
} else if assign.operator == AssignmentOperator::Addition
@@ -143,20 +193,35 @@ impl Emitter {
} else {
let val_reg = self.emit_expression(&assign.right, ctx)?;
let name = id_ref.name.as_str();
// Check if target is an upvalue reference
// 目标若是 upvalue 引用,走 STORE_UPVALUE
if let Some(uv_idx) = ctx.current_upvalue_captures.iter().position(|u| u.name == name) {
ctx.inst(Inst::new(OpCode::STORE_UPVALUE, Operand::None, Operand::Reg(val_reg), Operand::Imm(uv_idx as u16)));
ctx.inst(Inst::new(
OpCode::STORE_UPVALUE,
Operand::None,
Operand::Reg(val_reg),
Operand::Imm(uv_idx as u16),
));
return Ok(val_reg);
}
// Check if target is a captured cell
// 目标若是被捕获 cell,走 CELL_SET
if let Some(&cell_idx) = ctx.captured_bindings.get(name) {
ctx.inst(Inst::new(OpCode::CELL_SET, Operand::None, Operand::Reg(val_reg), Operand::Imm(cell_idx as u16)));
ctx.inst(Inst::new(
OpCode::CELL_SET,
Operand::None,
Operand::Reg(val_reg),
Operand::Imm(cell_idx as u16),
));
return Ok(val_reg);
}
let var_reg = ctx.lookup_or_global(name);
let is_const = ctx.lookup_const_flag(name);
let const_flag = if is_const { 1 } else { 0 };
ctx.inst(Inst::new(OpCode::STORE_VAR, Operand::Reg(var_reg), Operand::Reg(val_reg), Operand::Imm(const_flag)));
ctx.inst(Inst::new(
OpCode::STORE_VAR,
Operand::Reg(var_reg),
Operand::Reg(val_reg),
Operand::Imm(const_flag),
));
Ok(val_reg)
}
} else if matches!(
+17 -7
View File
@@ -2,10 +2,10 @@
//! 函数:`emit_call_expression`、`emit_call_domain`。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::Expression;
impl Emitter {
@@ -41,7 +41,12 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
let callee_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::GET_PRIVATE, Operand::Reg(callee_reg), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::GET_PRIVATE,
Operand::Reg(callee_reg),
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
));
(callee_reg, obj_reg)
}
Expression::StaticMemberExpression(member) => {
@@ -69,7 +74,12 @@ impl Emitter {
};
ctx.inst(Inst::new(op, Operand::Reg(callee_reg), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
} else {
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(callee_reg), Operand::Reg(obj_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(callee_reg),
Operand::Reg(obj_reg),
Operand::None,
));
ctx.inst(Inst::ic_get(Operand::Reg(callee_reg), Operand::Reg(key_reg)));
}
(callee_reg, obj_reg)
@@ -125,9 +135,9 @@ impl Emitter {
}
}
/// 把调用参数打包到连续寄存器块(VM 按 `regs[first_arg + i]` 连续读参数,D-17/调用契约)。
/// vreg 化(05-02)后各参数由独立 vreg 承载,复杂表达式(对象/数组字面量、嵌套调用)
/// 的临时寄存器会使参数 vreg 不连续——这里检测到不连续时用 MOV 打包到新连续块。
/// 把调用参数打包到连续寄存器块(VM 按 `regs[first_arg + i]` 连续读参数)。
/// 各参数由独立 vreg 承载,复杂表达式(对象/数组字面量、嵌套调用)的临时寄存器
/// 会使参数 vreg 不连续——检测到不连续时用 MOV 打包到新连续块。
/// 返回首参寄存器;参数为空时返回 0。
fn pack_arg_regs(arg_regs: &mut [u32], ctx: &mut CompileCtx) -> u32 {
let consecutive = arg_regs.windows(2).all(|w| w[1] == w[0] + 1);
+6 -7
View File
@@ -11,12 +11,12 @@ impl Emitter {
fn emit_arrow_function_expression(
&self, arrow: &oxide_parser::ArrowFunctionExpression, ctx: &mut CompileCtx,
) -> Result<u32, String> {
// Rest params not yet supported
// 未支持:箭头函数 rest 参数
if let Some(_rest) = &arrow.params.rest {
return Err("rest params in arrow functions not yet supported".into());
}
// Extract param names (same pattern as FunctionExpression)
// 提取形参名(与函数表达式相同的形态)
let mut param_names = Vec::new();
for (idx, param) in arrow.params.items.iter().enumerate() {
match &param.pattern {
@@ -32,8 +32,7 @@ impl Emitter {
}
}
// Expression body: pass body statements directly with is_expression_body=true.
// Statement body: pass body statements with is_expression_body=false.
// 表达式体:以 is_expression_body=true 编译;语句体:以 false 编译。
let body_stmts = &arrow.body.statements;
let is_expr_body = arrow.expression;
@@ -41,7 +40,7 @@ impl Emitter {
sub_module.is_arrow = true;
ctx.nested.push(sub_module);
// 1-indexed: 0 = no sub_module (sentinel)
// 子模块下标 1 起始:0 保留为无子模块哨兵
let sub_idx = ctx.nested.len() as u16;
let r = ctx.alloc_reg();
@@ -50,7 +49,7 @@ impl Emitter {
}
fn emit_function_expression(&self, fe: &oxide_parser::Function, ctx: &mut CompileCtx) -> Result<u32, String> {
// FunctionExpression: compile body, emit LOAD_CONST(BytecodeFunc)
// 函数表达式:编译函数体为子模块,create_closure 实例化闭包
let mut param_names = Vec::new();
for (idx, param) in fe.params.items.iter().enumerate() {
match &param.pattern {
@@ -73,7 +72,7 @@ impl Emitter {
sub_module.function_name = Some(id.name.to_string());
}
ctx.nested.push(sub_module);
// 1-indexed: 0 = no sub_module (sentinel)
// 子模块下标 1 起始:0 保留为无子模块哨兵
let sub_idx = ctx.nested.len() as u16;
let r = ctx.alloc_reg();
+7 -2
View File
@@ -1,9 +1,9 @@
//! 标识符表达式 emit:`emit_identifier_expression` 按绑定/builtin/全局解析寄存器。
use crate::{CompileCtx, Emitter};
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::opcode::OpCode;
impl Emitter {
pub(crate) fn emit_identifier_expression(
@@ -23,7 +23,12 @@ impl Emitter {
if let Some(&cell_idx) = ctx.captured_bindings.get(name) {
let r = ctx.alloc_reg();
if let Some((binding, _)) = ctx.scopes.symbols.lookup_any_binding(name) {
ctx.inst(Inst::new(OpCode::CELL_GET, Operand::Reg(r), Operand::Reg(binding.reg), Operand::Imm(cell_idx as u16)));
ctx.inst(Inst::new(
OpCode::CELL_GET,
Operand::Reg(r),
Operand::Reg(binding.reg),
Operand::Imm(cell_idx as u16),
));
} else {
ctx.inst(Inst::new(OpCode::CELL_GET, Operand::Reg(r), Operand::None, Operand::Imm(cell_idx as u16)));
}
+8 -3
View File
@@ -2,10 +2,10 @@
//! 整数走立即数编码(`is_int_literal`),其余入常量池。
use crate::{is_int_literal, CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::Expression;
impl Emitter {
@@ -74,7 +74,12 @@ impl Emitter {
let flags_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(flags_reg), flags_ci));
let r = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::CREATE_REGEXP, Operand::Reg(r), Operand::Reg(pat_reg), Operand::Reg(flags_reg)));
ctx.inst(Inst::new(
OpCode::CREATE_REGEXP,
Operand::Reg(r),
Operand::Reg(pat_reg),
Operand::Reg(flags_reg),
));
Ok(r)
} else {
Err(format!("unsupported regexp literal: {:?}", lit))
+23 -6
View File
@@ -3,10 +3,10 @@
//! `emit_private_field_expression`、`emit_chain_expression`、`emit_member_domain`。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::Expression;
impl Emitter {
@@ -47,7 +47,12 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_expression(&member.expression, ctx)?;
let r = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::GET_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(key_reg), Operand::Reg(r)));
ctx.inst(Inst::new(
OpCode::GET_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
Operand::Reg(r),
));
Ok(r)
}
@@ -57,16 +62,28 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_private_id_reg(member.field.name.as_str(), ctx)?;
let r = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::GET_PRIVATE, Operand::Reg(r), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::GET_PRIVATE,
Operand::Reg(r),
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
));
Ok(r)
}
fn emit_chain_expression(&self, chain: &oxide_parser::ChainExpression, ctx: &mut CompileCtx) -> Result<u32, String> {
fn emit_chain_expression(
&self, chain: &oxide_parser::ChainExpression, ctx: &mut CompileCtx,
) -> Result<u32, String> {
let short_label = ctx.next_label_id();
let end_label = ctx.next_label_id();
let value_reg = self.emit_chain_element(&chain.expression, Some(short_label), ctx)?;
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(value_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(value_reg),
Operand::None,
));
ctx.inst(Inst::jmp(end_label));
ctx.labels.set_label_pos(short_label, ctx.insts.len());
let undefined_idx = ctx.add_constant(Constant::Undefined);
+8 -3
View File
@@ -1,10 +1,10 @@
//! 数组字面量 emit:`emit_array_expression` 逐元素求值并建数组(含 holes)。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
impl Emitter {
pub(crate) fn emit_array_expression(
&self, arr: &oxide_parser::ArrayExpression, ctx: &mut CompileCtx,
@@ -20,7 +20,12 @@ impl Emitter {
let idx_reg = ctx.alloc_reg();
let idx = ctx.add_constant(Constant::Int(i as i32));
ctx.inst(Inst::load_const(Operand::Reg(idx_reg), idx));
ctx.inst(Inst::new(OpCode::SET_ELEM, Operand::Reg(arr_reg), Operand::Reg(idx_reg), Operand::Reg(val_reg)));
ctx.inst(Inst::new(
OpCode::SET_ELEM,
Operand::Reg(arr_reg),
Operand::Reg(idx_reg),
Operand::Reg(val_reg),
));
}
Ok(arr_reg)
}
@@ -1,10 +1,10 @@
//! 对象字面量 emit:`emit_object_expression` 逐属性定义(含 getter/setter/展开)。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
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};
impl Emitter {
@@ -52,7 +52,12 @@ impl Emitter {
sub_mod.function_name = Some(prop_name.to_string());
}
}
ctx.inst(Inst::new(OpCode::SET_PROP, Operand::Reg(obj_reg), Operand::Reg(val_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::SET_PROP,
Operand::Reg(obj_reg),
Operand::Reg(val_reg),
Operand::Reg(key_reg),
));
}
}
}
+80 -18
View File
@@ -3,10 +3,10 @@
//! 函数:`emit_operator` 及各类 `emit_*_expression`。
use crate::{is_side_effect_free, BinaryOperator, CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_parser::{ChainElement, Expression, LogicalOperator, SimpleAssignmentTarget, UnaryOperator, UpdateOperator};
impl Emitter {
@@ -16,11 +16,18 @@ impl Emitter {
let obj_reg = self.emit_expression(&pin.right, ctx)?;
let key_reg = self.emit_private_id_reg(pin.left.name.as_str(), ctx)?;
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::PRIVATE_BRAND_IN, Operand::Reg(result_reg), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::PRIVATE_BRAND_IN,
Operand::Reg(result_reg),
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
));
Ok(result_reg)
}
fn emit_binary_expression(&self, bin: &oxide_parser::BinaryExpression, ctx: &mut CompileCtx) -> Result<u32, String> {
fn emit_binary_expression(
&self, bin: &oxide_parser::BinaryExpression, ctx: &mut CompileCtx,
) -> Result<u32, String> {
let left = self.emit_expression(&bin.left, ctx)?;
let right = self.emit_expression(&bin.right, ctx)?;
let op = match bin.operator {
@@ -67,7 +74,12 @@ impl Emitter {
Expression::ComputedMemberExpression(member) => {
let obj_reg = self.emit_expression(&member.object, ctx)?;
let key_reg = self.emit_expression(&member.expression, ctx)?;
ctx.inst(Inst::new(OpCode::DELETE_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::DELETE_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
));
Ok(obj_reg)
}
Expression::ChainExpression(chain) => {
@@ -77,7 +89,12 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
if member.optional {
let dup_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(dup_reg), Operand::Reg(obj_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(dup_reg),
Operand::Reg(obj_reg),
Operand::None,
));
ctx.inst(Inst::jmp_if_nullish(dup_reg, short_label));
}
let prop_name = member.property.name.as_str();
@@ -89,11 +106,21 @@ impl Emitter {
let obj_reg = self.emit_expression(&member.object, ctx)?;
if member.optional {
let dup_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(dup_reg), Operand::Reg(obj_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(dup_reg),
Operand::Reg(obj_reg),
Operand::None,
));
ctx.inst(Inst::jmp_if_nullish(dup_reg, short_label));
}
let key_reg = self.emit_expression(&member.expression, ctx)?;
ctx.inst(Inst::new(OpCode::DELETE_PROP_DYNAMIC, Operand::Reg(obj_reg), Operand::Reg(obj_reg), Operand::Reg(key_reg)));
ctx.inst(Inst::new(
OpCode::DELETE_PROP_DYNAMIC,
Operand::Reg(obj_reg),
Operand::Reg(obj_reg),
Operand::Reg(key_reg),
));
obj_reg
}
_ => return Err("invalid delete target".into()),
@@ -150,13 +177,23 @@ impl Emitter {
let cons_reg = self.emit_expression(&cond.consequent, ctx)?;
let result_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(cons_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(cons_reg),
Operand::None,
));
ctx.inst(Inst::jmp(end_label));
ctx.labels.set_label_pos(else_label, ctx.insts.len());
let alt_reg = self.emit_expression(&cond.alternate, ctx)?;
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(result_reg), Operand::Reg(alt_reg), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(result_reg),
Operand::Reg(alt_reg),
Operand::None,
));
ctx.labels.set_label_pos(end_label, ctx.insts.len());
Ok(result_reg)
@@ -220,13 +257,18 @@ impl Emitter {
match &update.argument {
SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => {
let name = id.name.as_str();
// Check if this is an upvalue or captured cell reference
// 判断目标是 upvalue 还是被捕获 cell
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 + CONST(1) + ADD/SUB + STORE_UPVALUE
// upvalue:LOAD_UPVALUE + 常量 1 + ADD/SUB + STORE_UPVALUE
let val_reg = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::LOAD_UPVALUE, Operand::Reg(val_reg), Operand::Imm(uv as u16), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_UPVALUE,
Operand::Reg(val_reg),
Operand::Imm(uv as u16),
Operand::None,
));
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));
@@ -236,15 +278,30 @@ impl Emitter {
OpCode::SUB
};
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(val_reg), Operand::Reg(one_reg)));
ctx.inst(Inst::new(OpCode::STORE_UPVALUE, Operand::None, Operand::Reg(val_reg), Operand::Imm(uv as u16)));
ctx.inst(Inst::new(
OpCode::STORE_UPVALUE,
Operand::None,
Operand::Reg(val_reg),
Operand::Imm(uv as u16),
));
Ok(val_reg)
} else if let Some(cell_idx) = captured_cell {
// Captured cell: CELL_GET + CONST(1) + ADD/SUB + CELL_SET
// 被捕获 cell:CELL_GET + 常量 1 + ADD/SUB + CELL_SET
let val_reg = ctx.alloc_reg();
if let Some((binding, _)) = ctx.scopes.symbols.lookup_any_binding(name) {
ctx.inst(Inst::new(OpCode::CELL_GET, Operand::Reg(val_reg), Operand::Reg(binding.reg), Operand::Imm(cell_idx as u16)));
ctx.inst(Inst::new(
OpCode::CELL_GET,
Operand::Reg(val_reg),
Operand::Reg(binding.reg),
Operand::Imm(cell_idx as u16),
));
} else {
ctx.inst(Inst::new(OpCode::CELL_GET, Operand::Reg(val_reg), Operand::None, Operand::Imm(cell_idx as u16)));
ctx.inst(Inst::new(
OpCode::CELL_GET,
Operand::Reg(val_reg),
Operand::None,
Operand::Imm(cell_idx as u16),
));
}
let one_idx = ctx.add_constant(Constant::Int(1));
let one_reg = ctx.alloc_reg();
@@ -255,7 +312,12 @@ impl Emitter {
OpCode::SUB
};
ctx.inst(Inst::new(op, Operand::Reg(val_reg), Operand::Reg(val_reg), Operand::Reg(one_reg)));
ctx.inst(Inst::new(OpCode::CELL_SET, Operand::None, Operand::Reg(val_reg), Operand::Imm(cell_idx as u16)));
ctx.inst(Inst::new(
OpCode::CELL_SET,
Operand::None,
Operand::Reg(val_reg),
Operand::Imm(cell_idx as u16),
));
Ok(val_reg)
} else {
let var_reg = ctx.lookup_or_global(name);
+32 -7
View File
@@ -1,10 +1,10 @@
//! 标签模板表达式 emit:`emit_tagged_template_expression` 构造 template object 并调用标签函数。
use crate::{CompileCtx, Emitter};
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
impl Emitter {
pub(crate) fn emit_tagged_template_expression(
&self, tt: &oxide_parser::TaggedTemplateExpression, ctx: &mut CompileCtx,
@@ -15,7 +15,12 @@ impl Emitter {
let tag_reg = self.emit_expression(&tt.tag, ctx)?;
let cooked_temp = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::NEW_ARRAY, Operand::Reg(cooked_temp), Operand::Imm(quasis.len() as u16), Operand::None));
ctx.inst(Inst::new(
OpCode::NEW_ARRAY,
Operand::Reg(cooked_temp),
Operand::Imm(quasis.len() as u16),
Operand::None,
));
for (i, quasi) in quasis.iter().enumerate() {
let s = quasi.value.cooked.as_ref().map(|c| c.to_string()).unwrap_or_default();
let const_idx = ctx.add_constant(Constant::String(s));
@@ -24,11 +29,21 @@ impl Emitter {
let idx_const = ctx.add_constant(Constant::Int(i as i32));
let idx_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(idx_reg), idx_const));
ctx.inst(Inst::new(OpCode::SET_ELEM, Operand::Reg(cooked_temp), Operand::Reg(idx_reg), Operand::Reg(str_reg)));
ctx.inst(Inst::new(
OpCode::SET_ELEM,
Operand::Reg(cooked_temp),
Operand::Reg(idx_reg),
Operand::Reg(str_reg),
));
}
let raw_temp = ctx.alloc_reg();
ctx.inst(Inst::new(OpCode::NEW_ARRAY, Operand::Reg(raw_temp), Operand::Imm(quasis.len() as u16), Operand::None));
ctx.inst(Inst::new(
OpCode::NEW_ARRAY,
Operand::Reg(raw_temp),
Operand::Imm(quasis.len() as u16),
Operand::None,
));
for (i, quasi) in quasis.iter().enumerate() {
let raw = quasi.value.raw.to_string();
let const_idx = ctx.add_constant(Constant::String(raw));
@@ -37,7 +52,12 @@ impl Emitter {
let idx_const = ctx.add_constant(Constant::Int(i as i32));
let idx_reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(idx_reg), idx_const));
ctx.inst(Inst::new(OpCode::SET_ELEM, Operand::Reg(raw_temp), Operand::Reg(idx_reg), Operand::Reg(str_reg)));
ctx.inst(Inst::new(
OpCode::SET_ELEM,
Operand::Reg(raw_temp),
Operand::Reg(idx_reg),
Operand::Reg(str_reg),
));
}
let mut expr_temps = Vec::new();
@@ -52,7 +72,12 @@ impl Emitter {
expr_slots.push(ctx.alloc_reg());
}
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(cooked_slot), Operand::Reg(cooked_temp), Operand::None));
ctx.inst(Inst::new(
OpCode::LOAD_VAR,
Operand::Reg(cooked_slot),
Operand::Reg(cooked_temp),
Operand::None,
));
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(raw_slot), Operand::Reg(raw_temp), Operand::None));
for (slot, temp) in expr_slots.iter().zip(expr_temps.iter()) {
ctx.inst(Inst::new(OpCode::LOAD_VAR, Operand::Reg(*slot), Operand::Reg(*temp), Operand::None));
@@ -2,9 +2,9 @@
//! 拼接字面量段与内插表达式。
use crate::{CompileCtx, Emitter};
use oxide_bytecode::module::Constant;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::module::Constant;
impl Emitter {
pub(crate) fn emit_template_literal_expression(
@@ -42,12 +42,7 @@ impl Emitter {
}
}
ctx.inst(Inst::template_str(
Operand::Reg(r),
segment_count as u32,
total_len_hint as u16,
&parts,
));
ctx.inst(Inst::template_str(Operand::Reg(r), segment_count as u32, total_len_hint as u16, &parts));
Ok(r)
}
+1 -1
View File
@@ -1,9 +1,9 @@
//! `this` 表达式 emit:`emit_this_expression` 解析当前函数的 this 寄存器。
use crate::{CompileCtx, Emitter};
use oxide_bytecode::opcode::OpCode;
use oxide_ir::inst::Inst;
use oxide_ir::operand::Operand;
use oxide_bytecode::opcode::OpCode;
impl Emitter {
pub(crate) fn emit_this_expression(&self, ctx: &mut CompileCtx) -> Result<u32, String> {