lua: table library (insert/remove/concat/sort/unpack) +13 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user