mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
refactor: 拆分 oxide_emit 为独立 emit pass crate(依赖倒置)
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
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_parser::Expression;
|
||||
|
||||
impl Emitter {
|
||||
pub(crate) fn emit_literal(&self, expr: &Expression, ctx: &mut CompileCtx) -> Result<u8, String> {
|
||||
match expr {
|
||||
Expression::NumericLiteral(n) => self.emit_numeric_literal_expression(n, ctx),
|
||||
Expression::StringLiteral(s) => self.emit_string_literal_expression(s, ctx),
|
||||
Expression::BooleanLiteral(b) => self.emit_boolean_literal_expression(b, ctx),
|
||||
Expression::NullLiteral(_) => self.emit_null_literal_expression(ctx),
|
||||
Expression::RegExpLiteral(lit) => self.emit_reg_exp_literal_expression(lit, ctx),
|
||||
_ => self.emit_unsupported_expression(expr, ctx),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_numeric_literal_expression(
|
||||
&self, n: &oxide_parser::NumericLiteral, ctx: &mut CompileCtx,
|
||||
) -> Result<u8, String> {
|
||||
let idx = if is_int_literal(n.value) {
|
||||
ctx.add_constant(Constant::Int(n.value as i32))
|
||||
} else {
|
||||
ctx.add_constant(Constant::Number(n.value))
|
||||
};
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(r as u32), idx));
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn emit_string_literal_expression(
|
||||
&self, s: &oxide_parser::StringLiteral, ctx: &mut CompileCtx,
|
||||
) -> Result<u8, String> {
|
||||
let idx = ctx.add_constant(Constant::String(s.value.to_string()));
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(r as u32), idx));
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn emit_boolean_literal_expression(
|
||||
&self, b: &oxide_parser::BooleanLiteral, ctx: &mut CompileCtx,
|
||||
) -> Result<u8, String> {
|
||||
let idx = ctx.add_constant(Constant::Boolean(b.value));
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(r as u32), idx));
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn emit_null_literal_expression(&self, ctx: &mut CompileCtx) -> Result<u8, String> {
|
||||
let idx = ctx.add_constant(Constant::Null);
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(r as u32), idx));
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
fn emit_reg_exp_literal_expression(
|
||||
&self, lit: &oxide_parser::RegExpLiteral, ctx: &mut CompileCtx,
|
||||
) -> Result<u8, String> {
|
||||
if let Some(raw) = &lit.raw {
|
||||
let raw_str = raw.to_string();
|
||||
if raw_str.len() >= 2 && raw_str.starts_with('/') {
|
||||
let last_slash = raw_str.rfind('/').unwrap_or(raw_str.len() - 1);
|
||||
let pattern = raw_str[1..last_slash].to_string();
|
||||
let flags = raw_str[last_slash + 1..].to_string();
|
||||
let pat_ci = ctx.add_constant(Constant::String(pattern));
|
||||
let pat_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(pat_reg as u32), pat_ci));
|
||||
let flags_ci = ctx.add_constant(Constant::String(flags));
|
||||
let flags_reg = ctx.alloc_reg();
|
||||
ctx.inst(Inst::load_const(Operand::Reg(flags_reg as u32), flags_ci));
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.inst(Inst::new(OpCode::CREATE_REGEXP, Operand::Reg(r as u32), Operand::Reg(pat_reg as u32), Operand::Reg(flags_reg as u32)));
|
||||
Ok(r)
|
||||
} else {
|
||||
Err(format!("unsupported regexp literal: {:?}", lit))
|
||||
}
|
||||
} else {
|
||||
Err(format!("unsupported regexp literal: {:?}", lit))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user