feat(lang): L5 generic records and functions

property Pool<T> { ... }, function first<T>(xs: []T) -> T, map<T, U> over fn
types; a type writes an instance as Pool<Thing>, nested as deep as needed. The
parser names an instance Pool$Thing and remembers its generic and arguments; the
checker takes the generic declarations out, infers a call's type arguments from
its arguments or its result's declared slot, and makes each instance once as an
ordinary record or function, checked like any other. Errors print Pool<Thing>.
An instance keeps its generic's module and export (L3). ludic-fmt keeps type
arguments together while spacing comparisons and shifts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-24 02:21:09 +03:00
parent 57b66bdf47
commit 6a24b14f0e
26 changed files with 61796 additions and 51949 deletions

8
changes/generics.md Normal file
View file

@ -0,0 +1,8 @@
bump: minor
type: feature
**Generic records and functions.** `property Pool<T> { items: []T }`, `function first<T>(xs: []T)
-> T` and `function map<T, U>(xs: []T, f: fn(T) -> U) -> []U`; a type writes an instance as
`Pool<Thing>`, nested as deep as needed. A call's type arguments come from its arguments, or from
the declared type its result is written into, and are refused with the parameter named when
neither says. Each instance is compiled once as an ordinary record or function. `ludic-fmt` keeps
`Pool<Thing>` together while still spacing `a < b`.