Something went wrong. Try again.
The Monad language. Dependent types, functional programming compiled with LLVM. Hobby project. monad-lang.org
dependent-types language compiler programming-language functional-programming
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687/// Shared end-to-end codegen harness: write a `.mo` source string to/// disk, run it through the self-hosted pipeline (load -> compile to/// LLVM IR -> `llc` -> `clang` runtime -> link), execute the resulting/// binary, and compare its exit code against `expected`.////// This existed as EIGHT near-identical copies before (seven under/// `slow_tests/`, one in `test_closure_capture_e2e.mo`) -- three/// distinct hashes, but diffing them showed the only differences were/// `println` vs `IO.println` and two comments. They are unified here.////// The llc/clang/link steps themselves are NOT reimplemented here: they/// come from `llvm.link`, which the compiler's own CLI uses too. This file/// had its own inlined copy of them until the llvm mote was extracted, and/// the two had already drifted apart on flags.////// Lives under `lang/src/codegen/test/` rather than `slow_tests/` because/// both directories consume it and this is codegen test infrastructure;/// cross-directory `use` resolves fine (search paths are anchored at the/// repo root).open IO {println}use std::process {exec_cmd, process_id}use lang::module { LoadedModules, extract_directory, load_file_modules, resolve_runtime_src,}use llvm::ir {emit_module}use llvm::link {compile_ir_to_obj, compile_runtime_obj, link_objects}use runtime {}use lib::codegen::emit {compile_loaded_modules_to_ir}#[partial]pub def compile_source_run_expect (source : String) (basename : String) (expected : I64) : IO Bool := do { let output_dir := "/tmp/monad_e2e_" ++ I64.to_string process_id; let src_path := output_dir ++ "/" ++ basename ++ ".mo"; let ir_path := output_dir ++ "/" ++ basename ++ ".ll"; let obj_path := output_dir ++ "/" ++ basename ++ ".o"; let runtime_obj := output_dir ++ "/" ++ basename ++ "_runtime.o"; let output_path := output_dir ++ "/" ++ basename; exec_cmd "mkdir" ["-p", output_dir]; IO.write_file (Path.path src_path) source; let loaded_result <- load_file_modules src_path false; match loaded_result { Result.err e => do { println (basename ++ ": failed to load: " ++ e); return false }, Result.ok loaded => do { let mod_result <- compile_loaded_modules_to_ir loaded false; match mod_result { Result.err e => do { println (basename ++ ": failed to resolve class-method calls: " ++ e); return false }, Result.ok mod_ => do { let ir_text := emit_module mod_; IO.write_file (Path.path ir_path) ir_text; let llc_result <- compile_ir_to_obj ir_path obj_path; if not (llc_result == 0) then do { println (basename ++ ": llc failed"); return false } else do { let runtime_src <- resolve_runtime_src (extract_directory src_path); let rt_result <- compile_runtime_obj runtime_src [] runtime_obj; if not (rt_result == 0) then do { println (basename ++ ": compiling runtime failed"); return false } else do { let link_result <- link_objects [obj_path, runtime_obj] output_path []; if not (link_result == 0) then do { println (basename ++ ": clang linker failed"); return false } else do { let exec_result <- exec_cmd output_path []; exec_cmd "rm" ["-f", src_path, ir_path, obj_path, runtime_obj, output_path]; println (basename ++ ": expected " ++ I64.to_string expected ++ ", got " ++ I64.to_string exec_result); return (exec_result == expected) } } } }, } }, }}