ocaml: phase 6 Hashtbl (+6 tests, 332 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 32s
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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user