ocaml: phase 2 references ref/!/:= (+6 tests, 189 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 55s
ref is a builtin boxing its arg in a one-element list. Prefix ! parses to (:deref ...) and reads via (nth cell 0). := joins the binop precedence table at level 1 right-assoc and mutates via set-nth!. Closures share the underlying cell.
This commit is contained in:
@@ -38,7 +38,10 @@
|
||||
(list "min" (fn (a) (fn (b) (if (< a b) a b))))
|
||||
(list "fst" (fn (p) (nth p 1)))
|
||||
(list "snd" (fn (p) (nth p 2)))
|
||||
(list "ignore" (fn (x) nil)))))
|
||||
(list "ignore" (fn (x) nil))
|
||||
;; References. A ref cell is a one-element list; ! reads it and
|
||||
;; := mutates it via set-nth!.
|
||||
(list "ref" (fn (x) (list x))))))
|
||||
|
||||
(define ocaml-env-lookup
|
||||
(fn (env name)
|
||||
@@ -235,11 +238,22 @@
|
||||
(else (error (str "ocaml-eval: unbound variable " name))))))
|
||||
((= tag "neg") (- 0 (ocaml-eval (nth ast 1) env)))
|
||||
((= tag "not") (not (ocaml-eval (nth ast 1) env)))
|
||||
((= tag "deref")
|
||||
(let ((cell (ocaml-eval (nth ast 1) env)))
|
||||
(nth cell 0)))
|
||||
((= tag "op")
|
||||
(ocaml-eval-op
|
||||
(nth ast 1)
|
||||
(ocaml-eval (nth ast 2) env)
|
||||
(ocaml-eval (nth ast 3) env)))
|
||||
(let ((op (nth ast 1)))
|
||||
(cond
|
||||
;; := mutates the lhs cell — short-circuit before generic
|
||||
;; eval-op so we still evaluate lhs (to obtain the cell).
|
||||
((= op ":=")
|
||||
(let ((cell (ocaml-eval (nth ast 2) env))
|
||||
(new-val (ocaml-eval (nth ast 3) env)))
|
||||
(begin (set-nth! cell 0 new-val) nil)))
|
||||
(else
|
||||
(ocaml-eval-op op
|
||||
(ocaml-eval (nth ast 2) env)
|
||||
(ocaml-eval (nth ast 3) env))))))
|
||||
((= tag "if")
|
||||
(if (ocaml-eval (nth ast 1) env)
|
||||
(ocaml-eval (nth ast 2) env)
|
||||
|
||||
Reference in New Issue
Block a user