fix(parse): fn stays an ordinary name unless a function name follows on the same line

`fn name` read `while p < fn and ...` as a reference to a function called `and`, which broke
tools/ludic-cli/glgen.ludic and so the dev tool's own build. A reference now needs the name on
the same line and not one of and / or / not / in / is. The threads example checks `fn` as a
local before `and`. Reseeded; bootstrap-cfree reproduces the seed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-15 14:12:29 +03:00
parent c10abd9f9f
commit 04cda22d19
4 changed files with 41104 additions and 40800 deletions

View file

@ -49,6 +49,7 @@ program Threads {
if (Sync.cpu_count() > 1 and pooled > 0) or (Sync.cpu_count() == 1 and pooled == 0) { print(6) }
Job.parallel_for(0, fn square, sq) # nothing to do: returns at once
print(7)
let fn = 7 # `fn` is still an ordinary name, before `and` too
if 0 < fn and fn < 8 { print(fn) }
}
}

View file

@ -193,7 +193,8 @@ function p_primary() -> Node {
if (t.text == "new") { pi += 1; let n = node(E_NEW); n.s = ptype(); if is_op("{") { n.a = record() }; return n }
if (t.text == "spawn") { return parse_spawn() } # spawn as an expression: the new entity
# fn name — a top-level function as a value, for a worker entry point (Job.parallel_for)
if (t.text == "fn") and (toks[pi + 1].kind == TK_ID) { pi += 1; let n = node(E_FNREF); n.line = t.line; n.s = eat_id(); return n }
# `fn` stays an ordinary name before an operator word (`p < fn and ...`) or at the end of a line
if (t.text == "fn") and (toks[pi + 1].kind == TK_ID) and (toks[pi + 1].line == t.line) and (toks[pi + 1].text != "and") and (toks[pi + 1].text != "or") and (toks[pi + 1].text != "not") and (toks[pi + 1].text != "in") and (toks[pi + 1].text != "is") { pi += 1; let n = node(E_FNREF); n.line = t.line; n.s = eat_id(); return n }
# try EXPR else { ... } — evaluate a fallible (result-typed) expression; on
# `ok` the whole expression is its payload, on `err` the else block runs (with
# the message bound to `error`) and its trailing expression is the fallback.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff