Skip to content

Commit 736fe48

Browse files
committed
Merge remote-tracking branch 'willow/compromise-interface' into compromise-interface
2 parents 82ed37c + b00af4d commit 736fe48

File tree

3 files changed

+48
-49
lines changed

3 files changed

+48
-49
lines changed

README.md

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,62 +9,69 @@ You should define the following methods for an expression tree type `T` with sym
99
with TermInterface.jl, and therefore with [SymbolicUtils.jl](https://github.com/JuliaSymbolics/SymbolicUtils.jl)
1010
and [Metatheory.jl](https://github.com/0x0f0f0f/Metatheory.jl).
1111

12-
#### `istree(x::T)` or `istree(x::Type{T})`
12+
#### `isexpr(x::T)`
1313

14-
Check if `x` represents an expression tree. If returns true,
15-
it will be assumed that `operation(::T)` and `arguments(::T)`
16-
methods are defined. Definining these three should allow use
17-
of `SymbolicUtils.simplify` on custom types. Optionally `symtype(x)` can be
18-
defined to return the expected type of the symbolic expression.
14+
Returns `true` if `x` is an expression tree (an S-expression). If true, `head`
15+
and `children` methods must be defined for `x`.
1916

17+
#### `iscall(x::T)`
2018

21-
#### `exprhead(x)`
19+
Returns `true` if `x` is a function call expression. If true, `operation`, `arguments` must also be defined for `x::T`.
2220

23-
If `x` is a term as defined by `istree(x)`, `exprhead(x)` must return a symbol,
24-
corresponding to the head of the `Expr` most similar to the term `x`.
25-
If `x` represents a function call, for example, the `exprhead` is `:call`.
26-
If `x` represents an indexing operation, such as `arr[i]`, then `exprhead` is `:ref`.
27-
Note that `exprhead` is different from `operation` and both functions should
28-
be defined correctly in order to let other packages provide code generation
29-
and pattern matching features.
3021

31-
#### `operation(x::T)`
22+
#### `head(x)`
3223

33-
Returns the head (a function object) performed by an expression
34-
tree. Called only if `istree(::T)` is true. Part of the API required
35-
for `simplify` to work. Other required methods are `arguments` and `istree`
24+
Returns the head of the S-expression.
3625

37-
#### `arguments(x::T)`
26+
#### `children(x)`
3827

39-
Returns the arguments (a `Vector`) for an expression tree.
40-
Called only if `istree(x)` is `true`. Part of the API required
41-
for `simplify` to work. Other required methods are `operation` and `istree`
28+
Returns the children (aka tail) of the S-expression.
4229

43-
In addition, the methods for `Base.hash` and `Base.isequal` should also be implemented by the types for the purposes of substitution and equality matching respectively.
4430

45-
#### `similarterm(t::MyType, f, args, symtype=T; metadata=nothing, exprhead=exprhead(t))`
31+
#### `operation(x)`
4632

47-
Or `similarterm(t::Type{MyType}, f, args, symtype=T; metadata=nothing, exprhead=:call)`.
33+
Returns the function a function call expression is calling. `iscall(x)` must be
34+
true as a precondition.
4835

49-
Construct a new term with the operation `f` and arguments `args`, the term should be similar to `t` in type. if `t` is a `SymbolicUtils.Term` object a new Term is created with the same symtype as `t`. If not, the result is computed as `f(args...)`. Defining this method for your term type will reduce any performance loss in performing `f(args...)` (esp. the splatting, and redundant type computation). T is the symtype of the output term. You can use `SymbolicUtils.promote_symtype` to infer this type. The `exprhead` keyword argument is useful when creating `Expr`s.
36+
#### `arguments(x)`
37+
38+
Returns the arguments to the function call in a function call expression.
39+
`iscall(x)` must be true as a precondition.
40+
41+
#### `maketerm(T, head, children, type=nothing, metadata=nothing)`
42+
43+
Constructs an expression. `T` is a constructor type, `head` and `children` are
44+
the head and tail of the S-expression, `type` is the `type` of the S-expression.
45+
`metadata` is any metadata attached to this expression.
46+
47+
Note that `maketerm` may not necessarily return an object of type `T`. For example,
48+
it may return a representation which is more efficient.
49+
50+
This function is used by term-manipulation routines to construct terms generically.
51+
In these routines, `T` is usually the type of the input expression which is being manipulated.
52+
For example, when a subexpression is substituted, the outer expression is re-constructed with
53+
the sub-expression. `T` will be the type of the outer expression.
54+
55+
Packages providing expression types _must_ implement this method for each expression type.
56+
57+
If your types do not support type information or metadata, you still need to accept
58+
these arguments and may choose to not use them.
5059

5160
### Optional
5261

53-
#### `unsorted_arguments(x)`
62+
#### `arity(x)`
63+
64+
When `x` satisfies `iscall`, returns the number of arguments of `x`.
65+
Implicitly defined if `arguments(x)` is defined.
5466

55-
If x is a term satisfying `istree(x)` and your term type `T` provides
56-
an optimized implementation for storing the arguments, this function can
57-
be used to retrieve the arguments when the order of arguments does not matter
58-
but the speed of the operation does. Defaults to `arguments(x)`.
5967

60-
#### `symtype(x)`
68+
#### `metadata(x)`
6169

62-
The supposed type of values in the domain of x. Tracing tools can use this type to
63-
pick the right method to run or analyse code.
70+
Returns the metadata attached to `x`.
6471

65-
This defaults to `typeof(x)` if `x` is numeric, or `Any` otherwise.
66-
For the types defined in this SymbolicUtils.jl, namely `T<:Symbolic{S}` it is `S`.
72+
#### `symtype(expr)`
6773

74+
Returns the symbolic type of `expr`. By default this is just `typeof(expr)`.
6875
Define this for your symbolic types if you want `SymbolicUtils.simplify` to apply rules
6976
specific to numbers (such as commutativity of multiplication). Or such
7077
rules that may be implemented in the future.

src/TermInterface.jl

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@ must also be defined for `x`.
88
iscall(x) = false
99
export iscall
1010

11-
Base.@deprecate_binding istree iscall
12-
"""
13-
istree(x)
14-
15-
Alias of `iscall`
16-
"""
17-
istree
18-
1911
"""
2012
isexpr(x)
2113
Returns `true` if `x` is an expression tree (an S-expression). If true, `head` and `children` methods must be defined for `x`.
@@ -119,7 +111,7 @@ end
119111

120112

121113
"""
122-
maketerm(T, head, children, type, metadata)
114+
maketerm(T, head, children, type=nothing, metadata=nothing)
123115
124116
Constructs an expression. `T` is a constructor type, `head` and `children` are
125117
the head and tail of the S-expression, `type` is the `type` of the S-expression.

src/utils.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
is_operation(f)
33
44
Returns a single argument anonymous function predicate, that returns `true` if and only if
5-
the argument to the predicate satisfies `istree` and `operation(x) == f`
5+
the argument to the predicate satisfies `iscall` and `operation(x) == f`
66
"""
7-
is_operation(f) = @nospecialize(x) -> istree(x) && (operation(x) == f)
7+
is_operation(f) = @nospecialize(x) -> iscall(x) && (operation(x) == f)
88
export is_operation
99

1010

1111
"""
1212
node_count(t)
13-
Count the nodes in a symbolic expression tree satisfying `istree` and `arguments`.
13+
Count the nodes in a symbolic expression tree satisfying `isexpr` and `arguments`.
1414
"""
15-
node_count(t) = istree(t) ? reduce(+, node_count(x) for x in arguments(t), init = 0) + 1 : 1
15+
node_count(t) = isexpr(t) ? reduce(+, node_count(x) for x in children(t); init=0) + 1 : 1
1616
export node_count

0 commit comments

Comments
 (0)