Skip to content

Instantly share code, notes, and snippets.

@refset
Last active January 9, 2022 15:10
Show Gist options
  • Save refset/a03c026d56baeb61e1657215d5926ec3 to your computer and use it in GitHub Desktop.
Save refset/a03c026d56baeb61e1657215d5926ec3 to your computer and use it in GitHub Desktop.
visit.clj
(defn visit [m visitors]
;; [node node-s next-s down-s right-s get-right get-down init-right-s cut-down cut-right :as m]
;; {:keys [break]} next-s
;; ;use next-state by default, unless down or right is necessary
(let
[dovisit (fn [m dir]
(loop [s m [v & vs] visitors]
(if v (recur (apply v (concat [dir] s)) vs) s)))
m2 (dovisit m :pre)
;break/cut checks should be between each visitor (:pre :post and :in) according to zip-visit
;https://github.com/akhudek/zip-visit/blob/master/src/zip/visit.cljc#L5
;(if (or b c)
; {:node node* :state state* :break b :cut c}
m3
(let [[node* _ next-s* _ _ _ get-down* init-right-s* cut-down _] m2]
(if-let [down* (and (not cut-down)
(not (:break next-s*))
(get-down* node*))]
(assoc m2 2 (nth
(visit
(assoc m2
0 down*
1 nil
4 init-right-s*)
visitors) 2)
8 false)
(assoc m2 8 false)))
m4 (dovisit m3 :mid)
m5
(let [[_ _ _ down-s _ _ _ _ _ _] m
[node* _ next-s* _ _ get-right* _ _ _ cut-right] m3]
(if-let [right* (and (not cut-right)
(not (:break next-s*))
(get-right* node*))]
(let [mm
(visit
(assoc m4
0 right*
1 nil
3 down-s)
visitors)]
(assoc m4 2 (nth mm 2)
9 false))
(assoc m4 9 false)))
m6 (dovisit m5 :post)]
m6
;:in (needs get-up, such that an :in visitor can't replace the node), :in happens after post, it's about operations in the context of the parent between each child
))
;; probably can be made either non-recursive or loop/recur using zippers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment