|
@@ -5,82 +5,21 @@
|
5
|
5
|
*/
|
6
|
6
|
package org.openzen.zenscript.validator.visitors;
|
7
|
7
|
|
|
8
|
+import java.util.HashSet;
|
|
9
|
+import java.util.Set;
|
8
|
10
|
import org.openzen.zencode.shared.CodePosition;
|
9
|
11
|
import org.openzen.zenscript.codemodel.FunctionHeader;
|
10
|
12
|
import org.openzen.zenscript.codemodel.FunctionParameter;
|
11
|
|
-import org.openzen.zenscript.codemodel.expression.AndAndExpression;
|
12
|
|
-import org.openzen.zenscript.codemodel.expression.ArrayExpression;
|
13
|
|
-import org.openzen.zenscript.codemodel.expression.CompareExpression;
|
14
|
|
-import org.openzen.zenscript.codemodel.expression.CallArguments;
|
15
|
|
-import org.openzen.zenscript.codemodel.expression.CallExpression;
|
16
|
|
-import org.openzen.zenscript.codemodel.expression.CallStaticExpression;
|
17
|
|
-import org.openzen.zenscript.codemodel.expression.CapturedClosureExpression;
|
18
|
|
-import org.openzen.zenscript.codemodel.expression.CapturedDirectExpression;
|
19
|
|
-import org.openzen.zenscript.codemodel.expression.CapturedLocalVariableExpression;
|
20
|
|
-import org.openzen.zenscript.codemodel.expression.CapturedParameterExpression;
|
21
|
|
-import org.openzen.zenscript.codemodel.expression.CapturedThisExpression;
|
22
|
|
-import org.openzen.zenscript.codemodel.expression.CastExpression;
|
23
|
|
-import org.openzen.zenscript.codemodel.expression.CheckNullExpression;
|
24
|
|
-import org.openzen.zenscript.codemodel.expression.CoalesceExpression;
|
25
|
|
-import org.openzen.zenscript.codemodel.expression.ConditionalExpression;
|
26
|
|
-import org.openzen.zenscript.codemodel.expression.ConstExpression;
|
27
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantBoolExpression;
|
28
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantByteExpression;
|
29
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantCharExpression;
|
30
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantDoubleExpression;
|
31
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantFloatExpression;
|
32
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantIntExpression;
|
33
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantLongExpression;
|
34
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantSByteExpression;
|
35
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantShortExpression;
|
36
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantStringExpression;
|
37
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantUIntExpression;
|
38
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantULongExpression;
|
39
|
|
-import org.openzen.zenscript.codemodel.expression.ConstantUShortExpression;
|
40
|
|
-import org.openzen.zenscript.codemodel.expression.ConstructorSuperCallExpression;
|
41
|
|
-import org.openzen.zenscript.codemodel.expression.ConstructorThisCallExpression;
|
42
|
|
-import org.openzen.zenscript.codemodel.expression.EnumConstantExpression;
|
43
|
|
-import org.openzen.zenscript.codemodel.expression.Expression;
|
44
|
|
-import org.openzen.zenscript.codemodel.expression.ExpressionVisitor;
|
45
|
|
-import org.openzen.zenscript.codemodel.expression.FunctionExpression;
|
46
|
|
-import org.openzen.zenscript.codemodel.expression.GetFieldExpression;
|
47
|
|
-import org.openzen.zenscript.codemodel.expression.GetFunctionParameterExpression;
|
48
|
|
-import org.openzen.zenscript.codemodel.expression.GetLocalVariableExpression;
|
49
|
|
-import org.openzen.zenscript.codemodel.expression.GetMatchingVariantField;
|
50
|
|
-import org.openzen.zenscript.codemodel.expression.GetStaticFieldExpression;
|
51
|
|
-import org.openzen.zenscript.codemodel.expression.GetterExpression;
|
52
|
|
-import org.openzen.zenscript.codemodel.expression.GlobalCallExpression;
|
53
|
|
-import org.openzen.zenscript.codemodel.expression.GlobalExpression;
|
54
|
|
-import org.openzen.zenscript.codemodel.expression.InterfaceCastExpression;
|
55
|
|
-import org.openzen.zenscript.codemodel.expression.IsExpression;
|
56
|
|
-import org.openzen.zenscript.codemodel.expression.MakeConstExpression;
|
57
|
|
-import org.openzen.zenscript.codemodel.expression.MapExpression;
|
58
|
|
-import org.openzen.zenscript.codemodel.expression.MatchExpression;
|
59
|
|
-import org.openzen.zenscript.codemodel.expression.NewExpression;
|
60
|
|
-import org.openzen.zenscript.codemodel.expression.NullExpression;
|
61
|
|
-import org.openzen.zenscript.codemodel.expression.OrOrExpression;
|
62
|
|
-import org.openzen.zenscript.codemodel.expression.PanicExpression;
|
63
|
|
-import org.openzen.zenscript.codemodel.expression.PostCallExpression;
|
64
|
|
-import org.openzen.zenscript.codemodel.expression.RangeExpression;
|
65
|
|
-import org.openzen.zenscript.codemodel.expression.SameObjectExpression;
|
66
|
|
-import org.openzen.zenscript.codemodel.expression.SetFieldExpression;
|
67
|
|
-import org.openzen.zenscript.codemodel.expression.SetFunctionParameterExpression;
|
68
|
|
-import org.openzen.zenscript.codemodel.expression.SetLocalVariableExpression;
|
69
|
|
-import org.openzen.zenscript.codemodel.expression.SetStaticFieldExpression;
|
70
|
|
-import org.openzen.zenscript.codemodel.expression.SetterExpression;
|
71
|
|
-import org.openzen.zenscript.codemodel.expression.StaticGetterExpression;
|
72
|
|
-import org.openzen.zenscript.codemodel.expression.StaticSetterExpression;
|
73
|
|
-import org.openzen.zenscript.codemodel.expression.SupertypeCastExpression;
|
74
|
|
-import org.openzen.zenscript.codemodel.expression.ThisExpression;
|
75
|
|
-import org.openzen.zenscript.codemodel.expression.ThrowExpression;
|
76
|
|
-import org.openzen.zenscript.codemodel.expression.TryConvertExpression;
|
77
|
|
-import org.openzen.zenscript.codemodel.expression.TryRethrowAsExceptionExpression;
|
78
|
|
-import org.openzen.zenscript.codemodel.expression.TryRethrowAsResultExpression;
|
79
|
|
-import org.openzen.zenscript.codemodel.expression.VariantValueExpression;
|
80
|
|
-import org.openzen.zenscript.codemodel.expression.WrapOptionalExpression;
|
|
13
|
+import org.openzen.zenscript.codemodel.definition.EnumDefinition;
|
|
14
|
+import org.openzen.zenscript.codemodel.definition.VariantDefinition;
|
|
15
|
+import org.openzen.zenscript.codemodel.expression.*;
|
|
16
|
+import org.openzen.zenscript.codemodel.expression.switchvalue.EnumConstantSwitchValue;
|
|
17
|
+import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
|
|
18
|
+import org.openzen.zenscript.codemodel.member.EnumConstantMember;
|
81
|
19
|
import org.openzen.zenscript.codemodel.type.ArrayTypeID;
|
82
|
20
|
import org.openzen.zenscript.codemodel.type.AssocTypeID;
|
83
|
21
|
import org.openzen.zenscript.codemodel.type.BasicTypeID;
|
|
22
|
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
|
84
|
23
|
import org.openzen.zenscript.codemodel.type.ITypeID;
|
85
|
24
|
import org.openzen.zenscript.codemodel.type.RangeTypeID;
|
86
|
25
|
import org.openzen.zenscript.validator.ValidationLogEntry;
|
|
@@ -423,7 +362,77 @@ public class ExpressionValidator implements ExpressionVisitor<Void> {
|
423
|
362
|
|
424
|
363
|
@Override
|
425
|
364
|
public Void visitMatch(MatchExpression expression) {
|
426
|
|
- // TODO
|
|
365
|
+ expression.value.accept(this);
|
|
366
|
+ for (MatchExpression.Case case_ : expression.cases) {
|
|
367
|
+ case_.value.accept(this);
|
|
368
|
+ }
|
|
369
|
+
|
|
370
|
+ boolean hasDefault = false;
|
|
371
|
+ if (expression.value.type.isVariant()) {
|
|
372
|
+ Set<VariantDefinition.Option> options = new HashSet<>();
|
|
373
|
+ for (MatchExpression.Case case_ : expression.cases) {
|
|
374
|
+ if (case_.key == null) {
|
|
375
|
+ if (hasDefault)
|
|
376
|
+ validator.logError(ValidationLogEntry.Code.DUPLICATE_DEFAULT_CASE, expression.position, "Duplicate default in match");
|
|
377
|
+
|
|
378
|
+ hasDefault = true;
|
|
379
|
+ } else if (case_.key instanceof VariantOptionSwitchValue) {
|
|
380
|
+ VariantDefinition.Option option = ((VariantOptionSwitchValue)case_.key).option.getOption();
|
|
381
|
+ if (options.contains(option))
|
|
382
|
+ validator.logError(ValidationLogEntry.Code.DUPLICATE_CASE, expression.position, "Duplicate case in match: " + option.name);
|
|
383
|
+
|
|
384
|
+ options.add(option);
|
|
385
|
+ } else {
|
|
386
|
+ validator.logError(ValidationLogEntry.Code.INVALID_CASE, expression.position, "Invalid case: must be default or option value");
|
|
387
|
+ }
|
|
388
|
+ }
|
|
389
|
+
|
|
390
|
+ if (!hasDefault) {
|
|
391
|
+ VariantDefinition variant = (VariantDefinition)(((DefinitionTypeID)expression.value.type).definition);
|
|
392
|
+ for (VariantDefinition.Option option : variant.options) {
|
|
393
|
+ if (!options.contains(option))
|
|
394
|
+ validator.logError(ValidationLogEntry.Code.INCOMPLETE_MATCH, expression.position, "Incomplete match: missing option for " + option.name);
|
|
395
|
+ }
|
|
396
|
+ }
|
|
397
|
+ } else if (expression.type.isEnum()) {
|
|
398
|
+ Set<EnumConstantMember> options = new HashSet<>();
|
|
399
|
+ for (MatchExpression.Case case_ : expression.cases) {
|
|
400
|
+ if (case_.key == null) {
|
|
401
|
+ if (hasDefault)
|
|
402
|
+ validator.logError(ValidationLogEntry.Code.DUPLICATE_DEFAULT_CASE, expression.position, "Duplicate default in match");
|
|
403
|
+
|
|
404
|
+ hasDefault = true;
|
|
405
|
+ } else if (case_.key instanceof EnumConstantSwitchValue) {
|
|
406
|
+ EnumConstantMember option = ((EnumConstantSwitchValue)case_.key).constant;
|
|
407
|
+ if (options.contains(option))
|
|
408
|
+ validator.logError(ValidationLogEntry.Code.DUPLICATE_CASE, expression.position, "Duplicate case in match: " + option.name);
|
|
409
|
+
|
|
410
|
+ options.add(option);
|
|
411
|
+ } else {
|
|
412
|
+ validator.logError(ValidationLogEntry.Code.INVALID_CASE, expression.position, "Invalid case: must be default or enum value");
|
|
413
|
+ }
|
|
414
|
+ }
|
|
415
|
+
|
|
416
|
+ if (!hasDefault) {
|
|
417
|
+ EnumDefinition enum_ = (EnumDefinition)(((DefinitionTypeID)expression.value.type).definition);
|
|
418
|
+ for (EnumConstantMember option : enum_.enumConstants) {
|
|
419
|
+ if (!options.contains(option))
|
|
420
|
+ validator.logError(ValidationLogEntry.Code.INCOMPLETE_MATCH, expression.position, "Incomplete match: missing option for " + option.name);
|
|
421
|
+ }
|
|
422
|
+ }
|
|
423
|
+ } else {
|
|
424
|
+ for (MatchExpression.Case case_ : expression.cases) {
|
|
425
|
+ if (case_.key == null) {
|
|
426
|
+ if (hasDefault)
|
|
427
|
+ validator.logError(ValidationLogEntry.Code.DUPLICATE_DEFAULT_CASE, expression.position, "Duplicate default in match");
|
|
428
|
+
|
|
429
|
+ hasDefault = true;
|
|
430
|
+ }
|
|
431
|
+ }
|
|
432
|
+
|
|
433
|
+ if (!hasDefault)
|
|
434
|
+ validator.logError(ValidationLogEntry.Code.INCOMPLETE_MATCH, expression.position, "Incomplete match: must have a default option");
|
|
435
|
+ }
|
427
|
436
|
return null;
|
428
|
437
|
}
|
429
|
438
|
|