feat(lang): L6 namespaces declared in Ludic - alias

`alias meth(labels) = target` in a namespace block makes Ns.meth a call to
target with those labels (the target's own parameter names without a list). The
engine's 41 table-driven namespaces - 438 methods: Http, Udp, Process, Json,
Value, Screen, Input, Audio, World, Tiled, ... - leave emit_ns_call for
runtime/native/namespaces.ludic, spliced into every program; 532 lines of
compiler go and the seed shrinks by 23k lines of IR. The game's IR is byte
identical. The checker checks an alias call's arguments against its target.
Still built in: the inline namespaces (Math, Text, List, Vector, Color, Time,
Date, ...) and the methods that pick a target by argument type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-24 02:40:57 +03:00
parent 9662680bb0
commit 9259808f80
16 changed files with 49226 additions and 95736 deletions

View file

@ -20,6 +20,15 @@ function ck_call_fn(e: Node, name: pointer, f: Node) -> pointer {
if f.ty == null { return "void" }
return f.ty
}
function ck_call_alias(e: Node, name: pointer, al: int, f: Node) -> pointer {
let labels = new []pointer
let tys = new []pointer
ck_params(f, labels, tys)
let alabels = ns_alias_labels(al)
if len(alabels) == len(tys) { ck_args(e, name, alabels, tys) } else { ck_args(e, name, labels, tys) }
if f.ty == null { return "void" }
return f.ty
}
function ck_call_sig(e: Node, name: pointer, t: pointer) -> pointer {
ck_args(e, name, new []pointer, fn_ty_params(t))
return fn_ty_ret(t)
@ -97,8 +106,17 @@ function ck_call(e: Node) -> pointer {
if c.kind == E_MEMBER {
let b = c.a
if b.kind == E_ID and ck_local(b.s) < 0 and ck_global(b.s) == null {
# Ns.fn: the emitter's own table lowers it, supplying defaults and reordering, so the
# Ludic function behind it gives the result's type and nothing about the arguments
# an alias (L6) is its target, labels and all, so its arguments are checked in full
let al = ns_alias_find(b.s, c.s)
if al >= 0 {
var tf = ck_fn(g_al_target[al])
if tf == null { tf = ck_extern(g_al_target[al]) }
if tf != null { return ck_call_alias(e, `{b.s}.{c.s}`, al, tf) }
ck_walk_args(e)
return "?"
}
# any other Ns.fn is the emitter's own table, which supplies defaults and reorders,
# so the Ludic function behind it gives the result's type and nothing about the arguments
ck_walk_args(e)
let nf = ck_fn(ns_lower(b.s) + "_" + c.s)
if nf != null and nf.ty != null { return nf.ty }