feat: 搭建原生函数基础设施

This commit is contained in:
2026-06-07 01:07:45 +08:00
parent 5e78cb672f
commit 439b61e359
17 changed files with 271 additions and 15 deletions
+17
View File
@@ -57,6 +57,7 @@ pub(crate) struct CompileCtx {
pub(crate) switch_stack: Vec<Label>,
pub(crate) label_counter: u32,
pub(crate) projected_pc: usize,
pub(crate) builtin_reg_map: Vec<(String, u8)>,
}
impl CompileCtx {
@@ -72,6 +73,7 @@ impl CompileCtx {
switch_stack: Vec::new(),
label_counter: 0,
projected_pc: 0,
builtin_reg_map: Vec::new(),
}
}
@@ -164,6 +166,19 @@ impl CompileCtx {
pub(crate) fn current_switch(&self) -> Option<&Label> {
self.switch_stack.last()
}
pub(crate) fn pre_register_builtins(&mut self) {
let builtins = [
"NaN", "undefined", "Object", "Array", "String", "Number", "Boolean",
"Function", "Error", "Math", "JSON", "Promise", "parseInt", "parseFloat",
"isNaN", "isFinite",
];
for name in &builtins {
let reg = self.alloc_reg();
self.symbols.pre_register_global(name, reg);
self.builtin_reg_map.push((name.to_string(), reg));
}
}
}
impl Compiler {
@@ -173,6 +188,7 @@ impl Compiler {
pub fn compile(&self, program: &oxide_parser::Program) -> Result<CompiledModule, String> {
let mut ctx = CompileCtx::new();
ctx.pre_register_builtins();
for stmt in &program.body {
self.count_statement(stmt, &mut ctx);
@@ -205,6 +221,7 @@ impl Compiler {
bytecode: ctx.bytecode,
constants: ctx.constants,
n_registers: ctx.max_regs,
builtin_reg_map: ctx.builtin_reg_map,
})
}
}
+2 -1
View File
@@ -199,13 +199,14 @@ impl Compiler {
}
Expression::CallExpression(call) => {
self.count_expression(&call.callee, ctx);
ctx.alloc_reg();
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
self.count_expression(expr, ctx);
}
}
ctx.alloc_reg();
ctx.projected_pc += 1; // CALL
ctx.projected_pc += 2; // CALL + extension word (arg_count)
}
Expression::AssignmentExpression(assign) => {
if let oxide_parser::AssignmentTarget::StaticMemberExpression(member) = &assign.left
+33 -2
View File
@@ -668,10 +668,10 @@ impl Compiler {
ctx.emit(opcode::encode(op, var_reg, rhs, 0));
Ok(var_reg)
} else {
return Err(format!(
Err(format!(
"compound assignment operator {:?} not supported",
assign.operator
));
))
}
} else {
let val_reg = self.emit_expression(&assign.right, ctx)?;
@@ -738,6 +738,37 @@ impl Compiler {
Ok(r)
}
Expression::ParenthesizedExpression(p) => self.emit_expression(&p.expression, ctx),
Expression::CallExpression(call) => {
let callee_reg = self.emit_expression(&call.callee, ctx)?;
let this_idx = ctx.add_constant(Constant::Undefined);
let this_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(
OpCode::LOAD_CONST,
this_reg,
(this_idx & 0xFF) as u8,
((this_idx >> 8) & 0xFF) as u8,
));
let mut arg_regs = Vec::new();
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
arg_regs.push(self.emit_expression(expr, ctx)?);
}
}
let first_arg_reg = if arg_regs.is_empty() {
0u8
} else {
arg_regs[0]
};
let result_reg = ctx.alloc_reg();
ctx.emit(opcode::encode(
OpCode::CALL,
callee_reg,
this_reg,
first_arg_reg,
));
ctx.emit(arg_regs.len() as u32);
Ok(result_reg)
}
_ => Err(format!("unsupported expression type: {:?}", expr)),
}
}
+8 -1
View File
@@ -125,8 +125,15 @@ fn hash_expression(expr: &Expression, h: &mut rustc_hash::FxHasher) {
std::mem::discriminant(&un.operator).hash(h);
hash_expression(&un.argument, h);
}
Expression::CallExpression(_) => {
Expression::CallExpression(call) => {
2u8.hash(h);
(call.arguments.len() as u32).hash(h);
hash_expression(&call.callee, h);
for arg in &call.arguments {
if let Some(expr) = arg.as_expression() {
hash_expression(expr, h);
}
}
}
Expression::LogicalExpression(log) => {
3u8.hash(h);
+1
View File
@@ -16,6 +16,7 @@ pub struct CompiledModule {
pub bytecode: Vec<opcode::Instr>,
pub constants: Vec<Constant>,
pub n_registers: u8,
pub builtin_reg_map: Vec<(String, u8)>,
}
impl fmt::Display for CompiledModule {
@@ -73,6 +73,13 @@ impl SymbolTable {
reg_for_new
}
pub fn pre_register_global(&mut self, name: &str, reg: u8) {
self.scopes[0].entry(name.to_string()).or_insert(Binding {
reg,
initialized: true,
});
}
pub fn init_var(&mut self, name: &str) {
let current = self.scopes.last_mut().unwrap();
if let Some(b) = current.get_mut(name) {