diff --git a/lib/ocaml/baseline/expected.json b/lib/ocaml/baseline/expected.json index c4ea6f4e..27ecf27b 100644 --- a/lib/ocaml/baseline/expected.json +++ b/lib/ocaml/baseline/expected.json @@ -7,6 +7,7 @@ "factorial.ml": 3628800, "fizzbuzz.ml": 57, "list_ops.ml": 30, + "lambda_calc.ml": 7, "memo_fib.ml": 75025, "module_use.ml": 3, "mutable_record.ml": 10, diff --git a/lib/ocaml/baseline/lambda_calc.ml b/lib/ocaml/baseline/lambda_calc.ml new file mode 100644 index 00000000..7944be4e --- /dev/null +++ b/lib/ocaml/baseline/lambda_calc.ml @@ -0,0 +1,41 @@ +(* Baseline: untyped lambda calculus with closures over a Hashtbl env *) +type term = + | Var of string + | Abs of string * term + | App of term * term + | Num of int +;; + +type value = + | VNum of int + | VClos of string * term * (string * value) list +;; + +let rec lookup name env = + match env with + | [] -> failwith "unbound" + | (n, v) :: t -> if n = name then v else lookup name t +;; + +let rec eval env t = + match t with + | Num n -> VNum n + | Var x -> lookup x env + | Abs (x, body) -> VClos (x, body, env) + | App (f, a) -> + let fv = eval env f in + let av = eval env a in + (match fv with + | VClos (param, body, captured) -> + eval ((param, av) :: captured) body + | _ -> failwith "not a function") +;; + +let unwrap v = match v with VNum n -> n | _ -> failwith "not a number" ;; + +(* (\x. \y. x) 7 99 = 7 *) +let term = + App (App (Abs ("x", Abs ("y", Var "x")), Num 7), Num 99) +;; + +unwrap (eval [] term) diff --git a/plans/ocaml-on-sx.md b/plans/ocaml-on-sx.md index b404aad6..879a0226 100644 --- a/plans/ocaml-on-sx.md +++ b/plans/ocaml-on-sx.md @@ -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 5.1 — lambda_calc.ml baseline (17/17 pass). Untyped + lambda calculus interpreter using two ADTs (`type term = Var | Abs | + App | Num`, `type value = VNum | VClos`), an env as `(string * value) + list`, and recursive eval. `(\x.\y.x) 7 99 = 7` end-to-end. Demonstrates + the substrate handles a non-trivial AST + closure-based evaluator + written in OCaml-on-SX. - 2026-05-08 Phase 6 — Char predicates: is_digit/is_alpha/is_alnum/ is_whitespace/is_upper/is_lower (+7 tests, 461 total). All written in OCaml in runtime.sx using Char.code + ASCII range checks.