Browse Source

- Added key sorting to switches

- Fixed a couple more bugs with generics
Stan Hebben 6 years ago
parent
commit
1c213dd186

+ 1
- 1
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/FormattingUtils.java View File

93
 	}
93
 	}
94
 	
94
 	
95
 	public static void formatTypeParameters(StringBuilder result, TypeParameter[] parameters, TypeFormatter typeFormatter) {
95
 	public static void formatTypeParameters(StringBuilder result, TypeParameter[] parameters, TypeFormatter typeFormatter) {
96
-		if (parameters.length > 0) {
96
+		if (parameters != null) {
97
 			result.append("<");
97
 			result.append("<");
98
 			int index = 0;
98
 			int index = 0;
99
 			for (TypeParameter parameter : parameters) {
99
 			for (TypeParameter parameter : parameters) {

+ 1
- 1
CodeFormatter/src/main/java/org/openzen/zenscript/formatter/TypeFormatter.java View File

76
 	@Override
76
 	@Override
77
 	public String visitDefinition(DefinitionTypeID definition) {
77
 	public String visitDefinition(DefinitionTypeID definition) {
78
 		String importedName = importer.importDefinition(definition.definition);
78
 		String importedName = importer.importDefinition(definition.definition);
79
-		if (definition.typeParameters.length == 0)
79
+		if (definition.typeParameters == null)
80
 			return importedName;
80
 			return importedName;
81
 		
81
 		
82
 		StringBuilder result = new StringBuilder();
82
 		StringBuilder result = new StringBuilder();

+ 14
- 8
CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java View File

22
  * @author Hoofdgebruiker
22
  * @author Hoofdgebruiker
23
  */
23
  */
24
 public class FunctionHeader {
24
 public class FunctionHeader {
25
-	private static final TypeParameter[] NO_GENERIC_PARAMETERS = new TypeParameter[0];
26
 	private static final FunctionParameter[] NO_PARAMETERS = new FunctionParameter[0];
25
 	private static final FunctionParameter[] NO_PARAMETERS = new FunctionParameter[0];
27
 	
26
 	
28
 	public final TypeParameter[] typeParameters;
27
 	public final TypeParameter[] typeParameters;
30
 	public final FunctionParameter[] parameters;
29
 	public final FunctionParameter[] parameters;
31
 	
30
 	
32
 	public FunctionHeader(ITypeID returnType) {
31
 	public FunctionHeader(ITypeID returnType) {
33
-		this.typeParameters = NO_GENERIC_PARAMETERS;
32
+		this.typeParameters = null;
34
 		this.returnType = returnType;
33
 		this.returnType = returnType;
35
 		this.parameters = NO_PARAMETERS;
34
 		this.parameters = NO_PARAMETERS;
36
 	}
35
 	}
37
 	
36
 	
38
 	public FunctionHeader(ITypeID returnType, FunctionParameter... parameters) {
37
 	public FunctionHeader(ITypeID returnType, FunctionParameter... parameters) {
39
-		this.typeParameters = NO_GENERIC_PARAMETERS;
38
+		this.typeParameters = null;
40
 		this.returnType = returnType;
39
 		this.returnType = returnType;
41
 		this.parameters = parameters;
40
 		this.parameters = parameters;
42
 	}
41
 	}
47
 		this.parameters = parameters;
46
 		this.parameters = parameters;
48
 	}
47
 	}
49
 	
48
 	
49
+	public int getNumberOfTypeParameters() {
50
+		return typeParameters == null ? 0 : typeParameters.length;
51
+	}
52
+	
50
 	public FunctionHeader instance(GlobalTypeRegistry registry, Map<TypeParameter, ITypeID> mapping) {
53
 	public FunctionHeader instance(GlobalTypeRegistry registry, Map<TypeParameter, ITypeID> mapping) {
51
-		TypeParameter[] genericParameters = new TypeParameter[this.typeParameters.length];
52
-		for (int i = 0; i < genericParameters.length; i++)
53
-			genericParameters[i] = this.typeParameters[i].withGenericArguments(registry, mapping);
54
+		TypeParameter[] genericParameters = this.typeParameters == null ? null : new TypeParameter[this.typeParameters.length];
55
+		if (genericParameters != null)
56
+			for (int i = 0; i < genericParameters.length; i++)
57
+				genericParameters[i] = this.typeParameters[i].withGenericArguments(registry, mapping);
58
+		
54
 		ITypeID returnType = this.returnType.withGenericArguments(registry, mapping);
59
 		ITypeID returnType = this.returnType.withGenericArguments(registry, mapping);
55
 		FunctionParameter[] parameters = new FunctionParameter[this.parameters.length];
60
 		FunctionParameter[] parameters = new FunctionParameter[this.parameters.length];
56
 		for (int i = 0; i < parameters.length; i++)
61
 		for (int i = 0; i < parameters.length; i++)
193
 	
198
 	
194
 	public FunctionHeader withGenericArguments(GlobalTypeRegistry registry, ITypeID[] arguments) {
199
 	public FunctionHeader withGenericArguments(GlobalTypeRegistry registry, ITypeID[] arguments) {
195
 		Map<TypeParameter, ITypeID> typeArguments = new HashMap<>();
200
 		Map<TypeParameter, ITypeID> typeArguments = new HashMap<>();
196
-		for (int i = 0; i < typeParameters.length; i++)
197
-			typeArguments.put(typeParameters[i], arguments[i]);
201
+		if (typeParameters != null)
202
+			for (int i = 0; i < typeParameters.length; i++)
203
+				typeArguments.put(typeParameters[i], arguments[i]);
198
 		
204
 		
199
 		ITypeID returnType = this.returnType.withGenericArguments(registry, typeArguments);
205
 		ITypeID returnType = this.returnType.withGenericArguments(registry, typeArguments);
200
 		FunctionParameter[] parameters = new FunctionParameter[this.parameters.length];
206
 		FunctionParameter[] parameters = new FunctionParameter[this.parameters.length];

+ 4
- 0
CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/CallArguments.java View File

32
 		this.typeArguments = typeArguments;
32
 		this.typeArguments = typeArguments;
33
 		this.arguments = arguments;
33
 		this.arguments = arguments;
34
 	}
34
 	}
35
+	
36
+	public int getNumberOfTypeArguments() {
37
+		return typeArguments.length;
38
+	}
35
 }
39
 }

+ 1
- 1
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/DefinitionTypeID.java View File

19
  */
19
  */
20
 public class DefinitionTypeID implements ITypeID {
20
 public class DefinitionTypeID implements ITypeID {
21
 	public static DefinitionTypeID forType(HighLevelDefinition definition) {
21
 	public static DefinitionTypeID forType(HighLevelDefinition definition) {
22
-		if (definition.genericParameters.length > 0)
22
+		if (definition.genericParameters != null)
23
 			throw new IllegalArgumentException("Definition has type arguments!");
23
 			throw new IllegalArgumentException("Definition has type arguments!");
24
 		
24
 		
25
 		return new DefinitionTypeID(definition, null);
25
 		return new DefinitionTypeID(definition, null);

+ 5
- 3
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ITypeID.java View File

131
 				if (definitionType.definition != definition.definition)
131
 				if (definitionType.definition != definition.definition)
132
 					return false;
132
 					return false;
133
 				
133
 				
134
-				for (int i = 0; i < definitionType.typeParameters.length; i++) {
135
-					if (!match(definitionType.typeParameters[i], definition.typeParameters[i]))
136
-						return false;
134
+				if (definition.typeParameters != null) {
135
+					for (int i = 0; i < definitionType.typeParameters.length; i++) {
136
+						if (!match(definitionType.typeParameters[i], definition.typeParameters[i]))
137
+							return false;
138
+					}
137
 				}
139
 				}
138
 				
140
 				
139
 				return true;
141
 				return true;

+ 3
- 3
CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/member/DefinitionMemberGroup.java View File

215
 			if (header.parameters.length != arguments)
215
 			if (header.parameters.length != arguments)
216
 				continue;
216
 				continue;
217
 			
217
 			
218
-			if (header.typeParameters.length > 0) {
218
+			if (header.typeParameters != null) {
219
 				for (ITypeID resultHint : typeHints) {
219
 				for (ITypeID resultHint : typeHints) {
220
 					Map<TypeParameter, ITypeID> mapping = new HashMap<>();
220
 					Map<TypeParameter, ITypeID> mapping = new HashMap<>();
221
 					if (header.returnType.inferTypeParameters(scope.getMemberCache(), resultHint, mapping)) {
221
 					if (header.returnType.inferTypeParameters(scope.getMemberCache(), resultHint, mapping)) {
293
 			FunctionHeader header = method.member.getHeader();
293
 			FunctionHeader header = method.member.getHeader();
294
 			if (header.parameters.length != arguments.arguments.length)
294
 			if (header.parameters.length != arguments.arguments.length)
295
 				continue;
295
 				continue;
296
-			if (header.typeParameters.length != arguments.typeArguments.length)
296
+			if (header.getNumberOfTypeParameters() != arguments.getNumberOfTypeArguments())
297
 				continue;
297
 				continue;
298
 			
298
 			
299
 			if (arguments.typeArguments.length > 0) {
299
 			if (arguments.typeArguments.length > 0) {
317
 			FunctionHeader header = method.member.getHeader();
317
 			FunctionHeader header = method.member.getHeader();
318
 			if (header.parameters.length != arguments.arguments.length)
318
 			if (header.parameters.length != arguments.arguments.length)
319
 				continue;
319
 				continue;
320
-			if (header.typeParameters.length != arguments.typeArguments.length)
320
+			if (header.getNumberOfTypeParameters() != arguments.getNumberOfTypeArguments())
321
 				continue;
321
 				continue;
322
 			
322
 			
323
 			if (arguments.typeArguments.length > 0) {
323
 			if (arguments.typeArguments.length > 0) {

+ 13
- 12
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaStatementVisitor.java View File

163
         final boolean hasNoDefault = hasNoDefault(statement);
163
         final boolean hasNoDefault = hasNoDefault(statement);
164
 
164
 
165
         final List<SwitchCase> cases = statement.cases;
165
         final List<SwitchCase> cases = statement.cases;
166
-
167
-        final int[] keys = new int[hasNoDefault ? cases.size() : cases.size() - 1];
168
-        final Label[] labels = new Label[keys.length];
166
+		final JavaSwitchLabel[] switchLabels = new JavaSwitchLabel[hasNoDefault ? cases.size() : cases.size() - 1];
169
         final Label defaultLabel = new Label();
167
         final Label defaultLabel = new Label();
170
-
171
-        Arrays.parallelSetAll(labels, value -> new Label());
172
-
168
+		
173
         int i = 0;
169
         int i = 0;
174
-        for (final SwitchCase switchCase : cases)
175
-            if (switchCase.value != null)
176
-                keys[i++] = CompilerUtils.getKeyForSwitch(switchCase.value);
170
+        for (final SwitchCase switchCase : cases) {
171
+            if (switchCase.value != null) {
172
+				switchLabels[i++] = new JavaSwitchLabel(CompilerUtils.getKeyForSwitch(switchCase.value), new Label());
173
+			}
174
+		}
175
+		
176
+		JavaSwitchLabel[] sortedSwitchLabels = Arrays.copyOf(switchLabels, switchLabels.length);
177
+		Arrays.sort(sortedSwitchLabels, (a, b) -> a.key - b.key);
177
 
178
 
178
-        javaWriter.lookupSwitch(defaultLabel, keys, labels);
179
+        javaWriter.lookupSwitch(defaultLabel, sortedSwitchLabels);
179
 
180
 
180
         i = 0;
181
         i = 0;
181
         for (final SwitchCase switchCase : cases) {
182
         for (final SwitchCase switchCase : cases) {
182
             if (hasNoDefault || switchCase.value != null) {
183
             if (hasNoDefault || switchCase.value != null) {
183
-                javaWriter.label(labels[i++]);
184
+                javaWriter.label(switchLabels[i++].label);
184
             } else {
185
             } else {
185
                 javaWriter.label(defaultLabel);
186
                 javaWriter.label(defaultLabel);
186
             }
187
             }
203
         for (SwitchCase switchCase : switchStatement.cases)
204
         for (SwitchCase switchCase : switchStatement.cases)
204
             if (switchCase.value == null) return false;
205
             if (switchCase.value == null) return false;
205
         return true;
206
         return true;
206
-    }
207
+	}
207
 
208
 
208
     @Override
209
     @Override
209
     public Boolean visitThrow(ThrowStatement statement) {
210
     public Boolean visitThrow(ThrowStatement statement) {

+ 22
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaSwitchLabel.java View File

1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.javabytecode.compiler;
7
+
8
+import org.objectweb.asm.Label;
9
+
10
+/**
11
+ *
12
+ * @author Hoofdgebruiker
13
+ */
14
+public class JavaSwitchLabel {
15
+	public final int key;
16
+	public final Label label;
17
+	
18
+	public JavaSwitchLabel(int key, Label label) {
19
+		this.key = key;
20
+		this.label = label;
21
+	}
22
+}

+ 8
- 1
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java View File

1128
             visitor.visitParameter(name, modifier);
1128
             visitor.visitParameter(name, modifier);
1129
     }
1129
     }
1130
 
1130
 
1131
-    public void lookupSwitch(Label defaultLabel, int[] keys, Label[] labels) {
1131
+    public void lookupSwitch(Label defaultLabel, JavaSwitchLabel[] switchLabels) {
1132
+		int[] keys = new int[switchLabels.length];
1133
+		Label[] labels = new Label[switchLabels.length];
1134
+		for (int i = 0; i < switchLabels.length; i++) {
1135
+			keys[i] = switchLabels[i].key;
1136
+			labels[i] = switchLabels[i].label;
1137
+		}
1138
+		
1132
         visitor.visitLookupSwitchInsn(defaultLabel, keys, labels);
1139
         visitor.visitLookupSwitchInsn(defaultLabel, keys, labels);
1133
     }
1140
     }
1134
 
1141
 

+ 1
- 1
Linker/src/main/java/org/openzen/zenscript/linker/ExpressionScope.java View File

80
 	}
80
 	}
81
 	
81
 	
82
 	public ExpressionScope forCall(FunctionHeader header) {
82
 	public ExpressionScope forCall(FunctionHeader header) {
83
-		if (header.typeParameters.length == 0)
83
+		if (header.typeParameters == null)
84
 			return this;
84
 			return this;
85
 		
85
 		
86
 		Map<TypeParameter, ITypeID> genericInferenceMap = new HashMap<>();
86
 		Map<TypeParameter, ITypeID> genericInferenceMap = new HashMap<>();

+ 10
- 6
Linker/src/main/java/org/openzen/zenscript/linker/FunctionScope.java View File

61
 				}
61
 				}
62
 			}
62
 			}
63
 			
63
 			
64
-			for (TypeParameter parameter : header.typeParameters) {
65
-				if (parameter.name.equals(name.name))
66
-					return new PartialTypeExpression(position, getTypeRegistry().getGeneric(parameter));
64
+			if (header.typeParameters != null) {
65
+				for (TypeParameter parameter : header.typeParameters) {
66
+					if (parameter.name.equals(name.name))
67
+						return new PartialTypeExpression(position, getTypeRegistry().getGeneric(parameter));
68
+				}
67
 			}
69
 			}
68
 		}
70
 		}
69
 		
71
 		
73
 	@Override
75
 	@Override
74
 	public ITypeID getType(CodePosition position, List<GenericName> name) {
76
 	public ITypeID getType(CodePosition position, List<GenericName> name) {
75
 		if (name.size() == 1 && name.get(0).hasNoArguments()) {
77
 		if (name.size() == 1 && name.get(0).hasNoArguments()) {
76
-			for (TypeParameter parameter : header.typeParameters) {
77
-				if (parameter.name.equals(name.get(0).name))
78
-					return getTypeRegistry().getGeneric(parameter);
78
+			if (header.typeParameters != null) {
79
+				for (TypeParameter parameter : header.typeParameters) {
80
+					if (parameter.name.equals(name.get(0).name))
81
+						return getTypeRegistry().getGeneric(parameter);
82
+				}
79
 			}
83
 			}
80
 		}
84
 		}
81
 		
85
 		

+ 2
- 1
Parser/src/main/java/org/openzen/zenscript/parser/definitions/ParsedFunctionHeader.java View File

34
  */
34
  */
35
 public class ParsedFunctionHeader {
35
 public class ParsedFunctionHeader {
36
 	public static ParsedFunctionHeader parse(ZSTokenStream tokens) {
36
 	public static ParsedFunctionHeader parse(ZSTokenStream tokens) {
37
-		List<ParsedGenericParameter> genericParameters = new ArrayList<>();
37
+		List<ParsedGenericParameter> genericParameters = null;
38
 		if (tokens.optional(ZSTokenType.T_LESS) != null) {
38
 		if (tokens.optional(ZSTokenType.T_LESS) != null) {
39
+			genericParameters = new ArrayList<>();
39
 			do {
40
 			do {
40
 				genericParameters.add(ParsedGenericParameter.parse(tokens));
41
 				genericParameters.add(ParsedGenericParameter.parse(tokens));
41
 			} while (tokens.optional(ZSTokenType.T_COMMA) != null);
42
 			} while (tokens.optional(ZSTokenType.T_COMMA) != null);

+ 3
- 3
Parser/src/main/java/org/openzen/zenscript/parser/expression/ParsedCallArguments.java View File

87
 			innerScope = scope.forCall(candidates.get(0));
87
 			innerScope = scope.forCall(candidates.get(0));
88
 		} else {
88
 		} else {
89
 			candidates = candidates.stream()
89
 			candidates = candidates.stream()
90
-					.filter(candidate -> candidate.typeParameters.length == 0)
90
+					.filter(candidate -> candidate.typeParameters == null)
91
 					.collect(Collectors.toList());
91
 					.collect(Collectors.toList());
92
 			
92
 			
93
 			if (candidates.isEmpty()) {
93
 			if (candidates.isEmpty()) {
115
 		ITypeID[] typeParameters = genericParameters;
115
 		ITypeID[] typeParameters = genericParameters;
116
 		if (typeParameters == null) {
116
 		if (typeParameters == null) {
117
 			for (FunctionHeader candidate : candidates) {
117
 			for (FunctionHeader candidate : candidates) {
118
-				if (candidate.typeParameters.length > 0) {
118
+				if (candidate.typeParameters != null) {
119
 					typeParameters = new ITypeID[candidate.typeParameters.length];
119
 					typeParameters = new ITypeID[candidate.typeParameters.length];
120
 					for (int i = 0; i < typeParameters.length; i++) {
120
 					for (int i = 0; i < typeParameters.length; i++) {
121
 						if (innerScope.genericInferenceMap.get(candidate.typeParameters[i]) == null)
121
 						if (innerScope.genericInferenceMap.get(candidate.typeParameters[i]) == null)
146
 			return false;
146
 			return false;
147
 		
147
 		
148
 		for (int i = 0; i < arguments.size(); i++) {
148
 		for (int i = 0; i < arguments.size(); i++) {
149
-			if (typeParameters == null && header.parameters[i].type.hasInferenceBlockingTypeParameters(header.typeParameters))
149
+			if (typeParameters == null && header.typeParameters != null && header.parameters[i].type.hasInferenceBlockingTypeParameters(header.typeParameters))
150
 				return false;
150
 				return false;
151
 			
151
 			
152
 			if (!arguments.get(i).isCompatibleWith(scope, header.parameters[i].type))
152
 			if (!arguments.get(i).isCompatibleWith(scope, header.parameters[i].type))

Loading…
Cancel
Save