This is error-kit's dynamic scope form. The body will be executed
in a dynamic context that includes all of the following 'handle' and
'bind-continue' forms.
(defmacro with-handler
"This is error-kit's dynamic scope form. The body will be executed
in a dynamic context that includes all of the following 'handle' and
'bind-continue' forms."
[& forms]
(let [[body special-forms] (split-with (complement special-form) forms)]
(assert (every? special-form special-forms))
(let [blockid (gensym)
handlers (for [[type & more] special-forms
:when (= (resolve type) #'handle)]
(let [[htag args & hbody] (if (symbol? (first more))
more
(cons nil more))
argmap (if (vector? args) `{:keys ~args} args)]
`{:blockid '~blockid
:htag ~(when htag (list `quote (qualify-sym htag)))
:hfunc (fn [~argmap] ~@hbody)
:rfunc identity}))
continues (into {}
(for [[type & more] special-forms
:when (= (resolve type) #'bind-continue)]
[(list `quote (first more))
`{:blockid '~blockid
:rfunc (fn ~@(next more))}]))]
`(try
(binding [*handler-stack* (list* ~@handlers @#'*handler-stack*)
*continues* (merge @#'*continues* ~@continues)]
~@body)
(catch Throwable e#
(let [root-cause# (root-cause e#)]
(if-not (instance? @#'ctrl-exception-class root-cause#)
(throw e#)
(let [data# @root-cause#]
(if (= '~blockid (:blockid data#))
(apply (:rfunc data#) (:args data#))
(throw e#))))))))))
Comments top
No comments for with-handler. Log in to add a comment.