Add one-line comments to all 141 defines in spec/evaluator.sx
Every define now has a ;; comment explaining its purpose. Groups: - CEK state constructors and accessors (0-7) - Continuation frames — one per special form (8-42) - Continuation stack operations (43-56) - Configuration and global state (57-67) - Core evaluation functions (68-71) - Special form helpers (72-89) - CEK machine core (90-92) - Special form CEK steps (93-119) - Call dispatch and higher-order forms (120-133) - Continuation dispatch (134-136) - Entry points (137-140) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,47 +1,67 @@
|
|||||||
|
;; Construct a CEK state: expression to evaluate, env, continuation
|
||||||
(define make-cek-state (fn (control env kont) {:control control :env env :kont kont :value nil :phase "eval"}))
|
(define make-cek-state (fn (control env kont) {:control control :env env :kont kont :value nil :phase "eval"}))
|
||||||
|
|
||||||
|
;; Construct a CEK value state: computation complete, result ready
|
||||||
(define make-cek-value (fn (value env kont) {:control nil :env env :kont kont :value value :phase "continue"}))
|
(define make-cek-value (fn (value env kont) {:control nil :env env :kont kont :value value :phase "continue"}))
|
||||||
|
|
||||||
|
;; True if state is a terminal value (no more steps needed)
|
||||||
(define
|
(define
|
||||||
cek-terminal?
|
cek-terminal?
|
||||||
(fn
|
(fn
|
||||||
(state)
|
(state)
|
||||||
(and (= (get state "phase") "continue") (empty? (get state "kont")))))
|
(and (= (get state "phase") "continue") (empty? (get state "kont")))))
|
||||||
|
|
||||||
|
;; Extract the control expression from a CEK state
|
||||||
(define cek-control (fn (s) (get s "control")))
|
(define cek-control (fn (s) (get s "control")))
|
||||||
|
|
||||||
|
;; Extract the environment from a CEK state
|
||||||
(define cek-env (fn (s) (get s "env")))
|
(define cek-env (fn (s) (get s "env")))
|
||||||
|
|
||||||
|
;; Extract the continuation stack from a CEK state
|
||||||
(define cek-kont (fn (s) (get s "kont")))
|
(define cek-kont (fn (s) (get s "kont")))
|
||||||
|
|
||||||
|
;; Return state phase: "eval" or "value"
|
||||||
(define cek-phase (fn (s) (get s "phase")))
|
(define cek-phase (fn (s) (get s "phase")))
|
||||||
|
|
||||||
|
;; Extract the result value from a terminal CEK state
|
||||||
(define cek-value (fn (s) (get s "value")))
|
(define cek-value (fn (s) (get s "value")))
|
||||||
|
|
||||||
|
;; Frame for if: holds then/else branches, awaiting test result
|
||||||
(define make-if-frame (fn (then-expr else-expr env) {:else else-expr :env env :type "if" :then then-expr}))
|
(define make-if-frame (fn (then-expr else-expr env) {:else else-expr :env env :type "if" :then then-expr}))
|
||||||
|
|
||||||
|
;; Frame for when: holds body, awaiting test result
|
||||||
(define make-when-frame (fn (body-exprs env) {:body body-exprs :env env :type "when"}))
|
(define make-when-frame (fn (body-exprs env) {:body body-exprs :env env :type "when"}))
|
||||||
|
|
||||||
|
;; Frame for begin/do: holds remaining expressions
|
||||||
(define make-begin-frame (fn (remaining env) {:env env :type "begin" :remaining remaining}))
|
(define make-begin-frame (fn (remaining env) {:env env :type "begin" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for let: holds remaining bindings and body
|
||||||
(define make-let-frame (fn (name remaining body local) {:body body :env local :type "let" :remaining remaining :name name}))
|
(define make-let-frame (fn (name remaining body local) {:body body :env local :type "let" :remaining remaining :name name}))
|
||||||
|
|
||||||
|
;; Frame for define: holds name, awaiting value
|
||||||
(define make-define-frame (fn (name env has-effects effect-list) {:env env :effect-list effect-list :has-effects has-effects :type "define" :name name}))
|
(define make-define-frame (fn (name env has-effects effect-list) {:env env :effect-list effect-list :has-effects has-effects :type "define" :name name}))
|
||||||
|
|
||||||
|
;; Frame for set!: holds name, awaiting new value
|
||||||
(define make-set-frame (fn (name env) {:env env :type "set" :name name}))
|
(define make-set-frame (fn (name env) {:env env :type "set" :name name}))
|
||||||
|
|
||||||
|
;; Frame for function call: accumulates evaluated arguments
|
||||||
(define
|
(define
|
||||||
make-arg-frame
|
make-arg-frame
|
||||||
(fn (f evaled remaining env raw-args head-name) {:env env :head-name (or head-name nil) :evaled evaled :type "arg" :f f :remaining remaining :raw-args raw-args}))
|
(fn (f evaled remaining env raw-args head-name) {:env env :head-name (or head-name nil) :evaled evaled :type "arg" :f f :remaining remaining :raw-args raw-args}))
|
||||||
|
|
||||||
|
;; Frame for call dispatch: holds function and args
|
||||||
(define make-call-frame (fn (f args env) {:args args :env env :type "call" :f f}))
|
(define make-call-frame (fn (f args env) {:args args :env env :type "call" :f f}))
|
||||||
|
|
||||||
|
;; Frame for cond: holds remaining clauses
|
||||||
(define make-cond-frame (fn (remaining env scheme?) {:scheme scheme? :env env :type "cond" :remaining remaining}))
|
(define make-cond-frame (fn (remaining env scheme?) {:scheme scheme? :env env :type "cond" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for case: holds match value and remaining clauses
|
||||||
(define make-case-frame (fn (match-val remaining env) {:match-val match-val :env env :type "case" :remaining remaining}))
|
(define make-case-frame (fn (match-val remaining env) {:match-val match-val :env env :type "case" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for -> threading: holds remaining forms
|
||||||
(define make-thread-frame (fn (remaining env) {:env env :type "thread" :remaining remaining}))
|
(define make-thread-frame (fn (remaining env) {:env env :type "thread" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Insert threaded value as first arg in a form
|
||||||
(define
|
(define
|
||||||
thread-insert-arg
|
thread-insert-arg
|
||||||
(fn
|
(fn
|
||||||
@@ -53,52 +73,72 @@
|
|||||||
fenv)
|
fenv)
|
||||||
(eval-expr (list form (list (quote quote) value)) fenv))))
|
(eval-expr (list form (list (quote quote) value)) fenv))))
|
||||||
|
|
||||||
|
;; Frame for map: accumulates results over remaining items
|
||||||
(define make-map-frame (fn (f remaining results env) {:indexed false :env env :results results :type "map" :f f :remaining remaining}))
|
(define make-map-frame (fn (f remaining results env) {:indexed false :env env :results results :type "map" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for map-indexed: like map but tracks index
|
||||||
(define make-map-indexed-frame (fn (f remaining results env) {:indexed true :env env :results results :type "map" :f f :remaining remaining}))
|
(define make-map-indexed-frame (fn (f remaining results env) {:indexed true :env env :results results :type "map" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for filter: accumulates items passing predicate
|
||||||
(define
|
(define
|
||||||
make-filter-frame
|
make-filter-frame
|
||||||
(fn (f remaining results current-item env) {:current-item current-item :env env :results results :type "filter" :f f :remaining remaining}))
|
(fn (f remaining results current-item env) {:current-item current-item :env env :results results :type "filter" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for reduce: carries accumulator over remaining items
|
||||||
(define make-reduce-frame (fn (f remaining env) {:env env :type "reduce" :f f :remaining remaining}))
|
(define make-reduce-frame (fn (f remaining env) {:env env :type "reduce" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for for-each: side-effects over remaining items
|
||||||
(define make-for-each-frame (fn (f remaining env) {:env env :type "for-each" :f f :remaining remaining}))
|
(define make-for-each-frame (fn (f remaining env) {:env env :type "for-each" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for some: short-circuits on first truthy result
|
||||||
(define make-some-frame (fn (f remaining env) {:env env :type "some" :f f :remaining remaining}))
|
(define make-some-frame (fn (f remaining env) {:env env :type "some" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for every?: short-circuits on first falsy result
|
||||||
(define make-every-frame (fn (f remaining env) {:env env :type "every" :f f :remaining remaining}))
|
(define make-every-frame (fn (f remaining env) {:env env :type "every" :f f :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for scope: holds scope name, pops on completion
|
||||||
(define make-scope-frame (fn (name remaining env) {:env env :type "scope" :remaining remaining :name name}))
|
(define make-scope-frame (fn (name remaining env) {:env env :type "scope" :remaining remaining :name name}))
|
||||||
|
|
||||||
|
;; Frame for provide: scope with a downward value
|
||||||
(define make-provide-frame (fn (name value remaining env) {:env env :value value :type "provide" :remaining remaining :name name}))
|
(define make-provide-frame (fn (name value remaining env) {:env env :value value :type "provide" :remaining remaining :name name}))
|
||||||
|
|
||||||
|
;; Frame for scope accumulator: tracks emitted values
|
||||||
(define make-scope-acc-frame (fn (name value remaining env) {:env env :value (or value nil) :type "scope-acc" :remaining remaining :emitted (list) :name name}))
|
(define make-scope-acc-frame (fn (name value remaining env) {:env env :value (or value nil) :type "scope-acc" :remaining remaining :emitted (list) :name name}))
|
||||||
|
|
||||||
|
;; Frame for reset: delimits continuation capture boundary
|
||||||
(define make-reset-frame (fn (env) {:env env :type "reset"}))
|
(define make-reset-frame (fn (env) {:env env :type "reset"}))
|
||||||
|
|
||||||
|
;; Frame for dict literal: accumulates evaluated key-value pairs
|
||||||
(define make-dict-frame (fn (remaining results env) {:env env :results results :type "dict" :remaining remaining}))
|
(define make-dict-frame (fn (remaining results env) {:env env :results results :type "dict" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for and: short-circuits on first falsy value
|
||||||
(define make-and-frame (fn (remaining env) {:env env :type "and" :remaining remaining}))
|
(define make-and-frame (fn (remaining env) {:env env :type "and" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for or: short-circuits on first truthy value
|
||||||
(define make-or-frame (fn (remaining env) {:env env :type "or" :remaining remaining}))
|
(define make-or-frame (fn (remaining env) {:env env :type "or" :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for dynamic-wind: holds before/after thunks
|
||||||
(define
|
(define
|
||||||
make-dynamic-wind-frame
|
make-dynamic-wind-frame
|
||||||
(fn (phase body-thunk after-thunk env) {:env env :phase phase :after-thunk after-thunk :type "dynamic-wind" :body-thunk body-thunk}))
|
(fn (phase body-thunk after-thunk env) {:env env :phase phase :after-thunk after-thunk :type "dynamic-wind" :body-thunk body-thunk}))
|
||||||
|
|
||||||
|
;; Frame for reactive reset: delimits signal dependency tracking
|
||||||
(define
|
(define
|
||||||
make-reactive-reset-frame
|
make-reactive-reset-frame
|
||||||
(fn (env update-fn first-render?) {:first-render first-render? :update-fn update-fn :env env :type "reactive-reset"}))
|
(fn (env update-fn first-render?) {:first-render first-render? :update-fn update-fn :env env :type "reactive-reset"}))
|
||||||
|
|
||||||
|
;; Frame for deref: resolves signal value with dependency tracking
|
||||||
(define make-deref-frame (fn (env) {:env env :type "deref"}))
|
(define make-deref-frame (fn (env) {:env env :type "deref"}))
|
||||||
|
|
||||||
|
;; Frame for higher-order setup: staged arg evaluation for map/filter/etc.
|
||||||
(define
|
(define
|
||||||
make-ho-setup-frame
|
make-ho-setup-frame
|
||||||
(fn (ho-type remaining-args evaled-args env) {:ho-type ho-type :env env :evaled evaled-args :type "ho-setup" :remaining remaining-args}))
|
(fn (ho-type remaining-args evaled-args env) {:ho-type ho-type :env env :evaled evaled-args :type "ho-setup" :remaining remaining-args}))
|
||||||
|
|
||||||
|
;; Frame for component trace: records component render tree
|
||||||
(define make-comp-trace-frame (fn (name file) {:env file :type "comp-trace" :name name}))
|
(define make-comp-trace-frame (fn (name file) {:env file :type "comp-trace" :name name}))
|
||||||
|
|
||||||
|
;; Walk continuation stack collecting component trace entries
|
||||||
(define
|
(define
|
||||||
kont-collect-comp-trace
|
kont-collect-comp-trace
|
||||||
(fn
|
(fn
|
||||||
@@ -113,12 +153,16 @@
|
|||||||
(cons {:file (get frame "file") :name (get frame "name")} (kont-collect-comp-trace (rest kont)))
|
(cons {:file (get frame "file") :name (get frame "name")} (kont-collect-comp-trace (rest kont)))
|
||||||
(kont-collect-comp-trace (rest kont)))))))
|
(kont-collect-comp-trace (rest kont)))))))
|
||||||
|
|
||||||
|
;; Frame for handler-bind: condition handler scope
|
||||||
(define make-handler-frame (fn (handlers remaining env) {:env env :type "handler" :f handlers :remaining remaining}))
|
(define make-handler-frame (fn (handlers remaining env) {:env env :type "handler" :f handlers :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for restart-case: named restart scope
|
||||||
(define make-restart-frame (fn (restarts remaining env) {:env env :type "restart" :f restarts :remaining remaining}))
|
(define make-restart-frame (fn (restarts remaining env) {:env env :type "restart" :f restarts :remaining remaining}))
|
||||||
|
|
||||||
|
;; Frame for signal return: restores saved continuation after handler
|
||||||
(define make-signal-return-frame (fn (env saved-kont) {:env env :type "signal-return" :f saved-kont}))
|
(define make-signal-return-frame (fn (env saved-kont) {:env env :type "signal-return" :f saved-kont}))
|
||||||
|
|
||||||
|
;; Search handler list for one matching a condition type
|
||||||
(define
|
(define
|
||||||
find-matching-handler
|
find-matching-handler
|
||||||
(fn
|
(fn
|
||||||
@@ -135,6 +179,7 @@
|
|||||||
handler-fn
|
handler-fn
|
||||||
(find-matching-handler (rest handlers) condition)))))))
|
(find-matching-handler (rest handlers) condition)))))))
|
||||||
|
|
||||||
|
;; Walk continuation stack looking for a matching handler frame
|
||||||
(define
|
(define
|
||||||
kont-find-handler
|
kont-find-handler
|
||||||
(fn
|
(fn
|
||||||
@@ -154,6 +199,7 @@
|
|||||||
match))
|
match))
|
||||||
(kont-find-handler (rest kont) condition))))))
|
(kont-find-handler (rest kont) condition))))))
|
||||||
|
|
||||||
|
;; Search restart list for one matching a name
|
||||||
(define
|
(define
|
||||||
find-named-restart
|
find-named-restart
|
||||||
(fn
|
(fn
|
||||||
@@ -168,6 +214,7 @@
|
|||||||
entry
|
entry
|
||||||
(find-named-restart (rest restarts) name))))))
|
(find-named-restart (rest restarts) name))))))
|
||||||
|
|
||||||
|
;; Walk continuation stack looking for a named restart frame
|
||||||
(define
|
(define
|
||||||
kont-find-restart
|
kont-find-restart
|
||||||
(fn
|
(fn
|
||||||
@@ -187,16 +234,22 @@
|
|||||||
(list match frame (rest kont))))
|
(list match frame (rest kont))))
|
||||||
(kont-find-restart (rest kont) name))))))
|
(kont-find-restart (rest kont) name))))))
|
||||||
|
|
||||||
|
;; Get the type tag of a continuation frame
|
||||||
(define frame-type (fn (f) (get f "type")))
|
(define frame-type (fn (f) (get f "type")))
|
||||||
|
|
||||||
|
;; Push a frame onto the continuation stack
|
||||||
(define kont-push (fn (frame kont) (cons frame kont)))
|
(define kont-push (fn (frame kont) (cons frame kont)))
|
||||||
|
|
||||||
|
;; Peek at the top frame of the continuation stack
|
||||||
(define kont-top (fn (kont) (first kont)))
|
(define kont-top (fn (kont) (first kont)))
|
||||||
|
|
||||||
|
;; Pop the top frame, returning the rest of the stack
|
||||||
(define kont-pop (fn (kont) (rest kont)))
|
(define kont-pop (fn (kont) (rest kont)))
|
||||||
|
|
||||||
|
;; True if the continuation stack has no frames
|
||||||
(define kont-empty? (fn (kont) (empty? kont)))
|
(define kont-empty? (fn (kont) (empty? kont)))
|
||||||
|
|
||||||
|
;; Capture continuation frames up to the nearest reset delimiter
|
||||||
(define
|
(define
|
||||||
kont-capture-to-reset
|
kont-capture-to-reset
|
||||||
(fn
|
(fn
|
||||||
@@ -218,6 +271,7 @@
|
|||||||
(scan (rest k) (append captured (list frame))))))))
|
(scan (rest k) (append captured (list frame))))))))
|
||||||
(scan kont (list))))
|
(scan kont (list))))
|
||||||
|
|
||||||
|
;; Walk stack looking for a provide frame with matching name
|
||||||
(define
|
(define
|
||||||
kont-find-provide
|
kont-find-provide
|
||||||
(fn
|
(fn
|
||||||
@@ -234,6 +288,7 @@
|
|||||||
frame
|
frame
|
||||||
(kont-find-provide (rest kont) name))))))
|
(kont-find-provide (rest kont) name))))))
|
||||||
|
|
||||||
|
;; Walk stack looking for a scope accumulator with matching name
|
||||||
(define
|
(define
|
||||||
kont-find-scope-acc
|
kont-find-scope-acc
|
||||||
(fn
|
(fn
|
||||||
@@ -250,6 +305,7 @@
|
|||||||
frame
|
frame
|
||||||
(kont-find-scope-acc (rest kont) name))))))
|
(kont-find-scope-acc (rest kont) name))))))
|
||||||
|
|
||||||
|
;; True if stack contains a reactive-reset frame
|
||||||
(define
|
(define
|
||||||
has-reactive-reset-frame?
|
has-reactive-reset-frame?
|
||||||
(fn
|
(fn
|
||||||
@@ -262,6 +318,7 @@
|
|||||||
true
|
true
|
||||||
(has-reactive-reset-frame? (rest kont))))))
|
(has-reactive-reset-frame? (rest kont))))))
|
||||||
|
|
||||||
|
;; Capture frames up to the nearest reactive-reset delimiter
|
||||||
(define
|
(define
|
||||||
kont-capture-to-reactive-reset
|
kont-capture-to-reactive-reset
|
||||||
(fn
|
(fn
|
||||||
@@ -281,18 +338,23 @@
|
|||||||
(scan (rest k) (append captured (list frame))))))))
|
(scan (rest k) (append captured (list frame))))))))
|
||||||
(scan kont (list))))
|
(scan kont (list))))
|
||||||
|
|
||||||
|
;; Registry of user-defined special forms
|
||||||
(define *custom-special-forms* (dict))
|
(define *custom-special-forms* (dict))
|
||||||
|
|
||||||
|
;; Register a function as a custom special form
|
||||||
(define
|
(define
|
||||||
register-special-form!
|
register-special-form!
|
||||||
(fn
|
(fn
|
||||||
((name :as string) handler)
|
((name :as string) handler)
|
||||||
(dict-set! *custom-special-forms* name handler)))
|
(dict-set! *custom-special-forms* name handler)))
|
||||||
|
|
||||||
|
;; Function to check if a symbol is a renderable HTML tag
|
||||||
(define *render-check* nil)
|
(define *render-check* nil)
|
||||||
|
|
||||||
|
;; Function to render an HTML element
|
||||||
(define *render-fn* nil)
|
(define *render-fn* nil)
|
||||||
|
|
||||||
|
;; Trampoline: repeatedly evaluate thunks until a non-thunk value
|
||||||
(define
|
(define
|
||||||
trampoline
|
trampoline
|
||||||
(fn
|
(fn
|
||||||
@@ -305,14 +367,19 @@
|
|||||||
(trampoline (eval-expr (thunk-expr result) (thunk-env result)))
|
(trampoline (eval-expr (thunk-expr result) (thunk-env result)))
|
||||||
result)))))
|
result)))))
|
||||||
|
|
||||||
|
;; Flag: enable strict type checking mode
|
||||||
(define *strict* false)
|
(define *strict* false)
|
||||||
|
|
||||||
|
;; Enable or disable strict type checking
|
||||||
(define set-strict! (fn (val) (set! *strict* val)))
|
(define set-strict! (fn (val) (set! *strict* val)))
|
||||||
|
|
||||||
|
;; Type specs for primitive function parameters
|
||||||
(define *prim-param-types* nil)
|
(define *prim-param-types* nil)
|
||||||
|
|
||||||
|
;; Set the parameter type spec table for strict mode
|
||||||
(define set-prim-param-types! (fn (types) (set! *prim-param-types* types)))
|
(define set-prim-param-types! (fn (types) (set! *prim-param-types* types)))
|
||||||
|
|
||||||
|
;; Check if a value matches a declared type (for strict mode)
|
||||||
(define
|
(define
|
||||||
value-matches-type?
|
value-matches-type?
|
||||||
(fn
|
(fn
|
||||||
@@ -339,6 +406,7 @@
|
|||||||
(slice expected-type 0 (- (string-length expected-type) 1))))
|
(slice expected-type 0 (- (string-length expected-type) 1))))
|
||||||
true)))))
|
true)))))
|
||||||
|
|
||||||
|
;; Validate function arguments against declared types
|
||||||
(define
|
(define
|
||||||
strict-check-args
|
strict-check-args
|
||||||
(fn
|
(fn
|
||||||
@@ -408,8 +476,10 @@
|
|||||||
(fn (i v) (list i v))
|
(fn (i v) (list i v))
|
||||||
(slice args (len (or positional (list)))))))))))))
|
(slice args (len (or positional (list)))))))))))))
|
||||||
|
|
||||||
|
;; Evaluate an expression in an environment (CEK entry point)
|
||||||
(define eval-expr (fn (expr (env :as dict)) nil))
|
(define eval-expr (fn (expr (env :as dict)) nil))
|
||||||
|
|
||||||
|
;; Call a lambda with evaluated args, binding params in closure env
|
||||||
(define
|
(define
|
||||||
call-lambda
|
call-lambda
|
||||||
(fn
|
(fn
|
||||||
@@ -435,6 +505,7 @@
|
|||||||
(slice params (len args)))
|
(slice params (len args)))
|
||||||
(make-thunk (lambda-body f) local))))))
|
(make-thunk (lambda-body f) local))))))
|
||||||
|
|
||||||
|
;; Call a component with keyword args, binding params in closure env
|
||||||
(define
|
(define
|
||||||
call-component
|
call-component
|
||||||
(fn
|
(fn
|
||||||
@@ -452,6 +523,7 @@
|
|||||||
(env-bind! local "children" children))
|
(env-bind! local "children" children))
|
||||||
(make-thunk (component-body comp) local))))
|
(make-thunk (component-body comp) local))))
|
||||||
|
|
||||||
|
;; Parse &key and &rest args from a component call
|
||||||
(define
|
(define
|
||||||
parse-keyword-args
|
parse-keyword-args
|
||||||
(fn
|
(fn
|
||||||
@@ -483,12 +555,14 @@
|
|||||||
raw-args)
|
raw-args)
|
||||||
(list kwargs children))))
|
(list kwargs children))))
|
||||||
|
|
||||||
|
;; Detect if a cond uses scheme-style ((test body) ...) syntax
|
||||||
(define
|
(define
|
||||||
cond-scheme?
|
cond-scheme?
|
||||||
(fn
|
(fn
|
||||||
((clauses :as list))
|
((clauses :as list))
|
||||||
(every? (fn (c) (and (= (type-of c) "list") (= (len c) 2))) clauses)))
|
(every? (fn (c) (and (= (type-of c) "list") (= (len c) 2))) clauses)))
|
||||||
|
|
||||||
|
;; True if a cond clause is the :else / else fallback
|
||||||
(define
|
(define
|
||||||
is-else-clause?
|
is-else-clause?
|
||||||
(fn
|
(fn
|
||||||
@@ -499,6 +573,7 @@
|
|||||||
(= (type-of test) "symbol")
|
(= (type-of test) "symbol")
|
||||||
(or (= (symbol-name test) "else") (= (symbol-name test) ":else"))))))
|
(or (= (symbol-name test) "else") (= (symbol-name test) ":else"))))))
|
||||||
|
|
||||||
|
;; Handle named let: (let name ((var val) ...) body)
|
||||||
(define
|
(define
|
||||||
sf-named-let
|
sf-named-let
|
||||||
(fn
|
(fn
|
||||||
@@ -546,6 +621,7 @@
|
|||||||
((init-vals (map (fn (e) (trampoline (eval-expr e env))) inits)))
|
((init-vals (map (fn (e) (trampoline (eval-expr e env))) inits)))
|
||||||
(cek-call loop-fn init-vals))))))
|
(cek-call loop-fn init-vals))))))
|
||||||
|
|
||||||
|
;; Construct a lambda value from params and body
|
||||||
(define
|
(define
|
||||||
sf-lambda
|
sf-lambda
|
||||||
(fn
|
(fn
|
||||||
@@ -575,6 +651,7 @@
|
|||||||
params-expr)))
|
params-expr)))
|
||||||
(make-lambda param-names body env))))
|
(make-lambda param-names body env))))
|
||||||
|
|
||||||
|
;; Handle defcomp: register a named component
|
||||||
(define
|
(define
|
||||||
sf-defcomp
|
sf-defcomp
|
||||||
(fn
|
(fn
|
||||||
@@ -612,6 +689,7 @@
|
|||||||
(env-bind! env (symbol-name name-sym) comp)
|
(env-bind! env (symbol-name name-sym) comp)
|
||||||
comp))))
|
comp))))
|
||||||
|
|
||||||
|
;; Parse a single &key parameter with optional default
|
||||||
(define
|
(define
|
||||||
defcomp-kwarg
|
defcomp-kwarg
|
||||||
(fn
|
(fn
|
||||||
@@ -634,6 +712,7 @@
|
|||||||
(range 2 end 1))
|
(range 2 end 1))
|
||||||
result)))
|
result)))
|
||||||
|
|
||||||
|
;; Parse component parameter list (positional, &key, &rest)
|
||||||
(define
|
(define
|
||||||
parse-comp-params
|
parse-comp-params
|
||||||
(fn
|
(fn
|
||||||
@@ -680,6 +759,7 @@
|
|||||||
params-expr)
|
params-expr)
|
||||||
(list params has-children param-types))))
|
(list params has-children param-types))))
|
||||||
|
|
||||||
|
;; Handle defisland: register a reactive island component
|
||||||
(define
|
(define
|
||||||
sf-defisland
|
sf-defisland
|
||||||
(fn
|
(fn
|
||||||
@@ -705,6 +785,7 @@
|
|||||||
(env-bind! env (symbol-name name-sym) island)
|
(env-bind! env (symbol-name name-sym) island)
|
||||||
island))))
|
island))))
|
||||||
|
|
||||||
|
;; Handle defmacro: register a macro transformer
|
||||||
(define
|
(define
|
||||||
sf-defmacro
|
sf-defmacro
|
||||||
(fn
|
(fn
|
||||||
@@ -721,6 +802,7 @@
|
|||||||
(env-bind! env (symbol-name name-sym) mac)
|
(env-bind! env (symbol-name name-sym) mac)
|
||||||
mac))))
|
mac))))
|
||||||
|
|
||||||
|
;; Parse macro parameter list
|
||||||
(define
|
(define
|
||||||
parse-macro-params
|
parse-macro-params
|
||||||
(fn
|
(fn
|
||||||
@@ -749,6 +831,7 @@
|
|||||||
params-expr)
|
params-expr)
|
||||||
(list params rest-param))))
|
(list params rest-param))))
|
||||||
|
|
||||||
|
;; Expand a quasiquote template, splicing unquoted values
|
||||||
(define
|
(define
|
||||||
qq-expand
|
qq-expand
|
||||||
(fn
|
(fn
|
||||||
@@ -788,6 +871,7 @@
|
|||||||
(list)
|
(list)
|
||||||
template)))))))
|
template)))))))
|
||||||
|
|
||||||
|
;; Handle letrec: mutually recursive bindings
|
||||||
(define
|
(define
|
||||||
sf-letrec
|
sf-letrec
|
||||||
(fn
|
(fn
|
||||||
@@ -843,6 +927,7 @@
|
|||||||
(slice body 0 (dec (len body))))
|
(slice body 0 (dec (len body))))
|
||||||
(make-thunk (last body) local))))
|
(make-thunk (last body) local))))
|
||||||
|
|
||||||
|
;; CEK step for letrec continuation frame
|
||||||
(define
|
(define
|
||||||
step-sf-letrec
|
step-sf-letrec
|
||||||
(fn
|
(fn
|
||||||
@@ -851,6 +936,7 @@
|
|||||||
((thk (sf-letrec args env)))
|
((thk (sf-letrec args env)))
|
||||||
(make-cek-state (thunk-expr thk) (thunk-env thk) kont))))
|
(make-cek-state (thunk-expr thk) (thunk-env thk) kont))))
|
||||||
|
|
||||||
|
;; Handle dynamic-wind: before/body/after with guaranteed cleanup
|
||||||
(define
|
(define
|
||||||
sf-dynamic-wind
|
sf-dynamic-wind
|
||||||
(fn
|
(fn
|
||||||
@@ -861,6 +947,7 @@
|
|||||||
(after (trampoline (eval-expr (nth args 2) env))))
|
(after (trampoline (eval-expr (nth args 2) env))))
|
||||||
(dynamic-wind-call before body after env))))
|
(dynamic-wind-call before body after env))))
|
||||||
|
|
||||||
|
;; Handle scope special form: push/pop named scope
|
||||||
(define
|
(define
|
||||||
sf-scope
|
sf-scope
|
||||||
(fn
|
(fn
|
||||||
@@ -888,6 +975,7 @@
|
|||||||
(scope-pop! name)
|
(scope-pop! name)
|
||||||
result))))
|
result))))
|
||||||
|
|
||||||
|
;; Handle provide: scope with a downward-propagating value
|
||||||
(define
|
(define
|
||||||
sf-provide
|
sf-provide
|
||||||
(fn
|
(fn
|
||||||
@@ -904,6 +992,7 @@
|
|||||||
(scope-pop! name)
|
(scope-pop! name)
|
||||||
result)))
|
result)))
|
||||||
|
|
||||||
|
;; Expand a macro call: bind args, evaluate transformer body
|
||||||
(define
|
(define
|
||||||
expand-macro
|
expand-macro
|
||||||
(fn
|
(fn
|
||||||
@@ -929,12 +1018,14 @@
|
|||||||
(slice raw-args (len (macro-params mac)))))
|
(slice raw-args (len (macro-params mac)))))
|
||||||
(trampoline (eval-expr (macro-body mac) local)))))
|
(trampoline (eval-expr (macro-body mac) local)))))
|
||||||
|
|
||||||
|
;; Run the CEK machine to completion, returning final value
|
||||||
(define
|
(define
|
||||||
cek-run
|
cek-run
|
||||||
(fn
|
(fn
|
||||||
(state)
|
(state)
|
||||||
(if (cek-terminal? state) (cek-value state) (cek-run (cek-step state)))))
|
(if (cek-terminal? state) (cek-value state) (cek-run (cek-step state)))))
|
||||||
|
|
||||||
|
;; Single CEK machine step: eval or continue
|
||||||
(define
|
(define
|
||||||
cek-step
|
cek-step
|
||||||
(fn
|
(fn
|
||||||
@@ -944,6 +1035,7 @@
|
|||||||
(step-eval state)
|
(step-eval state)
|
||||||
(step-continue state))))
|
(step-continue state))))
|
||||||
|
|
||||||
|
;; Eval phase: dispatch on expression type (literal, symbol, list, dict)
|
||||||
(define
|
(define
|
||||||
step-eval
|
step-eval
|
||||||
(fn
|
(fn
|
||||||
@@ -1000,6 +1092,7 @@
|
|||||||
(step-eval-list expr env kont))
|
(step-eval-list expr env kont))
|
||||||
:else (make-cek-value expr env kont)))))
|
:else (make-cek-value expr env kont)))))
|
||||||
|
|
||||||
|
;; Eval a list expression: check for special forms, macros, then call
|
||||||
(define
|
(define
|
||||||
step-eval-list
|
step-eval-list
|
||||||
(fn
|
(fn
|
||||||
@@ -1089,6 +1182,7 @@
|
|||||||
:else (step-eval-call head args env kont)))))
|
:else (step-eval-call head args env kont)))))
|
||||||
(step-eval-call head args env kont))))))
|
(step-eval-call head args env kont))))))
|
||||||
|
|
||||||
|
;; Find matching clause in a match expression
|
||||||
(define
|
(define
|
||||||
match-find-clause
|
match-find-clause
|
||||||
(fn
|
(fn
|
||||||
@@ -1106,6 +1200,7 @@
|
|||||||
(list local body)
|
(list local body)
|
||||||
(match-find-clause val (rest clauses) env))))))
|
(match-find-clause val (rest clauses) env))))))
|
||||||
|
|
||||||
|
;; Match a value against a pattern, returning bindings or nil
|
||||||
(define
|
(define
|
||||||
match-pattern
|
match-pattern
|
||||||
(fn
|
(fn
|
||||||
@@ -1138,6 +1233,7 @@
|
|||||||
pairs)))
|
pairs)))
|
||||||
:else (= pattern value))))
|
:else (= pattern value))))
|
||||||
|
|
||||||
|
;; CEK step for match special form
|
||||||
(define
|
(define
|
||||||
step-sf-match
|
step-sf-match
|
||||||
(fn
|
(fn
|
||||||
@@ -1152,6 +1248,7 @@
|
|||||||
(error (str "match: no clause matched " (inspect val)))
|
(error (str "match: no clause matched " (inspect val)))
|
||||||
(make-cek-state (nth result 1) (first result) kont))))))
|
(make-cek-state (nth result 1) (first result) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for handler-bind (condition system)
|
||||||
(define
|
(define
|
||||||
step-sf-handler-bind
|
step-sf-handler-bind
|
||||||
(fn
|
(fn
|
||||||
@@ -1175,6 +1272,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-handler-frame handlers (rest body) env) kont))))))
|
(kont-push (make-handler-frame handlers (rest body) env) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for restart-case (condition system)
|
||||||
(define
|
(define
|
||||||
step-sf-restart-case
|
step-sf-restart-case
|
||||||
(fn
|
(fn
|
||||||
@@ -1199,6 +1297,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-restart-frame restarts (list) env) kont)))))
|
(kont-push (make-restart-frame restarts (list) env) kont)))))
|
||||||
|
|
||||||
|
;; CEK step for signal (raise a condition)
|
||||||
(define
|
(define
|
||||||
step-sf-signal
|
step-sf-signal
|
||||||
(fn
|
(fn
|
||||||
@@ -1216,6 +1315,7 @@
|
|||||||
(list condition)
|
(list condition)
|
||||||
(kont-push (make-signal-return-frame env kont) kont))))))
|
(kont-push (make-signal-return-frame env kont) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for invoke-restart (jump to named restart)
|
||||||
(define
|
(define
|
||||||
step-sf-invoke-restart
|
step-sf-invoke-restart
|
||||||
(fn
|
(fn
|
||||||
@@ -1244,6 +1344,7 @@
|
|||||||
(env-bind! restart-env (first params) restart-arg))
|
(env-bind! restart-env (first params) restart-arg))
|
||||||
(make-cek-state body restart-env rest-kont)))))))
|
(make-cek-state body restart-env rest-kont)))))))
|
||||||
|
|
||||||
|
;; CEK step for if: push if-frame, evaluate test
|
||||||
(define
|
(define
|
||||||
step-sf-if
|
step-sf-if
|
||||||
(fn
|
(fn
|
||||||
@@ -1258,6 +1359,7 @@
|
|||||||
env)
|
env)
|
||||||
kont))))
|
kont))))
|
||||||
|
|
||||||
|
;; CEK step for when: push when-frame, evaluate test
|
||||||
(define
|
(define
|
||||||
step-sf-when
|
step-sf-when
|
||||||
(fn
|
(fn
|
||||||
@@ -1267,6 +1369,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-when-frame (rest args) env) kont))))
|
(kont-push (make-when-frame (rest args) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for begin/do: evaluate forms sequentially
|
||||||
(define
|
(define
|
||||||
step-sf-begin
|
step-sf-begin
|
||||||
(fn
|
(fn
|
||||||
@@ -1282,6 +1385,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-begin-frame (rest args) env) kont))))))
|
(kont-push (make-begin-frame (rest args) env) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for let: evaluate first binding value
|
||||||
(define
|
(define
|
||||||
step-sf-let
|
step-sf-let
|
||||||
(fn
|
(fn
|
||||||
@@ -1326,6 +1430,7 @@
|
|||||||
(make-let-frame vname rest-bindings body local)
|
(make-let-frame vname rest-bindings body local)
|
||||||
kont)))))))))
|
kont)))))))))
|
||||||
|
|
||||||
|
;; CEK step for define: evaluate value, bind in env
|
||||||
(define
|
(define
|
||||||
step-sf-define
|
step-sf-define
|
||||||
(fn
|
(fn
|
||||||
@@ -1364,6 +1469,7 @@
|
|||||||
effect-list)
|
effect-list)
|
||||||
kont)))))
|
kont)))))
|
||||||
|
|
||||||
|
;; CEK step for set!: evaluate value, mutate existing binding
|
||||||
(define
|
(define
|
||||||
step-sf-set!
|
step-sf-set!
|
||||||
(fn
|
(fn
|
||||||
@@ -1373,6 +1479,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-set-frame (symbol-name (first args)) env) kont))))
|
(kont-push (make-set-frame (symbol-name (first args)) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for and: short-circuit on falsy
|
||||||
(define
|
(define
|
||||||
step-sf-and
|
step-sf-and
|
||||||
(fn
|
(fn
|
||||||
@@ -1385,6 +1492,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-and-frame (rest args) env) kont)))))
|
(kont-push (make-and-frame (rest args) env) kont)))))
|
||||||
|
|
||||||
|
;; CEK step for or: short-circuit on truthy
|
||||||
(define
|
(define
|
||||||
step-sf-or
|
step-sf-or
|
||||||
(fn
|
(fn
|
||||||
@@ -1397,6 +1505,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-or-frame (rest args) env) kont)))))
|
(kont-push (make-or-frame (rest args) env) kont)))))
|
||||||
|
|
||||||
|
;; CEK step for cond: evaluate first test
|
||||||
(define
|
(define
|
||||||
step-sf-cond
|
step-sf-cond
|
||||||
(fn
|
(fn
|
||||||
@@ -1430,6 +1539,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-cond-frame args env false) kont)))))))))
|
(kont-push (make-cond-frame args env false) kont)))))))))
|
||||||
|
|
||||||
|
;; CEK step for case: evaluate match value
|
||||||
(define
|
(define
|
||||||
step-sf-case
|
step-sf-case
|
||||||
(fn
|
(fn
|
||||||
@@ -1439,6 +1549,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-case-frame nil (rest args) env) kont))))
|
(kont-push (make-case-frame nil (rest args) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for ->: thread value through forms
|
||||||
(define
|
(define
|
||||||
step-sf-thread-first
|
step-sf-thread-first
|
||||||
(fn
|
(fn
|
||||||
@@ -1448,10 +1559,12 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-thread-frame (rest args) env) kont))))
|
(kont-push (make-thread-frame (rest args) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for lambda/fn: capture closure
|
||||||
(define
|
(define
|
||||||
step-sf-lambda
|
step-sf-lambda
|
||||||
(fn (args env kont) (make-cek-value (sf-lambda args env) env kont)))
|
(fn (args env kont) (make-cek-value (sf-lambda args env) env kont)))
|
||||||
|
|
||||||
|
;; CEK step for scope: push scope, evaluate body
|
||||||
(define
|
(define
|
||||||
step-sf-scope
|
step-sf-scope
|
||||||
(fn
|
(fn
|
||||||
@@ -1478,6 +1591,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-scope-acc-frame name val (rest body) env) kont))))))
|
(kont-push (make-scope-acc-frame name val (rest body) env) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for provide: push scoped value, evaluate body
|
||||||
(define
|
(define
|
||||||
step-sf-provide
|
step-sf-provide
|
||||||
(fn
|
(fn
|
||||||
@@ -1494,6 +1608,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-provide-frame name val (rest body) env) kont))))))
|
(kont-push (make-provide-frame name val (rest body) env) kont))))))
|
||||||
|
|
||||||
|
;; CEK step for context: read value from nearest enclosing scope
|
||||||
(define
|
(define
|
||||||
step-sf-context
|
step-sf-context
|
||||||
(fn
|
(fn
|
||||||
@@ -1511,6 +1626,7 @@
|
|||||||
env
|
env
|
||||||
kont))))
|
kont))))
|
||||||
|
|
||||||
|
;; CEK step for emit!: append value to scope accumulator
|
||||||
(define
|
(define
|
||||||
step-sf-emit
|
step-sf-emit
|
||||||
(fn
|
(fn
|
||||||
@@ -1527,6 +1643,7 @@
|
|||||||
(append (get frame "emitted") (list val))))
|
(append (get frame "emitted") (list val))))
|
||||||
(make-cek-value nil env kont))))
|
(make-cek-value nil env kont))))
|
||||||
|
|
||||||
|
;; CEK step for emitted: read accumulated values from scope
|
||||||
(define
|
(define
|
||||||
step-sf-emitted
|
step-sf-emitted
|
||||||
(fn
|
(fn
|
||||||
@@ -1539,6 +1656,7 @@
|
|||||||
env
|
env
|
||||||
kont))))
|
kont))))
|
||||||
|
|
||||||
|
;; CEK step for reset: push delimiter frame, evaluate body
|
||||||
(define
|
(define
|
||||||
step-sf-reset
|
step-sf-reset
|
||||||
(fn
|
(fn
|
||||||
@@ -1548,6 +1666,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-reset-frame env) kont))))
|
(kont-push (make-reset-frame env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for shift: capture continuation to reset, call handler
|
||||||
(define
|
(define
|
||||||
step-sf-shift
|
step-sf-shift
|
||||||
(fn
|
(fn
|
||||||
@@ -1565,6 +1684,7 @@
|
|||||||
(env-bind! shift-env k-name k)
|
(env-bind! shift-env k-name k)
|
||||||
(make-cek-state body shift-env rest-kont))))))
|
(make-cek-state body shift-env rest-kont))))))
|
||||||
|
|
||||||
|
;; CEK step for deref: resolve signal with dependency tracking
|
||||||
(define
|
(define
|
||||||
step-sf-deref
|
step-sf-deref
|
||||||
(fn
|
(fn
|
||||||
@@ -1574,6 +1694,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-deref-frame env) kont))))
|
(kont-push (make-deref-frame env) kont))))
|
||||||
|
|
||||||
|
;; Dispatch a function call: native fn, lambda, component, or macro
|
||||||
(define
|
(define
|
||||||
cek-call
|
cek-call
|
||||||
(fn
|
(fn
|
||||||
@@ -1587,6 +1708,7 @@
|
|||||||
(cek-run (continue-with-call f a (make-env) a (list)))
|
(cek-run (continue-with-call f a (make-env) a (list)))
|
||||||
:else nil))))
|
:else nil))))
|
||||||
|
|
||||||
|
;; Deref inside reactive context: capture deps via shift
|
||||||
(define
|
(define
|
||||||
reactive-shift-deref
|
reactive-shift-deref
|
||||||
(fn
|
(fn
|
||||||
@@ -1611,6 +1733,7 @@
|
|||||||
((initial-kont (concat captured-frames (list reset-frame) remaining-kont)))
|
((initial-kont (concat captured-frames (list reset-frame) remaining-kont)))
|
||||||
(make-cek-value (signal-value sig) env initial-kont)))))))
|
(make-cek-value (signal-value sig) env initial-kont)))))))
|
||||||
|
|
||||||
|
;; Evaluate function position, set up arg evaluation frames
|
||||||
(define
|
(define
|
||||||
step-eval-call
|
step-eval-call
|
||||||
(fn
|
(fn
|
||||||
@@ -1622,6 +1745,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-arg-frame nil (list) args env args hname) kont)))))
|
(kont-push (make-arg-frame nil (list) args env args hname) kont)))))
|
||||||
|
|
||||||
|
;; True if name is a higher-order form (map, filter, reduce, etc.)
|
||||||
(define
|
(define
|
||||||
ho-form-name?
|
ho-form-name?
|
||||||
(fn
|
(fn
|
||||||
@@ -1635,8 +1759,10 @@
|
|||||||
(= name "every?")
|
(= name "every?")
|
||||||
(= name "for-each"))))
|
(= name "for-each"))))
|
||||||
|
|
||||||
|
;; True if a value is a function (lambda or native callable)
|
||||||
(define ho-fn? (fn (v) (or (callable? v) (lambda? v))))
|
(define ho-fn? (fn (v) (or (callable? v) (lambda? v))))
|
||||||
|
|
||||||
|
;; Auto-detect data-first vs fn-first arg order for HO forms
|
||||||
(define
|
(define
|
||||||
ho-swap-args
|
ho-swap-args
|
||||||
(fn
|
(fn
|
||||||
@@ -1653,6 +1779,7 @@
|
|||||||
((a (first evaled)) (b (nth evaled 1)))
|
((a (first evaled)) (b (nth evaled 1)))
|
||||||
(if (and (not (ho-fn? a)) (ho-fn? b)) (list b a) evaled)))))
|
(if (and (not (ho-fn? a)) (ho-fn? b)) (list b a) evaled)))))
|
||||||
|
|
||||||
|
;; Dispatch a higher-order form after args are evaluated
|
||||||
(define
|
(define
|
||||||
ho-setup-dispatch
|
ho-setup-dispatch
|
||||||
(fn
|
(fn
|
||||||
@@ -1758,6 +1885,7 @@
|
|||||||
(kont-push (make-for-each-frame f (rest coll) env) kont)))))
|
(kont-push (make-for-each-frame f (rest coll) env) kont)))))
|
||||||
(_ (error (str "Unknown HO type: " ho-type))))))))
|
(_ (error (str "Unknown HO type: " ho-type))))))))
|
||||||
|
|
||||||
|
;; CEK step for map: apply fn to next item, accumulate
|
||||||
(define
|
(define
|
||||||
step-ho-map
|
step-ho-map
|
||||||
(fn
|
(fn
|
||||||
@@ -1767,6 +1895,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-ho-setup-frame "map" (rest args) (list) env) kont))))
|
(kont-push (make-ho-setup-frame "map" (rest args) (list) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for map-indexed: like map with index arg
|
||||||
(define
|
(define
|
||||||
step-ho-map-indexed
|
step-ho-map-indexed
|
||||||
(fn
|
(fn
|
||||||
@@ -1778,6 +1907,7 @@
|
|||||||
(make-ho-setup-frame "map-indexed" (rest args) (list) env)
|
(make-ho-setup-frame "map-indexed" (rest args) (list) env)
|
||||||
kont))))
|
kont))))
|
||||||
|
|
||||||
|
;; CEK step for filter: test next item, keep if truthy
|
||||||
(define
|
(define
|
||||||
step-ho-filter
|
step-ho-filter
|
||||||
(fn
|
(fn
|
||||||
@@ -1787,6 +1917,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-ho-setup-frame "filter" (rest args) (list) env) kont))))
|
(kont-push (make-ho-setup-frame "filter" (rest args) (list) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for reduce: apply fn to accumulator and next item
|
||||||
(define
|
(define
|
||||||
step-ho-reduce
|
step-ho-reduce
|
||||||
(fn
|
(fn
|
||||||
@@ -1796,6 +1927,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-ho-setup-frame "reduce" (rest args) (list) env) kont))))
|
(kont-push (make-ho-setup-frame "reduce" (rest args) (list) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for some: return first truthy result
|
||||||
(define
|
(define
|
||||||
step-ho-some
|
step-ho-some
|
||||||
(fn
|
(fn
|
||||||
@@ -1805,6 +1937,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-ho-setup-frame "some" (rest args) (list) env) kont))))
|
(kont-push (make-ho-setup-frame "some" (rest args) (list) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for every?: return false on first falsy
|
||||||
(define
|
(define
|
||||||
step-ho-every
|
step-ho-every
|
||||||
(fn
|
(fn
|
||||||
@@ -1814,6 +1947,7 @@
|
|||||||
env
|
env
|
||||||
(kont-push (make-ho-setup-frame "every" (rest args) (list) env) kont))))
|
(kont-push (make-ho-setup-frame "every" (rest args) (list) env) kont))))
|
||||||
|
|
||||||
|
;; CEK step for for-each: apply fn for side effects
|
||||||
(define
|
(define
|
||||||
step-ho-for-each
|
step-ho-for-each
|
||||||
(fn
|
(fn
|
||||||
@@ -1825,6 +1959,7 @@
|
|||||||
(make-ho-setup-frame "for-each" (rest args) (list) env)
|
(make-ho-setup-frame "for-each" (rest args) (list) env)
|
||||||
kont))))
|
kont))))
|
||||||
|
|
||||||
|
;; Continue phase: pop frame, dispatch on frame type
|
||||||
(define
|
(define
|
||||||
step-continue
|
step-continue
|
||||||
(fn
|
(fn
|
||||||
@@ -2399,6 +2534,7 @@
|
|||||||
("comp-trace" (make-cek-value value env rest-k))
|
("comp-trace" (make-cek-value value env rest-k))
|
||||||
(_ (error (str "Unknown frame type: " ft)))))))))
|
(_ (error (str "Unknown frame type: " ft)))))))))
|
||||||
|
|
||||||
|
;; Continue with a function call after args are evaluated
|
||||||
(define
|
(define
|
||||||
continue-with-call
|
continue-with-call
|
||||||
(fn
|
(fn
|
||||||
@@ -2460,6 +2596,7 @@
|
|||||||
kont)))
|
kont)))
|
||||||
:else (error (str "Not callable: " (inspect f))))))
|
:else (error (str "Not callable: " (inspect f))))))
|
||||||
|
|
||||||
|
;; Case dispatch: iterate clauses matching against value
|
||||||
(define
|
(define
|
||||||
sf-case-step-loop
|
sf-case-step-loop
|
||||||
(fn
|
(fn
|
||||||
@@ -2479,20 +2616,24 @@
|
|||||||
(make-cek-state body env kont)
|
(make-cek-state body env kont)
|
||||||
(sf-case-step-loop match-val (slice clauses 2) env kont))))))))
|
(sf-case-step-loop match-val (slice clauses 2) env kont))))))))
|
||||||
|
|
||||||
|
;; Full CEK evaluation: create initial state, run to completion
|
||||||
(define
|
(define
|
||||||
eval-expr-cek
|
eval-expr-cek
|
||||||
(fn (expr env) (cek-run (make-cek-state expr env (list)))))
|
(fn (expr env) (cek-run (make-cek-state expr env (list)))))
|
||||||
|
|
||||||
|
;; Trampoline wrapper for CEK: handles thunks from eval-expr-cek
|
||||||
(define
|
(define
|
||||||
trampoline-cek
|
trampoline-cek
|
||||||
(fn
|
(fn
|
||||||
(val)
|
(val)
|
||||||
(if (thunk? val) (eval-expr-cek (thunk-expr val) (thunk-env val)) val)))
|
(if (thunk? val) (eval-expr-cek (thunk-expr val) (thunk-env val)) val)))
|
||||||
|
|
||||||
|
;; Evaluate an expression in an environment (CEK entry point)
|
||||||
(define
|
(define
|
||||||
eval-expr
|
eval-expr
|
||||||
(fn (expr (env :as dict)) (cek-run (make-cek-state expr env (list)))))
|
(fn (expr (env :as dict)) (cek-run (make-cek-state expr env (list)))))
|
||||||
|
|
||||||
|
;; Trampoline: repeatedly evaluate thunks until a non-thunk value
|
||||||
(define
|
(define
|
||||||
trampoline
|
trampoline
|
||||||
(fn
|
(fn
|
||||||
|
|||||||
Reference in New Issue
Block a user