0eb33235eb
Three schema fields move bare → canonical (bare for same-module,
<module>.<Class> for cross-module): InstanceDef.class,
Constraint.class, SuperclassRef.class. Symmetric to ct.1's
Type::Con.name rule. ClassDef.name stays bare.
validate_canonical_type_names gains three field-walks via new
check_class_ref helper + two sibling diagnostics
BareCrossModuleClassRef / BadCrossModuleClassRef.
check_class_name_fields narrowed to ClassDef.name-only.
Workspace-internal class-name keys all qualified:
class_def_module, class_by_name, registry entries.0,
ClassMethodEntry.class_name, class_superclasses, mono's
class_index, Origin::Class.class_name. New qualify_class_ref
helper at workspace.rs scope plus sibling
qualify_class_ref_in_check in ailang-check.
Two new positive on-disk fixtures (mq1_xmod_constraint_class{,_dep})
exercise the qualified Constraint.class shape.
Recon claim that all existing fixtures' class-refs are intra-module
was empirically wrong — 10 fixtures required minimal canonical-form
migration. Duplicate-instance test architecturally restructured:
post-mq.1 orphan-freedom makes two-modules-on-same-(class,type)
structurally impossible; new test_22b1_dup_same_module fixture
lands both instances in the class's module.
Plan defects fixed inline: Origin::Class.class_name single
construction site (plan recon off-by-one); build_class_index in
mono.rs needed qualifying; build_module_globals needed Def::Instance
carve-out; check_fn declared-constraint matching needed inline
canonical-form lifting; NoInstance Float-aware message arm needed
prelude.Eq/prelude.Ord match; coherence type-leg needed qualified-
head split-and-lookup. Tasks 3-6 ran as one coherent fix.
7/7 tasks, 520 tests green. bench/compile_check.py + cross_lang.py
exit 0; bench/check.py exit 1 (4 improvements-beyond-tolerance,
audit-ratifiable, not a regression).
MethodNameCollision + dispatch path unchanged; iters mq.2 + mq.3
land them.
157 lines
5.0 KiB
JSON
157 lines
5.0 KiB
JSON
{
|
|
"schema": "ailang/v0",
|
|
"name": "eq_ord_user_adt",
|
|
"imports": [],
|
|
"defs": [
|
|
{
|
|
"kind": "type",
|
|
"name": "IntBox",
|
|
"vars": [],
|
|
"doc": "A one-field box around an Int, used to demonstrate that the unified mono pass synthesises eq__IntBox from a user-written instance, not from the primitive == operator.",
|
|
"ctors": [
|
|
{ "name": "MkIntBox", "fields": [{ "k": "con", "name": "Int" }] }
|
|
]
|
|
},
|
|
{
|
|
"kind": "instance",
|
|
"class": "prelude.Eq",
|
|
"type": { "k": "con", "name": "IntBox" },
|
|
"doc": "Eq IntBox by structural unwrap of the inner Int.",
|
|
"methods": [
|
|
{
|
|
"name": "eq",
|
|
"body": {
|
|
"t": "lam",
|
|
"params": ["a", "b"],
|
|
"paramTypes": [
|
|
{ "k": "con", "name": "IntBox" },
|
|
{ "k": "con", "name": "IntBox" }
|
|
],
|
|
"retType": { "k": "con", "name": "Bool" },
|
|
"body": {
|
|
"t": "match",
|
|
"scrutinee": { "t": "var", "name": "a" },
|
|
"arms": [{
|
|
"pat": { "p": "ctor", "ctor": "MkIntBox", "fields": [{ "p": "var", "name": "ai" }] },
|
|
"body": {
|
|
"t": "match",
|
|
"scrutinee": { "t": "var", "name": "b" },
|
|
"arms": [{
|
|
"pat": { "p": "ctor", "ctor": "MkIntBox", "fields": [{ "p": "var", "name": "bi" }] },
|
|
"body": {
|
|
"t": "app",
|
|
"fn": { "t": "var", "name": "==" },
|
|
"args": [
|
|
{ "t": "var", "name": "ai" },
|
|
{ "t": "var", "name": "bi" }
|
|
]
|
|
}
|
|
}]
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"kind": "instance",
|
|
"class": "prelude.Ord",
|
|
"type": { "k": "con", "name": "IntBox" },
|
|
"doc": "Ord IntBox by delegating to Int's compare on the inner field.",
|
|
"methods": [
|
|
{
|
|
"name": "compare",
|
|
"body": {
|
|
"t": "lam",
|
|
"params": ["a", "b"],
|
|
"paramTypes": [
|
|
{ "k": "con", "name": "IntBox" },
|
|
{ "k": "con", "name": "IntBox" }
|
|
],
|
|
"retType": { "k": "con", "name": "prelude.Ordering" },
|
|
"body": {
|
|
"t": "match",
|
|
"scrutinee": { "t": "var", "name": "a" },
|
|
"arms": [{
|
|
"pat": { "p": "ctor", "ctor": "MkIntBox", "fields": [{ "p": "var", "name": "ai" }] },
|
|
"body": {
|
|
"t": "match",
|
|
"scrutinee": { "t": "var", "name": "b" },
|
|
"arms": [{
|
|
"pat": { "p": "ctor", "ctor": "MkIntBox", "fields": [{ "p": "var", "name": "bi" }] },
|
|
"body": {
|
|
"t": "app",
|
|
"fn": { "t": "var", "name": "compare" },
|
|
"args": [
|
|
{ "t": "var", "name": "ai" },
|
|
{ "t": "var", "name": "bi" }
|
|
]
|
|
}
|
|
}]
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"kind": "fn",
|
|
"name": "main",
|
|
"type": {
|
|
"k": "fn", "params": [], "ret": { "k": "con", "name": "Unit" },
|
|
"effects": ["IO"]
|
|
},
|
|
"params": [],
|
|
"body": {
|
|
"t": "seq",
|
|
"lhs": {
|
|
"t": "do", "op": "io/print_int",
|
|
"args": [{
|
|
"t": "if",
|
|
"cond": {
|
|
"t": "app",
|
|
"fn": { "t": "var", "name": "eq" },
|
|
"args": [
|
|
{
|
|
"t": "ctor", "type": "IntBox", "ctor": "MkIntBox",
|
|
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 3 } }]
|
|
},
|
|
{
|
|
"t": "ctor", "type": "IntBox", "ctor": "MkIntBox",
|
|
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 3 } }]
|
|
}
|
|
]
|
|
},
|
|
"then": { "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
|
"else": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
|
}]
|
|
},
|
|
"rhs": {
|
|
"t": "do", "op": "io/print_int",
|
|
"args": [{
|
|
"t": "if",
|
|
"cond": {
|
|
"t": "app",
|
|
"fn": { "t": "var", "name": "eq" },
|
|
"args": [
|
|
{
|
|
"t": "ctor", "type": "IntBox", "ctor": "MkIntBox",
|
|
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 3 } }]
|
|
},
|
|
{
|
|
"t": "ctor", "type": "IntBox", "ctor": "MkIntBox",
|
|
"args": [{ "t": "lit", "lit": { "kind": "int", "value": 5 } }]
|
|
}
|
|
]
|
|
},
|
|
"then": { "t": "lit", "lit": { "kind": "int", "value": 1 } },
|
|
"else": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
|
|
}]
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|