6
6
# 3. Callback: takes arguments Dictionary × Number of elements matched
7
7
#
8
8
function matcher (val:: Any )
9
- iscall (val) && return term_matcher (val)
9
+ matcher (val, false )
10
+ end
11
+
12
+ # `fullac_flag == true` enables fully nested associative-commutative pattern matching
13
+ function matcher (val:: Any , fullac_flag)
14
+ iscall (val) && return term_matcher (val, fullac_flag)
10
15
function literal_matcher (next, data, bindings)
11
16
islist (data) && isequal (car (data), val) ? next (bindings, 1 ) : nothing
12
17
end
13
18
end
14
19
15
- function matcher (slot:: Slot )
20
+ function matcher (slot:: Slot , fullac_flag) # fullac_flag unused but needed to keep the interface uniform
16
21
function slot_matcher (next, data, bindings)
17
22
! islist (data) && return
18
23
val = get (bindings, slot. name, nothing )
@@ -56,7 +61,7 @@ function trymatchexpr(data, value, n)
56
61
end
57
62
end
58
63
59
- function matcher (segment:: Segment )
64
+ function matcher (segment:: Segment , fullac_flag) # fullac_flag unused but needed to keep the interface uniform
60
65
function segment_matcher (success, data, bindings)
61
66
val = get (bindings, segment. name, nothing )
62
67
@@ -84,8 +89,8 @@ function matcher(segment::Segment)
84
89
end
85
90
end
86
91
87
- function term_matcher (term)
88
- matchers = (matcher (operation (term)), map (matcher, arguments (term))... ,)
92
+ function term_matcher (term, fullac_flag = false )
93
+ matchers = (matcher (operation (term), fullac_flag ), map (a -> matcher (a, fullac_flag) , arguments (term))... ,)
89
94
function term_matcher (success, data, bindings)
90
95
91
96
! islist (data) && return nothing
@@ -103,6 +108,23 @@ function term_matcher(term)
103
108
end
104
109
end
105
110
106
- loop (car (data), bindings, matchers) # Try to eat exactly one term
111
+ if ! (fullac_flag && iscall (term) && operation (term) in ((+ ), (* )))
112
+ loop (car (data), bindings, matchers) # Try to eat exactly one term
113
+ else # try all permutations of `car(data)` to see if a match is possible
114
+ data1 = car (data)
115
+ args = arguments (data1)
116
+ op = operation (data1)
117
+ data_arg_perms = permutations (args)
118
+ result = nothing
119
+ T = symtype (data)
120
+ for perm in data_arg_perms
121
+ data_permuted = Term {T} (op, perm)
122
+ result = loop (data_permuted, bindings, matchers) # Try to eat exactly one term
123
+ if ! (result isa Nothing)
124
+ break
125
+ end
126
+ end
127
+ return result
128
+ end
107
129
end
108
130
end
0 commit comments