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:
parent
57b66bdf47
commit
6a24b14f0e
26 changed files with 61796 additions and 51949 deletions
|
|
@ -29,6 +29,8 @@ function ck_any(n: Node) -> void {
|
|||
}
|
||||
function ck_expr(e: Node) -> pointer {
|
||||
if e == null { return "?" }
|
||||
let ex = ck_expect
|
||||
ck_expect = null
|
||||
let k = e.kind
|
||||
if k == E_INT { return "int" }
|
||||
if k == E_FLOAT {
|
||||
|
|
@ -51,7 +53,10 @@ function ck_expr(e: Node) -> pointer {
|
|||
if k == E_UN { return ck_un(e) }
|
||||
if k == E_MEMBER { return ck_member(e) }
|
||||
if k == E_INDEX { return ck_index_of(e) }
|
||||
if k == E_CALL { return ck_call(e) }
|
||||
if k == E_CALL {
|
||||
ck_call_expect = ex
|
||||
return ck_call(e)
|
||||
}
|
||||
if k == S_EMIT { ck_emit(e); return "?" }
|
||||
ck_walk(e)
|
||||
return "?"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue