lua: require/package via package.preload +5 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:
@@ -1315,3 +1315,28 @@
|
|||||||
(dict-set! os "rename" lua-os-rename)
|
(dict-set! os "rename" lua-os-rename)
|
||||||
(dict-set! os "tmpname" lua-os-tmpname)
|
(dict-set! os "tmpname" lua-os-tmpname)
|
||||||
(dict-set! os "execute" lua-os-execute)
|
(dict-set! os "execute" lua-os-execute)
|
||||||
|
|
||||||
|
;; ── package / require ─────────────────────────────────────────
|
||||||
|
(define package {})
|
||||||
|
(define __package-loaded {})
|
||||||
|
(define __package-preload {})
|
||||||
|
|
||||||
|
(dict-set! package "loaded" __package-loaded)
|
||||||
|
(dict-set! package "preload" __package-preload)
|
||||||
|
(dict-set! package "path" "?;?.lua")
|
||||||
|
|
||||||
|
(define
|
||||||
|
lua-require
|
||||||
|
(fn (name)
|
||||||
|
(cond
|
||||||
|
((has-key? __package-loaded name) (get __package-loaded name))
|
||||||
|
((has-key? __package-preload name)
|
||||||
|
(let ((loader (get __package-preload name)))
|
||||||
|
(let ((m (lua-call loader name)))
|
||||||
|
(let ((result (if (= m nil) true m)))
|
||||||
|
(begin
|
||||||
|
(dict-set! __package-loaded name result)
|
||||||
|
result)))))
|
||||||
|
(else (error (str "lua: module '" name "' not found"))))))
|
||||||
|
|
||||||
|
(define require lua-require)
|
||||||
|
|||||||
@@ -876,6 +876,18 @@ cat > "$TMPFILE" << 'EPOCHS'
|
|||||||
(epoch 1507)
|
(epoch 1507)
|
||||||
(eval "(lua-eval-ast \"return type(os.tmpname())\")")
|
(eval "(lua-eval-ast \"return type(os.tmpname())\")")
|
||||||
|
|
||||||
|
;; ── Phase 7: require / package ────────────────────────────────
|
||||||
|
(epoch 1600)
|
||||||
|
(eval "(lua-eval-ast \"package.preload.mymath = function() local m = {} m.add = function(a, b) return a + b end return m end local mm = require(\\\"mymath\\\") return mm.add(3, 4)\")")
|
||||||
|
(epoch 1601)
|
||||||
|
(eval "(lua-eval-ast \"package.preload.counter = function() local n = 0 local m = {} m.inc = function() n = n + 1 return n end return m end local c1 = require(\\\"counter\\\") local c2 = require(\\\"counter\\\") c1.inc() c1.inc() return c2.inc()\")")
|
||||||
|
(epoch 1602)
|
||||||
|
(eval "(lua-eval-ast \"local ok, err = pcall(require, \\\"nope\\\") if ok then return 0 else return 1 end\")")
|
||||||
|
(epoch 1603)
|
||||||
|
(eval "(lua-eval-ast \"package.preload.x = function() return {val = 42} end require(\\\"x\\\") return package.loaded.x.val\")")
|
||||||
|
(epoch 1604)
|
||||||
|
(eval "(lua-eval-ast \"package.preload.noret = function() end local r = require(\\\"noret\\\") return type(r)\")")
|
||||||
|
|
||||||
EPOCHS
|
EPOCHS
|
||||||
|
|
||||||
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
OUTPUT=$(timeout 60 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||||
@@ -1317,6 +1329,13 @@ check 1505 "os.date(*t).year" '1970'
|
|||||||
check 1506 "os.getenv → nil" '1'
|
check 1506 "os.getenv → nil" '1'
|
||||||
check 1507 "os.tmpname → string" '"string"'
|
check 1507 "os.tmpname → string" '"string"'
|
||||||
|
|
||||||
|
# ── Phase 7: require / package ────────────────────────────────
|
||||||
|
check 1600 "require(preload) + call" '7'
|
||||||
|
check 1601 "require returns cached" '3'
|
||||||
|
check 1602 "require unknown module errors" '1'
|
||||||
|
check 1603 "package.loaded populated" '42'
|
||||||
|
check 1604 "nil return caches as true" '"boolean"'
|
||||||
|
|
||||||
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"
|
||||||
|
|||||||
@@ -75,13 +75,14 @@ Each item: implement → tests → tick box → update progress log.
|
|||||||
- [x] `os` — time/date subset
|
- [x] `os` — time/date subset
|
||||||
|
|
||||||
### Phase 7 — modules + full conformance
|
### Phase 7 — modules + full conformance
|
||||||
- [ ] `require` / `package` via SX `define-library`/`import`
|
- [x] `require` / `package` via SX `define-library`/`import`
|
||||||
- [ ] Drive PUC-Rio scoreboard to 100%
|
- [ ] Drive PUC-Rio scoreboard to 100%
|
||||||
|
|
||||||
## Progress log
|
## Progress log
|
||||||
|
|
||||||
_Newest first. Agent appends on every commit._
|
_Newest first. Agent appends on every commit._
|
||||||
|
|
||||||
|
- 2026-04-24: lua: `require`/`package` via preload-only (no filesystem search). `package.loaded` caching, nil-returning modules cache as `true`, unknown modules error. 347 tests.
|
||||||
- 2026-04-24: lua: `os` stub — time/clock monotonic counter, difftime, date (default string / `*t` dict), getenv/remove/rename/tmpname/execute/exit stubs. Phase 6 complete. 342 tests.
|
- 2026-04-24: lua: `os` stub — time/clock monotonic counter, difftime, date (default string / `*t` dict), getenv/remove/rename/tmpname/execute/exit stubs. Phase 6 complete. 342 tests.
|
||||||
- 2026-04-24: lua: `io` stub + `print`/`tostring`/`tonumber` globals. io buffers to internal `__io-buffer` (tests drain it via `io.__buffer()`). print: tab-sep + NL. tostring respects `__tostring` metamethod. 334 tests.
|
- 2026-04-24: lua: `io` stub + `print`/`tostring`/`tonumber` globals. io buffers to internal `__io-buffer` (tests drain it via `io.__buffer()`). print: tab-sep + NL. tostring respects `__tostring` metamethod. 334 tests.
|
||||||
- 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: `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.
|
||||||
@@ -110,6 +111,7 @@ _Shared-file issues that need someone else to fix. Minimal repro only._
|
|||||||
|
|
||||||
## Known limitations (own code, not shared)
|
## Known limitations (own code, not shared)
|
||||||
|
|
||||||
|
- **`require` supports `package.preload` only** — no filesystem search (we don't have Lua-file resolution inside sx_server). Users register a loader in `package.preload.name` and `require("name")` calls it with name as arg. Results cached in `package.loaded`; nil return caches as `true` per Lua convention.
|
||||||
- **`os` library is a stub** — `os.time()` returns a monotonic counter (not Unix epoch), `os.clock()` = counter/1000, `os.date()` returns hardcoded "1970-01-01 00:00:00" or a `*t` table with fixed fields; `os.getenv` returns nil; `os.remove`/`rename` return nil+error. No real clock/filesystem access.
|
- **`os` library is a stub** — `os.time()` returns a monotonic counter (not Unix epoch), `os.clock()` = counter/1000, `os.date()` returns hardcoded "1970-01-01 00:00:00" or a `*t` table with fixed fields; `os.getenv` returns nil; `os.remove`/`rename` return nil+error. No real clock/filesystem access.
|
||||||
- **`io` library is a stub** — `io.write`/`print` append to an internal `__io-buffer` (accessible via `io.__buffer()` which returns + clears it) instead of real stdout. `io.read`/`open`/`lines` return nil. Suitable for tests that inspect output; no actual stdio.
|
- **`io` library is a stub** — `io.write`/`print` append to an internal `__io-buffer` (accessible via `io.__buffer()` which returns + clears it) instead of real stdout. `io.read`/`open`/`lines` return nil. Suitable for tests that inspect output; no actual stdio.
|
||||||
- **`string.find`/`match`/`gmatch`/`gsub` patterns are LITERAL only** — no `%d`/`%a`/`.`/`*`/`+`/etc. Implementing Lua patterns is a separate work item; literal search covers the common case.
|
- **`string.find`/`match`/`gmatch`/`gsub` patterns are LITERAL only** — no `%d`/`%a`/`.`/`*`/`+`/etc. Implementing Lua patterns is a separate work item; literal search covers the common case.
|
||||||
|
|||||||
Reference in New Issue
Block a user