ocaml: phase 6 Hashtbl (+6 tests, 332 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 32s

Backing store is a one-element list cell holding a SX dict; keys
coerced to strings via str so int/string keys work uniformly. API:
create, add, replace, find, find_opt, mem, length.

_hashtbl_create / _hashtbl_add / _hashtbl_replace / _hashtbl_find_opt /
_hashtbl_mem / _hashtbl_length primitives wired in eval.sx; OCaml-side
Hashtbl module wraps them in lib/ocaml/runtime.sx.
This commit is contained in:
2026-05-08 12:57:22 +00:00
parent 6d7197182e
commit 812aa75d43
4 changed files with 66 additions and 1 deletions

View File

@@ -66,7 +66,30 @@
;; Print: prints to host stdout via println.
(list "print_string" (fn (s) (begin (print s) nil)))
(list "print_endline" (fn (s) (begin (println s) nil)))
(list "print_int" (fn (i) (begin (print (str i)) nil))))))
(list "print_int" (fn (i) (begin (print (str i)) nil)))
;; Hashtbl primitives (one-element list cell holding a dict).
;; Keys are coerced to strings via `str` so any value type works
;; as a key (matches Hashtbl's polymorphic-key semantics).
(list "_hashtbl_create" (fn (n) (list {})))
(list "_hashtbl_add"
(fn (t) (fn (k) (fn (v)
(begin
(set-nth! t 0 (merge (nth t 0) (dict (str k) v)))
nil)))))
(list "_hashtbl_replace"
(fn (t) (fn (k) (fn (v)
(begin
(set-nth! t 0 (merge (nth t 0) (dict (str k) v)))
nil)))))
(list "_hashtbl_find_opt"
(fn (t) (fn (k)
(cond
((has-key? (nth t 0) (str k)) (list "Some" (get (nth t 0) (str k))))
(else (list "None"))))))
(list "_hashtbl_mem"
(fn (t) (fn (k) (has-key? (nth t 0) (str k)))))
(list "_hashtbl_length"
(fn (t) (len (keys (nth t 0))))))))
(define ocaml-env-lookup
(fn (env name)

View File

@@ -266,6 +266,19 @@
module Printf = struct
let sprintf fmt = fmt
let printf fmt = print_string fmt
end ;;
module Hashtbl = struct
let create n = _hashtbl_create n
let add t k v = _hashtbl_add t k v
let replace t k v = _hashtbl_replace t k v
let find_opt t k = _hashtbl_find_opt t k
let find t k =
match _hashtbl_find_opt t k with
| None -> failwith \"Hashtbl.find: not found\"
| Some v -> v
let mem t k = _hashtbl_mem t k
let length t = _hashtbl_length t
end")
(define ocaml-stdlib-loaded false)

View File

@@ -814,6 +814,20 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 1506)
(eval "(ocaml-type-of \"[true; false]\")")
;; ── Hashtbl ────────────────────────────────────────────────────
(epoch 1600)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t \\\"x\\\" 42;; Hashtbl.find t \\\"x\\\"\")")
(epoch 1601)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t 1 \\\"a\\\";; Hashtbl.add t 2 \\\"b\\\";; Hashtbl.length t\")")
(epoch 1602)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t 1 100;; Hashtbl.find_opt t 99\")")
(epoch 1603)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t 1 100;; Hashtbl.mem t 1\")")
(epoch 1604)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t \\\"a\\\" 1;; Hashtbl.replace t \\\"a\\\" 2;; Hashtbl.find t \\\"a\\\"\")")
(epoch 1605)
(eval "(ocaml-run-program \"let t = Hashtbl.create 10;; Hashtbl.add t \\\"k\\\" 5;; Hashtbl.find_opt t \\\"k\\\"\")")
EPOCHS
OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1288,6 +1302,14 @@ check 1504 "type fn -> list" 'list"'
check 1505 "type fn -> tuple" ' * '
check 1506 "type Bool list" '"Bool list"'
# ── Hashtbl ─────────────────────────────────────────────────────
check 1600 "Hashtbl find" '42'
check 1601 "Hashtbl length" '2'
check 1602 "Hashtbl find_opt missing" '("None")'
check 1603 "Hashtbl mem" 'true'
check 1604 "Hashtbl replace" '2'
check 1605 "Hashtbl find_opt found" '("Some" 5)'
TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"

View File

@@ -248,6 +248,9 @@ SX CEK evaluator (both JS and OCaml hosts)
`iter`, `fold`, `to_list`. _(Pending: join/to_result.)_
- [~] `Result`: `map`, `bind`, `is_ok`, `is_error`, `get_ok`,
`get_error`, `map_error`, `to_option`. _(Pending: fold/join.)_
- [~] `Hashtbl`: `create`, `add`, `find`, `find_opt`, `replace`, `mem`,
`length`. Backed by a one-element list cell holding a SX dict;
keys coerced to strings via `str` for polymorphic-key support.
- [~] `String`: `length`, `get`, `sub`, `concat`, `uppercase_ascii`,
`lowercase_ascii`, `starts_with`. _(Pending: split_on_char, trim,
contains, ends_with, index_opt, replace_all.)_
@@ -362,6 +365,10 @@ the "mother tongue" closure: OCaml → SX → OCaml. This means:
_Newest first._
- 2026-05-08 Phase 6 — `Hashtbl` (+6 tests, 332 total). Backing store is
a one-element list cell holding a SX dict; keys are coerced to
strings via `str` so any value type can serve as a key. API: create,
add, replace, find, find_opt, mem, length.
- 2026-05-08 Phase 5 — HM extensions for tuples and lists (+7 tests,
326 total). Tuple type `(hm-con "*" TYPES)`, list type `(hm-con
"list" (TYPE))`. `ocaml-infer-tuple` threads substitution through