12e9a9c0cc
The 15a tester surfaced a real compiler limitation: cross-module
type and ctor references were not implemented. Iter 5b only
carried fns + consts via module_globals; types/ctors stayed
module-local with an explicit DESIGN comment. This iter completes
the cross-module mechanism using the Iter-5b convention:
qualified-only access via module.Name.
Implementation:
- ailang-check: Env.module_types populated by build_module_types.
Qualified resolution in Type::Con, Term::Ctor, with cross-module
fallback for pat-ctor (local wins, multi-import collision -> new
ambiguous-ctor diagnostic). Four new unit tests.
- ailang-codegen: workspace-level module_ctor_index replaces
per-Emitter table. lookup_ctor_by_type / lookup_ctor_in_pattern
thread qualified type names through box-tag and field-type
resolution.
- examples/std_maybe_demo.{ailx,ail.json}: type-name slots now
qualified (std_maybe.Maybe).
- New e2e test cross_module_maybe_demo asserts the demo prints
["7","99","true","true","42"].
Net diff ~550 LOC. Tests 80 -> 85. All Iter 14a regressions
(parameterised_box_round_trip, parameterised_maybe_match,
list_map_poly_inc_then_prints, polymorphic_id_at_int_and_bool)
verified green — the 14h derive_substitution change (default
unpinned forall vars to Unit for monomorphiser) sits on a
different layer than 14a's $u-wildcard fix and they coexist.
Hash invariance: all five std_maybe def hashes unchanged. All
80-test-suite fixtures retain bit-identical hashes — cross-module
support is purely additive at the language level.
Process note: the std_maybe.ailx file landed in the 14g commit
via a sloppy git-add-A; should have spotted it before staging.
Not a correctness issue but a hygiene one.
Implementer flagged Unit-default monomorphisation as wasteful-
but-correct; rethink if stdlib grows toward overload-resolution-
style cases needing distinct unconstrained instantiations.
std_maybe stdlib effectively ships: module + four combinators +
e2e-tested consumer demo. Plan 15b: std_list importing std_maybe,
exercising Maybe-returning head/tail and tail-call-marked
fold_left.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
31 lines
1.4 KiB
Plaintext
31 lines
1.4 KiB
Plaintext
; Iter 15a — first consumer of an stdlib module.
|
|
; Imports std_maybe, exercises from_maybe, is_some, is_none, map_maybe.
|
|
; First program to import a parameterised ADT (Maybe a) across module
|
|
; boundaries. Per the project's qualified-only convention (Iter 5b for
|
|
; fns, Iter 15a for types/ctors), every cross-module reference is
|
|
; qualified: `std_maybe.from_maybe` for the fn, `std_maybe.Maybe` for
|
|
; the type-name slot of `term-ctor`. The bare ctor names (`Just`,
|
|
; `Nothing`) stay unqualified — once the type is resolved, the ctor
|
|
; lookup is unambiguous within it.
|
|
|
|
(module std_maybe_demo
|
|
|
|
(import std_maybe)
|
|
|
|
(fn inc
|
|
(doc "Add 1 to an Int. Used as the (a -> b) arg to map_maybe.")
|
|
(type (fn-type (params (con Int)) (ret (con Int))))
|
|
(params x)
|
|
(body (app + x 1)))
|
|
|
|
(fn main
|
|
(doc "Drive each combinator once and print 7, 99, true, true, 42.")
|
|
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
|
(params)
|
|
(body
|
|
(seq (do io/print_int (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Just 7)))
|
|
(seq (do io/print_int (app std_maybe.from_maybe 99 (term-ctor std_maybe.Maybe Nothing)))
|
|
(seq (do io/print_bool (app std_maybe.is_some (term-ctor std_maybe.Maybe Just 5)))
|
|
(seq (do io/print_bool (app std_maybe.is_none (term-ctor std_maybe.Maybe Nothing)))
|
|
(do io/print_int (app std_maybe.from_maybe 0 (app std_maybe.map_maybe inc (term-ctor std_maybe.Maybe Just 41)))))))))))
|