lua: math library (abs/trig/log/pow/min/max/fmod/modf/random/...) +17 tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-24 18:53:28 +00:00
parent 8c25527205
commit 6dfef34a4b
3 changed files with 170 additions and 1 deletions

View File

@@ -878,3 +878,116 @@
(dict-set! string "gmatch" lua-string-gmatch)
(dict-set! string "gsub" lua-string-gsub)
(dict-set! string "format" lua-string-format)
;; ── math library ──────────────────────────────────────────────
(define math {})
(define lua-math-pi 3.141592653589793)
(define lua-math-huge (/ 1.0 0.0))
(define lua-math-abs (fn (x) (abs x)))
(define lua-math-ceil (fn (x) (ceil x)))
(define lua-math-floor (fn (x) (floor x)))
(define lua-math-sqrt (fn (x) (sqrt x)))
(define lua-math-exp (fn (x) (exp x)))
(define lua-math-sin (fn (x) (sin x)))
(define lua-math-cos (fn (x) (cos x)))
(define lua-math-tan (fn (x) (tan x)))
(define lua-math-asin (fn (x) (asin x)))
(define lua-math-acos (fn (x) (acos x)))
(define lua-math-atan (fn (x) (atan x)))
(define lua-math-atan2 (fn (y x) (atan2 y x)))
(define lua-math-pow (fn (a b) (pow a b)))
(define lua-math-log
(fn (&rest args)
(cond
((= (len args) 1) (log (first args)))
(else (/ (log (first args)) (log (nth args 1)))))))
(define lua-math-log10
(fn (x) (/ (log x) (log 10))))
(define lua-math-deg (fn (x) (* x (/ 180 lua-math-pi))))
(define lua-math-rad (fn (x) (* x (/ lua-math-pi 180))))
(define lua-math-min
(fn (&rest args)
(cond
((= (len args) 0) (error "lua: min: no values"))
((= (len args) 1) (first args))
(else
(let ((m (first args)))
(begin
(define
loop
(fn (i)
(when (< i (len args))
(begin
(when (< (nth args i) m) (set! m (nth args i)))
(loop (+ i 1))))))
(loop 1)
m))))))
(define lua-math-max
(fn (&rest args)
(cond
((= (len args) 0) (error "lua: max: no values"))
((= (len args) 1) (first args))
(else
(let ((m (first args)))
(begin
(define
loop
(fn (i)
(when (< i (len args))
(begin
(when (> (nth args i) m) (set! m (nth args i)))
(loop (+ i 1))))))
(loop 1)
m))))))
(define lua-math-fmod
(fn (a b) (- a (* b (if (> b 0) (floor (/ a b)) (ceil (/ a b)))))))
(define lua-math-modf
(fn (x)
(let ((i (if (>= x 0) (floor x) (ceil x))))
(list (quote lua-multi) i (- x i)))))
(define __rand-scale 1048576)
(define lua-math-random
(fn (&rest args)
(cond
((= (len args) 0)
(/ (random-int 0 (- __rand-scale 1)) (* 1.0 __rand-scale)))
((= (len args) 1) (random-int 1 (first args)))
(else (random-int (first args) (nth args 1))))))
(define lua-math-randomseed (fn (s) nil))
(dict-set! math "pi" lua-math-pi)
(dict-set! math "huge" lua-math-huge)
(dict-set! math "abs" lua-math-abs)
(dict-set! math "ceil" lua-math-ceil)
(dict-set! math "floor" lua-math-floor)
(dict-set! math "sqrt" lua-math-sqrt)
(dict-set! math "exp" lua-math-exp)
(dict-set! math "log" lua-math-log)
(dict-set! math "log10" lua-math-log10)
(dict-set! math "pow" lua-math-pow)
(dict-set! math "sin" lua-math-sin)
(dict-set! math "cos" lua-math-cos)
(dict-set! math "tan" lua-math-tan)
(dict-set! math "asin" lua-math-asin)
(dict-set! math "acos" lua-math-acos)
(dict-set! math "atan" lua-math-atan)
(dict-set! math "atan2" lua-math-atan2)
(dict-set! math "deg" lua-math-deg)
(dict-set! math "rad" lua-math-rad)
(dict-set! math "min" lua-math-min)
(dict-set! math "max" lua-math-max)
(dict-set! math "fmod" lua-math-fmod)
(dict-set! math "modf" lua-math-modf)
(dict-set! math "random" lua-math-random)
(dict-set! math "randomseed" lua-math-randomseed)

View File

@@ -768,6 +768,42 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 1181)
(eval "(lua-eval-ast \"return string.format(\\\"%d%%\\\", 50)\")")
;; ── Phase 6: math library ─────────────────────────────────────
(epoch 1200)
(eval "(lua-eval-ast \"return math.pi > 3.14 and math.pi < 3.15\")")
(epoch 1201)
(eval "(lua-eval-ast \"return math.huge > 1000000\")")
(epoch 1210)
(eval "(lua-eval-ast \"return math.abs(-7)\")")
(epoch 1211)
(eval "(lua-eval-ast \"return math.sqrt(16)\")")
(epoch 1212)
(eval "(lua-eval-ast \"return math.floor(3.7)\")")
(epoch 1213)
(eval "(lua-eval-ast \"return math.ceil(3.2)\")")
(epoch 1220)
(eval "(lua-eval-ast \"return math.max(3, 7, 1, 4)\")")
(epoch 1221)
(eval "(lua-eval-ast \"return math.min(3, 7, 1, 4)\")")
(epoch 1230)
(eval "(lua-eval-ast \"return math.pow(2, 8)\")")
(epoch 1231)
(eval "(lua-eval-ast \"return math.exp(0)\")")
(epoch 1232)
(eval "(lua-eval-ast \"return math.log(1)\")")
(epoch 1233)
(eval "(lua-eval-ast \"return math.log10(100)\")")
(epoch 1240)
(eval "(lua-eval-ast \"return math.sin(0) + math.cos(0)\")")
(epoch 1250)
(eval "(lua-eval-ast \"return math.fmod(10, 3)\")")
(epoch 1251)
(eval "(lua-eval-ast \"local i, f = math.modf(3.5) return i\")")
(epoch 1260)
(eval "(lua-eval-ast \"local r = math.random(100) return r >= 1 and r <= 100\")")
(epoch 1261)
(eval "(lua-eval-ast \"local r = math.random(5, 10) return r >= 5 and r <= 10\")")
EPOCHS
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1151,6 +1187,25 @@ check 1170 "string.gmatch iterator" '3'
check 1180 "string.format %s=%d" '"x=42"'
check 1181 "string.format %d%%" '"50%"'
# ── Phase 6: math library ─────────────────────────────────────
check 1200 "math.pi in range" 'true'
check 1201 "math.huge big" 'true'
check 1210 "math.abs(-7)" '7'
check 1211 "math.sqrt(16)" '4'
check 1212 "math.floor(3.7)" '3'
check 1213 "math.ceil(3.2)" '4'
check 1220 "math.max(3,7,1,4)" '7'
check 1221 "math.min(3,7,1,4)" '1'
check 1230 "math.pow(2,8)" '256'
check 1231 "math.exp(0)" '1'
check 1232 "math.log(1)" '0'
check 1233 "math.log10(100)" '2'
check 1240 "math.sin(0)+math.cos(0)" '1'
check 1250 "math.fmod(10,3)" '1'
check 1251 "math.modf(3.5) int part" '3'
check 1260 "math.random(n) in range" 'true'
check 1261 "math.random(m,n) in range" 'true'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL Lua-on-SX tests passed"

View File

@@ -69,7 +69,7 @@ Each item: implement → tests → tick box → update progress log.
### Phase 6 — standard library
- [x] `string``format`, `sub`, `find`, `match`, `gmatch`, `gsub`, `len`, `rep`, `upper`, `lower`, `byte`, `char`
- [ ] `math` — full surface
- [x] `math` — full surface
- [ ] `table``insert`, `remove`, `concat`, `sort`, `unpack`
- [ ] `io` — minimal stub (read/write to SX IO surface)
- [ ] `os` — time/date subset
@@ -82,6 +82,7 @@ Each item: implement → tests → tick box → update progress log.
_Newest first. Agent appends on every commit._
- 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: 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: generic `for … in …` — parser split (`=` → num, else `in`), new `lua-for-in` node, transpile to `let`-bound `f,s,var` + recursive `__for_loop`. Added `ipairs`/`pairs`/`next`/`lua-arg` globals. Lua fns now arity-tolerant (`&rest __args` + indexed bind) — needed because generic for always calls iter with 2 args. Noted early-return-in-nested-block as pre-existing limitation. 265 tests.