refactor(x): per-process scratch dirs, Ludic ports of the LSP test and Forgejo release
- every scratch file lives in `$TMPDIR/x_<pid>/` (tmp_dir/tmp_path in prelude.ludic), removed by main's new dispatch() → tmp_cleanup(); X_KEEP_TMP=1 keeps it. `x test` and `x check-*` may now run together. - `x test-lsp` (tools/x/lsp_test.ludic) replaces tools/test-lsp.py: the whole request stream is framed into one stdin file, the server runs to `exit`, and the response stream is parsed back by request id; adds a check that ludicc's own error is published on save - tools/x/forgejo.ludic replaces tools/ci/forgejo_release.py (curl with a 0600 header file; the token is no longer on the command line; LUDIC_FORGEJO_API for forks) - `x docs-palette --check` regenerates into scratch and compares, so the drift guard judges the working tree rather than git HEAD; the generator no longer emits a trailing blank line the formatter rejects - `x test-tools`: exit 2 from test-lsp / test-grammar.js is a visible skip, never a pass; the widget-prop test uses the `id: Root` syntax - tools/test-grammar.js: current vocabulary (property/model/handler/ prefab/scene/event/become/@Queries), LUDIC_NODE_MODULES, exit 2 on skip - tools/atlas.ludic rewritten in the current language (it did not compile) - operators.ludic / os.ludic registered in the suite - json.ludic: j_quote() writer helper Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
647dfec334
commit
8fed9add66
19 changed files with 1154 additions and 614 deletions
|
|
@ -11,7 +11,7 @@ function bucket_get(bs: []Bucket, k1: pointer, k2: pointer) -> Bucket {
|
|||
var i = 0
|
||||
while i < len(bs) {
|
||||
if bs[i].k1 == k1 and bs[i].k2 == k2 { return bs[i] }
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
let b = new Bucket
|
||||
b.k1 = k1
|
||||
|
|
@ -23,7 +23,7 @@ function bucket_get(bs: []Bucket, k1: pointer, k2: pointer) -> Bucket {
|
|||
function bucket_add(bs: []Bucket, k1: pointer, k2: pointer, v: pointer) -> void {
|
||||
let b = bucket_get(bs, k1, k2)
|
||||
var i = 0
|
||||
while i < len(b.vals) { if b.vals[i] == v { return }; i = i + 1 }
|
||||
while i < len(b.vals) { if b.vals[i] == v { return }; i += 1 }
|
||||
push(b.vals, v)
|
||||
}
|
||||
# ", ".join(sorted(vals))
|
||||
|
|
@ -34,7 +34,7 @@ function join_sorted(vals: []pointer) -> pointer {
|
|||
while i < len(vals) {
|
||||
if i > 0 { sb_puts(b, ", ") }
|
||||
sb_puts(b, vals[i])
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
return sb_str(b)
|
||||
}
|
||||
|
|
@ -70,7 +70,7 @@ function cp_len(s: pointer) -> int {
|
|||
let n = slen(s)
|
||||
var c = 0
|
||||
var i = 0
|
||||
while i < n { if (s[i] & 192) != 128 { c = c + 1 }; i = i + 1 }
|
||||
while i < n { if (s[i] & 192) != 128 { c += 1 }; i += 1 }
|
||||
return c
|
||||
}
|
||||
function replace_all(hay: pointer, needle: pointer, repl: pointer) -> pointer {
|
||||
|
|
@ -80,8 +80,8 @@ function replace_all(hay: pointer, needle: pointer, repl: pointer) -> pointer {
|
|||
let n = slen(hay)
|
||||
var i = 0
|
||||
while i < n {
|
||||
if s_starts_at(hay, i, needle) { sb_puts(b, repl); i = i + nl }
|
||||
else { sb_putc(b, hay[i]); i = i + 1 }
|
||||
if s_starts_at(hay, i, needle) { sb_puts(b, repl); i += nl }
|
||||
else { sb_putc(b, hay[i]); i += 1 }
|
||||
}
|
||||
return sb_str(b)
|
||||
}
|
||||
|
|
@ -110,14 +110,14 @@ function cmd_docs_check() -> int {
|
|||
var ci = 0
|
||||
while ci < len(cats) {
|
||||
let cat = cats[ci]
|
||||
ci = ci + 1
|
||||
ci += 1
|
||||
let cdir = "docs/language/" + cat
|
||||
if not is_dir(cdir) { continue }
|
||||
let files = list_sorted(cdir)
|
||||
var fi = 0
|
||||
while fi < len(files) {
|
||||
let fn = files[fi]
|
||||
fi = fi + 1
|
||||
fi += 1
|
||||
if not s_ends(fn, ".md") { continue }
|
||||
if fn == "_section.md" { continue }
|
||||
let d = parse_front(cdir + "/" + fn)
|
||||
|
|
@ -143,12 +143,12 @@ function cmd_docs_check() -> int {
|
|||
while k < len(inv.keys) {
|
||||
let cat = inv.keys[k]
|
||||
let ids = inv.kids[k]
|
||||
k = k + 1
|
||||
k += 1
|
||||
if ids.t != JV_ARR { continue }
|
||||
var m = 0
|
||||
while m < len(ids.kids) {
|
||||
let sid = ids.kids[m].s
|
||||
m = m + 1
|
||||
m += 1
|
||||
if meta_get(id2src, sid, "") == "" { push(problems, `no source file for inventory symbol: {sid} ({cat})`) }
|
||||
else if not file_exists(`{site}/{sid}.html`) { push(problems, `no generated page for symbol: {sid}.html`) }
|
||||
}
|
||||
|
|
@ -160,11 +160,11 @@ function cmd_docs_check() -> int {
|
|||
let tok2ids = new []Bucket # k1=kind, k2=tok -> ids
|
||||
let ns2dirs = new []Bucket # k1="", k2=ns -> dirs
|
||||
let id2dirs = new []Bucket # k1="", k2=section id -> dirs
|
||||
let title2dirs = new []Bucket # k1="", k2=lower(title) -> dirs
|
||||
let title2dirs = new []Bucket # k1="", k2=lower(title) -> dirs
|
||||
ci = 0
|
||||
while ci < len(cats) {
|
||||
let cat = cats[ci]
|
||||
ci = ci + 1
|
||||
ci += 1
|
||||
let cdir = "docs/language/" + cat
|
||||
if not is_dir(cdir) { continue }
|
||||
let secp = cdir + "/_section.md"
|
||||
|
|
@ -177,7 +177,7 @@ function cmd_docs_check() -> int {
|
|||
var fi = 0
|
||||
while fi < len(files) {
|
||||
let fn = files[fi]
|
||||
fi = fi + 1
|
||||
fi += 1
|
||||
if not s_ends(fn, ".md") { continue }
|
||||
if fn == "_section.md" { continue }
|
||||
let d = parse_front(cdir + "/" + fn)
|
||||
|
|
@ -185,7 +185,7 @@ function cmd_docs_check() -> int {
|
|||
let id = meta_get(d.m, "id", "")
|
||||
let toks = split_ws(meta_get(d.m, "tokens", ""))
|
||||
var ti = 0
|
||||
while ti < len(toks) { bucket_add(tok2ids, kind, toks[ti], id); ti = ti + 1 }
|
||||
while ti < len(toks) { bucket_add(tok2ids, kind, toks[ti], id); ti += 1 }
|
||||
let ns = meta_get(d.m, "ns", "")
|
||||
if slen(ns) > 0 { bucket_add(ns2dirs, "", ns, cat) }
|
||||
}
|
||||
|
|
@ -193,25 +193,25 @@ function cmd_docs_check() -> int {
|
|||
var bi = 0
|
||||
while bi < len(tok2ids) {
|
||||
let b = tok2ids[bi]
|
||||
bi = bi + 1
|
||||
bi += 1
|
||||
if len(b.vals) > 1 { push(problems, `token '{b.k2}' ({b.k1}) documented on multiple pages: {join_sorted(b.vals)}`) }
|
||||
}
|
||||
bi = 0
|
||||
while bi < len(ns2dirs) {
|
||||
let b = ns2dirs[bi]
|
||||
bi = bi + 1
|
||||
bi += 1
|
||||
if len(b.vals) > 1 { push(problems, `namespace '{b.k2}' documented from multiple dirs: {join_sorted(b.vals)}`) }
|
||||
}
|
||||
bi = 0
|
||||
while bi < len(id2dirs) {
|
||||
let b = id2dirs[bi]
|
||||
bi = bi + 1
|
||||
bi += 1
|
||||
if len(b.vals) > 1 { push(problems, `section id '{b.k2}' declared by multiple dirs: {join_sorted(b.vals)}`) }
|
||||
}
|
||||
bi = 0
|
||||
while bi < len(title2dirs) {
|
||||
let b = title2dirs[bi]
|
||||
bi = bi + 1
|
||||
bi += 1
|
||||
if slen(b.k2) > 0 and len(b.vals) > 1 { push(problems, `section title '{b.k2}' shared by multiple dirs: {join_sorted(b.vals)}`) }
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ function cmd_docs_check() -> int {
|
|||
while i < len(thin) and i < 12 {
|
||||
if i > 0 { sb_puts(b, ", ") }
|
||||
sb_puts(b, thin[i])
|
||||
i = i + 1
|
||||
i += 1
|
||||
}
|
||||
var tail = ""
|
||||
if len(thin) > 12 { tail = " …" }
|
||||
|
|
@ -247,18 +247,18 @@ function cmd_docs_check() -> int {
|
|||
var i = 0
|
||||
while i < len(targets) {
|
||||
let tgt = targets[i]
|
||||
i = i + 1
|
||||
i += 1
|
||||
if not file_exists(`{site}/{tgt}.html`) { push(problems, `highlighter links to {tgt}.html but it was not generated`) }
|
||||
}
|
||||
}
|
||||
|
||||
# report
|
||||
var wi = 0
|
||||
while wi < len(warnings) { print(` warning: {warnings[wi]}`); wi = wi + 1 }
|
||||
while wi < len(warnings) { print(` warning: {warnings[wi]}`); wi += 1 }
|
||||
if len(problems) > 0 {
|
||||
print("docs check FAILED:")
|
||||
var pi = 0
|
||||
while pi < len(problems) { print(` - {problems[pi]}`); pi = pi + 1 }
|
||||
while pi < len(problems) { print(` - {problems[pi]}`); pi += 1 }
|
||||
return 1
|
||||
}
|
||||
print(`docs check OK: {site} ({string(len(id2src.keys))} symbols documented)`)
|
||||
|
|
@ -271,7 +271,7 @@ function collect_targets_str(o: JVal, out: []pointer) -> void {
|
|||
var i = 0
|
||||
while i < len(o.kids) {
|
||||
let v = o.kids[i]
|
||||
i = i + 1
|
||||
i += 1
|
||||
if v.t == JV_STR { set_add(out, v.s) }
|
||||
}
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ function collect_targets_id(o: JVal, out: []pointer) -> void {
|
|||
var i = 0
|
||||
while i < len(o.kids) {
|
||||
let v = o.kids[i]
|
||||
i = i + 1
|
||||
i += 1
|
||||
let id = j_get(v, "id")
|
||||
if id.t == JV_STR { set_add(out, id.s) }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue