A fix for this is to replace the two recur s with recursive calls to terms. When recur is present, core.match generates code which ensures the recur is in tail position. However, the amount of code generated is much larger than code without recur (which uses a backtrack exception to handle non-matches).
The following function fails to compile. If I change the row
[:context _ _] formula
to
[:context _] formula
it works.
(defn terms [formula]
(match formula
[:root r] (recur r)
[:expr e] (recur e)
[:call f [:args & args]] (for [arg args] (terms arg))
[:refer _ _] formula
[:float _] formula
[:context _ _] formula
[:string _] formula
[:eq e1 _ e2] (concat (terms e1) (terms e2))
[:add & args ] (for [arg args] (terms arg))
[:sub & args ] (for [arg args] (terms arg))
[:div & args ] (for [arg args] (terms arg))
[:mul & args ] (for [arg args] (terms arg))
))