@@ -11,8 +11,38 @@ and [Metatheory.jl](https://github.com/0x0f0f0f/Metatheory.jl).
1111
1212#### ` isexpr(x::T) `
1313
14- Returns ` true ` if ` x ` is an expression tree (an S-expression). If true, ` head `
15- and ` children ` methods must be defined for ` x ` .
14+ Returns ` true ` if ` x ` is an expression tree. If true, ` head(x) ` and ` children(x) ` methods must be defined for ` x ` .
15+ Optionally, if ` x ` represents a function call, ` iscall(x) ` should be true, and ` operation(x) ` and ` arguments(x) ` should also be defined.
16+
17+ #### ` iscall(x::T) `
18+
19+ Returns ` true ` if ` x ` is a function call expression. If true, ` operation(x) ` , ` arguments(x) `
20+ must also be defined for ` x ` .
21+
22+ If ` iscall(x) ` is true, then also ` isexpr(x) ` * must* be true. The other way around is not true.
23+ (A function call is always an expression node, but not every expression tree represents a function call).
24+
25+ This means that, ` head(x) ` and ` children(x) ` must be defined. Together
26+ with ` operation(x) ` and ` arguments(x) ` .
27+
28+ ** Examples:**
29+
30+ In a functional language, all expression trees are function calls (e.g. SymbolicUtils.jl).
31+ Let's say that you have an hybrid array and functional language. ` iscall ` on the expression ` v[i] `
32+ is ` false ` , and ` iscall ` on expression ` f(x) ` is ` true ` , but both of them are nested
33+ expressions, and ` isexpr ` is ` true ` on both.
34+
35+ The same goes for Julia ` Expr ` . An ` Expr(:block, ...) ` is * not a function call*
36+ and has no ` operation ` and ` arguments ` , but has a ` head ` and ` children ` .
37+
38+
39+ The distinction between ` head ` /` children ` and ` operation ` /` arguments ` is needed
40+ when dealing with languages that are * not representing function call operations as their head* .
41+ The main example is ` Expr(:call, :f, :x) ` : it has both a ` head ` and an ` operation ` , which are
42+ respectively ` :call ` and ` :f ` .
43+
44+ In other symbolic expression languages, such as SymbolicUtils.jl, the ` head ` of a node
45+ can correspond to ` operation ` and ` children ` can correspond to ` arguments ` .
1646
1747#### ` head(x) `
1848
@@ -22,6 +52,16 @@ Returns the head of the S-expression.
2252
2353Returns the children (aka tail) of the S-expression.
2454
55+ #### ` operation(x) `
56+
57+ Returns the function a function call expression is calling. ` iscall(x) ` must be
58+ true as a precondition.
59+
60+ #### ` arguments(x) `
61+
62+ Returns the arguments to the function call in a function call expression.
63+ ` iscall(x) ` must be true as a precondition.
64+
2565#### ` maketerm(T, head, children, type=nothing, metadata=nothing) `
2666
2767Constructs an expression. ` T ` is a constructor type, ` head ` and ` children ` are
@@ -41,19 +81,6 @@ Packages providing expression types _must_ implement this method for each expres
4181If your types do not support type information or metadata, you still need to accept
4282these arguments and may choose to not use them.
4383
44- #### ` iscall(x::T) `
45-
46- Returns ` true ` if ` x ` is a function call expression. If true, ` operation ` , ` arguments ` must also be defined for ` x::T ` .
47-
48- #### ` operation(x) `
49-
50- Returns the function a function call expression is calling. ` iscall(x) ` must be
51- true as a precondition.
52-
53- #### ` arguments(x) `
54-
55- Returns the arguments to the function call in a function call expression.
56- ` iscall(x) ` must be true as a precondition.
5784
5885### Optional
5986
@@ -67,11 +94,34 @@ Implicitly defined if `arguments(x)` is defined.
6794
6895Returns the metadata attached to ` x ` .
6996
70- #### ` symtype(expr) `
97+ #### ` metadata(expr, md) `
98+
99+ Returns ` expr ` with metadata ` md ` attached to it.
100+
101+ ## Examples
102+
103+ ### Function call Julia Expressions
104+
105+ ``` julia
106+ ex = :(f (a, b))
107+ @test head (ex) == :call
108+ @test children (ex) == [:f , :a , :b ]
109+ @test operation (ex) == :f
110+ @test arguments (ex) == [:a , :b ]
111+ @test isexpr (ex)
112+ @test iscall (ex)
113+ @test ex == maketerm (Expr, :call , [:f , :a , :b ], nothing )
114+ ```
115+
71116
72- Returns the symbolic type of ` expr ` . By default this is just ` typeof(expr) ` .
73- Define this for your symbolic types if you want ` SymbolicUtils.simplify ` to apply rules
74- specific to numbers (such as commutativity of multiplication). Or such
75- rules that may be implemented in the future.
117+ ### Non-function call Julia Expressions
76118
77- <!-- TODO update examples -->
119+ ``` julia
120+ ex = :(arr[i, j])
121+ @test head (ex) == :ref
122+ @test_throws ErrorException operation (ex)
123+ @test_throws ErrorException arguments (ex)
124+ @test isexpr (ex)
125+ @test ! iscall (ex)
126+ @test ex == maketerm (Expr, :ref , [:arr , :i , :j ], nothing )
127+ ```
0 commit comments