ocaml: phase 6 stdlib slice (List/Option/Result, +23 tests, 248 total)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 45s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 45s
lib/ocaml/runtime.sx defines the stdlib in OCaml syntax (not SX): every function exercises the parser, evaluator, match engine, and module machinery built in earlier phases. Loaded once via ocaml-load-stdlib!, cached in ocaml-stdlib-env, layered under user code via ocaml-base-env. List: length, rev, rev_append, map, filter, fold_left/right, append, iter, mem, for_all, exists, hd, tl, nth. Option: map, bind, value, get, is_none, is_some. Result: map, bind, is_ok, is_error. Substrate validation: this stdlib is a nontrivial OCaml program — its mere existence proves the substrate works.
This commit is contained in:
173
lib/ocaml/runtime.sx
Normal file
173
lib/ocaml/runtime.sx
Normal file
@@ -0,0 +1,173 @@
|
||||
;; lib/ocaml/runtime.sx — minimal OCaml stdlib slice, written in OCaml.
|
||||
;;
|
||||
;; Defines List and Option modules with the most-used functions. Loaded
|
||||
;; on demand via `(ocaml-load-stdlib! env)` from eval.sx, which parses
|
||||
;; this source through `ocaml-parse-program` and evaluates each decl,
|
||||
;; threading the env so stdlib bindings become available to user code.
|
||||
;;
|
||||
;; What's here is intentionally minimal — Phase 6 grows this into the
|
||||
;; full ~150-function slice. Everything is defined in OCaml syntax (not
|
||||
;; SX) on purpose, both as substrate validation and as documentation.
|
||||
|
||||
(define ocaml-stdlib-src
|
||||
"module List = struct
|
||||
let rec length lst =
|
||||
match lst with
|
||||
| [] -> 0
|
||||
| _ :: t -> 1 + length t
|
||||
|
||||
let rec rev_append xs acc =
|
||||
match xs with
|
||||
| [] -> acc
|
||||
| h :: t -> rev_append t (h :: acc)
|
||||
|
||||
let rev xs = rev_append xs []
|
||||
|
||||
let rec map f lst =
|
||||
match lst with
|
||||
| [] -> []
|
||||
| h :: t -> f h :: map f t
|
||||
|
||||
let rec filter p lst =
|
||||
match lst with
|
||||
| [] -> []
|
||||
| h :: t -> if p h then h :: filter p t else filter p t
|
||||
|
||||
let rec fold_left f init lst =
|
||||
match lst with
|
||||
| [] -> init
|
||||
| h :: t -> fold_left f (f init h) t
|
||||
|
||||
let rec fold_right f lst init =
|
||||
match lst with
|
||||
| [] -> init
|
||||
| h :: t -> f h (fold_right f t init)
|
||||
|
||||
let rec append xs ys =
|
||||
match xs with
|
||||
| [] -> ys
|
||||
| h :: t -> h :: append t ys
|
||||
|
||||
let rec iter f lst =
|
||||
match lst with
|
||||
| [] -> ()
|
||||
| h :: t -> f h; iter f t
|
||||
|
||||
let rec mem x lst =
|
||||
match lst with
|
||||
| [] -> false
|
||||
| h :: t -> if h = x then true else mem x t
|
||||
|
||||
let rec for_all p lst =
|
||||
match lst with
|
||||
| [] -> true
|
||||
| h :: t -> if p h then for_all p t else false
|
||||
|
||||
let rec exists p lst =
|
||||
match lst with
|
||||
| [] -> false
|
||||
| h :: t -> if p h then true else exists p t
|
||||
|
||||
let hd lst =
|
||||
match lst with
|
||||
| [] -> failwith \"List.hd: empty\"
|
||||
| h :: _ -> h
|
||||
|
||||
let tl lst =
|
||||
match lst with
|
||||
| [] -> failwith \"List.tl: empty\"
|
||||
| _ :: t -> t
|
||||
|
||||
let rec nth lst n =
|
||||
match lst with
|
||||
| [] -> failwith \"List.nth: out of range\"
|
||||
| h :: t -> if n = 0 then h else nth t (n - 1)
|
||||
end ;;
|
||||
|
||||
module Option = struct
|
||||
let map f o =
|
||||
match o with
|
||||
| None -> None
|
||||
| Some x -> Some (f x)
|
||||
|
||||
let bind o f =
|
||||
match o with
|
||||
| None -> None
|
||||
| Some x -> f x
|
||||
|
||||
let value o default =
|
||||
match o with
|
||||
| None -> default
|
||||
| Some x -> x
|
||||
|
||||
let get o =
|
||||
match o with
|
||||
| None -> failwith \"Option.get: None\"
|
||||
| Some x -> x
|
||||
|
||||
let is_none o =
|
||||
match o with
|
||||
| None -> true
|
||||
| Some _ -> false
|
||||
|
||||
let is_some o =
|
||||
match o with
|
||||
| None -> false
|
||||
| Some _ -> true
|
||||
end ;;
|
||||
|
||||
module Result = struct
|
||||
let map f r =
|
||||
match r with
|
||||
| Ok x -> Ok (f x)
|
||||
| Error e -> Error e
|
||||
|
||||
let bind r f =
|
||||
match r with
|
||||
| Ok x -> f x
|
||||
| Error e -> Error e
|
||||
|
||||
let is_ok r =
|
||||
match r with
|
||||
| Ok _ -> true
|
||||
| Error _ -> false
|
||||
|
||||
let is_error r =
|
||||
match r with
|
||||
| Ok _ -> false
|
||||
| Error _ -> true
|
||||
end")
|
||||
|
||||
(define ocaml-stdlib-loaded false)
|
||||
(define ocaml-stdlib-env nil)
|
||||
|
||||
;; Build a stdlib env once, cache it. ocaml-run / ocaml-run-program both
|
||||
;; layer the user program on top of this base env.
|
||||
(define ocaml-load-stdlib!
|
||||
(fn ()
|
||||
(when (not ocaml-stdlib-loaded)
|
||||
(let ((env (ocaml-empty-env)))
|
||||
(begin
|
||||
(define run-decl
|
||||
(fn (decl)
|
||||
(let ((tag (ocaml-tag-of decl)))
|
||||
(cond
|
||||
((= tag "module-def")
|
||||
(let ((mn (nth decl 1)) (ds (nth decl 2)))
|
||||
(let ((mv (ocaml-eval-module ds env)))
|
||||
(set! env (ocaml-env-extend env mn mv)))))
|
||||
((= tag "def")
|
||||
(let ((nm (nth decl 1)) (ps (nth decl 2)) (rh (nth decl 3)))
|
||||
(let ((v (if (= (len ps) 0)
|
||||
(ocaml-eval rh env)
|
||||
(ocaml-make-curried ps rh env))))
|
||||
(set! env (ocaml-env-extend env nm v)))))))))
|
||||
(let ((prog (ocaml-parse-program ocaml-stdlib-src)))
|
||||
(begin
|
||||
(define loop
|
||||
(fn (xs)
|
||||
(when (not (= xs (list)))
|
||||
(begin (run-decl (first xs)) (loop (rest xs))))))
|
||||
(loop (rest prog))
|
||||
(set! ocaml-stdlib-env env)
|
||||
(set! ocaml-stdlib-loaded true))))))))
|
||||
Reference in New Issue
Block a user