lua: table library (insert/remove/concat/sort/unpack) +13 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-24 19:00:18 +00:00
parent 6dfef34a4b
commit 40439cf0e1
3 changed files with 183 additions and 1 deletions

View File

@@ -991,3 +991,141 @@
(dict-set! math "modf" lua-math-modf) (dict-set! math "modf" lua-math-modf)
(dict-set! math "random" lua-math-random) (dict-set! math "random" lua-math-random)
(dict-set! math "randomseed" lua-math-randomseed) (dict-set! math "randomseed" lua-math-randomseed)
;; ── table library ─────────────────────────────────────────────
(define table {})
(define
lua-table-insert
(fn (&rest args)
(cond
((= (len args) 2)
(let ((t (first args)) (v (nth args 1)))
(let ((n (lua-len t)))
(dict-set! t (str (+ n 1)) v))))
((= (len args) 3)
(let ((t (first args)) (pos (nth args 1)) (v (nth args 2)))
(let ((n (lua-len t)))
(begin
(define
tbl-shift-up
(fn (i)
(when (>= i pos)
(begin
(dict-set! t (str (+ i 1)) (get t (str i)))
(tbl-shift-up (- i 1))))))
(tbl-shift-up n)
(dict-set! t (str pos) v)))))
(else (error "lua: table.insert: wrong args")))))
(define
lua-table-remove
(fn (&rest args)
(let ((t (first args)))
(let ((n (lua-len t)))
(let ((pos (if (> (len args) 1) (nth args 1) n)))
(cond
((<= n 0) nil)
(else
(let ((v (get t (str pos))))
(begin
(define
tbl-shift-down
(fn (i)
(when (< i n)
(begin
(dict-set! t (str i) (get t (str (+ i 1))))
(tbl-shift-down (+ i 1))))))
(tbl-shift-down pos)
(dict-set! t (str n) nil)
v)))))))))
(define
lua-table-concat
(fn (&rest args)
(let ((t (first args))
(sep (if (> (len args) 1) (nth args 1) ""))
(i (if (> (len args) 2) (nth args 2) 1))
(j (if (> (len args) 3) (nth args 3) (lua-len (first args)))))
(cond
((> i j) "")
(else
(let ((out (lua-concat-coerce (get t (str i)))))
(begin
(define
loop
(fn (k)
(when (<= k j)
(begin
(set! out (str out sep (lua-concat-coerce (get t (str k)))))
(loop (+ k 1))))))
(loop (+ i 1))
out)))))))
;; Simple insertion sort for tables
(define
lua-table-sort
(fn (&rest args)
(let ((t (first args))
(comp (if (> (len args) 1) (nth args 1) nil)))
(let ((n (lua-len t)))
(begin
(define
lt?
(fn (a b)
(cond
((= comp nil) (lua-lt a b))
(else (lua-truthy? (lua-call comp a b))))))
(define
insert-sorted
(fn (i)
(when (> i 1)
(let ((v (get t (str i))) (prev (get t (str (- i 1)))))
(when (lt? v prev)
(begin
(dict-set! t (str i) prev)
(dict-set! t (str (- i 1)) v)
(insert-sorted (- i 1))))))))
(define
outer
(fn (i)
(when (<= i n)
(begin
(insert-sorted i)
(outer (+ i 1))))))
(outer 2)
nil)))))
(define
lua-unpack
(fn (&rest args)
(let ((t (first args))
(i (if (> (len args) 1) (nth args 1) 1))
(j (if (> (len args) 2) (nth args 2) (lua-len (first args)))))
(cond
((> i j) nil)
(else
(let ((out (list (quote lua-multi))))
(begin
(define
loop
(fn (k)
(when (<= k j)
(begin
(set! out (append out (list (get t (str k)))))
(loop (+ k 1))))))
(loop i)
out)))))))
(define
lua-table-maxn
(fn (t) (lua-len t)))
(dict-set! table "insert" lua-table-insert)
(dict-set! table "remove" lua-table-remove)
(dict-set! table "concat" lua-table-concat)
(dict-set! table "sort" lua-table-sort)
(dict-set! table "unpack" lua-unpack)
(dict-set! table "maxn" lua-table-maxn)
(define unpack lua-unpack)

View File

@@ -804,6 +804,34 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 1261) (epoch 1261)
(eval "(lua-eval-ast \"local r = math.random(5, 10) return r >= 5 and r <= 10\")") (eval "(lua-eval-ast \"local r = math.random(5, 10) return r >= 5 and r <= 10\")")
;; ── Phase 6: table library ────────────────────────────────────
(epoch 1300)
(eval "(lua-eval-ast \"local t = {1, 2, 3} table.insert(t, 4) return #t\")")
(epoch 1301)
(eval "(lua-eval-ast \"local t = {1, 2, 3} table.insert(t, 4) return t[4]\")")
(epoch 1302)
(eval "(lua-eval-ast \"local t = {10, 30} table.insert(t, 2, 20) return t[2]\")")
(epoch 1303)
(eval "(lua-eval-ast \"local t = {10, 20, 30} table.insert(t, 1, 5) return t[1] * 100 + t[2]\")")
(epoch 1310)
(eval "(lua-eval-ast \"local t = {1, 2, 3} local v = table.remove(t) return v * 10 + #t\")")
(epoch 1311)
(eval "(lua-eval-ast \"local t = {10, 20, 30} table.remove(t, 1) return t[1] * 10 + t[2]\")")
(epoch 1320)
(eval "(lua-eval-ast \"local t = {\\\"a\\\", \\\"b\\\", \\\"c\\\"} return table.concat(t)\")")
(epoch 1321)
(eval "(lua-eval-ast \"local t = {\\\"a\\\", \\\"b\\\", \\\"c\\\"} return table.concat(t, \\\"-\\\")\")")
(epoch 1322)
(eval "(lua-eval-ast \"local t = {1, 2, 3, 4} return table.concat(t, \\\",\\\", 2, 3)\")")
(epoch 1330)
(eval "(lua-eval-ast \"local t = {3, 1, 4, 1, 5, 9, 2, 6} table.sort(t) return t[1] * 100 + t[8]\")")
(epoch 1331)
(eval "(lua-eval-ast \"local t = {3, 1, 2} table.sort(t, function(a, b) return a > b end) return t[1] * 100 + t[3]\")")
(epoch 1340)
(eval "(lua-eval-ast \"local t = {10, 20, 30} local a, b, c = unpack(t) return a + b + c\")")
(epoch 1341)
(eval "(lua-eval-ast \"local t = {10, 20, 30, 40} local a, b = table.unpack(t, 2, 3) return a + b\")")
EPOCHS EPOCHS
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1206,6 +1234,21 @@ check 1251 "math.modf(3.5) int part" '3'
check 1260 "math.random(n) in range" 'true' check 1260 "math.random(n) in range" 'true'
check 1261 "math.random(m,n) in range" 'true' check 1261 "math.random(m,n) in range" 'true'
# ── Phase 6: table library ────────────────────────────────────
check 1300 "table.insert append → #t" '4'
check 1301 "table.insert value" '4'
check 1302 "table.insert(t,pos,v) mid" '20'
check 1303 "table.insert(t,1,v) prepend" '510'
check 1310 "table.remove() last" '33'
check 1311 "table.remove(t,1) shift" '230'
check 1320 "table.concat no sep" '"abc"'
check 1321 "table.concat with sep" '"a-b-c"'
check 1322 "table.concat range" '"2,3"'
check 1330 "table.sort asc" '109'
check 1331 "table.sort desc via cmp" '301'
check 1340 "unpack global" '60'
check 1341 "table.unpack(t,i,j)" '50'
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

@@ -70,7 +70,7 @@ Each item: implement → tests → tick box → update progress log.
### Phase 6 — standard library ### Phase 6 — standard library
- [x] `string``format`, `sub`, `find`, `match`, `gmatch`, `gsub`, `len`, `rep`, `upper`, `lower`, `byte`, `char` - [x] `string``format`, `sub`, `find`, `match`, `gmatch`, `gsub`, `len`, `rep`, `upper`, `lower`, `byte`, `char`
- [x] `math` — full surface - [x] `math` — full surface
- [ ] `table``insert`, `remove`, `concat`, `sort`, `unpack` - [x] `table``insert`, `remove`, `concat`, `sort`, `unpack`
- [ ] `io` — minimal stub (read/write to SX IO surface) - [ ] `io` — minimal stub (read/write to SX IO surface)
- [ ] `os` — time/date subset - [ ] `os` — time/date subset
@@ -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: `table` lib — insert (append / at pos, shifts up), remove (last / at pos, shifts down), concat (sep, i, j), sort (insertion sort, optional cmp), unpack + table.unpack, maxn. Caught trap: local helper named `shift` collides with SX's `shift` special form → renamed to `tbl-shift-up`/`tbl-shift-down`. 322 tests.
- 2026-04-24: lua: `math` lib — pi/huge + abs/ceil/floor/sqrt/exp/log/log10/pow/trig (sin/cos/tan/asin/acos/atan/atan2)/deg/rad/min/max (&rest)/fmod/modf/random (0/1/2 arg)/randomseed. Most ops delegate to SX primitives; log w/ base via change-of-base. 309 tests. - 2026-04-24: lua: `math` lib — pi/huge + abs/ceil/floor/sqrt/exp/log/log10/pow/trig (sin/cos/tan/asin/acos/atan/atan2)/deg/rad/min/max (&rest)/fmod/modf/random (0/1/2 arg)/randomseed. Most ops delegate to SX primitives; log w/ base via change-of-base. 309 tests.
- 2026-04-24: lua: `string` lib — len/upper/lower/rep/sub (1-idx + neg)/byte/char/find/match/gmatch/gsub/format. Patterns are literal-only (no `%d`/etc.); format is `%s`/`%d`/`%f`/`%%` only. `string.char` uses printable-ASCII lookup + tab/nl/cr. 292 tests. - 2026-04-24: lua: `string` lib — len/upper/lower/rep/sub (1-idx + neg)/byte/char/find/match/gmatch/gsub/format. Patterns are literal-only (no `%d`/etc.); format is `%s`/`%d`/`%f`/`%%` only. `string.char` uses printable-ASCII lookup + tab/nl/cr. 292 tests.
- 2026-04-24: lua: phase 5 — coroutines (create/resume/yield/status/wrap) via `call/cc` (perform/cek-resume not exposed to SX userland). Handles multi-yield + final return + arg passthrough. Fix: body's final return must jump via `caller-k` to the **current** resume's caller, not unwind through the stale first-call continuation. 273 tests. - 2026-04-24: lua: phase 5 — coroutines (create/resume/yield/status/wrap) via `call/cc` (perform/cek-resume not exposed to SX userland). Handles multi-yield + final return + arg passthrough. Fix: body's final return must jump via `caller-k` to the **current** resume's caller, not unwind through the stale first-call continuation. 273 tests.