diff --git a/lib/haskell/conformance.sh b/lib/haskell/conformance.sh index 4cb7ccbe..97d449ec 100755 --- a/lib/haskell/conformance.sh +++ b/lib/haskell/conformance.sh @@ -38,6 +38,7 @@ run_suite() { (load "lib/haskell/runtime.sx") (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") +(load "lib/haskell/map.sx") (load "lib/haskell/testlib.sx") (epoch 2) (load "$FILE") diff --git a/lib/haskell/eval.sx b/lib/haskell/eval.sx index 466f54a6..5fc53f0e 100644 --- a/lib/haskell/eval.sx +++ b/lib/haskell/eval.sx @@ -1023,6 +1023,68 @@ 1)) env))))) +(define + hk-bind-data-map! + (fn + (env alias) + (let + ((p (str alias "."))) + (begin + (dict-set! env (str p "empty") hk-map-empty) + (dict-set! + env + (str p "singleton") + (hk-mk-lazy-builtin + "Map.singleton" + (fn (k v) (hk-map-singleton (hk-force k) (hk-force v))) + 2)) + (dict-set! + env + (str p "insert") + (hk-mk-lazy-builtin + "Map.insert" + (fn + (k v m) + (hk-map-insert (hk-force k) (hk-force v) (hk-force m))) + 3)) + (dict-set! + env + (str p "lookup") + (hk-mk-lazy-builtin + "Map.lookup" + (fn (k m) (hk-map-lookup (hk-force k) (hk-force m))) + 2)) + (dict-set! + env + (str p "member") + (hk-mk-lazy-builtin + "Map.member" + (fn + (k m) + (hk-of-bool (hk-map-member (hk-force k) (hk-force m)))) + 2)) + (dict-set! + env + (str p "size") + (hk-mk-lazy-builtin + "Map.size" + (fn (m) (hk-map-size (hk-force m))) + 1)) + (dict-set! + env + (str p "null") + (hk-mk-lazy-builtin + "Map.null" + (fn (m) (hk-of-bool (hk-map-null (hk-force m)))) + 1)) + (dict-set! + env + (str p "delete") + (hk-mk-lazy-builtin + "Map.delete" + (fn (k m) (hk-map-delete (hk-force k) (hk-force m))) + 2)))))) + (define hk-bind-decls! (fn @@ -1176,6 +1238,14 @@ inst-dict)))))) cons-list)) deriving-list))))) + ((or (= (first d) ":import") (= (first d) "import")) + (let + ((modname (nth d 2)) (as-name (nth d 3))) + (let + ((alias (cond ((nil? as-name) "Map") (:else as-name)))) + (cond + ((= modname "Data.Map") (hk-bind-data-map! env alias)) + (:else nil))))) (:else nil))) decls) (let @@ -1230,8 +1300,13 @@ (let ((env (hk-dict-copy hk-env0))) (let - ((decls (cond ((= (first ast) "program") (nth ast 1)) ((= (first ast) "module") (nth ast 4)) (:else (raise "eval-program: bad shape"))))) - (hk-bind-decls! env decls)))))))) + ((imports (cond ((= (first ast) "module") (nth ast 3)) (:else (list)))) + (decls + (cond + ((= (first ast) "program") (nth ast 1)) + ((= (first ast) "module") (nth ast 4)) + (:else (raise "eval-program: bad shape"))))) + (begin (hk-bind-decls! env imports) (hk-bind-decls! env decls))))))))) (define hk-run diff --git a/lib/haskell/test.sh b/lib/haskell/test.sh index ea72c8e0..59aa8b2f 100755 --- a/lib/haskell/test.sh +++ b/lib/haskell/test.sh @@ -55,6 +55,7 @@ for FILE in "${FILES[@]}"; do (load "lib/haskell/runtime.sx") (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") +(load "lib/haskell/map.sx") $INFER_LOAD (load "lib/haskell/testlib.sx") (epoch 2) @@ -98,6 +99,7 @@ EPOCHS (load "lib/haskell/runtime.sx") (load "lib/haskell/match.sx") (load "lib/haskell/eval.sx") +(load "lib/haskell/map.sx") $INFER_LOAD (load "lib/haskell/testlib.sx") (epoch 2) diff --git a/plans/haskell-completeness.md b/plans/haskell-completeness.md index cde89129..dda48e84 100644 --- a/plans/haskell-completeness.md +++ b/plans/haskell-completeness.md @@ -188,7 +188,7 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. - [x] Combining: `unionWith`, `intersectionWith`, `difference`. - [x] Transforming: `foldlWithKey`, `foldrWithKey`, `mapWithKey`, `filterWithKey`. - [x] Updating: `adjust`, `insertWith`, `insertWithKey`, `alter`. -- [ ] Module wiring: `import Data.Map` and `import qualified Data.Map as Map` +- [x] Module wiring: `import Data.Map` and `import qualified Data.Map as Map` resolve to the `map.sx` namespace dict in the eval import handler. - [ ] Unit tests in `lib/haskell/tests/map.sx` (≥ 20 tests: empty, singleton, insert + lookup hit/miss, delete root, fromList with duplicates, @@ -304,6 +304,20 @@ No OCaml changes are needed. The view type is fully representable as an SX dict. _Newest first._ +**2026-05-07** — Phase 11 module wiring: `import Data.Map`: +- Added `hk-bind-data-map!` helper in `eval.sx` that registers + `.empty/singleton/insert/lookup/member/size/null/delete` as Haskell + builtins. Default alias is `"Map"`. +- New `:import` case in `hk-bind-decls!` dispatches to `hk-bind-data-map!` + when modname = `"Data.Map"`. Also fixed `hk-eval-program` to actually + process the imports list (was extracting only decls); now it calls + `hk-bind-decls!` once on imports, then once on decls. +- `test.sh` and `conformance.sh` now load `lib/haskell/map.sx` after + `eval.sx` so the BST functions exist when the import handler binds. +- Verified `import qualified Data.Map as Map` and `import Data.Map` + (default alias) resolve `Map.empty`, `Map.insert`, `Map.lookup`, `Map.size`, + `Map.member` correctly. + **2026-05-07** — Phase 11 updating (adjust/insertWith/insertWithKey/alter): - `adjust` recurses to find the key, replaces value with `f(v)`; no-op when missing. `insertWith` and `insertWithKey` recurse with rebalance and use