66# 3. Callback: takes arguments Dictionary × Number of elements matched
77#
88function 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)
1015 function literal_matcher (next, data, bindings)
1116 islist (data) && isequal (car (data), val) ? next (bindings, 1 ) : nothing
1217 end
1318end
1419
15- function matcher (slot:: Slot )
20+ function matcher (slot:: Slot , fullac_flag) # fullac_flag unused but needed to keep the interface uniform
1621 function slot_matcher (next, data, bindings)
1722 ! islist (data) && return
1823 val = get (bindings, slot. name, nothing )
@@ -56,7 +61,7 @@ function trymatchexpr(data, value, n)
5661 end
5762end
5863
59- function matcher (segment:: Segment )
64+ function matcher (segment:: Segment , fullac_flag) # fullac_flag unused but needed to keep the interface uniform
6065 function segment_matcher (success, data, bindings)
6166 val = get (bindings, segment. name, nothing )
6267
@@ -84,8 +89,8 @@ function matcher(segment::Segment)
8489 end
8590end
8691
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))... ,)
8994 function term_matcher (success, data, bindings)
9095
9196 ! islist (data) && return nothing
@@ -103,6 +108,23 @@ function term_matcher(term)
103108 end
104109 end
105110
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
107129 end
108130end
0 commit comments