diff --git a/crates/ailang-core/src/workspace.rs b/crates/ailang-core/src/workspace.rs index 5122344..24cf249 100644 --- a/crates/ailang-core/src/workspace.rs +++ b/crates/ailang-core/src/workspace.rs @@ -956,6 +956,45 @@ mod tests { eq_instance_types.contains(&"Str"), "prelude must contain `instance Eq Str`; saw Eq instances on: {eq_instance_types:?}" ); + + // Iter 23.3: prelude also ships the `Ord` class plus three + // primitive instances (Ord Int, Ord Bool, Ord Str). Ord + // extends Eq (Decision 11 single-superclass closure), so its + // shape is the same as Eq's instance set; the loader uses the + // superclass walk to verify the Eq instances exist. + assert!( + prelude.defs.iter().any(|d| matches!( + d, + crate::ast::Def::Class(c) if c.name == "Ord" + )), + "prelude must contain Ord class def" + ); + let ord_instance_types: Vec<&str> = prelude + .defs + .iter() + .filter_map(|d| match d { + crate::ast::Def::Instance(i) if i.class == "Ord" => { + if let crate::ast::Type::Con { name, .. } = &i.type_ { + Some(name.as_str()) + } else { + None + } + } + _ => None, + }) + .collect(); + assert!( + ord_instance_types.contains(&"Int"), + "prelude must contain `instance Ord Int`; saw: {ord_instance_types:?}" + ); + assert!( + ord_instance_types.contains(&"Bool"), + "prelude must contain `instance Ord Bool`; saw: {ord_instance_types:?}" + ); + assert!( + ord_instance_types.contains(&"Str"), + "prelude must contain `instance Ord Str`; saw: {ord_instance_types:?}" + ); } #[test] diff --git a/examples/prelude.ail.json b/examples/prelude.ail.json index 190ecef..9808c72 100644 --- a/examples/prelude.ail.json +++ b/examples/prelude.ail.json @@ -118,6 +118,106 @@ } } ] + }, + { + "kind": "class", + "name": "Ord", + "param": "a", + "superclass": { "class": "Eq", "type": "a" }, + "doc": "Total ordering. Ships in milestone 23 alongside Eq. `compare x y` returns LT, EQ, or GT (the three-ctor Ordering ADT also in the prelude). Decision 11's single-superclass closure requires `instance Eq T` for every `instance Ord T` — the three Ord instances below pair with the three Eq instances shipped in iter 23.2.3.", + "methods": [ + { + "name": "compare", + "type": { + "k": "fn", + "params": [ + { "k": "var", "name": "a" }, + { "k": "var", "name": "a" } + ], + "param_modes": ["borrow", "borrow"], + "ret": { "k": "con", "name": "Ordering" }, + "effects": [] + } + } + ] + }, + { + "kind": "instance", + "class": "Ord", + "type": { "k": "con", "name": "Int" }, + "doc": "Ord Int. The lambda body shape is a placeholder for round-trip stability; the codegen intercept `try_emit_primitive_instance_body::\"compare__Int\"` emits a three-way `icmp slt` / `icmp eq` branch ladder constructing LT / EQ / GT.", + "methods": [ + { + "name": "compare", + "body": { + "t": "lam", + "params": ["x", "y"], + "paramTypes": [ + { "k": "var", "name": "a" }, + { "k": "var", "name": "a" } + ], + "retType": { "k": "con", "name": "Ordering" }, + "body": { + "t": "ctor", + "type": "Ordering", + "ctor": "EQ", + "args": [] + } + } + } + ] + }, + { + "kind": "instance", + "class": "Ord", + "type": { "k": "con", "name": "Bool" }, + "doc": "Ord Bool. Body lowered via `try_emit_primitive_instance_body::\"compare__Bool\"` — `icmp ult i1` LT-test, `icmp eq i1` EQ-test, GT default.", + "methods": [ + { + "name": "compare", + "body": { + "t": "lam", + "params": ["x", "y"], + "paramTypes": [ + { "k": "var", "name": "a" }, + { "k": "var", "name": "a" } + ], + "retType": { "k": "con", "name": "Ordering" }, + "body": { + "t": "ctor", + "type": "Ordering", + "ctor": "EQ", + "args": [] + } + } + } + ] + }, + { + "kind": "instance", + "class": "Ord", + "type": { "k": "con", "name": "Str" }, + "doc": "Ord Str. Body lowered via `try_emit_primitive_instance_body::\"compare__Str\"` — `call i32 @ail_str_compare(ptr, ptr)` then branch on slt-0 / eq-0 against the normalised {-1, 0, +1} return.", + "methods": [ + { + "name": "compare", + "body": { + "t": "lam", + "params": ["x", "y"], + "paramTypes": [ + { "k": "var", "name": "a" }, + { "k": "var", "name": "a" } + ], + "retType": { "k": "con", "name": "Ordering" }, + "body": { + "t": "ctor", + "type": "Ordering", + "ctor": "EQ", + "args": [] + } + } + } + ] } ] }