iter 23.2.3: prelude — class Eq a + Eq Int/Bool/Str instances
This commit is contained in:
@@ -920,6 +920,42 @@ mod tests {
|
||||
)),
|
||||
"prelude must contain Ordering type def"
|
||||
);
|
||||
|
||||
// Iter 23.2: prelude also ships the `Eq` class plus three
|
||||
// primitive instances (Eq Int, Eq Bool, Eq Str).
|
||||
assert!(
|
||||
prelude.defs.iter().any(|d| matches!(
|
||||
d,
|
||||
crate::ast::Def::Class(c) if c.name == "Eq"
|
||||
)),
|
||||
"prelude must contain Eq class def"
|
||||
);
|
||||
let eq_instance_types: Vec<&str> = prelude
|
||||
.defs
|
||||
.iter()
|
||||
.filter_map(|d| match d {
|
||||
crate::ast::Def::Instance(i) if i.class == "Eq" => {
|
||||
if let crate::ast::Type::Con { name, .. } = &i.type_ {
|
||||
Some(name.as_str())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert!(
|
||||
eq_instance_types.contains(&"Int"),
|
||||
"prelude must contain `instance Eq Int`; saw Eq instances on: {eq_instance_types:?}"
|
||||
);
|
||||
assert!(
|
||||
eq_instance_types.contains(&"Bool"),
|
||||
"prelude must contain `instance Eq Bool`; saw Eq instances on: {eq_instance_types:?}"
|
||||
);
|
||||
assert!(
|
||||
eq_instance_types.contains(&"Str"),
|
||||
"prelude must contain `instance Eq Str`; saw Eq instances on: {eq_instance_types:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -13,6 +13,111 @@
|
||||
{ "name": "EQ", "fields": [] },
|
||||
{ "name": "GT", "fields": [] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "class",
|
||||
"name": "Eq",
|
||||
"param": "a",
|
||||
"doc": "Structural equality. Ships in milestone 23 alongside Ord. The primitive `==` operator stays as the surface-level comparator this iter; routing `==` through `Eq.eq` is the declared P2 follow-up (see docs/specs/2026-05-10-23-eq-ord-prelude.md, `Out of scope`).",
|
||||
"methods": [
|
||||
{
|
||||
"name": "eq",
|
||||
"type": {
|
||||
"k": "fn",
|
||||
"params": [
|
||||
{ "k": "var", "name": "a" },
|
||||
{ "k": "var", "name": "a" }
|
||||
],
|
||||
"param_modes": ["borrow", "borrow"],
|
||||
"ret": { "k": "con", "name": "Bool" },
|
||||
"effects": []
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "instance",
|
||||
"class": "Eq",
|
||||
"type": { "k": "con", "name": "Int" },
|
||||
"doc": "Eq Int. Body lowers to `icmp eq i64` via the existing primitive `==` dispatch in `lower_eq`.",
|
||||
"methods": [
|
||||
{
|
||||
"name": "eq",
|
||||
"body": {
|
||||
"t": "lam",
|
||||
"params": ["x", "y"],
|
||||
"paramTypes": [
|
||||
{ "k": "var", "name": "a" },
|
||||
{ "k": "var", "name": "a" }
|
||||
],
|
||||
"retType": { "k": "con", "name": "Bool" },
|
||||
"body": {
|
||||
"t": "app",
|
||||
"fn": { "t": "var", "name": "==" },
|
||||
"args": [
|
||||
{ "t": "var", "name": "x" },
|
||||
{ "t": "var", "name": "y" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "instance",
|
||||
"class": "Eq",
|
||||
"type": { "k": "con", "name": "Bool" },
|
||||
"doc": "Eq Bool. Body lowers to `icmp eq i1` via the existing primitive `==` dispatch in `lower_eq`.",
|
||||
"methods": [
|
||||
{
|
||||
"name": "eq",
|
||||
"body": {
|
||||
"t": "lam",
|
||||
"params": ["x", "y"],
|
||||
"paramTypes": [
|
||||
{ "k": "var", "name": "a" },
|
||||
{ "k": "var", "name": "a" }
|
||||
],
|
||||
"retType": { "k": "con", "name": "Bool" },
|
||||
"body": {
|
||||
"t": "app",
|
||||
"fn": { "t": "var", "name": "==" },
|
||||
"args": [
|
||||
{ "t": "var", "name": "x" },
|
||||
{ "t": "var", "name": "y" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "instance",
|
||||
"class": "Eq",
|
||||
"type": { "k": "con", "name": "Str" },
|
||||
"doc": "Eq Str. The lambda body shape mirrors Int/Bool for round-trip stability, but the codegen intercept in `emit_fn` overrides the body to call `@ail_str_eq` directly — see `try_emit_primitive_instance_body` in `crates/ailang-codegen/src/lib.rs`.",
|
||||
"methods": [
|
||||
{
|
||||
"name": "eq",
|
||||
"body": {
|
||||
"t": "lam",
|
||||
"params": ["x", "y"],
|
||||
"paramTypes": [
|
||||
{ "k": "var", "name": "a" },
|
||||
{ "k": "var", "name": "a" }
|
||||
],
|
||||
"retType": { "k": "con", "name": "Bool" },
|
||||
"body": {
|
||||
"t": "app",
|
||||
"fn": { "t": "var", "name": "==" },
|
||||
"args": [
|
||||
{ "t": "var", "name": "x" },
|
||||
{ "t": "var", "name": "y" }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user