mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
feat: 支持位运算字节码与 ToInt32/ToUint32
This commit is contained in:
@@ -669,6 +669,12 @@ impl Compiler {
|
||||
BinaryOperator::Multiplication => OpCode::MUL,
|
||||
BinaryOperator::Division => OpCode::DIV,
|
||||
BinaryOperator::Remainder => OpCode::MOD,
|
||||
BinaryOperator::BitwiseAnd => OpCode::BIT_AND,
|
||||
BinaryOperator::BitwiseOR => OpCode::BIT_OR,
|
||||
BinaryOperator::BitwiseXOR => OpCode::BIT_XOR,
|
||||
BinaryOperator::ShiftLeft => OpCode::SHL,
|
||||
BinaryOperator::ShiftRight => OpCode::SHR,
|
||||
BinaryOperator::ShiftRightZeroFill => OpCode::USHR,
|
||||
BinaryOperator::Equality => OpCode::EQ,
|
||||
BinaryOperator::Inequality => OpCode::NEQ,
|
||||
BinaryOperator::LessThan => OpCode::LT,
|
||||
@@ -708,6 +714,11 @@ impl Compiler {
|
||||
ctx.emit(opcode::encode(OpCode::NOT, r, arg, 0));
|
||||
Ok(r)
|
||||
}
|
||||
UnaryOperator::BitwiseNot => {
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.emit(opcode::encode(OpCode::BIT_NOT, r, arg, 0));
|
||||
Ok(r)
|
||||
}
|
||||
UnaryOperator::UnaryPlus => {
|
||||
let r = ctx.alloc_reg();
|
||||
ctx.emit(opcode::encode(OpCode::UNARY_PLUS, r, arg, 0));
|
||||
@@ -735,7 +746,6 @@ impl Compiler {
|
||||
}
|
||||
_ => Err("invalid delete target".into()),
|
||||
},
|
||||
_ => Err(format!("unsupported unary operator: {:?}", un.operator)),
|
||||
}
|
||||
}
|
||||
Expression::ConditionalExpression(cond) => {
|
||||
@@ -938,6 +948,12 @@ impl Compiler {
|
||||
|| assign.operator == AssignmentOperator::Division
|
||||
|| assign.operator == AssignmentOperator::Remainder
|
||||
|| assign.operator == AssignmentOperator::Exponential
|
||||
|| assign.operator == AssignmentOperator::BitwiseAnd
|
||||
|| assign.operator == AssignmentOperator::BitwiseOR
|
||||
|| assign.operator == AssignmentOperator::BitwiseXOR
|
||||
|| assign.operator == AssignmentOperator::ShiftLeft
|
||||
|| assign.operator == AssignmentOperator::ShiftRight
|
||||
|| assign.operator == AssignmentOperator::ShiftRightZeroFill
|
||||
{
|
||||
let rhs = self.emit_expression(&assign.right, ctx)?;
|
||||
let name = id_ref.name.as_str();
|
||||
@@ -949,6 +965,12 @@ impl Compiler {
|
||||
AssignmentOperator::Division => OpCode::COMPOUND_DIV,
|
||||
AssignmentOperator::Remainder => OpCode::COMPOUND_MOD,
|
||||
AssignmentOperator::Exponential => OpCode::COMPOUND_EXP,
|
||||
AssignmentOperator::BitwiseAnd => OpCode::COMPOUND_AND,
|
||||
AssignmentOperator::BitwiseOR => OpCode::COMPOUND_OR,
|
||||
AssignmentOperator::BitwiseXOR => OpCode::COMPOUND_XOR,
|
||||
AssignmentOperator::ShiftLeft => OpCode::COMPOUND_SHL,
|
||||
AssignmentOperator::ShiftRight => OpCode::COMPOUND_SHR,
|
||||
AssignmentOperator::ShiftRightZeroFill => OpCode::COMPOUND_USHR,
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"compound assignment operator {:?} not supported",
|
||||
|
||||
@@ -122,6 +122,21 @@ pub enum OpCode {
|
||||
FORK = 0x70,
|
||||
JOIN = 0x71,
|
||||
|
||||
// -- Bitwise (0x80-0x8F) --
|
||||
BIT_AND = 0x80,
|
||||
BIT_OR = 0x81,
|
||||
BIT_XOR = 0x82,
|
||||
SHL = 0x83,
|
||||
SHR = 0x84,
|
||||
USHR = 0x85,
|
||||
BIT_NOT = 0x86,
|
||||
COMPOUND_AND = 0x88,
|
||||
COMPOUND_OR = 0x89,
|
||||
COMPOUND_XOR = 0x8A,
|
||||
COMPOUND_SHL = 0x8B,
|
||||
COMPOUND_SHR = 0x8C,
|
||||
COMPOUND_USHR = 0x8D,
|
||||
|
||||
// ── Misc (0xF0-0xFF) ──
|
||||
NOP = 0xF0,
|
||||
HALT = 0xF1,
|
||||
@@ -250,6 +265,19 @@ impl TryFrom<u8> for OpCode {
|
||||
0x66 => Ok(OpCode::PROFILE_CALL),
|
||||
0x70 => Ok(OpCode::FORK),
|
||||
0x71 => Ok(OpCode::JOIN),
|
||||
0x80 => Ok(OpCode::BIT_AND),
|
||||
0x81 => Ok(OpCode::BIT_OR),
|
||||
0x82 => Ok(OpCode::BIT_XOR),
|
||||
0x83 => Ok(OpCode::SHL),
|
||||
0x84 => Ok(OpCode::SHR),
|
||||
0x85 => Ok(OpCode::USHR),
|
||||
0x86 => Ok(OpCode::BIT_NOT),
|
||||
0x88 => Ok(OpCode::COMPOUND_AND),
|
||||
0x89 => Ok(OpCode::COMPOUND_OR),
|
||||
0x8A => Ok(OpCode::COMPOUND_XOR),
|
||||
0x8B => Ok(OpCode::COMPOUND_SHL),
|
||||
0x8C => Ok(OpCode::COMPOUND_SHR),
|
||||
0x8D => Ok(OpCode::COMPOUND_USHR),
|
||||
0xF0 => Ok(OpCode::NOP),
|
||||
0xF1 => Ok(OpCode::HALT),
|
||||
0xF2 => Ok(OpCode::TYPEOF),
|
||||
@@ -348,6 +376,19 @@ impl fmt::Display for OpCode {
|
||||
OpCode::PROFILE_CALL => "PROFILE_CALL",
|
||||
OpCode::FORK => "FORK",
|
||||
OpCode::JOIN => "JOIN",
|
||||
OpCode::BIT_AND => "BIT_AND",
|
||||
OpCode::BIT_OR => "BIT_OR",
|
||||
OpCode::BIT_XOR => "BIT_XOR",
|
||||
OpCode::SHL => "SHL",
|
||||
OpCode::SHR => "SHR",
|
||||
OpCode::USHR => "USHR",
|
||||
OpCode::BIT_NOT => "BIT_NOT",
|
||||
OpCode::COMPOUND_AND => "COMPOUND_AND",
|
||||
OpCode::COMPOUND_OR => "COMPOUND_OR",
|
||||
OpCode::COMPOUND_XOR => "COMPOUND_XOR",
|
||||
OpCode::COMPOUND_SHL => "COMPOUND_SHL",
|
||||
OpCode::COMPOUND_SHR => "COMPOUND_SHR",
|
||||
OpCode::COMPOUND_USHR => "COMPOUND_USHR",
|
||||
OpCode::NOP => "NOP",
|
||||
OpCode::HALT => "HALT",
|
||||
OpCode::TYPEOF => "TYPEOF",
|
||||
|
||||
@@ -79,6 +79,12 @@ fn compile_binary_ops() {
|
||||
("10 / 2", OpCode::DIV),
|
||||
("7 % 3", OpCode::MOD),
|
||||
("5 - 2", OpCode::SUB),
|
||||
("5 & 3", OpCode::BIT_AND),
|
||||
("5 | 2", OpCode::BIT_OR),
|
||||
("5 ^ 1", OpCode::BIT_XOR),
|
||||
("1 << 3", OpCode::SHL),
|
||||
("-8 >> 1", OpCode::SHR),
|
||||
("-1 >>> 0", OpCode::USHR),
|
||||
];
|
||||
|
||||
for (src, expected_op) in tests {
|
||||
@@ -88,6 +94,15 @@ fn compile_binary_ops() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_bitwise_not() {
|
||||
let module = compile_source("~0");
|
||||
assert!(
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::BIT_NOT),
|
||||
"~0 should emit BIT_NOT opcode"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_ternary_emits_jumps() {
|
||||
let module = compile_source("true ? 1 : 2");
|
||||
@@ -206,6 +221,27 @@ fn compile_compound_exp() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_compound_bitwise_ops() {
|
||||
let tests = [
|
||||
("var x=5; x&=3", OpCode::COMPOUND_AND),
|
||||
("var x=5; x|=2", OpCode::COMPOUND_OR),
|
||||
("var x=5; x^=1", OpCode::COMPOUND_XOR),
|
||||
("var x=1; x<<=5", OpCode::COMPOUND_SHL),
|
||||
("var x=-8; x>>=1", OpCode::COMPOUND_SHR),
|
||||
("var x=-1; x>>>=0", OpCode::COMPOUND_USHR),
|
||||
];
|
||||
|
||||
for (src, expected_op) in tests {
|
||||
let module = compile_source(src);
|
||||
assert!(
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == expected_op),
|
||||
"expected {:?} in '{src}'",
|
||||
expected_op
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_compound_assign_no_error() {
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
|
||||
Reference in New Issue
Block a user