ocaml: phase 4 'lazy EXPR' + Lazy.force (+2 tests, 496 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Tokenizer already had 'lazy' as a keyword. This commit wires it through:
parser : parse-prefix emits (:lazy EXPR), like the existing 'assert'
handler.
eval : creates a one-element cell with state ('Thunk' expr env).
host : _lazy_force flips the cell to ('Forced' v) on first call
and returns the cached value thereafter.
runtime : module Lazy = struct let force lz = _lazy_force lz end.
Memoisation confirmed by tracking a side-effect counter through two
forces of the same lazy:
let counter = ref 0 in
let lz = lazy (counter := !counter + 1; 42) in
let a = Lazy.force lz in
let b = Lazy.force lz in
(a + b) * 100 + !counter = 8401 (= 84*100 + 1)
This commit is contained in:
@@ -116,6 +116,20 @@
|
||||
(fn (t) (fn (k) (has-key? (nth t 0) (str k)))))
|
||||
(list "_hashtbl_length"
|
||||
(fn (t) (len (keys (nth t 0)))))
|
||||
;; _lazy_force: evaluate the thunk on first force, cache result.
|
||||
;; cell: one-elt list whose value is ("Thunk" expr env) or
|
||||
;; ("Forced" v).
|
||||
(list "_lazy_force"
|
||||
(fn (cell)
|
||||
(let ((state (nth cell 0)))
|
||||
(cond
|
||||
((= (first state) "Forced") (nth state 1))
|
||||
(else
|
||||
(let ((expr (nth state 1)) (env (nth state 2)))
|
||||
(let ((v (ocaml-eval expr env)))
|
||||
(begin
|
||||
(set-nth! cell 0 (list "Forced" v))
|
||||
v))))))))
|
||||
;; _hashtbl_to_list: returns [(k, v); ...] as a list of pairs.
|
||||
;; Keys are returned as the stringified form used internally.
|
||||
(list "_hashtbl_to_list"
|
||||
@@ -451,6 +465,11 @@
|
||||
(cond
|
||||
((= v false) (error "Assert_failure"))
|
||||
(else nil))))
|
||||
((= tag "lazy")
|
||||
;; (:lazy EXPR) — create a one-element cell containing
|
||||
;; ("Thunk" EXPR env); _lazy_force evaluates and caches.
|
||||
(let ((expr (nth ast 1)))
|
||||
(list (list "Thunk" expr env))))
|
||||
((= tag "deref")
|
||||
(let ((cell (ocaml-eval (nth ast 1) env)))
|
||||
(nth cell 0)))
|
||||
|
||||
Reference in New Issue
Block a user