//! The primitive-name set: `Int`, `Bool`, `Str`, `Unit`. Single //! source of truth for "is this name a built-in zero-arity type //! constructor?" Every typecheck and codegen site that gates //! behaviour on the primitive set goes through this module. //! //! Adding a primitive: append to BOTH functions below. The lockstep //! invariant ([`is_primitive_name`] is `true` iff //! [`primitive_surface_name`] is `Some`) is pinned by the unit test //! at the bottom of this file — extending only one of the two //! fails the test before the bug reaches a consumer. /// Returns `true` iff `name` is one of the built-in zero-arity /// primitive type constructors. Cross-crate predicate used by /// typecheck-time well-formedness gating, the heap-type filter, /// the local-type qualifier, and the codegen substitution path. pub fn is_primitive_name(name: &str) -> bool { matches!(name, "Int" | "Bool" | "Str" | "Unit" | "Float") } /// Returns the static-lifetime surface name iff `name` is a /// primitive. Used by the mono pass to embed the human-readable /// form in monomorphised symbol names; the static lifetime is what /// makes the symbol-builder's `&'static str` signature work. pub fn primitive_surface_name(name: &str) -> Option<&'static str> { match name { "Int" => Some("Int"), "Bool" => Some("Bool"), "Str" => Some("Str"), "Unit" => Some("Unit"), "Float" => Some("Float"), _ => None, } } #[cfg(test)] mod tests { use super::*; /// The two functions must agree on which names are primitive: /// `is_primitive_name(n)` true iff `primitive_surface_name(n)` /// is `Some`. The list of names tested mirrors the literal set /// inside both functions plus a sample non-primitive. #[test] fn predicate_and_surface_name_agree() { for name in ["Int", "Bool", "Str", "Unit", "Float", "List", "Foo", "", "int"] { assert_eq!( is_primitive_name(name), primitive_surface_name(name).is_some(), "lockstep violation for {name:?}" ); } // The loop's assert_eq! passes vacuously when both functions // return `false`/`None` for a name; the explicit assertions // below catch the case where a primitive is silently removed // from both functions but stays in the loop list. assert!(is_primitive_name("Float"), "Float must be a primitive"); assert_eq!( primitive_surface_name("Float"), Some("Float"), "Float surface name must be \"Float\"" ); } }