fix(lang): the action drain is the program's; --check runs every check a build makes; a registry key named count is refused; name lookups are tables
- the function that calls every reducer (and the action queue) is written in the program's own file: in the first action's file it belonged to that module, depended on every module with a reducer, and joined a game's modules into one 69-module cycle (examples/actions/modules and a ludic deps case hold it); the state instances, the queue and the reducers make no deps edges - ludicc --check / ludic build --check lower the program too and write nothing, so the code writer's refusals are in it: a bind to a function that is gone, an unknown name (and the checker now refuses fn <missing> itself); rejects bind_missing_fn, unknown_name, registry_count_key - def R count is refused: its constant would be PREFIX_COUNT, the registry's size - a file's module, package, trust and numbers-float are tables, and from the check on the lookups of functions, enums, records, globals and externs are too (tagged enums kept as a list): Maroon Lake's check-only build went from about 20 s to 7 s including lowering, its IR from about 2 minutes to under 10 s; duplicate declarations are found by table, not a pair of loops - threads.ludic's pool check gives each call a little work, so a busy machine cannot run them all on the caller before a worker wakes (it failed one run in three under load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2fdefa6040
commit
8cf4b3fed6
24 changed files with 67169 additions and 64398 deletions
|
|
@ -213,19 +213,19 @@ function emit_test_runner() -> void {
|
|||
# two `function`s with one name would collide in the object file; say so in
|
||||
# source terms (and name both files) instead of leaving it to the IR assembler.
|
||||
function check_duplicate_fns() -> void {
|
||||
let k = new []pointer # by name, in a table: a pair of loops was quadratic
|
||||
let v = new []Node
|
||||
ck_tab_init(k, v)
|
||||
var i = 0
|
||||
while i < len(prog) {
|
||||
let d = prog[i]
|
||||
if d.kind == N_FN {
|
||||
var j = i + 1
|
||||
while j < len(prog) {
|
||||
let o = prog[j]
|
||||
if o.kind == N_FN and (o.s == d.s) {
|
||||
g_err_file = o.file; g_err_line = o.line
|
||||
perr(`function '{d.s}' is defined twice (first in {d.file}:{itoa(d.line)})`)
|
||||
}
|
||||
j += 1
|
||||
let first = ck_tab_get(k, v, d.s)
|
||||
if first != null {
|
||||
g_err_file = d.file; g_err_line = d.line
|
||||
perr(`function '{d.s}' is defined twice (first in {first.file}:{itoa(first.line)})`)
|
||||
}
|
||||
ck_tab_put(k, v, d.s, d)
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
|
@ -240,22 +240,23 @@ function decl_group(k: int) -> int {
|
|||
return 0
|
||||
}
|
||||
function check_duplicate_decls() -> void {
|
||||
let k = new []pointer
|
||||
let v = new []Node
|
||||
ck_tab_init(k, v)
|
||||
let n = g_prog_user_end
|
||||
var i = 0
|
||||
while i < n and i < len(prog) {
|
||||
let d = prog[i]
|
||||
let g = decl_group(d.kind)
|
||||
if g > 0 {
|
||||
var j = i + 1
|
||||
while j < n and j < len(prog) {
|
||||
let o = prog[j]
|
||||
if decl_group(o.kind) == g and (o.s == d.s) {
|
||||
g_err_file = o.file
|
||||
g_err_line = o.line
|
||||
perr(`'{d.s}' is defined twice (first in {d.file}:{itoa(d.line)})`)
|
||||
}
|
||||
j += 1
|
||||
let key = `{itoa(g)}:{d.s}`
|
||||
let first = ck_tab_get(k, v, key)
|
||||
if first != null {
|
||||
g_err_file = d.file
|
||||
g_err_line = d.line
|
||||
perr(`'{d.s}' is defined twice (first in {first.file}:{itoa(first.line)})`)
|
||||
}
|
||||
ck_tab_put(k, v, key, d)
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
|
|
@ -264,6 +265,7 @@ function check_duplicate_decls() -> void {
|
|||
function emit_program() -> void {
|
||||
check_duplicate_fns()
|
||||
check_duplicate_decls()
|
||||
ix_start() # the lookups by name, as tables from here on
|
||||
head = buf_new()
|
||||
code = buf_new()
|
||||
g_uses_str = false
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue