ocaml: phase 1+5.1 type aliases + poly_stack baseline (+3 tests, 469 / 19 baseline)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 39s

Parser: in parse-decl-type, dispatch on the post-= token:
  '|' or Ctor   -> sum type
  '{'           -> record type
  otherwise     -> type alias (skip to boundary)
AST (:type-alias NAME PARAMS) with body discarded. Runtime no-op since
SX has no nominal types.

poly_stack.ml baseline exercises:
  module type ELEMENT = sig type t val show : t -> string end
  module IntElem = struct type t = int let show x = ... end
  module Make (E : ELEMENT) = struct ... use E.show ... end
  module IntStack = Make(IntElem)

Demonstrates the substrate handles signature decls + abstract types +
functor parameter with sig constraint.
This commit is contained in:
2026-05-08 20:49:26 +00:00
parent c7d8b7dd62
commit ce75bd6848
6 changed files with 72 additions and 0 deletions

View File

@@ -13,6 +13,7 @@
"module_use.ml": 3, "module_use.ml": 3,
"mutable_record.ml": 10, "mutable_record.ml": 10,
"option_match.ml": 5, "option_match.ml": 5,
"poly_stack.ml": 5,
"queens.ml": 2, "queens.ml": 2,
"quicksort.ml": 44, "quicksort.ml": 44,
"sum_squares.ml": 385, "sum_squares.ml": 385,

View File

@@ -0,0 +1,27 @@
(* Baseline: polymorphic stack via functor over an Element module *)
module type ELEMENT = sig type t val show : t -> string end ;;
module IntElem = struct
type t = int
let show x = Int.to_string x
end ;;
module Make (E : ELEMENT) = struct
let create () = ref []
let push x s = s := x :: !s
let pop s =
match !s with
| [] -> None
| h :: t -> s := t ; Some h
let length s = List.length !s
let to_string s =
String.concat "," (List.map E.show !s)
end ;;
module IntStack = Make(IntElem) ;;
let s = IntStack.create () ;;
IntStack.push 1 s ;;
IntStack.push 2 s ;;
IntStack.push 3 s ;;
String.length (IntStack.to_string s)

View File

@@ -807,6 +807,7 @@
(set! result (merge result (dict mname mod-val)))))))) (set! result (merge result (dict mname mod-val))))))))
((= tag "type-def") nil) ((= tag "type-def") nil)
((= tag "type-def-record") nil) ((= tag "type-def-record") nil)
((= tag "type-alias") nil)
((= tag "exception-def") nil) ((= tag "exception-def") nil)
((= tag "module-type-def") nil) ((= tag "module-type-def") nil)
((= tag "open") ((= tag "open")
@@ -993,6 +994,9 @@
;; type r = { x : T; y : T } — runtime no-op; records ;; type r = { x : T; y : T } — runtime no-op; records
;; are already dynamic dicts. ;; are already dynamic dicts.
nil) nil)
((= tag "type-alias")
;; type t = SomeType — runtime no-op (no nominal types).
nil)
((= tag "module-type-def") ((= tag "module-type-def")
;; module type S = sig … end — no-op at runtime. ;; module type S = sig … end — no-op at runtime.
nil) nil)

View File

@@ -1242,6 +1242,29 @@
(field-more) (field-more)
(consume! "op" "}") (consume! "op" "}")
(list :type-def-record name tparams fields))))) (list :type-def-record name tparams fields)))))
;; Type alias: type t = int / type t = 'a list / etc.
;; Detected when next token is NOT `|` and NOT a ctor.
((and (not (at-op? "|"))
(not (= (ocaml-tok-type (peek-tok)) "ctor")))
(begin
;; Skip the alias source up to the next boundary.
(define skip-alias
(fn ()
(cond
((>= idx tok-len) nil)
((= (ocaml-tok-type (peek-tok)) "eof") nil)
((at-op? ";;") nil)
((at-kw? "let") nil)
((at-kw? "type") nil)
((at-kw? "and") nil)
((at-kw? "module") nil)
((at-kw? "exception") nil)
((at-kw? "open") nil)
((at-kw? "include") nil)
((at-kw? "end") nil)
(else (begin (advance-tok!) (skip-alias))))))
(skip-alias)
(list :type-alias name tparams)))
(else (else
(begin (begin
(when (at-op? "|") (advance-tok!)) (when (at-op? "|") (advance-tok!))

View File

@@ -1156,6 +1156,12 @@ cat > "$TMPFILE" << 'EPOCHS'
(epoch 4502) (epoch 4502)
(eval "(ocaml-run \"try raise (E 5) with | E n when n > 100 -> n | E n -> n + 1000\")") (eval "(ocaml-run \"try raise (E 5) with | E n when n > 100 -> n | E n -> n + 1000\")")
;; ── type aliases ──────────────────────────────────────────────
(epoch 4600)
(eval "(ocaml-parse-program \"type t = int\")")
(epoch 4601)
(eval "(ocaml-run-program \"type t = int;; 42\")")
EPOCHS EPOCHS
OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null) OUTPUT=$(timeout 180 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
@@ -1831,6 +1837,10 @@ check 4500 "try when guard fires" '5'
check 4501 "try when guard skips" '0' check 4501 "try when guard skips" '0'
check 4502 "try when fall through" '1005' check 4502 "try when fall through" '1005'
# ── type aliases ───────────────────────────────────────────────
check 4600 "type t = int parses" '("type-alias" "t" ())'
check 4601 "type alias decl + use" '42'
TOTAL=$((PASS + FAIL)) TOTAL=$((PASS + FAIL))
if [ $FAIL -eq 0 ]; then if [ $FAIL -eq 0 ]; then
echo "ok $PASS/$TOTAL OCaml-on-SX tests passed" echo "ok $PASS/$TOTAL OCaml-on-SX tests passed"

View File

@@ -407,6 +407,13 @@ _Newest first._
binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree * binary search tree (`type 'a tree = Leaf | Node of 'a * 'a tree *
'a tree`) with insert + in-order traversal. Tests parametric ADT, 'a tree`) with insert + in-order traversal. Tests parametric ADT,
recursive match, List.append, List.fold_left. recursive match, List.append, List.fold_left.
- 2026-05-08 Phase 1+5.1 — type aliases + poly_stack baseline (+3
tests, 469 total + 19 baseline). Parser dispatch on the post-`=`
token: `|` or `Ctor` → sum, `{` → record, otherwise → alias (skip
to boundary). AST `(:type-alias NAME PARAMS)` with body discarded.
Runtime no-op. poly_stack.ml baseline exercises a functor whose
parameter has `type t = int` (record alias) + `let show : t ->
string`. Stack uses ref + module field lookup to format ints.
- 2026-05-08 Phase 2+3 — `try ... with | pat when GUARD -> body` guard - 2026-05-08 Phase 2+3 — `try ... with | pat when GUARD -> body` guard
support (+3 tests, 467 total). parse-try mirrors match/function; support (+3 tests, 467 total). parse-try mirrors match/function;
eval-try clause loop now dispatches on `case`/`case-when` and falls eval-try clause loop now dispatches on `case`/`case-when` and falls