let valid_program = {| struct Item { int value; }; fn fold(xs: int[]) -> int { let mut total: int = 0; foreach (int x in xs) { total = total + x; } return total; } fn main() -> int { let xs: int[]; let it: Item; let mut y = 2 + 3 * 4; it.value = y; if (y >= 0) { y = fold(xs); } else { y = 0; } return y; } |} let invalid_program = {| fn main() -> int { let flag = true; let mut x = 1; x = flag; return x; } |} let combo_valid_program = {| fn get_value() -> int#int { let x = 1; return x; } fn do_work(v: int#int) -> int { return 0; } fn main() -> int { let x = get_value(); return do_work(x); } |} let combo_invalid_program = {| fn get_value() -> int { return 1; } fn get_comptime() -> #int { return 2; } fn do_work(v: int#int) -> int { return 0; } fn main() -> int { let x = get_value(); let y = get_comptime(); return do_work(x); } |} let test_valid_program () = match Spooky.parse_and_type_check valid_program with | Ok _ -> () | Error msg -> failwith ("expected valid program, got: " ^ msg) let test_invalid_program () = match Spooky.parse_and_type_check invalid_program with | Ok _ -> failwith "expected type error, but got success" | Error _ -> () let test_combo_valid_program () = match Spooky.parse_and_type_check combo_valid_program with | Ok _ -> () | Error msg -> failwith ("expected valid combo program, got: " ^ msg) let test_combo_invalid_program () = match Spooky.parse_and_type_check combo_invalid_program with | Ok _ -> failwith "expected combo type error, but got success" | Error _ -> () let write_file path content = let oc = open_out_bin path in Fun.protect ~finally:(fun () -> close_out oc) (fun () -> output_string oc content) let test_imports () = let base = Filename.concat (Filename.get_temp_dir_name ()) "spooky_import_test" in let modules_dir = Filename.concat base "modules" in Unix.mkdir base 0o755; Unix.mkdir modules_dir 0o755; let cleanup () = (try Sys.remove (Filename.concat modules_dir "math.spooky") with _ -> ()); (try Sys.remove (Filename.concat base "main.spooky") with _ -> ()); (try Unix.rmdir modules_dir with _ -> ()); (try Unix.rmdir base with _ -> ()) in Fun.protect ~finally:cleanup (fun () -> write_file (Filename.concat modules_dir "math.spooky") "fn add(a: int, b: int) -> int { return a + b; }\n"; write_file (Filename.concat base "main.spooky") "import \"modules/math.spooky\";\nfn main() -> int { return add(1, 2); }\n"; match Spooky.parse_and_type_check_file (Filename.concat base "main.spooky") with | Ok _ -> () | Error msg -> failwith ("expected valid import program, got: " ^ msg)) let () = test_valid_program (); test_invalid_program (); test_combo_valid_program (); test_combo_invalid_program (); test_imports (); print_endline "All parser/type-check tests passed."