use crate::executor::JITExecutor;
use shape_runtime::engine::{ProgramExecutor, ShapeEngine};
use shape_runtime::initialize_shared_runtime;
use shape_wire::WireValue;
fn jit_eval(source: &str) -> WireValue {
let _ = initialize_shared_runtime();
let mut engine = ShapeEngine::new().expect("engine creation failed");
let program = shape_ast::parse_program(source).expect("parse failed");
let result = JITExecutor::new()
.execute_program(&mut engine, &program)
.expect("JIT execution failed");
result.wire_value
}
fn jit_expect_int(source: &str, expected: i64) {
match jit_eval(source) {
WireValue::Integer(n) => {
assert_eq!(n, expected, "Expected integer {}, got {}", expected, n);
}
WireValue::Number(n) => {
assert!(
(n - expected as f64).abs() < 1e-9,
"Expected integer {} (got Number {})",
expected,
n
);
}
other => panic!("Expected Integer({}), got {:?}", expected, other),
}
}
fn jit_expect_number(source: &str, expected: f64) {
match jit_eval(source) {
WireValue::Number(n) => {
assert!(
(n - expected).abs() < 1e-9,
"Expected number {}, got {}",
expected,
n
);
}
WireValue::Integer(n) => {
assert!(
(n as f64 - expected).abs() < 1e-9,
"Expected number {} (got Integer {})",
expected,
n
);
}
other => panic!("Expected Number({}), got {:?}", expected, other),
}
}
fn jit_expect_bool(source: &str, expected: bool) {
match jit_eval(source) {
WireValue::Bool(b) => {
assert_eq!(b, expected, "Expected bool {}, got {}", expected, b);
}
other => panic!("Expected Bool({}), got {:?}", expected, other),
}
}
#[test]
fn jit_field_ref_mut_int_mutates_in_place() {
jit_expect_int(
r#"
type Box { value: int }
fn bump(&mut r) { r = r + 1 }
let mut b = Box { value: 10 }
bump(&mut b.value)
b.value
"#,
11,
);
}
#[test]
fn jit_field_ref_mut_number_mutates_in_place() {
jit_expect_number(
r#"
type Pt { x: number }
fn bump(&mut r) { r = r + 1.0 }
let mut p = Pt { x: 5.0 }
bump(&mut p.x)
p.x
"#,
6.0,
);
}
#[test]
fn jit_field_ref_shared_read_through() {
jit_expect_int(
r#"
type Box { value: int }
fn readit(&r) -> int { r }
let b = Box { value: 77 }
readit(&b.value)
"#,
77,
);
}
#[test]
fn jit_field_ref_mut_targets_correct_slot() {
jit_expect_int(
r#"
type Rec { a: int, b: int, c: int }
fn bump(&mut r) { r = r + 100 }
let mut rec = Rec { a: 1, b: 2, c: 3 }
bump(&mut rec.b)
rec.a + rec.b + rec.c
"#,
106,
);
}
#[test]
fn jit_field_ref_mut_last_field() {
jit_expect_int(
r#"
type Rec { a: int, b: int, c: int }
fn bump(&mut r) { r = r + 7 }
let mut rec = Rec { a: 1, b: 2, c: 3 }
bump(&mut rec.c)
rec.c
"#,
10,
);
}
#[test]
fn jit_field_ref_sequential_calls_compose() {
jit_expect_int(
r#"
type Box { value: int }
fn bump(&mut r) { r = r + 1 }
let mut b = Box { value: 0 }
bump(&mut b.value)
bump(&mut b.value)
bump(&mut b.value)
b.value
"#,
3,
);
}
#[test]
fn jit_field_ref_mut_bool_field() {
jit_expect_bool(
r#"
type Flag { on: bool }
fn flip(&mut r) { r = !r }
let mut f = Flag { on: false }
flip(&mut f.on)
f.on
"#,
true,
);
}
#[test]
fn jit_field_ref_then_plain_field_access() {
jit_expect_int(
r#"
type Box { value: int }
fn bump(&mut r) { r = r + 5 }
let mut b = Box { value: 10 }
bump(&mut b.value)
b.value = b.value * 2
b.value
"#,
30,
);
}