Kaynağa Gözat

Fixed validator not checking for match completeness.

Stan Hebben 6 yıl önce
ebeveyn
işleme
096c8dfb71

+ 5
- 1
Validator/src/main/java/org/openzen/zenscript/validator/ValidationLogEntry.java Dosyayı Görüntüle

@@ -73,6 +73,10 @@ public class ValidationLogEntry {
73 73
 		SUPERTYPE_NOT_DESTRUCTIBLE,
74 74
 		INVALID_IMPLEMENTATION_TYPE,
75 75
 		INCOMPLETE_IMPLEMENTATION,
76
-		MATCHING_VARIANT_FIELD_INVALID
76
+		MATCHING_VARIANT_FIELD_INVALID,
77
+		DUPLICATE_DEFAULT_CASE,
78
+		DUPLICATE_CASE,
79
+		INCOMPLETE_MATCH,
80
+		INVALID_CASE
77 81
 	}
78 82
 }

+ 0
- 1
Validator/src/main/java/org/openzen/zenscript/validator/visitors/DefinitionMemberValidator.java Dosyayı Görüntüle

@@ -29,7 +29,6 @@ import org.openzen.zenscript.codemodel.member.InnerDefinitionMember;
29 29
 import org.openzen.zenscript.codemodel.member.MemberVisitor;
30 30
 import org.openzen.zenscript.codemodel.member.MethodMember;
31 31
 import org.openzen.zenscript.codemodel.member.OperatorMember;
32
-import org.openzen.zenscript.codemodel.member.PropertyMember;
33 32
 import org.openzen.zenscript.codemodel.member.SetterMember;
34 33
 import org.openzen.zenscript.codemodel.member.StaticInitializerMember;
35 34
 import org.openzen.zenscript.codemodel.scope.TypeScope;

+ 80
- 71
Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java Dosyayı Görüntüle

@@ -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
 

Loading…
İptal
Kaydet