6
6
# 3. Callback: takes arguments Dictionary × Number of elements matched
7
7
#
8
8
9
- function matcher (val:: Any )
9
+ function matcher (val:: Any ; acSets = nothing )
10
10
# if val is a call (like an operation) creates a term matcher or term matcher with defslot
11
11
if iscall (val)
12
12
# if has two arguments and one of them is a DefSlot, create a term matcher with defslot
13
13
# just two arguments bc defslot is only supported with operations with two args: *, ^, +
14
14
if any (x -> isa (x, DefSlot), arguments (val))
15
- return defslot_term_matcher_constructor (val)
15
+ return defslot_term_matcher_constructor (val, acSets )
16
16
end
17
17
# else return a normal term matcher
18
- return term_matcher_constructor (val)
18
+ return term_matcher_constructor (val, acSets )
19
19
end
20
20
21
21
function literal_matcher (next, data, bindings)
@@ -24,7 +24,8 @@ function matcher(val::Any)
24
24
end
25
25
end
26
26
27
- function matcher (slot:: Slot )
27
+ # acSets is not used but needs to be there in case matcher(::Slot) is directly called from the macro
28
+ function matcher (slot:: Slot ; acSets = nothing )
28
29
function slot_matcher (next, data, bindings)
29
30
! islist (data) && return nothing
30
31
val = get (bindings, slot. name, nothing )
43
44
# this is called only when defslot_term_matcher finds the operation and tries
44
45
# to match it, so no default value used. So the same function as slot_matcher
45
46
# can be used
46
- function matcher (defslot:: DefSlot )
47
+ function matcher (defslot:: DefSlot ; acSets = nothing )
47
48
matcher (Slot (defslot. name, defslot. predicate))
48
49
end
49
50
@@ -59,7 +60,7 @@ function opposite_sign_matcher(slot::Slot)
59
60
return next (bindings, 1 )
60
61
end
61
62
elseif slot. predicate (car (data))
62
- next (assoc (bindings, slot. name, - car (data)), 1 ) # this - is the only differenct wrt matcher(slot::Slot)
63
+ next (assoc (bindings, slot. name, - car (data)), 1 ) # this - is the only difference wrt matcher(slot::Slot)
63
64
end
64
65
end
65
66
end
@@ -96,7 +97,7 @@ function trymatchexpr(data, value, n)
96
97
end
97
98
end
98
99
99
- function matcher (segment:: Segment )
100
+ function matcher (segment:: Segment ; acSets = nothing )
100
101
function segment_matcher (success, data, bindings)
101
102
val = get (bindings, segment. name, nothing )
102
103
@@ -124,8 +125,8 @@ function matcher(segment::Segment)
124
125
end
125
126
end
126
127
127
- function term_matcher_constructor (term)
128
- matchers = (matcher (operation (term)), map (matcher, arguments (term))... ,)
128
+ function term_matcher_constructor (term, acSets )
129
+ matchers = (matcher (operation (term); acSets = acSets ), map (x -> matcher (x;acSets = acSets) , arguments (term))... ,)
129
130
130
131
function loop (term, bindings′, matchers′) # Get it to compile faster
131
132
if ! islist (matchers′)
@@ -137,7 +138,7 @@ function term_matcher_constructor(term)
137
138
car (matchers′)(term, bindings′) do b, n
138
139
loop (drop_n (term, n), b, cdr (matchers′))
139
140
end
140
- # explenation of above 3 lines:
141
+ # explanation of above 3 lines:
141
142
# car(matchers′)(b,n -> loop(drop_n(term, n), b, cdr(matchers′)), term, bindings′)
142
143
# <------ next(b,n) ---------------------------->
143
144
# car = first element of list, cdr = rest of the list, drop_n = drop first n elements of list
@@ -171,7 +172,7 @@ function term_matcher_constructor(term)
171
172
frankestein = arguments (denominator)[1 ] ^ - (arguments (denominator)[2 ])
172
173
result = loop (frankestein, bindings, matchers)
173
174
# if b is a number, like 3, we cant call loop with a^-3 bc it
174
- # will automatically transform into 1/a^3. Therfore we need to
175
+ # will automatically transform into 1/a^3. Therefore we need to
175
176
# create a matcher that flips the sign of the exponent. I created
176
177
# this matecher just for `Slot`s and `DefSlot`s, but not for
177
178
# terms or literals, because if b is a number and not a call,
@@ -181,21 +182,27 @@ function term_matcher_constructor(term)
181
182
result = loop (denominator, bindings, matchers_modified)
182
183
end
183
184
end
184
- if result != = nothing
185
- return success (result, 1 )
186
- end
185
+ result != = nothing && return success (result, 1 )
186
+ return nothing
187
187
end
188
188
return term_matcher_pow
189
189
# if the operation is commutative
190
- elseif operation (term) in [+ , * ]
190
+ elseif acSets != = nothing && ! isa ( arguments (term)[ 1 ], Segment) && operation (term) in [+ , * ]
191
191
function term_matcher_comm (success, data, bindings)
192
192
! islist (data) && return nothing # if data is not a list, return nothing
193
193
! iscall (car (data)) && return nothing # if first element is not a call, return nothing
194
194
195
- for m in all_matchers
196
- result = loop (car (data), bindings, m)
197
- result != = nothing && return success (result, 1 )
195
+ T = symtype (car (data))
196
+ f = operation (car (data))
197
+ data_args = arguments (car (data))
198
+
199
+ for inds in acSets (eachindex (data_args), length (arguments (term)))
200
+ candidate = Term {T} (f, @views data_args[inds])
201
+
202
+ result = loop (candidate, bindings, matchers)
203
+ result != = nothing && length (data_args) == length (inds) && return success (result,1 )
198
204
end
205
+ return nothing
199
206
end
200
207
return term_matcher_comm
201
208
else
@@ -204,9 +211,8 @@ function term_matcher_constructor(term)
204
211
! iscall (car (data)) && return nothing # if first element is not a call, return nothing
205
212
206
213
result = loop (car (data), bindings, matchers)
207
- if result != = nothing
208
- return success (result, 1 )
209
- end
214
+ result != = nothing && return success (result, 1 )
215
+ return nothing
210
216
end
211
217
return term_matcher
212
218
end
@@ -215,35 +221,31 @@ end
215
221
# creates a matcher for a term containing a defslot, such as:
216
222
# (~x + ...complicated pattern...) * ~!y
217
223
# normal part (can bee a tree) operation defslot part
218
- function defslot_term_matcher_constructor (term)
224
+ function defslot_term_matcher_constructor (term, acSets )
219
225
a = arguments (term)
220
226
defslot_index = findfirst (x -> isa (x, DefSlot), a) # find the defslot in the term
221
227
defslot = a[defslot_index]
222
228
if length (a) == 2
223
- other_part_matcher = matcher (a[defslot_index == 1 ? 2 : 1 ])
229
+ other_part_matcher = matcher (a[defslot_index == 1 ? 2 : 1 ]; acSets = acSets )
224
230
else
225
231
others = [a[i] for i in eachindex (a) if i != defslot_index]
226
232
T = symtype (term)
227
233
f = operation (term)
228
- other_part_matcher = term_matcher_constructor (Term {T} (f, others))
234
+ other_part_matcher = term_matcher_constructor (Term {T} (f, others), acSets )
229
235
end
230
236
231
- normal_matcher = term_matcher_constructor (term)
237
+ normal_matcher = term_matcher_constructor (term, acSets )
232
238
233
239
function defslot_term_matcher (success, data, bindings)
234
240
! islist (data) && return nothing # if data is not a list, return nothing
235
241
result = normal_matcher (success, data, bindings)
236
242
result != = nothing && return result
237
- # if no match, try to match with a defslot
238
- # if data (is not a tree and is just a symbol) or (is a tree not starting with the default operation)
239
-
240
- # checks wether it matches the normal part if yes executes (foo)
243
+ # if no match, try to match with a defslot.
244
+ # checks whether it matches the normal part if yes executes (foo)
241
245
# (foo): adds the pair (default value name, default value) to the found bindings
242
246
# <------------------(foo)---------------------------->
243
247
result = other_part_matcher ((b,n) -> assoc (b, defslot. name, defslot. defaultValue), data, bindings)
244
- println (result)
245
248
result != = nothing && return success (result, 1 )
246
-
247
249
nothing
248
250
end
249
251
end
0 commit comments