Skip to content

Commit f594e03

Browse files
committed
fixed bug in defslot functionality
1 parent 3ece18f commit f594e03

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

src/matchers.jl

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,20 @@ end
250250
# creates a matcher for a term containing a defslot, such as:
251251
# (~x + ...complicated pattern...) * ~!y
252252
# normal part (can bee a tree) operation defslot part
253+
254+
# Note: there is a bit of a waste here bc the matcher get created twice, both
255+
# in the normal_matcher and in defslot_matcher and other_part_matcher
253256
function defslot_term_matcher_constructor(term, acSets)
254257
a = arguments(term)
255258
defslot_index = findfirst(x -> isa(x, DefSlot), a) # find the defslot in the term
256259
defslot = a[defslot_index]
260+
defslot_matcher = matcher(defslot, acSets)
257261
if length(a) == 2
258262
other_part_matcher = matcher(a[defslot_index == 1 ? 2 : 1], acSets)
259263
else
264+
# if we hare here the operation is a multiplication or sum of n>2 terms
265+
# (because ^ cannot have more than 2 terms).
266+
# creates the term matcher of the multiplication or sum of n-1 terms
260267
others = [a[i] for i in eachindex(a) if i != defslot_index]
261268
T = symtype(term)
262269
f = operation(term)
@@ -267,15 +274,18 @@ function defslot_term_matcher_constructor(term, acSets)
267274

268275
function defslot_term_matcher(success, data, bindings)
269276
!islist(data) && return nothing # if data is not a list, return nothing
270-
# call the normal matcher, with success function foo1 that simply returns the bindings
271-
# <--foo1-->
272-
result = normal_matcher((b,n) -> b, data, bindings)
277+
# call the normal matcher, with success function that returns the bindings (foo1)
278+
# <-foo1->
279+
result = normal_matcher((b,n)->b, data, bindings)
273280
result !== nothing && return success(result, 1)
274281
# if no match, try to match with a defslot.
275282
# checks whether it matches the normal part if yes executes foo2
276283
# foo2: adds the pair (default value name, default value) to the found bindings
277-
# <-------------------foo2---------------------------->
278-
result = other_part_matcher((b,n) -> assoc(b, defslot.name, defslot.defaultValue), data, bindings)
284+
# after checking predicate and presence in the bindings. If added succesfully
285+
# returns the bindings (foo3), otherwise return nothing
286+
# <-------------------foo2----------------------------------->
287+
# <-foo3->
288+
result = other_part_matcher((b,n)->defslot_matcher((b,n)->b, (defslot.defaultValue,), b), data, bindings)
279289
result !== nothing && return success(result, 1)
280290
nothing
281291
end

test/rewrite.jl

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,20 @@ end
109109
@test r_mixmix(exp(x)*sin(x+x^2)*2) === (2, 0, x)
110110
@test r_mixmix(exp(x)*sin(x+x^2)) === (1, 0, x)
111111

112-
r_predicate = @rule ~x + (~!m::(var->isa(var, Int))) => (~x, ~m)
113-
@test r_predicate(x+2) === (x, 2)
114-
@test r_predicate(x+2.0) !== (x, 2.0)
115-
# Note: r_predicate(x+2.0) doesnt return nothing, but (x+2.0, 0)
116-
# because of the defslot
112+
# predicate checked in normal matching process
113+
r_predicate1 = @rule x + (~!m::(var->isa(var, Int))) => ~m
114+
@test r_predicate1(x+2) === 2
115+
@test r_predicate1(x+2.0) === nothing
116+
117+
# predicate checked in defslot mathcing process
118+
r_predicate2 = @rule x + ~!m::(var->!(var===0)) => ~m
119+
@test r_predicate2(x+1)===1 # matches normally
120+
@test r_predicate2(x)===nothing # doesnt matches bc the default value is 0 and doesnt respect the predicate
121+
122+
# multiple defslots with the same name
123+
r3 = @rule sin(~!f*~x)+cos(~!f*~x) => ~
124+
@test r3(sin(2x)+cos(2x))[:f]===2
125+
@test r3(sin(2x)+cos(x))===nothing
117126
end
118127

119128
@testset "power matcher with negative exponent" begin

0 commit comments

Comments
 (0)