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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101/// Small, shared building blocks for the LLVM backend.////// These are the defs the rest of `lang/codegen/` reaches for constantly/// -- `List.empty`/`List.cons` alone have 39 callers each, and/// `str_map_lookup` 28. They lived in `lang/codegen/emit.mo` until that/// file reached 8,204 lines, and they are extracted FIRST because every/// other candidate extraction pulls them in: nothing else could be split/// out cleanly while they had no home of their own.////// Deliberately dependency-light -- `lang.types` and `llvm.ir`/// only -- so that every other backend module can import this one/// without creating a cycle.use lib::types {Decl, Identifier}use llvm::ir { LLVMBasicBlock, LLVMFunction, LLVMGlobal, LLVMInstruction, LLVMValue, ParamPair,}// Re-exported, not redefined. They moved to a leaf module so `ir.mo` can use// them too -- `ir.mo` cannot import THIS file, since the `use` above makes the// dependency run the other way. `pub use` keeps all eight existing// `use lang.codegen.util {str_map_*}` importers working unchanged; a second// copy here would be two definitions of one bare LLVM symbol (AGENTS.md// item 18).pub use llvm::strmap {str_map_empty, str_map_insert, str_map_lookup}#[partial]def identifier_eq (a : Identifier) (b : Identifier) : Bool := match a { Identifier.id as => match b { Identifier.id bs => String.beq as bs, },}#[partial]def rev_vals (xs : List LLVMValue) (acc : List LLVMValue) : List LLVMValue := match xs { List.cons x rest => rev_vals rest (List.cons x acc), List.empty => acc,}#[partial]def ident_in_list (xs : List Identifier) (x : Identifier) : Bool := match xs { List.empty => false, List.cons y rest => if identifier_eq y x then true else ident_in_list rest x,}#[partial]def dedup_idents (names : List Identifier) : List Identifier := dedup_idents_go names List.empty#[partial]def dedup_idents_go (names : List Identifier) (seen : List Identifier) : List Identifier := match names { List.empty => List.empty, List.cons n rest => if ident_in_list seen n then dedup_idents_go rest seen else List.cons n (dedup_idents_go rest (List.cons n seen)),}/// `"; "`-join a fail-fast validator's error messages. Unlike/// `validate_no_unresolved_class_calls` (first message only), a broken/// compile from the fail-fast validator family usually has a whole/// FAMILY of defects at once (the self-hosted compiler's own closure/// references ~20 unwired natives), and naming them one/// per compile would cost one full ~8-minute self-compile run each./// The complete list is the point. Shared by both fail-fast/// gates: `validate_no_unwired_natives` and/// `validate_no_undesugared_struct_lits`.#[partial]def join_semicolon_msgs (msgs : List String) (acc : String) : String := match msgs { List.empty => acc, List.cons m rest => if String.beq acc "" then join_semicolon_msgs rest m else join_semicolon_msgs rest (String.concat acc (String.concat "; " m)), }#[partial]def dedup_strs (xs : List String) : List String := dedup_strs_go xs List.empty#[partial]def dedup_strs_go (xs : List String) (seen : List String) : List String := match xs { List.empty => List.empty, List.cons x rest => if list_contains_str seen x then dedup_strs_go rest seen else List.cons x (dedup_strs_go rest (List.cons x seen)),}#[partial]def list_contains_str (xs : List String) (x : String) : Bool := match xs { List.empty => false, List.cons hd rest => if String.beq hd x then true else list_contains_str rest x,}#[partial]def drop_last_instr (instrs : List LLVMInstruction) : List LLVMInstruction := match instrs { List.empty => List.empty, List.cons i rest => match rest { List.empty => List.empty, List.cons _ _ => List.cons i (drop_last_instr rest), },}