77import com .annimon .ownlang .lib .Value ;
88import com .annimon .ownlang .lib .Variables ;
99import java .util .ArrayList ;
10+ import java .util .Iterator ;
1011import java .util .List ;
1112
1213/**
1314 *
1415 * @author aNNiMON
1516 */
1617public final class MatchExpression implements Expression , Statement {
17-
18+
1819 public final Expression expression ;
1920 public final List <Pattern > patterns ;
2021
2122 public MatchExpression (Expression expression , List <Pattern > patterns ) {
2223 this .expression = expression ;
2324 this .patterns = patterns ;
2425 }
25-
26+
2627 @ Override
2728 public void execute () {
2829 eval ();
2930 }
30-
31+
3132 @ Override
3233 public Value eval () {
3334 final Value value = expression .eval ();
@@ -41,15 +42,15 @@ public Value eval() {
4142 if (p instanceof VariablePattern ) {
4243 final VariablePattern pattern = (VariablePattern ) p ;
4344 if (pattern .variable .equals ("_" )) return evalResult (p .result );
44-
45+
4546 if (Variables .isExists (pattern .variable )) {
4647 if (match (value , Variables .get (pattern .variable )) && optMatches (p )) {
4748 return evalResult (p .result );
4849 }
4950 } else {
5051 Variables .define (pattern .variable , value );
5152 if (optMatches (p )) {
52- final Value result = evalResult (p .result );;
53+ final Value result = evalResult (p .result );
5354 Variables .remove (pattern .variable );
5455 return result ;
5556 }
@@ -67,10 +68,29 @@ public Value eval() {
6768 return result ;
6869 }
6970 }
71+ if ((value .type () == Types .ARRAY ) && (p instanceof TuplePattern )) {
72+ final TuplePattern pattern = (TuplePattern ) p ;
73+ if (matchTuplePattern ((ArrayValue ) value , pattern ) && optMatches (p )) {
74+ return evalResult (p .result );
75+ }
76+ }
7077 }
7178 throw new PatternMatchingException ("No pattern were matched" );
7279 }
73-
80+
81+ private boolean matchTuplePattern (ArrayValue array , TuplePattern p ) {
82+ if (p .values .size () != array .size ()) return false ;
83+
84+ final int size = array .size ();
85+ for (int i = 0 ; i < size ; i ++) {
86+ final Expression expr = p .values .get (i );
87+ if ( (expr != TuplePattern .ANY ) && (expr .eval ().compareTo (array .get (i )) != 0 ) ) {
88+ return false ;
89+ }
90+ }
91+ return true ;
92+ }
93+
7494 private boolean matchListPattern (ArrayValue array , ListPattern p ) {
7595 final List <String > parts = p .parts ;
7696 final int partsSize = parts .size ();
@@ -90,7 +110,7 @@ private boolean matchListPattern(ArrayValue array, ListPattern p) {
90110 }
91111 Variables .remove (variable );
92112 return false ;
93-
113+
94114 default : { // match arr { case [...]: .. }
95115 if (partsSize == arraySize ) {
96116 // match [0, 1, 2] { case [a::b::c]: a=0, b=1, c=2 ... }
@@ -102,7 +122,7 @@ private boolean matchListPattern(ArrayValue array, ListPattern p) {
102122 return false ;
103123 }
104124 }
105- }
125+ }
106126
107127 private boolean matchListPatternEqualsSize (ListPattern p , List <String > parts , int partsSize , ArrayValue array ) {
108128 // Set variables
@@ -119,7 +139,7 @@ private boolean matchListPatternEqualsSize(ListPattern p, List<String> parts, in
119139 }
120140 return false ;
121141 }
122-
142+
123143 private boolean matchListPatternWithTail (ListPattern p , List <String > parts , int partsSize , ArrayValue array , int arraySize ) {
124144 // Set element variables
125145 final int lastPart = partsSize - 1 ;
@@ -143,17 +163,17 @@ private boolean matchListPatternWithTail(ListPattern p, List<String> parts, int
143163 }
144164 return false ;
145165 }
146-
166+
147167 private boolean match (Value value , Value constant ) {
148168 if (value .type () != constant .type ()) return false ;
149169 return value .equals (constant );
150170 }
151-
171+
152172 private boolean optMatches (Pattern pattern ) {
153173 if (pattern .optCondition == null ) return true ;
154174 return pattern .optCondition .eval () != NumberValue .ZERO ;
155175 }
156-
176+
157177 private Value evalResult (Statement s ) {
158178 try {
159179 s .execute ();
@@ -162,7 +182,7 @@ private Value evalResult(Statement s) {
162182 }
163183 return NumberValue .ZERO ;
164184 }
165-
185+
166186 @ Override
167187 public void accept (Visitor visitor ) {
168188 visitor .visit (this );
@@ -183,15 +203,15 @@ public String toString() {
183203 sb .append ("\n }" );
184204 return sb .toString ();
185205 }
186-
206+
187207 public static abstract class Pattern {
188208 public Statement result ;
189209 public Expression optCondition ;
190210 }
191-
211+
192212 public static class ConstantPattern extends Pattern {
193213 public Value constant ;
194-
214+
195215 public ConstantPattern (Value pattern ) {
196216 this .constant = pattern ;
197217 }
@@ -201,10 +221,10 @@ public String toString() {
201221 return constant + ": " + result ;
202222 }
203223 }
204-
224+
205225 public static class VariablePattern extends Pattern {
206226 public String variable ;
207-
227+
208228 public VariablePattern (String pattern ) {
209229 this .variable = pattern ;
210230 }
@@ -214,14 +234,14 @@ public String toString() {
214234 return variable + ": " + result ;
215235 }
216236 }
217-
237+
218238 public static class ListPattern extends Pattern {
219239 public List <String > parts ;
220-
240+
221241 public ListPattern () {
222242 this (new ArrayList <String >());
223243 }
224-
244+
225245 public ListPattern (List <String > parts ) {
226246 this .parts = parts ;
227247 }
@@ -232,7 +252,73 @@ public void add(String part) {
232252
233253 @ Override
234254 public String toString () {
235- return parts + ": " + result ;
255+ final Iterator <String > it = parts .iterator ();
256+ if (it .hasNext ()) {
257+ final StringBuilder sb = new StringBuilder ();
258+ sb .append ("[" ).append (it .next ());
259+ while (it .hasNext ()) {
260+ sb .append (" :: " ).append (it .next ());
261+ }
262+ sb .append ("]: " ).append (result );
263+ return sb .toString ();
264+ }
265+ return "[]: " + result ;
266+ }
267+ }
268+
269+ public static class TuplePattern extends Pattern {
270+ public List <Expression > values ;
271+
272+ public TuplePattern () {
273+ this (new ArrayList <Expression >());
236274 }
275+
276+ public TuplePattern (List <Expression > parts ) {
277+ this .values = parts ;
278+ }
279+
280+ public void addAny () {
281+ values .add (ANY );
282+ }
283+
284+ public void add (Expression value ) {
285+ values .add (value );
286+ }
287+
288+ @ Override
289+ public String toString () {
290+ final Iterator <Expression > it = values .iterator ();
291+ if (it .hasNext ()) {
292+ final StringBuilder sb = new StringBuilder ();
293+ sb .append ("(" ).append (it .next ());
294+ while (it .hasNext ()) {
295+ sb .append (", " ).append (it .next ());
296+ }
297+ sb .append ("): " ).append (result );
298+ return sb .toString ();
299+ }
300+ return "(): " + result ;
301+ }
302+
303+ private static final Expression ANY = new Expression () {
304+ @ Override
305+ public Value eval () {
306+ return NumberValue .ONE ;
307+ }
308+
309+ @ Override
310+ public void accept (Visitor visitor ) {
311+ }
312+
313+ @ Override
314+ public <R , T > R accept (ResultVisitor <R , T > visitor , T input ) {
315+ return null ;
316+ }
317+
318+ @ Override
319+ public String toString () {
320+ return "_" ;
321+ }
322+ };
237323 }
238324}
0 commit comments