(-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 builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |