let valid_program = {| struct Item { int value; }; int fold(int[] xs) { int total = 0; foreach (int x in xs) { total = total + x; } return total; } int main() { int[] xs; struct Item it; int y = 2 + 3 * 4; it.value = y; if (y >= 0) { y = fold(xs); } else { y = 0; } return y; } |} let invalid_program = {| int main() { bool flag = true; int x = 1; x = flag; return 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 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") "int add(int a, int b) { return a + b; }\n"; write_file (Filename.concat base "main.spooky") "import \"modules/math.spooky\";\nint main() { 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_imports (); print_endline "All parser/type-check tests passed."