7
7
import com .annimon .ownlang .lib .Value ;
8
8
import com .annimon .ownlang .lib .Variables ;
9
9
import java .util .ArrayList ;
10
+ import java .util .Iterator ;
10
11
import java .util .List ;
11
12
12
13
/**
13
14
*
14
15
* @author aNNiMON
15
16
*/
16
17
public final class MatchExpression implements Expression , Statement {
17
-
18
+
18
19
public final Expression expression ;
19
20
public final List <Pattern > patterns ;
20
21
21
22
public MatchExpression (Expression expression , List <Pattern > patterns ) {
22
23
this .expression = expression ;
23
24
this .patterns = patterns ;
24
25
}
25
-
26
+
26
27
@ Override
27
28
public void execute () {
28
29
eval ();
29
30
}
30
-
31
+
31
32
@ Override
32
33
public Value eval () {
33
34
final Value value = expression .eval ();
@@ -41,15 +42,15 @@ public Value eval() {
41
42
if (p instanceof VariablePattern ) {
42
43
final VariablePattern pattern = (VariablePattern ) p ;
43
44
if (pattern .variable .equals ("_" )) return evalResult (p .result );
44
-
45
+
45
46
if (Variables .isExists (pattern .variable )) {
46
47
if (match (value , Variables .get (pattern .variable )) && optMatches (p )) {
47
48
return evalResult (p .result );
48
49
}
49
50
} else {
50
51
Variables .define (pattern .variable , value );
51
52
if (optMatches (p )) {
52
- final Value result = evalResult (p .result );;
53
+ final Value result = evalResult (p .result );
53
54
Variables .remove (pattern .variable );
54
55
return result ;
55
56
}
@@ -67,10 +68,29 @@ public Value eval() {
67
68
return result ;
68
69
}
69
70
}
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
+ }
70
77
}
71
78
throw new PatternMatchingException ("No pattern were matched" );
72
79
}
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
+
74
94
private boolean matchListPattern (ArrayValue array , ListPattern p ) {
75
95
final List <String > parts = p .parts ;
76
96
final int partsSize = parts .size ();
@@ -90,7 +110,7 @@ private boolean matchListPattern(ArrayValue array, ListPattern p) {
90
110
}
91
111
Variables .remove (variable );
92
112
return false ;
93
-
113
+
94
114
default : { // match arr { case [...]: .. }
95
115
if (partsSize == arraySize ) {
96
116
// 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) {
102
122
return false ;
103
123
}
104
124
}
105
- }
125
+ }
106
126
107
127
private boolean matchListPatternEqualsSize (ListPattern p , List <String > parts , int partsSize , ArrayValue array ) {
108
128
// Set variables
@@ -119,7 +139,7 @@ private boolean matchListPatternEqualsSize(ListPattern p, List<String> parts, in
119
139
}
120
140
return false ;
121
141
}
122
-
142
+
123
143
private boolean matchListPatternWithTail (ListPattern p , List <String > parts , int partsSize , ArrayValue array , int arraySize ) {
124
144
// Set element variables
125
145
final int lastPart = partsSize - 1 ;
@@ -143,17 +163,17 @@ private boolean matchListPatternWithTail(ListPattern p, List<String> parts, int
143
163
}
144
164
return false ;
145
165
}
146
-
166
+
147
167
private boolean match (Value value , Value constant ) {
148
168
if (value .type () != constant .type ()) return false ;
149
169
return value .equals (constant );
150
170
}
151
-
171
+
152
172
private boolean optMatches (Pattern pattern ) {
153
173
if (pattern .optCondition == null ) return true ;
154
174
return pattern .optCondition .eval () != NumberValue .ZERO ;
155
175
}
156
-
176
+
157
177
private Value evalResult (Statement s ) {
158
178
try {
159
179
s .execute ();
@@ -162,7 +182,7 @@ private Value evalResult(Statement s) {
162
182
}
163
183
return NumberValue .ZERO ;
164
184
}
165
-
185
+
166
186
@ Override
167
187
public void accept (Visitor visitor ) {
168
188
visitor .visit (this );
@@ -183,15 +203,15 @@ public String toString() {
183
203
sb .append ("\n }" );
184
204
return sb .toString ();
185
205
}
186
-
206
+
187
207
public static abstract class Pattern {
188
208
public Statement result ;
189
209
public Expression optCondition ;
190
210
}
191
-
211
+
192
212
public static class ConstantPattern extends Pattern {
193
213
public Value constant ;
194
-
214
+
195
215
public ConstantPattern (Value pattern ) {
196
216
this .constant = pattern ;
197
217
}
@@ -201,10 +221,10 @@ public String toString() {
201
221
return constant + ": " + result ;
202
222
}
203
223
}
204
-
224
+
205
225
public static class VariablePattern extends Pattern {
206
226
public String variable ;
207
-
227
+
208
228
public VariablePattern (String pattern ) {
209
229
this .variable = pattern ;
210
230
}
@@ -214,14 +234,14 @@ public String toString() {
214
234
return variable + ": " + result ;
215
235
}
216
236
}
217
-
237
+
218
238
public static class ListPattern extends Pattern {
219
239
public List <String > parts ;
220
-
240
+
221
241
public ListPattern () {
222
242
this (new ArrayList <String >());
223
243
}
224
-
244
+
225
245
public ListPattern (List <String > parts ) {
226
246
this .parts = parts ;
227
247
}
@@ -232,7 +252,73 @@ public void add(String part) {
232
252
233
253
@ Override
234
254
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 >());
236
274
}
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
+ };
237
323
}
238
324
}
0 commit comments