ocaml: phase 4 's.[i]' string indexing syntax (+3 tests, 484 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 44s
parse-atom-postfix now dispatches three cases after consuming '.':
.field -> existing field/module access
.(EXPR) -> existing local-open
.[EXPR] -> new string-get syntax (this commit)
Eval reduces (:string-get S I) to host (nth S I), which already returns
a one-character string for OCaml's char model.
Lets us write idiomatic OCaml string traversal:
let s = "hi" in
let n = ref 0 in
for i = 0 to String.length s - 1 do
n := !n + Char.code s.[i]
done;
!n (* = 209 *)
This commit is contained in:
@@ -557,6 +557,11 @@
|
||||
((dict? target) (get target fname))
|
||||
(else (error
|
||||
(str "ocaml-eval: not a record/module on .field: " target)))))))
|
||||
((= tag "string-get")
|
||||
;; (:string-get S I) — evaluate s.[i] as a char access.
|
||||
(let ((s (ocaml-eval (nth ast 1) env))
|
||||
(i (ocaml-eval (nth ast 2) env)))
|
||||
(nth s i)))
|
||||
((= tag "for")
|
||||
;; (:for NAME LO HI DIR BODY) — DIR is "ascend" or "descend".
|
||||
(let ((name (nth ast 1))
|
||||
|
||||
@@ -571,6 +571,14 @@
|
||||
(consume! "op" ")")
|
||||
(set! head (list :let-open head inner))
|
||||
(loop)))))
|
||||
((at-op? "[")
|
||||
(begin
|
||||
(advance-tok!)
|
||||
(let ((idx-expr (parse-expr)))
|
||||
(begin
|
||||
(consume! "op" "]")
|
||||
(set! head (list :string-get head idx-expr))
|
||||
(loop)))))
|
||||
(else
|
||||
(let ((tok (peek-tok)))
|
||||
(begin
|
||||
|
||||
@@ -1194,6 +1194,14 @@ cat > "$TMPFILE" << 'EPOCHS'
|
||||
(epoch 4912)
|
||||
(eval "(ocaml-run \"Option.(map (fun x -> x * 10) (Some 4))\")")
|
||||
|
||||
;; ── s.[i] string indexing ─────────────────────────────────────
|
||||
(epoch 4920)
|
||||
(eval "(ocaml-run \"let s = \\\"hello\\\" in s.[0]\")")
|
||||
(epoch 4921)
|
||||
(eval "(ocaml-run \"let s = \\\"abc\\\" in Char.code s.[2]\")")
|
||||
(epoch 4922)
|
||||
(eval "(ocaml-run \"let s = \\\"hi\\\" in let n = ref 0 in for i = 0 to String.length s - 1 do n := !n + Char.code s.[i] done; !n\")")
|
||||
|
||||
EPOCHS
|
||||
|
||||
OUTPUT=$(timeout 360 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||
@@ -1893,6 +1901,11 @@ check 4910 "M.(expr) length" '3'
|
||||
check 4911 "M.(expr) map" '(2 3 4)'
|
||||
check 4912 "M.(expr) Option map" '("Some" 40)'
|
||||
|
||||
# ── s.[i] string indexing ────────────────────────────────────────
|
||||
check 4920 "s.[0] hello" '"h"'
|
||||
check 4921 "Char.code s.[2] abc" '99'
|
||||
check 4922 "for i s.[i] sum hi" '209'
|
||||
|
||||
TOTAL=$((PASS + FAIL))
|
||||
if [ $FAIL -eq 0 ]; then
|
||||
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"
|
||||
|
||||
@@ -407,6 +407,12 @@ _Newest first._
|
||||
binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree *
|
||||
'a tree`) with insert + in-order traversal. Tests parametric ADT,
|
||||
recursive match, List.append, List.fold_left.
|
||||
- 2026-05-08 Phase 4 — `s.[i]` string indexing syntax (+3 tests, 484
|
||||
total). parse-atom-postfix now handles `.[expr]` after `.`,
|
||||
emitting `(:string-get S I)`; eval reduces to host `(nth s i)`.
|
||||
Pairs with the existing `M.(expr)` and `.field` postfixes — all three
|
||||
share one dot loop. `let s = "hi" in for i = 0 to String.length s -
|
||||
1 do n := !n + Char.code s.[i] done; !n` returns 209 (h+i).
|
||||
- 2026-05-08 Phase 5.1 — roman.ml baseline (Roman numeral greedy
|
||||
encoding). Side-quest: top-level `let () = expr` was unsupported by
|
||||
ocaml-parse-program — now parse-decl-let recognises `()` as a unit
|
||||
|
||||
Reference in New Issue
Block a user