Phase 4: Eliminate nested CEK from HO form handlers
Higher-order forms (map, filter, reduce, some, every?, for-each, map-indexed) now evaluate their arguments via CEK frames instead of nested trampoline(eval-expr(...)) calls. Added HoSetupFrame — staged evaluation of HO form arguments. When all args are evaluated, ho-setup-dispatch sets up the iteration frame. This keeps a single linear CEK continuation chain instead of spawning nested CEK instances. 14 nested eval-expr calls eliminated (39 → 25 remaining). The remaining 25 are in delegate functions (sf-letrec, sf-scope, parse-keyword-args, qq-expand, etc.) called infrequently. All tests unchanged: JS 747/747, Full 864/870, Python 679/679. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -197,6 +197,14 @@
|
||||
(fn (env)
|
||||
{:type "deref" :env env}))
|
||||
|
||||
;; HoSetupFrame: staged evaluation of higher-order form arguments
|
||||
;; ho-type is "map", "filter", "reduce", etc.
|
||||
;; Evaluates args one at a time, then dispatches to the iteration frame.
|
||||
(define make-ho-setup-frame
|
||||
(fn (ho-type remaining-args evaled-args env)
|
||||
{:type "ho-setup" :ho-type ho-type :remaining remaining-args
|
||||
:evaled evaled-args :env env}))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 3. Frame accessors
|
||||
@@ -1571,69 +1579,101 @@
|
||||
;; Function and collection args are evaluated via tree-walk (simple exprs),
|
||||
;; then the loop is driven by CEK frames.
|
||||
|
||||
;; HO step handlers — push HoSetupFrame to evaluate args via CEK
|
||||
;; (no nested eval-expr calls). When all args are evaluated, the
|
||||
;; HoSetupFrame dispatch in step-continue sets up the iteration frame.
|
||||
|
||||
;; ho-setup-dispatch: all HO args evaluated, set up iteration
|
||||
(define ho-setup-dispatch
|
||||
(fn (ho-type evaled env kont)
|
||||
(let ((f (first evaled)))
|
||||
(cond
|
||||
(= ho-type "map")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-map-frame f (rest coll) (list) env) kont))))
|
||||
|
||||
(= ho-type "map-indexed")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list 0 (first coll)) env (list)
|
||||
(kont-push (make-map-indexed-frame f (rest coll) (list) env) kont))))
|
||||
|
||||
(= ho-type "filter")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-filter-frame f (rest coll) (list) (first coll) env) kont))))
|
||||
|
||||
(= ho-type "reduce")
|
||||
(let ((init (nth evaled 1))
|
||||
(coll (nth evaled 2)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value init env kont)
|
||||
(continue-with-call f (list init (first coll)) env (list)
|
||||
(kont-push (make-reduce-frame f (rest coll) env) kont))))
|
||||
|
||||
(= ho-type "some")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value false env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-some-frame f (rest coll) env) kont))))
|
||||
|
||||
(= ho-type "every")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value true env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-every-frame f (rest coll) env) kont))))
|
||||
|
||||
(= ho-type "for-each")
|
||||
(let ((coll (nth evaled 1)))
|
||||
(if (empty? coll)
|
||||
(make-cek-value nil env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-for-each-frame f (rest coll) env) kont))))
|
||||
|
||||
:else (error (str "Unknown HO type: " ho-type))))))
|
||||
|
||||
(define step-ho-map
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-map-frame f (rest coll) (list) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "map" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-map-indexed
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list 0 (first coll)) env (list)
|
||||
(kont-push (make-map-indexed-frame f (rest coll) (list) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "map-indexed" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-filter
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value (list) env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-filter-frame f (rest coll) (list) (first coll) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "filter" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-reduce
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(init (trampoline (eval-expr (nth args 1) env)))
|
||||
(coll (trampoline (eval-expr (nth args 2) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value init env kont)
|
||||
(continue-with-call f (list init (first coll)) env (list)
|
||||
(kont-push (make-reduce-frame f (rest coll) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "reduce" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-some
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value false env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-some-frame f (rest coll) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "some" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-every
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value true env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-every-frame f (rest coll) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "every" (rest args) (list) env) kont))))
|
||||
|
||||
(define step-ho-for-each
|
||||
(fn (args env kont)
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(if (empty? coll)
|
||||
(make-cek-value nil env kont)
|
||||
(continue-with-call f (list (first coll)) env (list)
|
||||
(kont-push (make-for-each-frame f (rest coll) env) kont))))))
|
||||
(make-cek-state (first args) env
|
||||
(kont-push (make-ho-setup-frame "for-each" (rest args) (list) env) kont))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -1908,6 +1948,22 @@
|
||||
fenv)
|
||||
rest-k))))))
|
||||
|
||||
;; --- HoSetupFrame: evaluating HO form arguments ---
|
||||
(= ft "ho-setup")
|
||||
(let ((ho-type (get frame "ho-type"))
|
||||
(remaining (get frame "remaining"))
|
||||
(evaled (append (get frame "evaled") (list value)))
|
||||
(fenv (get frame "env")))
|
||||
(if (empty? remaining)
|
||||
;; All args evaluated — dispatch to iteration
|
||||
(ho-setup-dispatch ho-type evaled fenv rest-k)
|
||||
;; More args to evaluate
|
||||
(make-cek-state
|
||||
(first remaining) fenv
|
||||
(kont-push
|
||||
(make-ho-setup-frame ho-type (rest remaining) evaled fenv)
|
||||
rest-k))))
|
||||
|
||||
;; --- ResetFrame: body evaluated normally (no shift) ---
|
||||
(= ft "reset")
|
||||
(make-cek-value value env rest-k)
|
||||
|
||||
Reference in New Issue
Block a user