(-add-env-args rule-list env-args)
(combine-rules dialects form-rules)
Combine a collection of rule combinators which each handle inputs tagged with a specific type and create an [[on-mutual]] rule for them.
form-rules
is map of group-type
to rule-fn
, or may be a flat list of
pairs in the typical Clojure style.
Each group-type
is one of the arrow expressions =>
==>
===>
. For
example (=> FromForm ToForm)
. Arrow length is used to decide which forms
are used for the entry expression. If any long ===>
arrows are present, they
will be tried unconditionally of expression type. If they do not match, or if
there are no long arrows, then if any medium ==>
arrows are present, they
will be tried, but respecting their input type. If any long or medium arrows
are present, short =>
arrows are not tried. If there are only short arrows,
then they are all treated like medium arrows.
Combine a collection of rule combinators which each handle inputs tagged with a specific type and create an [[on-mutual]] rule for them. `form-rules` is map of `group-type` to `rule-fn`, or may be a flat list of pairs in the typical Clojure style. Each `group-type` is one of the arrow expressions `=>` `==>` `===>`. For example `(=> FromForm ToForm)`. Arrow length is used to decide which forms are used for the entry expression. If any long `===>` arrows are present, they will be tried unconditionally of expression type. If they do not match, or if there are no long arrows, then if any medium `==>` arrows are present, they will be tried, but respecting their input type. If any long or medium arrows are present, short `=>` arrows are not tried. If there are only short arrows, then they are all treated like medium arrows.
(defpass name dialects compiled & fn-tail)
Define a pass with the given name and dialects. Use
(=> FromDialect ToDialect)
to specify the dialect pair.
This may be used either as a simple pass definition with no function body defined, in
which case it will define name
to be the value of the compiled
argument, which may
be a rule, let-rulefn
, or any other expression.
Alternately, if a fn-tail is defined then the compiled
expression must contain <>
exactly once in the location you want the function definition to be inserted. The
point of this exercise is to allow the rule functions to be precompiled while
still allowing a clear syntax for defining a pass.
Example usage:
(defpass naive-cps (=> LambdaCalc CPS)
(let-rulefn [(M (=> Expr MExpr)
[(rule '(fn [?var] ?expr)
(let [k (gensym 'k)]
(sub (fn [?var ?k] ~(T expr k)))))
(rule '(? s symbol?) s)])
(T* (=> Expr TExpr) [cont]
[(rule '(?:as expr (fn ??_))
`(~cont ~(M expr)))
(rule '(? s symbol?)
`(~cont ~(M s)))
(rule '(?f ?e)
(let [fs (gensym 'f)
es (gensym 'e)]
(T f (sub (fn [?fs]
~(T e (sub (fn [?es]
(?fs ?es ?cont)))))))))])
(fn T [expr cont]
(first (T* expr {:cont cont})))]
<>)
[expr cont]
(T expr cont))
(naive-cps '(g a) ''halt)
;; => ((fn [f48299] ((fn [e48300] (f48299 e48300 (quote halt))) a)) g)
In the above example, M
is a simple rule, but T*
uses its env to get the
value of cont
. The [cont]
clause in the T* definition causes the rule
handler to be wrapped in (let [cont (:cont %env)] ...).
At the end of the definition, the [expr cont] (T expr cont)
expression gets
wrapped with (defn naive-cps ...)
, and the defn is placed at the point
indicated by <>
.
LambdaCalc and CPS are the dialects being transformed between. Expr is a form in LambdaCalc and MExpr and TExpr are forms in CPS.
Define a pass with the given name and dialects. Use `(=> FromDialect ToDialect)` to specify the dialect pair. This may be used either as a simple pass definition with no function body defined, in which case it will define `name` to be the value of the `compiled` argument, which may be a rule, [[let-rulefn]], or any other expression. Alternately, if a fn-tail is defined then the `compiled` expression must contain `<>` exactly once in the location you want the function definition to be inserted. The point of this exercise is to allow the rule functions to be precompiled while still allowing a clear syntax for defining a pass. Example usage: (defpass naive-cps (=> LambdaCalc CPS) (let-rulefn [(M (=> Expr MExpr) [(rule '(fn [?var] ?expr) (let [k (gensym 'k)] (sub (fn [?var ?k] ~(T expr k))))) (rule '(? s symbol?) s)]) (T* (=> Expr TExpr) [cont] [(rule '(?:as expr (fn ??_)) `(~cont ~(M expr))) (rule '(? s symbol?) `(~cont ~(M s))) (rule '(?f ?e) (let [fs (gensym 'f) es (gensym 'e)] (T f (sub (fn [?fs] ~(T e (sub (fn [?es] (?fs ?es ?cont)))))))))]) (fn T [expr cont] (first (T* expr {:cont cont})))] <>) [expr cont] (T expr cont)) (naive-cps '(g a) ''halt) ;; => ((fn [f48299] ((fn [e48300] (f48299 e48300 (quote halt))) a)) g) In the above example, `M` is a simple rule, but `T*` uses its env to get the value of `cont`. The `[cont]` clause in the T* definition causes the rule handler to be wrapped in (let [cont (:cont %env)] ...). At the end of the definition, the `[expr cont] (T expr cont)` expression gets wrapped with `(defn naive-cps ...)`, and the defn is placed at the point indicated by `<>`. LambdaCalc and CPS are the dialects being transformed between. Expr is a form in LambdaCalc and MExpr and TExpr are forms in CPS.
(dialectify dialects expr)
Used by defpass to rewrite let-rulefn to use its dialects
Used by defpass to rewrite let-rulefn to use its dialects
(get-form dialect form-name)
(insert-defn compiled name fn-tail)
Used by defpass to replace <> with the pass entry function
Used by defpass to replace <> with the pass entry function
(let-rulefn rulefns & body)
This does a simple transformation to allow all of the rules in rule-fns to
refer to each other. Each rule list is made [[directed]], and all of the rule
lists are assembled into an [[on-mutual]] set of rules via combine-rules
.
The combined ruleset is bound to %pass
.
If no body expressions are provided, this will return %pass
, otherwise it
will return the value of the last expression in the body.
When used inside defpass
, this call is rewritten to use let-rulefn*
with
the dialect pair specified in the pass. If you don't want this behaviour, use
let-rulefn*
directly with nil for the dialects argument.
This does a simple transformation to allow all of the rules in rule-fns to refer to each other. Each rule list is made [[directed]], and all of the rule lists are assembled into an [[on-mutual]] set of rules via [[combine-rules]]. The combined ruleset is bound to `%pass`. If no body expressions are provided, this will return `%pass`, otherwise it will return the value of the last expression in the body. When used inside [[defpass]], this call is rewritten to use [[let-rulefn*]] with the dialect pair specified in the pass. If you don't want this behaviour, use [[let-rulefn*]] directly with nil for the dialects argument.
(let-rulefn* dialects rulefns & body)
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close