Browse Source

Some work on match cases, committing to merge Stans changes

kindlich 6 years ago
parent
commit
794dedb9ee
No known key found for this signature in database

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

@@ -15,6 +15,7 @@ import org.openzen.zenscript.codemodel.type.BasicTypeID;
15 15
 import org.openzen.zenscript.codemodel.type.ITypeID;
16 16
 import org.openzen.zenscript.javabytecode.JavaModule;
17 17
 import org.openzen.zenscript.javabytecode.JavaParameterInfo;
18
+import org.openzen.zenscript.javabytecode.compiler.definitions.JavaOptionInfoTag;
18 19
 
19 20
 import java.io.FileOutputStream;
20 21
 import java.io.IOException;
@@ -195,7 +196,7 @@ public class CompilerUtils {
195 196
 
196 197
 		@Override
197 198
 		public Integer acceptVariantOption(VariantOptionSwitchValue value) {
198
-			throw new UnsupportedOperationException("Not there yet");
199
+			return value.option.getTag(JavaOptionInfoTag.class).number;
199 200
 		}
200 201
 	}
201 202
 }

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

@@ -8,11 +8,15 @@ import org.openzen.zencode.shared.CompileException;
8 8
 import org.openzen.zencode.shared.CompileExceptionCode;
9 9
 import org.openzen.zenscript.codemodel.CompareType;
10 10
 import org.openzen.zenscript.codemodel.expression.*;
11
+import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
11 12
 import org.openzen.zenscript.codemodel.member.ref.ConstMemberRef;
12 13
 import org.openzen.zenscript.codemodel.member.ref.DefinitionMemberRef;
13 14
 import org.openzen.zenscript.codemodel.member.ref.FieldMemberRef;
14 15
 import org.openzen.zenscript.codemodel.statement.ReturnStatement;
15
-import org.openzen.zenscript.codemodel.type.*;
16
+import org.openzen.zenscript.codemodel.type.ArrayTypeID;
17
+import org.openzen.zenscript.codemodel.type.AssocTypeID;
18
+import org.openzen.zenscript.codemodel.type.BasicTypeID;
19
+import org.openzen.zenscript.codemodel.type.DefinitionTypeID;
16 20
 import org.openzen.zenscript.codemodel.type.member.BuiltinID;
17 21
 import org.openzen.zenscript.implementations.IntRange;
18 22
 import org.openzen.zenscript.javabytecode.*;
@@ -155,7 +159,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
155 159
 	private static final JavaMethodInfo COLLECTION_SIZE = new JavaMethodInfo(COLLECTION, "size", "()I", PUBLIC);
156 160
 	private static final JavaMethodInfo COLLECTION_TOARRAY = new JavaMethodInfo(COLLECTION, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", PUBLIC);
157 161
 
158
-	private final JavaWriter javaWriter;
162
+	protected final JavaWriter javaWriter;
159 163
 	private final JavaCapturedExpressionVisitor capturedExpressionVisitor = new JavaCapturedExpressionVisitor(this);
160 164
 
161 165
 	public JavaExpressionVisitor(JavaWriter javaWriter) {
@@ -1533,9 +1537,9 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
1533 1537
 		return null;
1534 1538
 	}
1535 1539
 
1536
-    @Override
1537
-    public Void visitConstructorThisCall(ConstructorThisCallExpression expression) {
1538
-        Type type = expression.objectType.accept(JavaTypeVisitor.INSTANCE);
1540
+	@Override
1541
+	public Void visitConstructorThisCall(ConstructorThisCallExpression expression) {
1542
+		Type type = expression.objectType.accept(JavaTypeVisitor.INSTANCE);
1539 1543
 		try {
1540 1544
 			type.getInternalName();
1541 1545
 		} catch (NullPointerException ex) {
@@ -1548,13 +1552,13 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
1548 1552
 			javaWriter.loadInt(2);
1549 1553
 		}
1550 1554
 
1551
-        for (Expression argument : expression.arguments.arguments) {
1552
-            argument.accept(this);
1553
-        }
1555
+		for (Expression argument : expression.arguments.arguments) {
1556
+			argument.accept(this);
1557
+		}
1554 1558
 		String internalName = type.getInternalName();
1555
-        javaWriter.invokeSpecial(internalName, "<init>", CompilerUtils.calcDesc(expression.constructor.getHeader(), javaWriter.method.javaClass.isEnum));
1556
-        return null;
1557
-    }
1559
+		javaWriter.invokeSpecial(internalName, "<init>", CompilerUtils.calcDesc(expression.constructor.getHeader(), javaWriter.method.javaClass.isEnum));
1560
+		return null;
1561
+	}
1558 1562
 
1559 1563
 	@Override
1560 1564
 	public Void visitConstructorSuperCall(ConstructorSuperCallExpression expression) {
@@ -1982,9 +1986,22 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
1982 1986
 
1983 1987
 		javaWriter.label(start);
1984 1988
 		expression.value.accept(this);
1989
+
1990
+
1991
+		//TODO replace beforeSwitch visitor or similar
1985 1992
 		if (expression.value.type == BasicTypeID.STRING)
1986 1993
 			javaWriter.invokeVirtual(new JavaMethodInfo(new JavaClassInfo("java/lang/Object"), "hashCode", "()I", 0));
1987 1994
 
1995
+		//TODO replace with beforeSwitch visitor or similar
1996
+		for (MatchExpression.Case aCase : expression.cases) {
1997
+			if (aCase.key instanceof VariantOptionSwitchValue) {
1998
+				VariantOptionSwitchValue variantOptionSwitchValue = (VariantOptionSwitchValue) aCase.key;
1999
+				javaWriter.invokeVirtual(new JavaMethodInfo(new JavaClassInfo(variantOptionSwitchValue.option.getName()), "getDenominator", "()I", 0));
2000
+				break;
2001
+			}
2002
+		}
2003
+
2004
+
1988 2005
 		final boolean hasNoDefault = hasNoDefault(expression);
1989 2006
 
1990 2007
 		final MatchExpression.Case[] cases = expression.cases;
@@ -2011,12 +2028,16 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
2011 2028
 				javaWriter.label(defaultLabel);
2012 2029
 			}
2013 2030
 			//switchCase.value.body.setTag(MatchExpression.class, expression);
2014
-			switchCase.value.accept(this);
2031
+			switchCase.value.accept(new MatchExpressionVisitor(this.javaWriter));
2015 2032
 			javaWriter.goTo(end);
2016 2033
 		}
2017 2034
 
2018 2035
 		if (hasNoDefault) {
2019 2036
 			javaWriter.label(defaultLabel);
2037
+			if (Object.class.isAssignableFrom(expression.type.accept(JavaTypeClassVisitor.INSTANCE)))
2038
+				javaWriter.aConstNull();
2039
+			else
2040
+				javaWriter.iConst0();
2020 2041
 		}
2021 2042
 
2022 2043
 		javaWriter.label(end);
@@ -2327,7 +2348,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
2327 2348
 		expression.value.accept(this);
2328 2349
 
2329 2350
 		//i.e. if it was a primitive
2330
-		if(info != null)
2351
+		if (info != null)
2331 2352
 			javaWriter.invokeSpecial(info);
2332 2353
 		return null;
2333 2354
 	}
@@ -2398,4 +2419,27 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
2398 2419
 		}
2399 2420
 		return true;
2400 2421
 	}
2422
+
2423
+
2424
+	private static final class MatchExpressionVisitor extends JavaExpressionVisitor {
2425
+		public MatchExpressionVisitor(JavaWriter javaWriter) {
2426
+			super(javaWriter);
2427
+		}
2428
+
2429
+		@Override
2430
+		public Void visitGetLocalVariable(GetLocalVariableExpression expression) {
2431
+			final Label label = new Label();
2432
+			final JavaLocalVariableInfo tag = expression.variable.getTag(JavaLocalVariableInfo.class);
2433
+			if (tag != null) {
2434
+				tag.end = label;
2435
+				javaWriter.load(tag.type, tag.local);
2436
+				javaWriter.label(label);
2437
+				return null;
2438
+			}
2439
+
2440
+			javaWriter.aConstNull();
2441
+			return null;
2442
+
2443
+		}
2444
+	}
2401 2445
 }

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

@@ -142,7 +142,7 @@ public class JavaStatementVisitor implements StatementVisitor<Boolean> {
142 142
 	@Override
143 143
 	public Boolean visitReturn(ReturnStatement statement) {
144 144
 		statement.value.accept(expressionVisitor);
145
-		javaWriter.returnType(Type.getType(statement.value.type.accept(JavaTypeClassVisitor.INSTANCE)));
145
+		javaWriter.returnType(statement.value.type.accept(JavaTypeVisitor.INSTANCE));
146 146
 		return true;
147 147
 	}
148 148
 

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

@@ -78,7 +78,7 @@ public class JavaTypeClassVisitor implements ITypeVisitor<Class> {
78 78
 
79 79
 	@Override
80 80
 	public Class visitGeneric(GenericTypeID generic) {
81
-		return null;
81
+		return Object.class;
82 82
 	}
83 83
 
84 84
 	@Override

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

@@ -40,7 +40,8 @@ public class JavaTypeVisitor implements ITypeVisitor<Type> {
40 40
 
41 41
 	@Override
42 42
 	public Type visitGeneric(GenericTypeID generic) {
43
-		return Type.getType(generic.accept(JavaTypeClassVisitor.INSTANCE));
43
+		final Class<?> clazz = generic.accept(JavaTypeClassVisitor.INSTANCE);
44
+		return Type.getType(clazz == null ? Object.class : clazz);
44 45
 	}
45 46
 
46 47
 	@Override

+ 101
- 12
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaDefinitionVisitor.java View File

@@ -1,8 +1,10 @@
1 1
 package org.openzen.zenscript.javabytecode.compiler.definitions;
2 2
 
3 3
 import org.objectweb.asm.ClassWriter;
4
+import org.objectweb.asm.MethodVisitor;
4 5
 import org.objectweb.asm.Opcodes;
5 6
 import org.objectweb.asm.Type;
7
+import org.openzen.zenscript.codemodel.Modifiers;
6 8
 import org.openzen.zenscript.codemodel.definition.*;
7 9
 import org.openzen.zenscript.codemodel.member.IDefinitionMember;
8 10
 import org.openzen.zenscript.codemodel.type.BasicTypeID;
@@ -12,6 +14,10 @@ import org.openzen.zenscript.javabytecode.JavaMethodInfo;
12 14
 import org.openzen.zenscript.javabytecode.JavaModule;
13 15
 import org.openzen.zenscript.javabytecode.compiler.*;
14 16
 
17
+import java.io.FileOutputStream;
18
+import java.io.IOException;
19
+import java.util.List;
20
+
15 21
 
16 22
 public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
17 23
 	private static final JavaClassInfo T_CLASS = new JavaClassInfo("java/lang/Class");
@@ -39,11 +45,11 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
39 45
 	public byte[] visitClass(ClassDefinition definition) {
40 46
 		//Classes will always be created in a new File/Class
41 47
 
42
-        final Type superType;
43
-        if (definition.getSuperType() == null)
44
-            superType = Type.getType(Object.class);
45
-        else
46
-            superType = Type.getType(definition.getSuperType().accept(JavaTypeClassVisitor.INSTANCE));
48
+		final Type superType;
49
+		if (definition.getSuperType() == null)
50
+			superType = Type.getType(Object.class);
51
+		else
52
+			superType = Type.getType(definition.getSuperType().accept(JavaTypeClassVisitor.INSTANCE));
47 53
 
48 54
 		JavaClassInfo toClass = new JavaClassInfo(definition.name);
49 55
 		JavaClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
@@ -84,12 +90,12 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
84 90
 	@Override
85 91
 	public byte[] visitEnum(EnumDefinition definition) {
86 92
 		System.out.println("Compiling enum " + definition.name + " in " + definition.position.filename);
87
-		
88
-        final Type superType;
89
-        if (definition.getSuperType() == null)
90
-            superType = Type.getType(Object.class);
91
-        else
92
-            superType = Type.getType(definition.getSuperType().accept(JavaTypeClassVisitor.INSTANCE));
93
+
94
+		final Type superType;
95
+		if (definition.getSuperType() == null)
96
+			superType = Type.getType(Object.class);
97
+		else
98
+			superType = Type.getType(definition.getSuperType().accept(JavaTypeClassVisitor.INSTANCE));
93 99
 
94 100
 		ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
95 101
 
@@ -178,6 +184,89 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
178 184
 
179 185
 	@Override
180 186
 	public byte[] visitVariant(VariantDefinition variant) {
181
-		throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
187
+
188
+		final String variantName = variant.name;
189
+		final JavaClassInfo toClass = new JavaClassInfo(variantName);
190
+		final JavaClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
191
+
192
+		writer.visit(Opcodes.V1_8, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, variantName, null, "java/lang/Object", null);
193
+		writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, "getDenominator", "()I", null, null).visitEnd();
194
+
195
+
196
+		final JavaMemberVisitor visitor = new JavaMemberVisitor(writer, toClass, variant);
197
+
198
+
199
+		final List<VariantDefinition.Option> options = variant.options;
200
+		for (int optionNo = 0, optionsSize = options.size(); optionNo < optionsSize; optionNo++) {
201
+			final VariantDefinition.Option option = options.get(optionNo);
202
+			option.setTag(JavaOptionInfoTag.class, new JavaOptionInfoTag(optionNo));
203
+		}
204
+
205
+		for (final IDefinitionMember member : variant.members) {
206
+			member.accept(visitor);
207
+		}
208
+
209
+
210
+
211
+
212
+		//Each option is one of the possible child classes
213
+		for (int optionNo = 0, optionsSize = options.size(); optionNo < optionsSize; ++optionNo) {
214
+			final VariantDefinition.Option option = options.get(optionNo);
215
+
216
+			final String optionClassName = variantName + "$" + option.name;
217
+			final JavaClassInfo optionClass = new JavaClassInfo(variantName);
218
+			final JavaClassWriter optionWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
219
+
220
+
221
+			//Generic option signature
222
+			final String signature;
223
+			{
224
+				StringBuilder builder = new StringBuilder();
225
+				for (int i = 0; i < option.types.length; ++i) {
226
+					builder.append("<T").append(i).append(":");
227
+					builder.append(option.types[i].accept(JavaTypeVisitor.INSTANCE).getDescriptor());
228
+				}
229
+				builder.append(">");
230
+				builder.append("L").append(variantName).append(";");
231
+
232
+
233
+				signature = builder.toString();
234
+			}
235
+
236
+			optionWriter.visit(Opcodes.V1_8, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, optionClassName, signature, variantName, null);
237
+			final JavaMemberVisitor optionVisitor = new JavaMemberVisitor(optionWriter, optionClass, variant);
238
+
239
+			ITypeID[] types = option.types;
240
+			for (int i = 0; i < types.length; ++i) {
241
+				final ITypeID type = types[i];
242
+				final String internalName = type.accept(JavaTypeVisitor.INSTANCE).getInternalName();
243
+				optionWriter.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "Field" + i, internalName, "TT" + i + ";", null).visitEnd();
244
+			}
245
+
246
+
247
+			//Denominator for switch-cases
248
+			final JavaWriter getDenominator = new JavaWriter(optionWriter, new JavaMethodInfo(optionClass, "getDenominator", "()I", Modifiers.PUBLIC), null,null, null, "java/lang/Override");
249
+			getDenominator.start();
250
+			getDenominator.constant(optionNo);
251
+			getDenominator.returnInt();
252
+			getDenominator.end();
253
+
254
+
255
+
256
+			//Print the option files, won't be in production
257
+			optionVisitor.end();
258
+			optionWriter.visitEnd();
259
+			JavaModule.classes.put(optionClassName, optionWriter.toByteArray());
260
+			try (FileOutputStream out = new FileOutputStream(optionClassName + ".class")) {
261
+				out.write(optionWriter.toByteArray());
262
+			} catch (IOException e) {
263
+				e.printStackTrace();
264
+			}
265
+		}
266
+		visitor.end();
267
+		writer.visitEnd();
268
+
269
+
270
+		return writer.toByteArray();
182 271
 	}
183 272
 }

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

@@ -143,7 +143,7 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
143 143
 		for (final FunctionParameter parameter : member.header.parameters) {
144 144
 			methodWriter.nameParameter(0, parameter.name);
145 145
 			if (!isAbstract)
146
-				methodWriter.nameVariable(parameter.getTag(JavaParameterInfo.class).index, parameter.name, methodStart, methodEnd, Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
146
+				methodWriter.nameVariable(parameter.getTag(JavaParameterInfo.class).index, parameter.name, methodStart, methodEnd, parameter.type.accept(JavaTypeVisitor.INSTANCE));
147 147
 		}
148 148
 
149 149
 		final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(methodWriter);

+ 9
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaOptionInfoTag.java View File

@@ -0,0 +1,9 @@
1
+package org.openzen.zenscript.javabytecode.compiler.definitions;
2
+
3
+public class JavaOptionInfoTag {
4
+	public final int number;
5
+
6
+	public JavaOptionInfoTag(int number) {
7
+		this.number = number;
8
+	}
9
+}

Loading…
Cancel
Save