feat(lang): L4 type checker between parse and emit

selfhost/check/ walks every function, the entry, tests, globals' initializers and
@On listeners with real scopes, and refuses mixed number kinds, text and numbers,
two record types, mismatched slices and fn types, wrong argument counts, wrong
returns and wrong push elements - every mix-up at once, each at its line.
LUDIC_CHECK_REPORT=1 lists them by category. pointer stays untyped (L7's).

What it found is fixed: render3d's HDR scan calling the float-bits extern f_lt
with floats; ludic.shooter's right-stick aim overflowing past half a push;
prof.ludic storing longs in []int; extern arguments now coerced to their
parameters. Text-returning runtime functions say string; Assets.ready says bool.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-24 01:34:49 +03:00
parent 0677aee93f
commit 57b66bdf47
52 changed files with 27005 additions and 11844 deletions

View file

@ -28,8 +28,8 @@ function compound_op(tok: pointer) -> pointer {
function emit_assign(st: Node) -> void {
# resolve the target's address and type
let t = st.a
var addr = "0"
var ty = "int"
var addr: pointer = "0"
var ty: pointer = "int"
if t.kind == E_ID {
let li = loc_find(t.s)
if li >= 0 {
@ -209,7 +209,7 @@ function emit_match_tagged(st: Node, sv: Val, en: Node) -> void {
let arm = st.kids[i]
if arm_is_default(arm) { deflt = arm }
else {
var acc = "0"
var acc: pointer = "0"
var first = true
var bindPat: Node = null
var p = 0
@ -262,7 +262,7 @@ function emit_match(st: Node) -> void {
let arm = st.kids[i]
if arm_is_default(arm) { deflt = arm }
else {
var acc = "0"
var acc: pointer = "0"
var first = true
var p = 0
while p < len(arm.kids) {
@ -303,7 +303,7 @@ function emit_emit(st: Node) -> Val {
var j = 0
while j < len(st.a.kids) { if (st.a.kids[j].s == fd.s) { av = st.a.kids[j].a }; j += 1 }
let lt = llty(fd.ty)
var code = "0"
var code: pointer = "0"
if (lt == "ptr") { code = "null" }
if (av != null) { let v = emit_expr(av); code = v.code }
else { if (fd.a != null) { let dv = emit_expr(fd.a); code = dv.code } } # declared default