lua: if/else/elseif body scoping via (let () …); else-branch leak fixed +3 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-24 20:26:20 +00:00
parent 54d7fcf436
commit f0a4dfbea8
5 changed files with 52 additions and 33 deletions

View File

@@ -39,7 +39,7 @@
"name": "attrib.lua", "name": "attrib.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 5565 "ms": 5754
}, },
{ {
"name": "big.lua", "name": "big.lua",
@@ -51,7 +51,7 @@
"name": "calls.lua", "name": "calls.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 4455 "ms": 4651
}, },
{ {
"name": "checktable.lua", "name": "checktable.lua",
@@ -63,7 +63,7 @@
"name": "closure.lua", "name": "closure.lua",
"status": "timeout", "status": "timeout",
"reason": "per-test timeout", "reason": "per-test timeout",
"ms": 8007 "ms": 8006
}, },
{ {
"name": "code.lua", "name": "code.lua",
@@ -75,7 +75,7 @@
"name": "constructs.lua", "name": "constructs.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 4074 "ms": 4212
}, },
{ {
"name": "db.lua", "name": "db.lua",
@@ -87,13 +87,13 @@
"name": "errors.lua", "name": "errors.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 2974 "ms": 3006
}, },
{ {
"name": "events.lua", "name": "events.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 6657 "ms": 6900
}, },
{ {
"name": "files.lua", "name": "files.lua",
@@ -111,13 +111,13 @@
"name": "literals.lua", "name": "literals.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 1730 "ms": 1804
}, },
{ {
"name": "locals.lua", "name": "locals.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 1597 "ms": 1596
}, },
{ {
"name": "main.lua", "name": "main.lua",
@@ -129,43 +129,43 @@
"name": "math.lua", "name": "math.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 3721 "ms": 3930
}, },
{ {
"name": "nextvar.lua", "name": "nextvar.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 6582 "ms": 6822
}, },
{ {
"name": "pm.lua", "name": "pm.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 5582 "ms": 5745
}, },
{ {
"name": "sort.lua", "name": "sort.lua",
"status": "timeout", "status": "timeout",
"reason": "per-test timeout", "reason": "per-test timeout",
"ms": 8008 "ms": 8007
}, },
{ {
"name": "strings.lua", "name": "strings.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 3704 "ms": 3814
}, },
{ {
"name": "vararg.lua", "name": "vararg.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"assertion failed!\\\\\\\"\\",
"ms": 2041 "ms": 2140
}, },
{ {
"name": "verybig.lua", "name": "verybig.lua",
"status": "fail", "status": "fail",
"reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to call non-functio", "reason": "other: Unhandled exception: \\\"Unhandled exception: \\\\\\\"lua: attempt to call non-functio",
"ms": 528 "ms": 558
} }
] ]
} }

View File

@@ -15,25 +15,25 @@ fail=13 timeout=3 skip=8 total=24
|---|---|---|---:| |---|---|---|---:|
| all.lua | skip | driver uses dofile to chain other tests | 0 | | all.lua | skip | driver uses dofile to chain other tests | 0 |
| api.lua | skip | requires testC (C debug library) | 0 | | api.lua | skip | requires testC (C debug library) | 0 |
| attrib.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 5565 | | attrib.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 5754 |
| big.lua | timeout | per-test timeout | 8008 | | big.lua | timeout | per-test timeout | 8008 |
| calls.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 4455 | | calls.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 4651 |
| checktable.lua | skip | internal debug helpers | 0 | | checktable.lua | skip | internal debug helpers | 0 |
| closure.lua | timeout | per-test timeout | 8007 | | closure.lua | timeout | per-test timeout | 8006 |
| code.lua | skip | bytecode inspection via debug library | 0 | | code.lua | skip | bytecode inspection via debug library | 0 |
| constructs.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 4074 | | constructs.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 4212 |
| db.lua | skip | debug library | 0 | | db.lua | skip | debug library | 0 |
| errors.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2974 | | errors.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3006 |
| events.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 6657 | | events.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 6900 |
| files.lua | skip | io library | 0 | | files.lua | skip | io library | 0 |
| gc.lua | skip | collectgarbage / finalisers | 0 | | gc.lua | skip | collectgarbage / finalisers | 0 |
| literals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 1730 | | literals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 1804 |
| locals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 1597 | | locals.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 1596 |
| main.lua | skip | standalone interpreter driver | 0 | | main.lua | skip | standalone interpreter driver | 0 |
| math.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3721 | | math.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3930 |
| nextvar.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 6582 | | nextvar.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 6822 |
| pm.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 5582 | | pm.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 5745 |
| sort.lua | timeout | per-test timeout | 8008 | | sort.lua | timeout | per-test timeout | 8007 |
| strings.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3704 | | strings.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 3814 |
| vararg.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2041 | | vararg.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"assertion failed!\\\"\ | 2140 |
| verybig.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 528 | | verybig.lua | fail | other: Unhandled exception: \"Unhandled exception: \\\"lua: attempt to call non-functio | 558 |

View File

@@ -908,6 +908,14 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 1801) (epoch 1801)
(eval "(lua-eval-ast \"do local i = 10 do local i = 100 assert(i == 100) end assert(i == 10) end return \\\"ok\\\"\")") (eval "(lua-eval-ast \"do local i = 10 do local i = 100 assert(i == 100) end assert(i == 10) end return \\\"ok\\\"\")")
;; ── if/else/elseif body scoping ──────────────────────────────
(epoch 1810)
(eval "(lua-eval-ast \"local x = 10 if true then local x = 99 end return x\")")
(epoch 1811)
(eval "(lua-eval-ast \"local x = 10 if false then else local x = 99 end return x\")")
(epoch 1812)
(eval "(lua-eval-ast \"local x = 10 if false then elseif true then local x = 99 end return x\")")
EPOCHS EPOCHS
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1368,6 +1376,11 @@ check 1705 "f(a, b, ...) mixed" '783'
check 1800 "inner do local shadows" '10' check 1800 "inner do local shadows" '10'
check 1801 "nested do scopes" '"ok"' check 1801 "nested do scopes" '"ok"'
# ── if/else/elseif body scoping ──────────────────────────────
check 1810 "if then local shadows" '10'
check 1811 "else local shadows" '10'
check 1812 "elseif local shadows" '10'
TOTAL=$((PASS + FAIL)) TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL Lua-on-SX tests passed" echo "ok $PASS/$TOTAL Lua-on-SX tests passed"

View File

@@ -303,13 +303,18 @@
rhs)) rhs))
(else (error "lua-transpile: bad assignment target"))))) (else (error "lua-transpile: bad assignment target")))))
(define
lua-tx-if-body
(fn (body)
(list (make-symbol "let") (list) body)))
(define (define
lua-tx-if lua-tx-if
(fn (fn
(node) (node)
(let (let
((cnd (lua-tx (nth node 1))) ((cnd (lua-tx (nth node 1)))
(then-body (lua-tx (nth node 2))) (then-body (lua-tx-if-body (lua-tx (nth node 2))))
(elseifs (nth node 3)) (elseifs (nth node 3))
(else-body (nth node 4))) (else-body (nth node 4)))
(if (if
@@ -333,7 +338,7 @@
clauses clauses
(append (append
clauses clauses
(list (list (make-symbol "else") (lua-tx else-body))))))))) (list (list (make-symbol "else") (lua-tx-if-body (lua-tx else-body))))))))))
(define (define
lua-tx-elseif lua-tx-elseif
@@ -341,7 +346,7 @@
(pair) (pair)
(list (list
(list (make-symbol "lua-truthy?") (lua-tx (first pair))) (list (make-symbol "lua-truthy?") (lua-tx (first pair)))
(lua-tx (nth pair 1))))) (lua-tx-if-body (lua-tx (nth pair 1))))))
(define (define
lua-tx-while lua-tx-while

View File

@@ -82,6 +82,7 @@ Each item: implement → tests → tick box → update progress log.
_Newest first. Agent appends on every commit._ _Newest first. Agent appends on every commit._
- 2026-04-24: lua: scoreboard iteration — **`if`/`else`/`elseif` body scoping** (latent bug). `else local x = 99` was leaking to enclosing scope. Wrap all three branches in `(let () …)` via `lua-tx-if-body`. 358 tests.
- 2026-04-24: lua: scoreboard iteration — **`do`-block proper scoping**. Was transpiling `do ... end` to a raw `lua-tx` pass-through, so `define`s inside leaked to the enclosing scope (`do local i = 100 end` overwrote outer `i`). Now wraps in `(let () body)` for proper lexical isolation. 355 tests, +2 scoping tests. - 2026-04-24: lua: scoreboard iteration — **`do`-block proper scoping**. Was transpiling `do ... end` to a raw `lua-tx` pass-through, so `define`s inside leaked to the enclosing scope (`do local i = 100 end` overwrote outer `i`). Now wraps in `(let () body)` for proper lexical isolation. 355 tests, +2 scoping tests.
- 2026-04-24: lua: scoreboard iteration — `lua-to-number` trims whitespace before `parse-number` (Lua coerces `" 3e0 "` in arithmetic). math.lua moved past the arith-type error to deeper assertion-land. 12× asserts / 3× timeouts / 1× call-non-fn. - 2026-04-24: lua: scoreboard iteration — `lua-to-number` trims whitespace before `parse-number` (Lua coerces `" 3e0 "` in arithmetic). math.lua moved past the arith-type error to deeper assertion-land. 12× asserts / 3× timeouts / 1× call-non-fn.
- 2026-04-24: lua: scoreboard iteration — `table.getn`/`setn`/`foreach`/`foreachi` (Lua 5.0-era), `string.reverse`. `sort.lua` unblocked past `getn`-undef; now times out on the 30k-element sort body (insertion sort too slow). 13 fail / 3 timeout / 0 pass. - 2026-04-24: lua: scoreboard iteration — `table.getn`/`setn`/`foreach`/`foreachi` (Lua 5.0-era), `string.reverse`. `sort.lua` unblocked past `getn`-undef; now times out on the 30k-element sort body (insertion sort too slow). 13 fail / 3 timeout / 0 pass.