//! Eq-primitive codegen pin tests, relocated from //! `ailang-codegen/src/lib.rs` `#[cfg(test)] mod tests` to a `tests/*` //! integration crate in iter form-a.1 Task 5. The relocation switches //! workspace loading from `ailang_core::load_workspace` (the JSON-only //! loader) to `ailang_surface::load_workspace` (the //! extension-dispatching superset), so the post-iter `.ail` corpus is //! loaded from Form A rather than the deleted `.ail.json` siblings. use ailang_check::{check_workspace, monomorphise_workspace, Severity}; use ailang_codegen::lower_workspace; use ailang_surface::load_workspace; use std::path::Path; fn eq_primitives_smoke_path() -> std::path::PathBuf { let manifest = env!("CARGO_MANIFEST_DIR"); Path::new(manifest) .parent().unwrap().parent().unwrap() .join("examples").join("eq_primitives_smoke.ail") } fn lower_eq_primitives_smoke() -> String { let entry = eq_primitives_smoke_path(); let ws = load_workspace(&entry).expect("load workspace"); let diags = check_workspace(&ws); assert!( diags.iter().all(|d| !matches!(d.severity, Severity::Error)), "unexpected check_workspace errors: {diags:?}" ); let ws = monomorphise_workspace(&ws).expect("monomorphise"); lower_workspace(&ws).expect("lower") } /// Iter 23.2: integration with the auto-loaded prelude. Compiling a /// workspace that calls `eq` on an Int pair must produce a /// mono-synthesised `@ail_prelude_eq__Int` whose body lowers to /// `icmp eq i64`. Full pipeline: end-of-typecheck → monomorphise → /// codegen, then substring-shape assertions on the IR. #[test] fn eq_int_call_produces_icmp_i64_mono_fn() { let ir = lower_eq_primitives_smoke(); assert!( ir.contains("@ail_prelude_eq__Int"), "ir must contain mono-synthesised @ail_prelude_eq__Int; ir was:\n{ir}" ); assert!( ir.contains("icmp eq i64"), "eq__Int body must lower to icmp eq i64; ir was:\n{ir}" ); } /// Iter 23.2: same shape as `eq_int_call_produces_icmp_i64_mono_fn` /// for Bool. Asserts the mono-synthesised `@ail_prelude_eq__Bool` /// lowers to `icmp eq i1`. #[test] fn eq_bool_call_produces_icmp_i1_mono_fn() { let ir = lower_eq_primitives_smoke(); assert!( ir.contains("@ail_prelude_eq__Bool"), "ir must contain mono-synthesised @ail_prelude_eq__Bool; ir was:\n{ir}" ); assert!( ir.contains("icmp eq i1"), "eq__Bool body must lower to icmp eq i1; ir was:\n{ir}" ); } /// Iter 23.2: Str's mono-symbol body is hand-rolled by the /// `try_emit_primitive_instance_body` intercept. Asserts the intercept /// fires for the prelude-loaded `eq__Str` synthesised against a real /// user fixture that calls `eq` on Str. #[test] fn eq_str_call_produces_ail_str_eq_call_mono_fn() { let ir = lower_eq_primitives_smoke(); assert!( ir.contains("@ail_prelude_eq__Str"), "ir must contain mono-synthesised @ail_prelude_eq__Str; ir was:\n{ir}" ); assert!( ir.contains("call zeroext i1 @ail_str_eq("), "eq__Str body must call @ail_str_eq; ir was:\n{ir}" ); }