(schedule passes & [opts])
Takes a set of Vars that represent tools.analyzer passes and returns a function
that takes an AST and applies all the passes and their dependencies to the AST,
trying to compose together as many passes as possible to reduce the number of
full tree traversals.
Each pass must have a :pass-info element in its Var's metadata and it must point
to a map with the following parameters (:before, :after, :affects and :state are
optional):
* :after a set of Vars, the passes that must be run before this pass
* :before a set of Vars, the passes that must be run after this pass
* :depends a set of Vars, the passes this pass depends on, implies :after
* :walk a keyword, one of:
- :none if the pass does its own tree walking and cannot be composed
with other passes
- :post if the pass requires a postwalk and can be composed with other
passes
- :pre if the pass requires a prewalk and can be composed with other
passes
- :any if the pass can be composed with other passes in both a prewalk
or a postwalk
* :affects a set of Vars, this pass must be the last in the same tree traversal that all
the specified passes must partecipate in
This pass must take a function as argument and return the actual pass, the
argument represents the reified tree traversal which the pass can use to
control a recursive traversal, implies :depends
* :state a no-arg function that should return an atom holding an init value that will be
passed as the first argument to the pass (the pass will thus take the ast
as the second parameter), the atom will be the same for the whole tree traversal
and thus can be used to preserve state across the traversal
An opts map might be provided, valid parameters:
* :debug? if true, returns a vector of the scheduled passes rather than the concrete
function
Source
(defn schedule
"Takes a set of Vars that represent tools.analyzer passes and returns a function
that takes an AST and applies all the passes and their dependencies to the AST,
trying to compose together as many passes as possible to reduce the number of
full tree traversals.
Each pass must have a :pass-info element in its Var's metadata and it must point
to a map with the following parameters (:before, :after, :affects and :state are
optional):
* :after a set of Vars, the passes that must be run before this pass
* :before a set of Vars, the passes that must be run after this pass
* :depends a set of Vars, the passes this pass depends on, implies :after
* :walk a keyword, one of:
- :none if the pass does its own tree walking and cannot be composed
with other passes
- :post if the pass requires a postwalk and can be composed with other
passes
- :pre if the pass requires a prewalk and can be composed with other
passes
- :any if the pass can be composed with other passes in both a prewalk
or a postwalk
* :affects a set of Vars, this pass must be the last in the same tree traversal that all
the specified passes must partecipate in
This pass must take a function as argument and return the actual pass, the
argument represents the reified tree traversal which the pass can use to
control a recursive traversal, implies :depends
* :state a no-arg function that should return an atom holding an init value that will be
passed as the first argument to the pass (the pass will thus take the ast
as the second parameter), the atom will be the same for the whole tree traversal
and thus can be used to preserve state across the traversal
An opts map might be provided, valid parameters:
* :debug? if true, returns a vector of the scheduled passes rather than the concrete
function"
[passes & [opts]]
{:pre [(set? passes)
(every? var? passes)]}
(let [info (indicize (mapv (fn [p] (merge {:name p} (:pass-info (meta p)))) passes))
passes+deps (into passes (mapcat :depends (vals info)))]
(if (not= passes passes+deps)
(recur passes+deps [opts])
(if (:debug? opts)
(mapv #(select-keys % [:passes :walk])
(schedule-passes info))
(reduce (fn [f {:keys [passes walk]}]
(let [pass (if (= walk :none)
(first passes)
(compile-passes passes (if (= :pre walk) prewalk postwalk) info))]
(comp pass f)))
identity (schedule-passes info))))))