Files
rose-ash/spec/test-continuations.sx
giles 1a3d7b3d77
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m49s
Separate core spec from web framework
Three-layer architecture:
  spec/  — Core language (19 files): evaluator, parser, primitives,
           CEK machine, types, continuations. Host-independent.
  web/   — Web framework (20 files): signals, adapters, engine,
           orchestration, boot, router, CSSX. Built on core spec.
  sx/    — Application (sx-docs website). Built on web framework.

Split boundary.sx into boundary-core.sx (type-of, make-env, identical?)
and boundary-web.sx (IO primitives, signals, spreads, page helpers).

Bootstrappers search spec/ → web/ → shared/sx/ref/ for .sx files.
Original files remain in shared/sx/ref/ as fallback during transition.
All 63 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 01:42:19 +00:00

141 lines
4.3 KiB
Plaintext

;; ==========================================================================
;; test-continuations.sx — Tests for delimited continuations (shift/reset)
;;
;; Requires: test-framework.sx loaded, continuations extension enabled.
;; ==========================================================================
;; --------------------------------------------------------------------------
;; 1. Basic shift/reset
;; --------------------------------------------------------------------------
(defsuite "basic-shift-reset"
(deftest "reset passthrough"
(assert-equal 42 (reset 42)))
(deftest "reset evaluates expression"
(assert-equal 3 (reset (+ 1 2))))
(deftest "shift aborts to reset"
(assert-equal 42 (reset (+ 1 (shift k 42)))))
(deftest "shift with single invoke"
(assert-equal 11 (reset (+ 1 (shift k (k 10))))))
(deftest "shift with multiple invokes"
(assert-equal (list 11 21)
(reset (+ 1 (shift k (list (k 10) (k 20)))))))
(deftest "shift returns string"
(assert-equal "aborted"
(reset (+ 1 (shift k "aborted")))))
(deftest "shift returns nil"
(assert-nil (reset (+ 1 (shift k nil)))))
(deftest "nested expression with shift"
(assert-equal 16
(+ 1 (reset (+ 10 (shift k (k 5))))))))
;; --------------------------------------------------------------------------
;; 2. Continuation predicates
;; --------------------------------------------------------------------------
(defsuite "continuation-predicates"
(deftest "k is a continuation inside shift"
(assert-true
(reset (shift k (continuation? k)))))
(deftest "number is not a continuation"
(assert-false (continuation? 42)))
(deftest "function is not a continuation"
(assert-false (continuation? (fn (x) x))))
(deftest "nil is not a continuation"
(assert-false (continuation? nil)))
(deftest "string is not a continuation"
(assert-false (continuation? "hello"))))
;; --------------------------------------------------------------------------
;; 3. Continuation as value
;; --------------------------------------------------------------------------
(defsuite "continuation-as-value"
(deftest "k returned from reset"
;; shift body returns k itself — reset returns the continuation
(let ((k (reset (+ 1 (shift k k)))))
(assert-true (continuation? k))
(assert-equal 11 (k 10))))
(deftest "invoke returned k multiple times"
(let ((k (reset (+ 1 (shift k k)))))
(assert-equal 11 (k 10))
(assert-equal 21 (k 20))
(assert-equal 2 (k 1))))
(deftest "pass k to another function"
(let ((apply-k (fn (k v) (k v))))
(assert-equal 15
(reset (+ 5 (shift k (apply-k k 10)))))))
(deftest "k in data structure"
(let ((result (reset (+ 1 (shift k (list k 42))))))
(assert-equal 42 (nth result 1))
(assert-equal 100 ((first result) 99)))))
;; --------------------------------------------------------------------------
;; 4. Nested reset
;; --------------------------------------------------------------------------
(defsuite "nested-reset"
(deftest "inner reset captures independently"
(assert-equal 12
(reset (+ 1 (reset (+ 10 (shift k (k 1))))))))
(deftest "inner abort outer continues"
(assert-equal 43
(reset (+ 1 (reset (+ 10 (shift k 42)))))))
(deftest "outer shift captures outer reset"
(assert-equal 100
(reset (+ 1 (shift k (k 99)))))))
;; --------------------------------------------------------------------------
;; 5. Interaction with scoped effects
;; --------------------------------------------------------------------------
(defsuite "continuations-with-scopes"
(deftest "provide survives resume"
(assert-equal "dark"
(reset (provide "theme" "dark"
(+ 0 (shift k (k 0)))
(context "theme")))))
(deftest "scope and emit across shift"
(assert-equal (list "a")
(reset (scope "acc"
(emit! "acc" "a")
(+ 0 (shift k (k 0)))
(emitted "acc"))))))
;; --------------------------------------------------------------------------
;; 6. TCO interaction
;; --------------------------------------------------------------------------
(defsuite "tco-interaction"
(deftest "shift in tail position"
(assert-equal 42
(reset (if true (shift k (k 42)) 0))))
(deftest "shift in let body"
(assert-equal 10
(reset (let ((x 5))
(+ x (shift k (k 5))))))))