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_eval_err(source: &str) -> String {
let _ = initialize_shared_runtime();
let mut engine = ShapeEngine::new().expect("engine creation failed");
let program = shape_ast::parse_program(source).expect("parse failed");
match JITExecutor::new().execute_program(&mut engine, &program) {
Ok(result) => panic!(
"expected a runtime error, but the program ran cleanly: {:?}",
result.wire_value
),
Err(e) => format!("{}", e),
}
}
fn as_f64(val: WireValue) -> f64 {
match val {
WireValue::Number(n) => n,
WireValue::Integer(n) => n as f64,
other => panic!("expected number/integer, got {:?}", other),
}
}
fn as_i64(val: WireValue) -> i64 {
match val {
WireValue::Integer(n) => n,
WireValue::Number(n) => n as i64,
other => panic!("expected integer/number, got {:?}", other),
}
}
fn as_bool(val: WireValue) -> bool {
match val {
WireValue::Bool(b) => b,
other => panic!("expected bool, got {:?}", other),
}
}
#[test]
fn v2_array_f64_index_sum_two_elements() {
let v = jit_eval(
r#"
let arr: Array<number> = [1.0, 2.0, 3.0]
arr[0] + arr[1]
"#,
);
assert!((as_f64(v) - 3.0).abs() < 1e-9);
}
#[test]
fn v2_array_f64_index_each_element() {
let v = jit_eval(
r#"
let arr: Array<number> = [1.5, 2.5, 3.5]
arr[0] + arr[1] + arr[2]
"#,
);
assert!((as_f64(v) - 7.5).abs() < 1e-9);
}
#[test]
fn v2_array_f64_length() {
let v = jit_eval(
r#"
let arr: Array<number> = [10.0, 20.0, 30.0, 40.0]
arr.length
"#,
);
assert_eq!(as_i64(v), 4);
}
#[test]
fn v2_array_i64_index_first_element() {
let v = jit_eval(
r#"
let arr: Array<int> = [10, 20, 30]
arr[0]
"#,
);
assert_eq!(as_i64(v), 10);
}
#[test]
fn v2_array_i64_index_sum() {
let v = jit_eval(
r#"
let arr: Array<int> = [10, 20, 30]
arr[0] + arr[1] + arr[2]
"#,
);
assert_eq!(as_i64(v), 60);
}
#[test]
fn v2_array_i64_length() {
let v = jit_eval(
r#"
let arr: Array<int> = [1, 2, 3, 4, 5]
arr.length
"#,
);
assert_eq!(as_i64(v), 5);
}
#[test]
fn v2_array_i32_index_and_length() {
let v = jit_eval(
r#"
let arr: Array<i32> = [7, 11, 13]
arr.length
"#,
);
assert_eq!(as_i64(v), 3);
}
#[test]
fn v2_array_bool_fallback_first_element() {
let v = jit_eval(
r#"
let arr = [true, false, true]
arr[0]
"#,
);
assert_eq!(as_bool(v), true);
}
#[test]
fn v2_array_f64_out_of_bounds_raises_error() {
let msg = jit_eval_err(
r#"
let arr: Array<number> = [1.0, 2.0, 3.0]
arr[10]
"#,
);
assert!(
msg.contains("out of bounds"),
"expected an out-of-bounds error, got: {}",
msg
);
}
#[test]
fn v2_array_i64_out_of_bounds_raises_error() {
let msg = jit_eval_err(
r#"
let arr: Array<int> = [10, 20, 30]
arr[100]
"#,
);
assert!(
msg.contains("out of bounds"),
"expected an out-of-bounds error, got: {}",
msg
);
}
#[test]
fn v2_array_i64_out_of_bounds_store_raises_error() {
let msg = jit_eval_err(
r#"
let mut arr: Array<int> = [10, 20, 30]
arr[100] = 7
arr[0]
"#,
);
assert!(
msg.contains("out of bounds"),
"expected an out-of-bounds error, got: {}",
msg
);
}
#[test]
fn legacy_array_index_still_works() {
let v = jit_eval(
r#"
let arr = [10, 20, 30]
arr[1]
"#,
);
assert_eq!(as_i64(v), 20);
}
#[test]
fn legacy_array_length_still_works() {
let v = jit_eval(
r#"
let arr = [10, 20, 30, 40, 50]
arr.length
"#,
);
assert_eq!(as_i64(v), 5);
}
#[test]
fn v2_array_i64_slice_first_element() {
let v = jit_eval(
r#"
let arr: Array<int> = [10, 20, 30, 40]
let s = arr[1..3]
s[0]
"#,
);
assert_eq!(as_i64(v), 20);
}
#[test]
fn v2_array_i64_slice_second_element() {
let v = jit_eval(
r#"
let arr: Array<int> = [10, 20, 30, 40]
let s = arr[1..3]
s[1]
"#,
);
assert_eq!(as_i64(v), 30);
}
#[test]
fn v2_array_f64_slice_first_element() {
let v = jit_eval(
r#"
let arr: Array<number> = [1.5, 2.5, 3.5, 4.5]
let s = arr[1..3]
s[0]
"#,
);
assert!((as_f64(v) - 2.5).abs() < 1e-9);
}
#[test]
fn v2_array_i64_open_range_iteration_sum() {
let v = jit_eval(
r#"
let arr: Array<int> = [10, 20, 30, 40]
let mut sum: int = 0
for i in 0..arr.length {
sum = sum + arr[i]
}
sum
"#,
);
assert_eq!(as_i64(v), 100);
}