Browse Source

Fixed validator not checking for match completeness.

Stan Hebben 6 years ago
parent
commit
096c8dfb71

+ 5
- 1
Validator/src/main/java/org/openzen/zenscript/validator/ValidationLogEntry.java View File

73
 		SUPERTYPE_NOT_DESTRUCTIBLE,
73
 		SUPERTYPE_NOT_DESTRUCTIBLE,
74
 		INVALID_IMPLEMENTATION_TYPE,
74
 		INVALID_IMPLEMENTATION_TYPE,
75
 		INCOMPLETE_IMPLEMENTATION,
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 View File

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

+ 80
- 71
Validator/src/main/java/org/openzen/zenscript/validator/visitors/ExpressionValidator.java View File

5
  */
5
  */
6
 package org.openzen.zenscript.validator.visitors;
6
 package org.openzen.zenscript.validator.visitors;
7
 
7
 
8
+import java.util.HashSet;
9
+import java.util.Set;
8
 import org.openzen.zencode.shared.CodePosition;
10
 import org.openzen.zencode.shared.CodePosition;
9
 import org.openzen.zenscript.codemodel.FunctionHeader;
11
 import org.openzen.zenscript.codemodel.FunctionHeader;
10
 import org.openzen.zenscript.codemodel.FunctionParameter;
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
 import org.openzen.zenscript.codemodel.type.ArrayTypeID;
19
 import org.openzen.zenscript.codemodel.type.ArrayTypeID;
82
 import org.openzen.zenscript.codemodel.type.AssocTypeID;
20
 import org.openzen.zenscript.codemodel.type.AssocTypeID;
83
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
21
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
22
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
84
 import org.openzen.zenscript.codemodel.type.ITypeID;
23
 import org.openzen.zenscript.codemodel.type.ITypeID;
85
 import org.openzen.zenscript.codemodel.type.RangeTypeID;
24
 import org.openzen.zenscript.codemodel.type.RangeTypeID;
86
 import org.openzen.zenscript.validator.ValidationLogEntry;
25
 import org.openzen.zenscript.validator.ValidationLogEntry;
423
 
362
 
424
 	@Override
363
 	@Override
425
 	public Void visitMatch(MatchExpression expression) {
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
 		return null;
436
 		return null;
428
 	}
437
 	}
429
 
438
 

Loading…
Cancel
Save