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

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:
2026-05-09 01:03:40 +00:00
parent 207dfc60ad
commit 9907c1c58c
5 changed files with 42 additions and 0 deletions

View File

@@ -407,6 +407,13 @@ _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-09 Phase 4 — `lazy EXPR` + `Lazy.force` (+2 tests, 496
total). Tokenizer already had `lazy` as a keyword. parse-prefix now
emits `(:lazy EXPR)`; eval creates a one-element cell with state
`("Thunk" expr env)`. Host primitive `_lazy_force` flips the cell to
`("Forced" v)` on first call and returns the cached value on
subsequent calls. Memoization confirmed by tracking a side-effect
counter through two forces (counter increments only once).
- 2026-05-09 Phase 6 — Hashtbl.iter / Hashtbl.fold (+2 tests, 494
total). New host primitive `_hashtbl_to_list` returns the entries
as a list of OCaml tuples (`("tuple" k v)` form, matching the AST