style: 减少自动格式化换行
This commit is contained in:
@@ -27,29 +27,20 @@ fn hash_arrow_expression_body() {
|
||||
fn hash_arrow_different_params() {
|
||||
let hash_a = parse_to_hash("var f = (x) => x;");
|
||||
let hash_b = parse_to_hash("var f = (x, y) => x;");
|
||||
assert_ne!(
|
||||
hash_a, hash_b,
|
||||
"different param counts must produce different hashes"
|
||||
);
|
||||
assert_ne!(hash_a, hash_b, "different param counts must produce different hashes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_arrow_vs_regular_function() {
|
||||
let hash_a = parse_to_hash("var f = () => 42;");
|
||||
let hash_b = parse_to_hash("var f = function() { return 42; };");
|
||||
assert_ne!(
|
||||
hash_a, hash_b,
|
||||
"arrow and regular functions must have different hashes"
|
||||
);
|
||||
assert_ne!(hash_a, hash_b, "arrow and regular functions must have different hashes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_arrow_block_body() {
|
||||
let hash = parse_to_hash("var f = (a, b) => { return a + b; };");
|
||||
assert!(
|
||||
hash != 0,
|
||||
"arrow with block body should produce a non-zero hash"
|
||||
);
|
||||
assert!(hash != 0, "arrow with block body should produce a non-zero hash");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -57,10 +48,7 @@ fn hash_arrow_same_shape() {
|
||||
// Same structural shape: different variable name, same arrow expression
|
||||
let hash_a = parse_to_hash("var f = () => 1 + 2;");
|
||||
let hash_b = parse_to_hash("var g = () => 1 + 2;");
|
||||
assert_eq!(
|
||||
hash_a, hash_b,
|
||||
"same-shaped arrow functions should have same hash"
|
||||
);
|
||||
assert_eq!(hash_a, hash_b, "same-shaped arrow functions should have same hash");
|
||||
}
|
||||
|
||||
// -- Arrow function compilation tests --
|
||||
@@ -70,20 +58,14 @@ fn compile_arrow_expression_body() {
|
||||
let module = compile_source("var f = () => 42; f();");
|
||||
// Verify the sub_module for the arrow is marked as is_arrow
|
||||
let arrow_found = module.sub_modules.iter().any(|m| m.is_arrow);
|
||||
assert!(
|
||||
arrow_found,
|
||||
"arrow function sub_module should have is_arrow=true"
|
||||
);
|
||||
assert!(arrow_found, "arrow function sub_module should have is_arrow=true");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_arrow_block_body() {
|
||||
let module = compile_source("var f = (a, b) => { return a + b; }; f(1, 2);");
|
||||
let arrow_found = module.sub_modules.iter().any(|m| m.is_arrow);
|
||||
assert!(
|
||||
arrow_found,
|
||||
"arrow with block body should have is_arrow=true"
|
||||
);
|
||||
assert!(arrow_found, "arrow with block body should have is_arrow=true");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -94,10 +76,7 @@ fn compile_arrow_name_inference() {
|
||||
.sub_modules
|
||||
.iter()
|
||||
.any(|m| m.is_arrow && m.function_name.as_deref() == Some("myArrow"));
|
||||
assert!(
|
||||
named,
|
||||
"arrow function should have function_name='myArrow' from D-04 inference"
|
||||
);
|
||||
assert!(named, "arrow function should have function_name='myArrow' from D-04 inference");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -105,20 +84,14 @@ fn compile_regular_function_not_arrow() {
|
||||
let module = compile_source("var f = function() { return 42; }; f();");
|
||||
// Regular FunctionExpression should NOT have is_arrow=true
|
||||
let has_arrow = module.sub_modules.iter().any(|m| m.is_arrow);
|
||||
assert!(
|
||||
!has_arrow,
|
||||
"regular function expression should not be marked as arrow"
|
||||
);
|
||||
assert!(!has_arrow, "regular function expression should not be marked as arrow");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_arrow_single_param_no_parens() {
|
||||
let module = compile_source("var double = x => x * 2; double(5);");
|
||||
let arrow_found = module.sub_modules.iter().any(|m| m.is_arrow);
|
||||
assert!(
|
||||
arrow_found,
|
||||
"single-param arrow without parens should compile"
|
||||
);
|
||||
assert!(arrow_found, "single-param arrow without parens should compile");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -25,20 +25,14 @@ fn compile_constants() {
|
||||
let module = compile_source("42");
|
||||
|
||||
assert!(!module.constants.is_empty());
|
||||
assert_eq!(
|
||||
module.constants[0],
|
||||
oxide_compiler::compiler::Constant::Int(42)
|
||||
);
|
||||
assert_eq!(module.constants[0], oxide_compiler::compiler::Constant::Int(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_negation() {
|
||||
let module = compile_source("-5");
|
||||
|
||||
let has_neg = module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::NEG);
|
||||
let has_neg = module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::NEG);
|
||||
assert!(has_neg);
|
||||
}
|
||||
|
||||
@@ -65,10 +59,7 @@ fn compile_binary_ops() {
|
||||
|
||||
for (src, expected_op) in tests {
|
||||
let module = compile_source(src);
|
||||
let has_op = module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == expected_op);
|
||||
let has_op = module.bytecode.iter().any(|&i| opcode::opcode(i) == expected_op);
|
||||
assert!(has_op, "expected {:?} in '{src}'", expected_op);
|
||||
}
|
||||
}
|
||||
@@ -77,10 +68,7 @@ fn compile_binary_ops() {
|
||||
fn compile_ternary_emits_jumps() {
|
||||
let module = compile_source("true ? 1 : 2");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
"ternary should contain JMP_IF_FALSE"
|
||||
);
|
||||
}
|
||||
@@ -89,10 +77,7 @@ fn compile_ternary_emits_jumps() {
|
||||
fn compile_logical_not() {
|
||||
let module = compile_source("!true");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::NOT),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::NOT),
|
||||
"!true should emit NOT opcode"
|
||||
);
|
||||
}
|
||||
@@ -101,10 +86,7 @@ fn compile_logical_not() {
|
||||
fn compile_logical_and_simple() {
|
||||
let module = compile_source("1 && 2");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::AND),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::AND),
|
||||
"simple && should emit AND opcode"
|
||||
);
|
||||
}
|
||||
@@ -113,10 +95,7 @@ fn compile_logical_and_simple() {
|
||||
fn compile_logical_or_simple() {
|
||||
let module = compile_source("0 || 1");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::OR),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::OR),
|
||||
"simple || should emit OR opcode"
|
||||
);
|
||||
}
|
||||
@@ -126,20 +105,14 @@ fn regression_coalesce_consistency() {
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
compile_source("a ?? b");
|
||||
});
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"a ?? b should produce an error (not silently misbehave)"
|
||||
);
|
||||
assert!(result.is_err(), "a ?? b should produce an error (not silently misbehave)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_strict_eq() {
|
||||
let module = compile_source("1 === 2");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::STRICT_EQ),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::STRICT_EQ),
|
||||
"1 === 2 should emit STRICT_EQ opcode"
|
||||
);
|
||||
}
|
||||
@@ -148,10 +121,7 @@ fn compile_strict_eq() {
|
||||
fn compile_strict_neq() {
|
||||
let module = compile_source("1 !== 2");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::STRICT_NEQ),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::STRICT_NEQ),
|
||||
"1 !== 2 should emit STRICT_NEQ opcode"
|
||||
);
|
||||
}
|
||||
@@ -160,10 +130,7 @@ fn compile_strict_neq() {
|
||||
fn compile_unary_plus() {
|
||||
let module = compile_source("+'hello'");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::UNARY_PLUS),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::UNARY_PLUS),
|
||||
"+'hello' should emit UNARY_PLUS opcode"
|
||||
);
|
||||
}
|
||||
@@ -172,17 +139,11 @@ fn compile_unary_plus() {
|
||||
fn compile_typeof_strict_eq() {
|
||||
let module = compile_source("typeof 42 === 'number'");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::TYPEOF),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::TYPEOF),
|
||||
"should emit TYPEOF opcode"
|
||||
);
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::STRICT_EQ),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::STRICT_EQ),
|
||||
"should emit STRICT_EQ opcode"
|
||||
);
|
||||
}
|
||||
@@ -207,10 +168,7 @@ fn compile_unary_plus_no_error() {
|
||||
fn compile_compound_add() {
|
||||
let module = compile_source("var x=0; x+=1");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::COMPOUND_ADD),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::COMPOUND_ADD),
|
||||
"x+=1 should emit COMPOUND_ADD opcode"
|
||||
);
|
||||
}
|
||||
@@ -219,10 +177,7 @@ fn compile_compound_add() {
|
||||
fn compile_compound_exp() {
|
||||
let module = compile_source("var x=0; x**=2");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::COMPOUND_EXP),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::COMPOUND_EXP),
|
||||
"x**=2 should emit COMPOUND_EXP opcode"
|
||||
);
|
||||
}
|
||||
@@ -247,10 +202,7 @@ fn compile_compound_exp_no_error() {
|
||||
fn compile_inc_pre() {
|
||||
let module = compile_source("++x");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::INC_PRE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::INC_PRE),
|
||||
"++x should emit INC_PRE opcode"
|
||||
);
|
||||
}
|
||||
@@ -259,10 +211,7 @@ fn compile_inc_pre() {
|
||||
fn compile_inc_post() {
|
||||
let module = compile_source("x++");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::INC_POST),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::INC_POST),
|
||||
"x++ should emit INC_POST opcode"
|
||||
);
|
||||
}
|
||||
@@ -287,14 +236,8 @@ fn compile_dec_no_error() {
|
||||
fn compile_inc_dec_diff_opcodes() {
|
||||
let m1 = compile_source("++x");
|
||||
let m2 = compile_source("--x");
|
||||
let has_inc_pre = m1
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::INC_PRE);
|
||||
let has_dec_pre = m2
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::DEC_PRE);
|
||||
let has_inc_pre = m1.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::INC_PRE);
|
||||
let has_dec_pre = m2.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::DEC_PRE);
|
||||
assert!(has_inc_pre, "++x should emit INC_PRE");
|
||||
assert!(has_dec_pre, "--x should emit DEC_PRE");
|
||||
}
|
||||
@@ -303,10 +246,7 @@ fn compile_inc_dec_diff_opcodes() {
|
||||
fn compile_member_inc() {
|
||||
let module = compile_source("var obj={x:1}; obj.x++");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::MEMBER_INC),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::MEMBER_INC),
|
||||
"obj.x++ should emit MEMBER_INC"
|
||||
);
|
||||
}
|
||||
@@ -315,10 +255,7 @@ fn compile_member_inc() {
|
||||
fn compile_dyn_member_inc() {
|
||||
let module = compile_source("var obj={a:3}; var k='a'; obj[k]++");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::DYN_MEMBER_INC),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::DYN_MEMBER_INC),
|
||||
"obj[k]++ should emit DYN_MEMBER_INC"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,7 @@ fn compile_source(source: &str) -> oxide_compiler::module::CompiledModule {
|
||||
fn compile_var_declaration() {
|
||||
let module = compile_source("var x = 42;");
|
||||
assert!(!module.bytecode.is_empty());
|
||||
assert_eq!(
|
||||
module.constants[0],
|
||||
oxide_compiler::compiler::Constant::Int(42)
|
||||
);
|
||||
assert_eq!(module.constants[0], oxide_compiler::compiler::Constant::Int(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -29,27 +26,18 @@ fn compile_return_nothing() {
|
||||
#[test]
|
||||
fn compile_return_value() {
|
||||
let module = compile_source("function f() { return 42; }");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"function declaration should produce bytecode"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "function declaration should produce bytecode");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_if_else_emits_jmp_if_false() {
|
||||
let module = compile_source("if (true) { 1 } else { 2 }");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
"if/else should contain JMP_IF_FALSE"
|
||||
);
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP),
|
||||
"if/else should contain JMP"
|
||||
);
|
||||
}
|
||||
@@ -57,17 +45,10 @@ fn compile_if_else_emits_jmp_if_false() {
|
||||
#[test]
|
||||
fn compile_while_emits_jump_back() {
|
||||
let module = compile_source("while (true) { 1 }");
|
||||
let jmp_ops: Vec<_> = module
|
||||
.bytecode
|
||||
.iter()
|
||||
.filter(|&&i| opcode::opcode(i) == OpCode::JMP)
|
||||
.collect();
|
||||
let jmp_ops: Vec<_> = module.bytecode.iter().filter(|&&i| opcode::opcode(i) == OpCode::JMP).collect();
|
||||
assert!(!jmp_ops.is_empty(), "while should contain JMP (backward)");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
"while should contain JMP_IF_FALSE"
|
||||
);
|
||||
}
|
||||
@@ -76,10 +57,7 @@ fn compile_while_emits_jump_back() {
|
||||
fn compile_for_emits_jumps() {
|
||||
let module = compile_source("for (i=0; i<3; i=i+1) { 1 }");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
"for should contain JMP_IF_FALSE"
|
||||
);
|
||||
}
|
||||
@@ -87,19 +65,13 @@ fn compile_for_emits_jumps() {
|
||||
#[test]
|
||||
fn compile_break_in_loop() {
|
||||
let module = compile_source("while (true) { break; }");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"break should compile without error"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "break should compile without error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_continue_in_loop() {
|
||||
let module = compile_source("while (true) { continue; }");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"continue should compile without error"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "continue should compile without error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -126,10 +98,7 @@ fn compile_nested_if() {
|
||||
.iter()
|
||||
.filter(|&&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE)
|
||||
.count();
|
||||
assert!(
|
||||
jmp_if_false_count >= 2,
|
||||
"nested if should have 2+ JMP_IF_FALSE"
|
||||
);
|
||||
assert!(jmp_if_false_count >= 2, "nested if should have 2+ JMP_IF_FALSE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -143,10 +112,7 @@ fn regression_for_var_init() {
|
||||
let module = compile_source("for (var i = 0; i < 3; i = i + 1) {}");
|
||||
assert!(!module.bytecode.is_empty(), "for(var) init should compile");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_FALSE),
|
||||
"for(var) init should contain JMP_IF_FALSE"
|
||||
);
|
||||
}
|
||||
@@ -165,26 +131,16 @@ fn regression_var_decl_counter_no_init() {
|
||||
#[test]
|
||||
fn regression_redundant_jmp_if_without_else() {
|
||||
let module = compile_source("if (true) { 1 }");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"if without else should compile"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "if without else should compile");
|
||||
let last = opcode::opcode(*module.bytecode.last().unwrap());
|
||||
assert_eq!(
|
||||
last,
|
||||
OpCode::HALT,
|
||||
"final opcode should be HALT, not dangling JMP"
|
||||
);
|
||||
assert_eq!(last, OpCode::HALT, "final opcode should be HALT, not dangling JMP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_do_while_emits_jmp_if_true() {
|
||||
let module = compile_source("do { 1 } while (true)");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_TRUE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_TRUE),
|
||||
"do-while should contain JMP_IF_TRUE"
|
||||
);
|
||||
}
|
||||
@@ -204,36 +160,24 @@ fn compile_do_while_emits_body_before_test() {
|
||||
#[test]
|
||||
fn compile_do_while_break() {
|
||||
let module = compile_source("do { break; } while (true)");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"do-while with break should compile"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "do-while with break should compile");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_do_while_continue() {
|
||||
let module = compile_source("var x = 0; do { continue; } while (x < 5)");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"do-while with continue should compile"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "do-while with continue should compile");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn compile_for_in_emits_opcodes() {
|
||||
let module = compile_source("var obj={a:1}; for (k in obj) {}");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::FOR_IN_INIT),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::FOR_IN_INIT),
|
||||
"for-in should emit FOR_IN_INIT"
|
||||
);
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::FOR_IN_NEXT),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::FOR_IN_NEXT),
|
||||
"for-in should emit FOR_IN_NEXT"
|
||||
);
|
||||
}
|
||||
@@ -254,10 +198,7 @@ fn compile_for_in_let_decl() {
|
||||
fn compile_switch_emits_jmp_if_true() {
|
||||
let module = compile_source("var x=0; switch(x){case 1:1;case 2:2;}");
|
||||
assert!(
|
||||
module
|
||||
.bytecode
|
||||
.iter()
|
||||
.any(|&i| opcode::opcode(i) == OpCode::JMP_IF_TRUE),
|
||||
module.bytecode.iter().any(|&i| opcode::opcode(i) == OpCode::JMP_IF_TRUE),
|
||||
"switch should emit JMP_IF_TRUE"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,17 +23,10 @@ fn structural_hash_hit() {
|
||||
let allocator = Allocator::default();
|
||||
let program = oxide_parser::parse(&allocator, "1 + 2").expect("parse failed");
|
||||
|
||||
let m1 = forge
|
||||
.get_or_compile(&program, &compiler)
|
||||
.expect("first compile");
|
||||
let m2 = forge
|
||||
.get_or_compile(&program, &compiler)
|
||||
.expect("second compile");
|
||||
let m1 = forge.get_or_compile(&program, &compiler).expect("first compile");
|
||||
let m2 = forge.get_or_compile(&program, &compiler).expect("second compile");
|
||||
|
||||
assert_eq!(
|
||||
(m1.bytecode.len(), m1.n_registers),
|
||||
(m2.bytecode.len(), m2.n_registers)
|
||||
);
|
||||
assert_eq!((m1.bytecode.len(), m1.n_registers), (m2.bytecode.len(), m2.n_registers));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -75,27 +68,18 @@ fn structural_hash_different_shape() {
|
||||
fn regression_forstatement_hash() {
|
||||
let hash_a = parse_to_hash("for(i=0;i<3;i++){1}");
|
||||
let hash_b = parse_to_hash("for(;;){1}");
|
||||
assert_ne!(
|
||||
hash_a, hash_b,
|
||||
"different for-loop init/test/update must produce different hashes"
|
||||
);
|
||||
assert_ne!(hash_a, hash_b, "different for-loop init/test/update must produce different hashes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_conditionalexpression_hash() {
|
||||
let hash_a = parse_to_hash("a?1:2");
|
||||
let hash_b = parse_to_hash("a?3:4");
|
||||
assert_ne!(
|
||||
hash_a, hash_b,
|
||||
"different ternary branches must produce different hashes"
|
||||
);
|
||||
assert_ne!(hash_a, hash_b, "different ternary branches must produce different hashes");
|
||||
|
||||
let hash_c = parse_to_hash("a?1:2");
|
||||
let hash_d = parse_to_hash("a?1:2||3");
|
||||
assert_ne!(
|
||||
hash_c, hash_d,
|
||||
"different expression types with same test must produce different hashes"
|
||||
);
|
||||
assert_ne!(hash_c, hash_d, "different expression types with same test must produce different hashes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -13,10 +13,7 @@ fn compile_source(source: &str) -> oxide_compiler::module::CompiledModule {
|
||||
fn symbol_table_declare_and_lookup() {
|
||||
let module = compile_source("var x = 42;");
|
||||
assert!(!module.bytecode.is_empty());
|
||||
assert_eq!(
|
||||
module.constants[0],
|
||||
oxide_compiler::compiler::Constant::Int(42)
|
||||
);
|
||||
assert_eq!(module.constants[0], oxide_compiler::compiler::Constant::Int(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -36,10 +33,7 @@ fn symbol_table_tdz_global_shadow() {
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
compile_source("var x = 1; { var x = x; }");
|
||||
});
|
||||
assert!(
|
||||
result.is_err(),
|
||||
"TDZ: accessing x in its own initializer inside a block should error"
|
||||
);
|
||||
assert!(result.is_err(), "TDZ: accessing x in its own initializer inside a block should error");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -56,8 +50,5 @@ fn symbol_table_duplicate_var() {
|
||||
#[test]
|
||||
fn symbol_table_undeclared_auto_global() {
|
||||
let module = compile_source("x = 5;");
|
||||
assert!(
|
||||
!module.bytecode.is_empty(),
|
||||
"undeclared assignment should auto-create global"
|
||||
);
|
||||
assert!(!module.bytecode.is_empty(), "undeclared assignment should auto-create global");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user