From d170d5fbaef463bdf11b32ed7db8ed067e42f25c Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 25 Apr 2026 00:14:15 +0000 Subject: [PATCH] lua: skip top-level guard when chunk has no top-level return; loadstring sees user globals --- lib/lua/scoreboard.json | 44 +++++++++++++++++++---------------------- lib/lua/scoreboard.md | 35 ++++++++++++++++---------------- lib/lua/transpile.sx | 33 ++++++++++++++++++++++++++++--- plans/lua-on-sx.md | 1 + 4 files changed, 68 insertions(+), 45 deletions(-) diff --git a/lib/lua/scoreboard.json b/lib/lua/scoreboard.json index 6e6f18b6..ece8ffe3 100644 --- a/lib/lua/scoreboard.json +++ b/lib/lua/scoreboard.json @@ -1,8 +1,8 @@ { "totals": { "pass": 1, - "fail": 12, - "timeout": 3, + "fail": 11, + "timeout": 4, "skip": 8, "total": 24, "runnable": 16, @@ -15,16 +15,12 @@ ], [ "timeout", - 3 + 4 ], [ "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to call non-functio", 2 ], - [ - "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: module 'C' not found\\\\\\\"\\", - 1 - ], [ "undefined symbol: fat\\", 1 @@ -49,9 +45,9 @@ }, { "name": "attrib.lua", - "status": "fail", - "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: module 'C' not found\\\\\\\"\\", - "ms": 6525 + "status": "timeout", + "reason": "per-test timeout", + "ms": 8008 }, { "name": "big.lua", @@ -63,7 +59,7 @@ "name": "calls.lua", "status": "fail", "reason": "undefined symbol: fat\\", - "ms": 5092 + "ms": 6184 }, { "name": "checktable.lua", @@ -75,7 +71,7 @@ "name": "closure.lua", "status": "timeout", "reason": "per-test timeout", - "ms": 8006 + "ms": 8001 }, { "name": "code.lua", @@ -87,7 +83,7 @@ "name": "constructs.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to compare incompat", - "ms": 6780 + "ms": 7870 }, { "name": "db.lua", @@ -99,13 +95,13 @@ "name": "errors.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 3208 + "ms": 3808 }, { "name": "events.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 7307 + "ms": 7990 }, { "name": "files.lua", @@ -123,13 +119,13 @@ "name": "literals.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 1816 + "ms": 2085 }, { "name": "locals.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to call non-functio", - "ms": 1627 + "ms": 1811 }, { "name": "main.lua", @@ -141,43 +137,43 @@ "name": "math.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to call non-functio", - "ms": 4156 + "ms": 4436 }, { "name": "nextvar.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 7064 + "ms": 7759 }, { "name": "pm.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 5813 + "ms": 6473 }, { "name": "sort.lua", "status": "timeout", "reason": "per-test timeout", - "ms": 8008 + "ms": 8007 }, { "name": "strings.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 3987 + "ms": 4366 }, { "name": "vararg.lua", "status": "fail", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", - "ms": 2243 + "ms": 2422 }, { "name": "verybig.lua", "status": "pass", "reason": "", - "ms": 1085 + "ms": 1077 } ] } \ No newline at end of file diff --git a/lib/lua/scoreboard.md b/lib/lua/scoreboard.md index 30be0498..060e4435 100644 --- a/lib/lua/scoreboard.md +++ b/lib/lua/scoreboard.md @@ -1,14 +1,13 @@ # Lua-on-SX conformance scoreboard **Pass rate:** 1/16 runnable (6.2%) -fail=12 timeout=3 skip=8 total=24 +fail=11 timeout=4 skip=8 total=24 ## Top failure modes - **7x** other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ -- **3x** timeout +- **4x** timeout - **2x** other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio -- **1x** other: Unhandled exception: \"Unhandled exception: \\\"lua: module 'C' not found\\\"\ - **1x** undefined symbol: fat\ - **1x** other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to compare incompat @@ -18,25 +17,25 @@ fail=12 timeout=3 skip=8 total=24 |---|---|---|---:| | all.lua | skip | driver uses dofile to chain other tests | 0 | | api.lua | skip | requires testC (C debug library) | 0 | -| attrib.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: module 'C' not found\\\"\ | 6525 | +| attrib.lua | timeout | per-test timeout | 8008 | | big.lua | timeout | per-test timeout | 8007 | -| calls.lua | fail | undefined symbol: fat\ | 5092 | +| calls.lua | fail | undefined symbol: fat\ | 6184 | | checktable.lua | skip | internal debug helpers | 0 | -| closure.lua | timeout | per-test timeout | 8006 | +| closure.lua | timeout | per-test timeout | 8001 | | code.lua | skip | bytecode inspection via debug library | 0 | -| constructs.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to compare incompat | 6780 | +| constructs.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to compare incompat | 7870 | | db.lua | skip | debug library | 0 | -| errors.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3208 | -| events.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 7307 | +| errors.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3808 | +| events.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 7990 | | files.lua | skip | io library | 0 | | gc.lua | skip | collectgarbage / finalisers | 0 | -| literals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 1816 | -| locals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 1627 | +| literals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2085 | +| locals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 1811 | | main.lua | skip | standalone interpreter driver | 0 | -| math.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 4156 | -| nextvar.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 7064 | -| pm.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 5813 | -| sort.lua | timeout | per-test timeout | 8008 | -| strings.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3987 | -| vararg.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2243 | -| verybig.lua | pass | - | 1085 | +| math.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 4436 | +| nextvar.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 7759 | +| pm.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 6473 | +| sort.lua | timeout | per-test timeout | 8007 | +| strings.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 4366 | +| vararg.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2422 | +| verybig.lua | pass | - | 1077 | diff --git a/lib/lua/transpile.sx b/lib/lua/transpile.sx index 94b12e01..400d514d 100644 --- a/lib/lua/transpile.sx +++ b/lib/lua/transpile.sx @@ -568,12 +568,39 @@ (else sx))))))) (else sx)))) +(define + lua-has-top-return? + (fn (node) + (cond + ((not (= (type-of node) "list")) false) + ((= (len node) 0) false) + ((= (first node) (quote lua-return)) true) + ((or (= (first node) (quote lua-function)) + (= (first node) (quote lua-local-function)) + (= (first node) (quote lua-function-decl))) + false) + (else + (lua-has-top-return-children? (rest node) 0))))) + +(define + lua-has-top-return-children? + (fn (children i) + (cond + ((>= i (len children)) false) + ((lua-has-top-return? (nth children i)) true) + (else (lua-has-top-return-children? children (+ i 1)))))) + (define lua-eval-ast (fn (src) - (let ((sx (lua-transpile src))) - (let ((sx2 (lua-unwrap-final-return sx))) - (eval-expr (lua-tx-function-guard sx2)))))) + (let ((parsed (lua-parse src))) + (let ((sx (lua-tx parsed))) + (let ((sx2 (lua-unwrap-final-return sx))) + (cond + ((lua-has-top-return? parsed) + (eval-expr (lua-tx-function-guard sx2))) + (else + (eval-expr sx2)))))))) (define lua-tx-multi-args diff --git a/plans/lua-on-sx.md b/plans/lua-on-sx.md index 45fb945a..4d933d56 100644 --- a/plans/lua-on-sx.md +++ b/plans/lua-on-sx.md @@ -82,6 +82,7 @@ Each item: implement → tests → tick box → update progress log. _Newest first. Agent appends on every commit._ +- 2026-04-25: lua: scoreboard iteration — `lua-eval-ast` now SKIPS the top-level guard when the parsed chunk has no top-level `return` (recursive AST walk via `lua-has-top-return?` that descends through control-flow but stops at function-body boundaries). Without the guard, top-level user defines leak to the SX top env, and `loadstring`-captured closures can find them. Verified: `function fat(x)...loadstring("return fat(...)")...end; x=fat(5)` works (was undefined). Most PUC-Rio tests still have top-level returns elsewhere, so they still need the guard. Scoreboard unchanged at 1/16 but unblocks future work. - 2026-04-25: lua: scoreboard iteration — math fns now error on bad/missing args (was silently returning 0). New `lua-math-num "name" x` validator wraps `abs`/`ceil`/`floor`/`sqrt`/`exp`/`sin`/`cos`/`tan`/`asin`/`acos`/`atan`/`atan2`/`pow`. errors.lua moves past assert #4 (`pcall(math.sin)` now returns false+err as expected). - 2026-04-24: lua: scoreboard iteration — **pattern character sets** `[...]` and `[^...]`. New `lua-pat-set-end`/`lua-pat-set-match` helpers handle ranges (`[a-z]`), classes inside sets (`[%d%a]`), negation (`[^abc]`), and `[]...]`/`[^]...]` (literal `]` as first char). Asserts 6→4, but timeouts 3→7 — many tests now reach loop-heavy code. 387/387 green (+3 charset tests). - 2026-04-24: lua: scoreboard iteration — `tonumber(s, base)` for bases 2-36. Validates digit ranges per base, supports leading `+`/`-`, trims whitespace. `math.lua` past assert #21. Asserts 8→6, timeouts 3→4. 384/384 green.