Skip to content

Commit 16d3143

Browse files
authored
Merge pull request #73 from JuliaSymbolics/s/doc-ctx
Document "contexts"
2 parents 005d32d + a49ed2a commit 16d3143

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

src/matchers.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ Base.show(io::IO, s::Segment) = (print(io, "~~"); print(io, s.name))
2929
makesegment(s::Symbol, keys) = (push!(keys, s); Segment(s))
3030

3131
"""
32-
A wrapper for slot and segment predicates which allows them to
33-
take two arguments: the value and a Context
32+
A wrapper indicating that the function inside must be called with
33+
2 arguments. An expression, and the current context.
3434
"""
3535
struct Contextual{F}
3636
f::F

src/rule_dsl.jl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function (r::Rule)(term, ctx=EmptyCtx())
4040
end
4141

4242
"""
43-
`@rule LHS => RHS`
43+
@rule LHS => RHS
4444
4545
Creates a `Rule` object. A rule object is callable, and takes an expression and rewrites
4646
it if it matches the LHS pattern to the RHS pattern, returns `nothing` otherwise.
@@ -141,6 +141,19 @@ sin((a + c))
141141
```
142142
143143
Predicate function gets an array of values if attached to a segment variable (`~~x`).
144+
145+
**Context**:
146+
147+
_In predicates_: Contextual predicates are functions wrapped in the `Contextual` type.
148+
The function is called with 2 arguments: the expression and a context object
149+
passed during a call to the Rule object (maybe done by passing a context to `simplify` or
150+
a `RuleSet` object).
151+
152+
The function can use the inputs however it wants, and must return a boolean indicating
153+
whether the predicate holds or not.
154+
155+
_In the consequent pattern_: Use `(@ctx)` to access the context object on the right hand side
156+
of an expression.
144157
"""
145158
macro rule(expr)
146159
@assert expr.head == :call && expr.args[1] == :(=>)
@@ -206,11 +219,12 @@ end
206219
#### Rulesets
207220

208221
"""
209-
RuleSet(rules::Vector{AbstractRules})(expr; depth=typemax(Int), applyall=false, recurse=true)
222+
RuleSet(rules::Vector{AbstractRules}, context=EmptyCtx())(expr; depth=typemax(Int), applyall=false, recurse=true)
210223
211-
`RuleSet` is an `AbstractRule` which applies the given `rules` throughout an `expr`.
224+
`RuleSet` is an `AbstractRule` which applies the given `rules` throughout an `expr` with the
225+
context `context`.
212226
213-
`RuleSet(rules)(expr)` Note that this only applies the rules in one pass, not until there are no
227+
Note that this only applies the rules in one pass, not until there are no
214228
changes to be applied. Use `SymbolicUtils.fixpoint(ruleset, expr)` to apply a RuleSet until there
215229
are no changes.
216230

src/simplify.jl

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
##### Numeric simplification
22

3-
default_rules(::EmptyCtx) = SIMPLIFY_RULES
43
"""
5-
simplify(x, [rules=SIMPLIFY_RULES]; fixpoint=true, applyall=true, recurse=true)
4+
default_rules(expr, context::T)::RuleSet
65
7-
Apply a `RuleSet` of rules provided in `rules`. By default
8-
these rules are `SymbolicUtils.SIMPLIFY_RULES`. If `fixpoint=true`
9-
repeatedly applies the set of rules until there are no changes.
6+
The `RuleSet` to be used by default for a given expression and the context.
7+
Julia packages defining their own context types should define this method.
8+
9+
By default SymbolicUtils will try to apply appropriate rules for expressions
10+
of symtype Number.
11+
"""
12+
default_rules(x, ctx) = SIMPLIFY_RULES
13+
14+
"""
15+
simplify(x, ctx=EmptyCtx();
16+
rules=default_rules(x, ctx),
17+
fixpoint=true,
18+
applyall=true,
19+
recurse=true)
20+
21+
Simplify an expression by applying `rules` until there are no changes.
22+
The second argument, the context is passed to every [`Contextual`](#Contextual)
23+
predicate and can be accessed as `(@ctx)` in the right hand side of `@rule` expression.
24+
25+
By default the context is an `EmptyCtx()` -- which means there is no contextual information.
26+
Any arbitrary type can be used as a context, and packages defining their own contexts
27+
should define `default_rules(ctx::TheContextType)` to return a `RuleSet` that will
28+
be used by default while simplifying under that context.
29+
30+
If `fixpoint=true` this will repeatedly apply the set of rules until there are no changes.
1031
Applies them once if `fixpoint=false`.
1132
1233
The `applyall` and `recurse` keywords are forwarded to the enclosed
13-
`RuleSet`.
34+
`RuleSet`, they are mainly used for internal optimization.
1435
"""
15-
function simplify(x, ctx=EmptyCtx(); rules=default_rules(ctx), fixpoint=true, applyall=true, recurse=true)
36+
function simplify(x, ctx=EmptyCtx(); rules=default_rules(x, ctx), fixpoint=true, applyall=true, recurse=true)
1637
if fixpoint
1738
SymbolicUtils.fixpoint(rules, x, ctx; recurse=recurse, applyall=recurse)
1839
else

0 commit comments

Comments
 (0)