fix(migrate): 0.R4 - --prune keeps a state declared after a plain parameter; a parameter named twice is refused

On Maroon Lake the prune gave home_keep_records(base_app_st, home_st, r: RunRecords, save_app_st) a
second save_app_st at the front, and every call a second argument: a state declared after a plain
parameter was not counted as declared. It is now, and a call to such a function is never given the
state again. `ludic build --check` let the duplicate through and clang refused it; the checker now
refuses a function that names two parameters alike (`add names two parameters n`).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-26 05:32:08 +03:00
parent 71735b10a2
commit c35481f344
8 changed files with 47291 additions and 46599 deletions

View file

@ -154,12 +154,26 @@ function ck_stmt(s: Node) -> void {
}
ck_walk(s)
}
# a name given to two parameters: the second would shadow the first, and nothing could reach it
function ck_param_twice(d: Node, i: int) -> void {
var j = 0
while j < i {
if d.kids[j].kind == N_PARAM and (d.kids[j].s == d.kids[i].s) {
ck_err("arity", d.kids[i], `{d.s} names two parameters {d.kids[i].s}`)
return
}
j += 1
}
}
function ck_fn_body(d: Node) -> void {
mg_enter(d, 0)
let m = ck_mark()
var i = 0
while i < len(d.kids) {
if d.kids[i].kind == N_PARAM { ck_bind_param(d.kids[i]) }
if d.kids[i].kind == N_PARAM {
ck_param_twice(d, i)
ck_bind_param(d.kids[i])
}
i += 1
}
ck_ret = d.ty

View file

@ -559,8 +559,22 @@ function mg_list(set: pointer) -> []int {
function mg_declared(n: Node, s: int) -> bool {
if n.kind != N_FN { return false }
var i = 0
while i < len(n.kids) and n.kids[i].kind == N_PARAM and is_state_ty(n.kids[i].ty) {
if (n.kids[i].ty == g_ms_name[s]) { return true }
while i < len(n.kids) { # anywhere in the list: a state after a plain parameter is declared too
if n.kids[i].kind == N_PARAM and (n.kids[i].ty == g_ms_name[s]) { return true }
i += 1
}
return false
}
# a state declared after a plain parameter: every call already names it where it stands
function mg_declared_late(n: Node, s: int) -> bool {
if n.kind != N_FN { return false }
var plain = false
var i = 0
while i < len(n.kids) {
if n.kids[i].kind == N_PARAM {
if not is_state_ty(n.kids[i].ty) { plain = true }
else if plain and (n.kids[i].ty == g_ms_name[s]) { return true }
}
i += 1
}
return false
@ -972,7 +986,7 @@ function mg_calls() -> void {
let passed = g_mc_passed[c] == 1
var k = 0
while k < len(need) {
if not (mg_declared(callee, need[k]) and passed) {
if not (mg_declared(callee, need[k]) and (passed or mg_declared_late(callee, need[k]))) {
if len(text) > 0 { text = text + ", " }
text = text + g_ms_param[need[k]]
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff