;; ==========================================================================
;; callcc.sx — Full first-class continuations (call/cc)
;;
;; OPTIONAL EXTENSION — not required by the core evaluator.
;; Bootstrappers include this only when the target supports it naturally.
;;
;; Full call/cc (call-with-current-continuation) captures the ENTIRE
;; remaining computation as a first-class function — not just up to a
;; delimiter, but all the way to the top level. Invoking a continuation
;; captured by call/cc abandons the current computation entirely and
;; resumes from where the continuation was captured.
;;
;; This is strictly more powerful than delimited continuations (shift/reset)
;; but harder to implement in targets that don't support it natively.
;; Recommended only for targets where it's natural:
;;   - Scheme/Racket (native call/cc)
;;   - Haskell (ContT monad transformer)
;;
;; For targets like Python, JavaScript, and Rust, delimited continuations
;; (continuations.sx) are more practical and cover the same use cases
;; without requiring a global CPS transform.
;;
;; One new special form:
;;   (call/cc f)         — call f with the current continuation
;;
;; One new type:
;;   continuation        — same type as in continuations.sx
;;
;; If both extensions are loaded, the continuation type is shared.
;; Delimited and undelimited continuations are the same type —
;; the difference is in how they are captured, not what they are.
;;
;; Platform requirements:
;;   (make-continuation fn)   — wrap a function as a continuation value
;;   (continuation? x)        — type predicate
;;   (type-of continuation)   → "continuation"
;;   (call-with-cc f env)     — target-specific call/cc implementation
;; ==========================================================================


;; --------------------------------------------------------------------------
;; 1. Semantics
;; --------------------------------------------------------------------------
;;
;; (call/cc f)
;;
;; Evaluates f (which must be a function of one argument), passing it the
;; current continuation as a continuation value. f can:
;;
;;   a) Return normally — call/cc returns whatever f returns
;;   b) Invoke the continuation — abandons f's computation, call/cc
;;      "returns" the value passed to the continuation
;;   c) Store the continuation — invoke it later, possibly multiple times
;;
;; Key difference from shift/reset: invoking an undelimited continuation
;; NEVER RETURNS to the caller. It abandons the current computation and
;; jumps back to where call/cc was originally called.
;;
;;   ;; Delimited (shift/reset) — k returns a value:
;;   (reset (+ 1 (shift k (+ (k 10) (k 20)))))
;;   ;; (k 10) → 11, returns to the (+ ... (k 20)) expression
;;   ;; (k 20) → 21, returns to the (+ 11 ...) expression
;;   ;; result: 32
;;
;;   ;; Undelimited (call/cc) — k does NOT return:
;;   (+ 1 (call/cc (fn (k)
;;     (+ (k 10) (k 20)))))
;;   ;; (k 10) abandons (+ (k 10) (k 20)) entirely
;;   ;; jumps back to (+ 1 _) with 10
;;   ;; result: 11
;;   ;; (k 20) is never reached
;;
;; --------------------------------------------------------------------------


;; --------------------------------------------------------------------------
;; 2. call/cc — call with current continuation
;; --------------------------------------------------------------------------


(define-library (sx callcc)
  (export
    sf-callcc)
  (begin

(define sf-callcc
  (fn (args env)
    ;; Single argument: a function to call with the current continuation.
    (let ((f-expr (first args))
          (f (trampoline (eval-expr f-expr env))))
      (call-with-cc f env))))


;; --------------------------------------------------------------------------
;; 3. Derived forms
;; --------------------------------------------------------------------------
;;
;; With call/cc available, several patterns become expressible:
;;
;; --- Early return ---
;;
;;   (define find-first
;;     (fn (pred items)
;;       (call/cc (fn (return)
;;         (for-each (fn (item)
;;           (when (pred item)
;;             (return item)))
;;           items)
;;         nil))))
;;
;; --- Exception-like flow ---
;;
;;   (define try-catch
;;     (fn (body handler)
;;       (call/cc (fn (throw)
;;         (body throw)))))
;;
;;   (try-catch
;;     (fn (throw)
;;       (let ((result (dangerous-operation)))
;;         (when (not result) (throw "failed"))
;;         result))
;;     (fn (error) (str "Caught: " error)))
;;
;; --- Coroutines ---
;;
;;   Two call/cc captures that alternate control between two
;;   computations. Each captures its own continuation, then invokes
;;   the other's. This gives cooperative multitasking without threads.
;;
;; --- Undo ---
;;
;;   (define with-undo
;;     (fn (action)
;;       (call/cc (fn (restore)
;;         (action)
;;         restore))))
;;
;;   ;; (let ((undo (with-undo (fn () (delete-item 42)))))
;;   ;;   (undo "anything"))  → item 42 is back
;;
;; --------------------------------------------------------------------------


;; --------------------------------------------------------------------------
;; 4. Interaction with delimited continuations
;; --------------------------------------------------------------------------
;;
;; If both callcc.sx and continuations.sx are loaded:
;;
;; - The continuation type is shared. (continuation? k) returns true
;;   for both delimited and undelimited continuations.
;;
;; - shift inside a call/cc body captures up to the nearest reset,
;;   not up to the call/cc. The two mechanisms compose.
;;
;; - call/cc inside a reset body captures the entire continuation
;;   (past the reset). This is the expected behavior — call/cc is
;;   undelimited by definition.
;;
;; - A delimited continuation (from shift) returns a value when invoked.
;;   An undelimited continuation (from call/cc) does not return.
;;   Both are callable with the same syntax: (k value).
;;   The caller cannot distinguish them by type — only by behavior.
;;
;; --------------------------------------------------------------------------


;; --------------------------------------------------------------------------
;; 5. Interaction with I/O and state
;; --------------------------------------------------------------------------
;;
;; Full call/cc has well-known interactions with side effects:
;;
;; Re-entry:
;;   Invoking a saved continuation re-enters a completed computation.
;;   If that computation mutated state (set!, I/O writes), the mutations
;;   are NOT undone. The continuation resumes in the current state,
;;   not the state at the time of capture.
;;
;; I/O:
;;   Same as delimited continuations — I/O executes at invocation time.
;;   A continuation containing (current-user) will call current-user
;;   when invoked, in whatever request context exists then.
;;
;; Dynamic extent:
;;   call/cc captures the continuation, not the dynamic environment.
;;   Host-language context (Python's Quart request context, JavaScript's
;;   async context) may not be valid when a saved continuation is invoked
;;   later. Typed targets can enforce this; dynamic targets fail at runtime.
;;
;; Recommendation:
;;   Use call/cc for pure control flow (early return, coroutines,
;;   backtracking). Use delimited continuations for effectful patterns
;;   (suspense, cooperative scheduling) where the delimiter provides
;;   a natural boundary.
;;
;; --------------------------------------------------------------------------


;; --------------------------------------------------------------------------
;; 6. Implementation notes per target
;; --------------------------------------------------------------------------
;;
;; Scheme / Racket:
;;   Native call/cc. Zero implementation effort.
;;
;; Haskell:
;;   ContT monad transformer. The evaluator runs in ContT, and call/cc
;;   is callCC from Control.Monad.Cont. Natural and type-safe.
;;
;; Python:
;;   Requires full CPS transform of the evaluator, or greenlet-based
;;   stack capture. Significantly more invasive than delimited
;;   continuations. NOT RECOMMENDED — use continuations.sx instead.
;;
;; JavaScript:
;;   Requires full CPS transform. Cannot be implemented with generators
;;   alone (generators only support delimited yield, not full escape).
;;   NOT RECOMMENDED — use continuations.sx instead.
;;
;; Rust:
;;   Full CPS transform at compile time. Possible but adds significant
;;   complexity. Delimited continuations are more natural (enum-based).
;;   Consider only if the target genuinely needs undelimited escape.
;;
;; --------------------------------------------------------------------------


;; --------------------------------------------------------------------------
;; 7. Platform interface — what each target must provide
;; --------------------------------------------------------------------------
;;
;;   (call-with-cc f env)
;;     Call f with the current continuation. f is a function of one
;;     argument (the continuation). If f returns normally, call-with-cc
;;     returns f's result. If f invokes the continuation, the computation
;;     jumps to the call-with-cc call site with the provided value.
;;
;;   (make-continuation fn)
;;     Wrap a native function as a continuation value.
;;     (Shared with continuations.sx if both are loaded.)
;;
;;   (continuation? x)
;;     Type predicate.
;;     (Shared with continuations.sx if both are loaded.)
;;
;;   Continuations must be callable via the standard function-call
;;   dispatch in eval-list (same path as lambda calls).
;;
;; --------------------------------------------------------------------------


)) ;; end define-library

;; Re-export to global namespace for backward compatibility
(import (sx callcc))
