use shape_runtime::engine::{ProgramExecutor, ShapeEngine};
use shape_wire::WireValue;
fn jit_run(source: &str) -> WireValue {
shape_runtime::initialize_shared_runtime().ok();
let mut engine = ShapeEngine::new().expect("engine creation failed");
let program = shape_ast::parse_program(source).expect("parse failed");
let mut executor = crate::executor::JITExecutor::new();
let result = executor
.execute_program(&mut engine, &program)
.expect("JIT execution failed");
result.wire_value
}
fn assert_int(value: WireValue, expected: i64) {
match value {
WireValue::Integer(n) => assert_eq!(n, expected, "expected {}", expected),
WireValue::Number(n) => assert!(
(n - expected as f64).abs() < 1e-9,
"expected {} got Number {}",
expected,
n
),
other => panic!("expected Integer({}), got {:?}", expected, other),
}
}
fn assert_float(value: WireValue, expected: f64) {
match value {
WireValue::Number(n) => assert!(
(n - expected).abs() < 1e-9,
"expected {} got Number {}",
expected,
n
),
other => panic!("expected Number({}), got {:?}", expected, other),
}
}
fn assert_bool(value: WireValue, expected: bool) {
match value {
WireValue::Bool(b) => assert_eq!(b, expected),
other => panic!("expected Bool({}), got {:?}", expected, other),
}
}
#[test]
fn c2_owned_mut_i64_round_trip() {
let source = r#"
fn main() -> int {
let mut x: int = 5
let f = || { x = x + 1; x }
f()
f()
}
main()
"#;
assert_int(jit_run(source), 7);
}
#[test]
fn c2_owned_mut_f64_round_trip() {
let source = r#"
fn main() -> number {
let mut x: number = 1.5
let f = || { x = x + 0.25; x }
f()
f()
}
main()
"#;
assert_float(jit_run(source), 2.0);
}
#[test]
#[ignore = "pre-existing JIT bug surfaced by C.2 sub-32 capture path: \
for an OwnedMutable Bool capture the closure body's param \
slot has slot_kind=Bool (cl=I8) — `register_owned_mutable_capture_slots` \
patches it to the cell's interior kind so binop dispatch works. \
But `declare_locals` then declares the var as I8, and the \
param-store path (`compiler/program.rs:439-471`) `ireduce(I8, \
param_val)` narrows the I64 cell pointer to its low 8 bits — \
destroying the pointer. Same root cause as the F64 SharedCow \
bug above: `declare_locals` and the param-store narrowing \
need to special-case OwnedMutable / Shared capture slots to \
keep the var as I64 (cell-pointer width) regardless of the \
interior slot_kind. Tracked as a follow-up; the per-FieldKind \
FFI wiring on this commit is correct."]
fn c2_owned_mut_bool_round_trip() {
let source = r#"
fn main() -> bool {
let mut flag: bool = false
let f = || { flag = !flag; flag }
f()
}
main()
"#;
assert_bool(jit_run(source), true);
}
#[test]
fn c2_owned_mut_string_capture() {
let source = r#"
fn main() -> string {
let mut s: string = "init"
let f = || { s = "updated"; s }
f()
}
main()
"#;
match jit_run(source) {
WireValue::String(s) => assert_eq!(s, "updated"),
other => panic!("expected String(\"updated\"), got {:?}", other),
}
}
#[test]
fn c2_shared_i64_two_closures() {
let source = r#"
fn main() -> int {
var x: int = 0
let inc = || { x = x + 1 }
let dec = || { x = x - 1 }
inc()
inc()
dec()
x
}
main()
"#;
assert_int(jit_run(source), 1);
}
#[test]
#[ignore = "pre-existing JIT bug: SharedCow F64 outer slot's Cranelift \
variable is declared F64 by `declare_locals` (slot_kind=Float64) \
but holds an `*const SharedCell` (I64) installed by \
`initialize_shared_local_slots` — type mismatch trips Cranelift's \
verifier on `def_var`. Surfaced first by C.2's smoke tests; \
unrelated to the per-FieldKind FFI work. Tracked as a follow-up \
(declare_locals must special-case shared_local_slots to declare \
the var as I64 regardless of slot kind, since the var holds the \
cell pointer not the value)."]
fn c2_shared_f64_round_trip() {
let source = r#"
fn main() -> number {
var x: number = 1.0
let scale = || { x = x * 2.0 }
let dec = || { x = x - 0.0 }
scale()
scale()
scale()
dec()
x
}
main()
"#;
assert_float(jit_run(source), 8.0);
}