e1587ebdae
First stdlib fn that imports three other stdlib modules (std_list,
std_either, std_pair) and returns a compound polymorphic ADT tree
(Pair<List<e>, List<a>>). Stresses monomorphisation across nested
parameterised ADTs.
What shipped:
- examples/std_either_list.{ailx,ail.json}: 3 combinators —
- lefts : forall e a. (List<Either<e, a>>) -> List<e>
- rights : forall e a. (List<Either<e, a>>) -> List<a>
- partition_eithers : forall e a. (List<Either<e, a>>)
-> Pair<List<e>, List<a>>
lefts/rights use depth-2 nested Ctor patterns (Cons (Left l) t)
— exercises 16a's desugar pass at a depth not reached by any
prior fixture.
- examples/std_either_list_demo.{ailx,ail.json}: drives all three
combinators on a five-element List<Either<Int, Int>>; expected
output one per line: 2, 3, 2, 3.
- crates/ail/tests/e2e.rs::std_either_list_demo: e2e count 34 → 35.
- docs/JOURNAL.md: Iter 15g entry.
Compiler bug surfaced (queued as 15g-aux, not fixed):
unify_for_subst in ailang-codegen/src/lib.rs accepts $u wildcards
only on the arg side. Mixing inline (Either Left n) and (Either
Right n) in a list literal lands $u on the param side via the
outer List<a>'s binding and errors. Reduced repro: `length [Left
1, Right 10]`. Demo works around with monomorphic mkleft/mkright
helpers; workaround documented inline. Fix is a one-line symmetric
extension of the early-return.
Tests: 94/94. Stdlib: 5 modules, 27 combinators.
47 lines
3.4 KiB
Plaintext
47 lines
3.4 KiB
Plaintext
; Iter 15g — fifth consumer demo. First demo to import four stdlib
|
|
; modules (std_list, std_either, std_pair, std_either_list); first to
|
|
; thread a List<Either<Int, Int>> through three combinators that
|
|
; together exercise every monomorphisation site introduced by 15g.
|
|
;
|
|
; The list is constructed via the monomorphic helpers `mkleft` and
|
|
; `mkright` rather than bare `(term-ctor std_either.Either Left ...)` /
|
|
; `(term-ctor std_either.Either Right ...)`. This sidesteps a codegen
|
|
; bug that 15g surfaced: when an inline list literal mixes
|
|
; `Either Left n` (pins e, leaves a as `$u`) and `Either Right n` (pins
|
|
; a, leaves e as `$u`), the synth-time unification of the outer
|
|
; `List<a>`'s parameter against the `$u`-bearing element types fails
|
|
; on the param side because `unify_for_subst` only accepts arg-side
|
|
; `$u` wildcards. The helpers fully pin both type vars at the call
|
|
; site, so each list element arrives with concrete `Either<Int, Int>`
|
|
; and the bug is dodged. Logged as known-debt under 15g; the fix is
|
|
; a one-line symmetric extension of the `$u` early-return.
|
|
|
|
(module std_either_list_demo
|
|
|
|
(import std_list)
|
|
(import std_either)
|
|
(import std_pair)
|
|
(import std_either_list)
|
|
|
|
(fn mkleft
|
|
(doc "Monomorphic Left-injector at Either<Int, Int>. Pins both type vars at the call site so the codegen synth doesn't leave a `$u` wildcard on the second var.")
|
|
(type (fn-type (params (con Int)) (ret (con std_either.Either (con Int) (con Int)))))
|
|
(params x)
|
|
(body (term-ctor std_either.Either Left x)))
|
|
|
|
(fn mkright
|
|
(doc "Monomorphic Right-injector at Either<Int, Int>. Symmetric to mkleft.")
|
|
(type (fn-type (params (con Int)) (ret (con std_either.Either (con Int) (con Int)))))
|
|
(params x)
|
|
(body (term-ctor std_either.Either Right x)))
|
|
|
|
(fn main
|
|
(doc "Drive lefts, rights, and partition_eithers on the same five-element List<Either<Int, Int>> (Left 1, Right 10, Left 2, Right 20, Right 30). Expected output (one per line): 2, 3, 2, 3.")
|
|
(type (fn-type (params) (ret (con Unit)) (effects IO)))
|
|
(params)
|
|
(body
|
|
(seq (do io/print_int (app std_list.length (app std_either_list.lefts (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil)))))))))
|
|
(seq (do io/print_int (app std_list.length (app std_either_list.rights (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil)))))))))
|
|
(seq (do io/print_int (app std_list.length (app std_pair.fst (app std_either_list.partition_eithers (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil))))))))))
|
|
(do io/print_int (app std_list.length (app std_pair.snd (app std_either_list.partition_eithers (term-ctor std_list.List Cons (app mkleft 1) (term-ctor std_list.List Cons (app mkright 10) (term-ctor std_list.List Cons (app mkleft 2) (term-ctor std_list.List Cons (app mkright 20) (term-ctor std_list.List Cons (app mkright 30) (term-ctor std_list.List Nil))))))))))))))))
|