feat(cli): ludic build --check / ludicc --check - check without building
The parse, the types and the module rules (export, uses, layers, ports, registries) run and nothing is emitted or linked: about three seconds on Maroon Lake. In this mode the checker asks vis_check at each reference it resolves, with a global's initializer and a registry's entries seen from the files the emitter would use. Reseed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
7ef6c7ec75
commit
8892f51096
12 changed files with 15546 additions and 14721 deletions
|
|
@ -180,6 +180,7 @@ function ck_call(e: Node) -> pointer {
|
|||
if tf != null { ck_raw(e, `{b.s}.{c.s}, a C function`) }
|
||||
}
|
||||
if tf != null {
|
||||
if ck_fn(g_al_target[al]) != null { ck_vis(tf, g_al_target[al], e) }
|
||||
ck_extern_arg = ck_extern(g_al_target[al]) != null
|
||||
let at = ck_call_alias(e, `{b.s}.{c.s}`, al, tf)
|
||||
ck_extern_arg = false
|
||||
|
|
@ -192,6 +193,7 @@ function ck_call(e: Node) -> pointer {
|
|||
# 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 { ck_vis(nf, nf.s, e) }
|
||||
if nf != null and nf.ty != null { return nf.ty }
|
||||
return "?"
|
||||
}
|
||||
|
|
@ -218,9 +220,15 @@ function ck_call_named(e: Node, name: pointer) -> pointer {
|
|||
let bt = ck_builtin(e, name)
|
||||
if bt != null { return bt }
|
||||
let f = ck_fn(name)
|
||||
if f != null { return ck_call_fn(e, name, f) }
|
||||
if f != null {
|
||||
ck_vis(f, name, e)
|
||||
return ck_call_fn(e, name, f)
|
||||
}
|
||||
let gt = gen_template(g_gen_fns, name)
|
||||
if gt != null { return gen_call(e, name, gt) }
|
||||
if gt != null {
|
||||
ck_vis(gt, name, e)
|
||||
return gen_call(e, name, gt)
|
||||
}
|
||||
let x = ck_extern(name)
|
||||
if x != null {
|
||||
ck_raw(e, `the C function {name}`)
|
||||
|
|
@ -237,6 +245,7 @@ function ck_call_named(e: Node, name: pointer) -> pointer {
|
|||
# emit E(field: v): each field gets the type the event declares for it
|
||||
function ck_emit(s: Node) -> void {
|
||||
let ev = find_event(s.s)
|
||||
ck_vis(ev, s.s, s)
|
||||
if s.a == null { return }
|
||||
var i = 0
|
||||
while i < len(s.a.kids) {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ function ck_expr(e: Node) -> pointer {
|
|||
if k == E_ID { return ck_id(e) }
|
||||
if k == E_FNREF {
|
||||
let f = ck_fn(e.s)
|
||||
ck_vis(f, e.s, e)
|
||||
if f != null { return fn_sig_of(f) }
|
||||
return "?"
|
||||
}
|
||||
|
|
@ -68,11 +69,30 @@ function ck_id(e: Node) -> pointer {
|
|||
let li = ck_local(e.s)
|
||||
if li >= 0 { return ck_tys[li] }
|
||||
let g = ck_global(e.s)
|
||||
if g != null { return g.ty }
|
||||
if g != null {
|
||||
ck_vis(g, e.s, e)
|
||||
return g.ty
|
||||
}
|
||||
return "?"
|
||||
}
|
||||
# --check: the module rules (uses, export, ports - emit_vis.ludic) asked here, where every reference
|
||||
# is resolved, since a check-only build stops before the emitter that asks them otherwise
|
||||
var g_check_only: bool = false
|
||||
var ck_vis_file: pointer = null # a global's initializer is its declaration's file's code (as emitted)
|
||||
var ck_vis_skip: bool = false # a port's bind, checked where it was written (ports.ludic)
|
||||
function ck_vis(d: Node, name: pointer, at: Node) -> void {
|
||||
if not g_check_only or ck_vis_skip or d == null or at == null or at.file == null { return }
|
||||
g_err_file = at.file
|
||||
if ck_vis_file != null { g_err_file = ck_vis_file }
|
||||
g_err_line = at.line
|
||||
vis_check(d, name)
|
||||
}
|
||||
function ck_new(e: Node) -> pointer {
|
||||
let r = ck_record(e.s)
|
||||
ck_vis(r, e.s, e)
|
||||
if r == null and g_check_only and port_find(e.s) >= 0 {
|
||||
ck_err("port", e, `{e.s} is a port: it is filled once with 'bind {e.s} {{ ... }}' where the program is put together, not made with new`)
|
||||
}
|
||||
if e.a != null {
|
||||
var i = 0
|
||||
while i < len(e.a.kids) {
|
||||
|
|
@ -91,8 +111,12 @@ function ck_new(e: Node) -> pointer {
|
|||
function ck_list(e: Node) -> pointer {
|
||||
var t: pointer = "?"
|
||||
var i = 0
|
||||
let saved = ck_vis_file
|
||||
while i < len(e.kids) {
|
||||
# a registry's entries are their defs' files' code (emit_list_elem)
|
||||
if saved != null and e.kids[i].file != null { ck_vis_file = e.kids[i].file }
|
||||
let et = ck_expr(e.kids[i])
|
||||
ck_vis_file = saved
|
||||
if ck_unknown(t) { t = et }
|
||||
else { ck_give(t, et, e.kids[i], `an element of a []{t}`) }
|
||||
i += 1
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ function ck_fn_body(d: Node) -> void {
|
|||
}
|
||||
function ck_listener(l: Node) -> void {
|
||||
let ev = find_event(l.s)
|
||||
ck_vis(ev, l.s, l)
|
||||
let m = ck_mark()
|
||||
if ev != null {
|
||||
var i = 0
|
||||
|
|
@ -177,7 +178,13 @@ function check_program() -> void {
|
|||
let d = prog[i]
|
||||
if d.kind == N_FN { ck_fn_body(d) }
|
||||
if d.kind == N_MAIN or d.kind == N_TEST { ck_block(d.a) }
|
||||
if (d.kind == N_VAR or d.kind == N_CONST) and d.a != null { ck_give(d.ty, ck_expr(d.a), d.a, d.s) }
|
||||
if (d.kind == N_VAR or d.kind == N_CONST) and d.a != null {
|
||||
ck_vis_file = d.file
|
||||
ck_vis_skip = d.kind == N_VAR and is_port_var(d)
|
||||
ck_give(d.ty, ck_expr(d.a), d.a, d.s)
|
||||
ck_vis_file = null
|
||||
ck_vis_skip = false
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
var j = 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue