|
@@ -1,10 +1,13 @@
|
1
|
1
|
package org.openzen.zenscript.javabytecode.compiler.definitions;
|
2
|
2
|
|
|
3
|
+import org.openzen.zenscript.javashared.JavaTypeGenericVisitor;
|
3
|
4
|
import org.objectweb.asm.ClassWriter;
|
4
|
5
|
import org.objectweb.asm.Opcodes;
|
5
|
6
|
import org.openzen.zenscript.codemodel.definition.*;
|
|
7
|
+import org.openzen.zenscript.codemodel.generic.TypeParameter;
|
6
|
8
|
import org.openzen.zenscript.codemodel.member.IDefinitionMember;
|
7
|
9
|
import org.openzen.zenscript.codemodel.type.BasicTypeID;
|
|
10
|
+import org.openzen.zenscript.codemodel.type.GenericTypeID;
|
8
|
11
|
import org.openzen.zenscript.codemodel.type.ITypeID;
|
9
|
12
|
import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
|
10
|
13
|
import org.openzen.zenscript.javabytecode.compiler.*;
|
|
@@ -27,13 +30,15 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
27
|
30
|
= JavaMethod.getNativeStatic(JavaClass.CLASS, "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;");
|
28
|
31
|
private static final JavaMethod ARRAY_CLONE
|
29
|
32
|
= JavaMethod.getNativeVirtual(JavaClass.ARRAYS, "clone", "()Ljava/lang/Object;");
|
30
|
|
-
|
|
33
|
+
|
31
|
34
|
private final JavaClassWriter outerWriter;
|
32
|
35
|
private final JavaBytecodeContext context;
|
|
36
|
+ final JavaTypeGenericVisitor javaTypeGenericVisitor;
|
33
|
37
|
|
34
|
38
|
public JavaDefinitionVisitor(JavaBytecodeContext context, JavaClassWriter outerWriter) {
|
35
|
39
|
this.context = context;
|
36
|
40
|
this.outerWriter = outerWriter;
|
|
41
|
+ this.javaTypeGenericVisitor = new JavaTypeGenericVisitor(context);
|
37
|
42
|
}
|
38
|
43
|
|
39
|
44
|
@Override
|
|
@@ -50,9 +55,9 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
50
|
55
|
interfaces.add(context.getInternalName(((ImplementationMember) member).type));
|
51
|
56
|
}
|
52
|
57
|
String signature = null;
|
53
|
|
-
|
|
58
|
+
|
54
|
59
|
writer.visit(Opcodes.V1_8, definition.modifiers, toClass.internalName, signature, superTypeInternalName, interfaces.toArray(new String[interfaces.size()]));
|
55
|
|
- JavaMemberVisitor memberVisitor = new JavaMemberVisitor(context, writer, toClass, definition);
|
|
60
|
+ JavaMemberVisitor memberVisitor = new JavaMemberVisitor(context, writer, toClass, definition);
|
56
|
61
|
for (IDefinitionMember member : definition.members) {
|
57
|
62
|
member.accept(memberVisitor);
|
58
|
63
|
}
|
|
@@ -64,14 +69,14 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
64
|
69
|
@Override
|
65
|
70
|
public byte[] visitInterface(InterfaceDefinition definition) {
|
66
|
71
|
JavaClass toClass = definition.getTag(JavaClass.class);
|
67
|
|
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
72
|
+ ClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
|
68
|
73
|
|
69
|
74
|
//TODO: Calculate signature from generic parameters
|
70
|
75
|
String signature = null;
|
71
|
76
|
String[] baseInterfaces = new String[definition.baseInterfaces.size()];
|
72
|
77
|
for (int i = 0; i < baseInterfaces.length; i++)
|
73
|
78
|
baseInterfaces[i] = context.getInternalName(definition.baseInterfaces.get(i));
|
74
|
|
-
|
|
79
|
+
|
75
|
80
|
writer.visit(Opcodes.V1_8, definition.modifiers | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT, toClass.internalName, signature, "java/lang/Object", baseInterfaces);
|
76
|
81
|
JavaMemberVisitor memberVisitor = new JavaMemberVisitor(context, writer, toClass, definition);
|
77
|
82
|
for (IDefinitionMember member : definition.members) {
|
|
@@ -85,10 +90,10 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
85
|
90
|
@Override
|
86
|
91
|
public byte[] visitEnum(EnumDefinition definition) {
|
87
|
92
|
System.out.println("Compiling enum " + definition.name + " in " + definition.position.getFilename());
|
88
|
|
-
|
|
93
|
+
|
89
|
94
|
String superTypeInternalName = definition.getSuperType() == null ? "java/lang/Object" : context.getInternalName(definition.getSuperType());
|
90
|
95
|
|
91
|
|
- ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
96
|
+ ClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
|
92
|
97
|
|
93
|
98
|
JavaClass toClass = definition.getTag(JavaClass.class);
|
94
|
99
|
writer.visit(Opcodes.V1_8, Opcodes.ACC_ENUM | Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL, toClass.internalName, "Ljava/lang/Enum<L" + toClass.internalName + ";>;", superTypeInternalName, null);
|
|
@@ -100,7 +105,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
100
|
105
|
for (IDefinitionMember member : definition.members) {
|
101
|
106
|
member.accept(visitor);
|
102
|
107
|
}
|
103
|
|
-
|
|
108
|
+
|
104
|
109
|
JavaMethod valuesMethod = JavaMethod.getStatic(toClass, "values", "()[L" + toClass.internalName + ";", Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC);
|
105
|
110
|
JavaWriter valuesWriter = new JavaWriter(writer, true, valuesMethod, definition, null, null);
|
106
|
111
|
valuesWriter.start();
|
|
@@ -119,7 +124,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
119
|
124
|
valueOfWriter.checkCast(toClass.internalName);
|
120
|
125
|
valueOfWriter.returnObject();
|
121
|
126
|
valueOfWriter.end();
|
122
|
|
-
|
|
127
|
+
|
123
|
128
|
writer.visitEnd();
|
124
|
129
|
return writer.toByteArray();
|
125
|
130
|
}
|
|
@@ -132,9 +137,9 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
132
|
137
|
@Override
|
133
|
138
|
public byte[] visitFunction(FunctionDefinition definition) {
|
134
|
139
|
CompilerUtils.tagMethodParameters(context, definition.header, true);
|
135
|
|
-
|
|
140
|
+
|
136
|
141
|
final String signature = context.getMethodSignature(definition.header);
|
137
|
|
-
|
|
142
|
+
|
138
|
143
|
final JavaMethod method = definition.caller.getTag(JavaMethod.class);
|
139
|
144
|
|
140
|
145
|
final JavaWriter writer = new JavaWriter(outerWriter, true, method, definition, signature, null);
|
|
@@ -169,7 +174,13 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
169
|
174
|
final JavaClass toClass = variant.getTag(JavaClass.class);
|
170
|
175
|
final JavaClassWriter writer = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
|
171
|
176
|
|
172
|
|
- writer.visit(Opcodes.V1_8, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, toClass.internalName, null, "java/lang/Object", null);
|
|
177
|
+ final String variantName = variant.name;
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+ final String ss = "<" + javaTypeGenericVisitor.getGenericSignature(variant.genericParameters) + ">Ljava/lang/Object;";
|
|
181
|
+ JavaClassWriter.registerSuperClass(variantName, "java/lang/Object");
|
|
182
|
+
|
|
183
|
+ writer.visit(Opcodes.V1_8, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, toClass.internalName, ss, "java/lang/Object", null);
|
173
|
184
|
writer.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT, "getDenominator", "()I", null, null).visitEnd();
|
174
|
185
|
|
175
|
186
|
final JavaMemberVisitor visitor = new JavaMemberVisitor(context, writer, toClass, variant);
|
|
@@ -179,6 +190,8 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
179
|
190
|
for (final VariantDefinition.Option option : options) {
|
180
|
191
|
JavaVariantOption optionTag = option.getTag(JavaVariantOption.class);
|
181
|
192
|
final JavaClassWriter optionWriter = new JavaClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
193
|
+ final String optionClassName = variantName + "$" + option.name;
|
|
194
|
+ JavaClassWriter.registerSuperClass(optionClassName, variantName);
|
182
|
195
|
|
183
|
196
|
writer.visitInnerClass(optionTag.variantOptionClass.internalName, optionTag.variantClass.internalName, option.name, Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL);
|
184
|
197
|
|
|
@@ -186,30 +199,50 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
186
|
199
|
final String signature;
|
187
|
200
|
{
|
188
|
201
|
StringBuilder builder = new StringBuilder();
|
189
|
|
- for (int i = 0; i < option.types.length; ++i) {
|
190
|
|
- builder.append("<T").append(i).append(":");
|
191
|
|
- builder.append(context.getDescriptor(option.types[i]));
|
|
202
|
+ //TODO check if this can be changed to what Stan was up to
|
|
203
|
+ builder.append("<");
|
|
204
|
+ for (final ITypeID type : option.types) {
|
|
205
|
+ builder.append(javaTypeGenericVisitor.getSignatureWithBound(type));
|
192
|
206
|
}
|
193
|
207
|
builder.append(">");
|
194
|
|
- builder.append("L").append(toClass.internalName).append(";");
|
195
|
|
-
|
196
|
|
- signature = builder.toString();
|
|
208
|
+ builder.append("L").append(toClass.internalName).append("<");
|
|
209
|
+
|
|
210
|
+ for (final TypeParameter genericParameter : variant.genericParameters) {
|
|
211
|
+ boolean t = true;
|
|
212
|
+ for (final ITypeID type : option.types)
|
|
213
|
+ if (type instanceof GenericTypeID) {
|
|
214
|
+ final GenericTypeID genericTypeID = (GenericTypeID) type;
|
|
215
|
+ if (genericParameter == genericTypeID.parameter) {
|
|
216
|
+ builder.append("T").append(genericParameter.name).append(";");
|
|
217
|
+ t = false;
|
|
218
|
+ }
|
|
219
|
+ }
|
|
220
|
+ if (t)
|
|
221
|
+ builder.append(javaTypeGenericVisitor.getGenericBounds(genericParameter.bounds));
|
|
222
|
+
|
|
223
|
+ }
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+ signature = builder.append(">;").toString();
|
197
|
227
|
}
|
198
|
228
|
|
199
|
229
|
optionWriter.visit(Opcodes.V1_8, Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, optionTag.variantOptionClass.internalName, signature, optionTag.variantClass.internalName, null);
|
200
|
230
|
final JavaMemberVisitor optionVisitor = new JavaMemberVisitor(context, optionWriter, optionTag.variantOptionClass, variant);
|
201
|
231
|
final StringBuilder optionInitDescBuilder = new StringBuilder("(");
|
|
232
|
+ final StringBuilder optionInitSignatureBuilder = new StringBuilder("(");
|
202
|
233
|
|
203
|
234
|
ITypeID[] types = option.types;
|
204
|
235
|
for (int i = 0; i < types.length; ++i) {
|
205
|
236
|
final String descriptor = context.getDescriptor(types[i]);
|
206
|
237
|
optionInitDescBuilder.append(descriptor);
|
207
|
|
- optionWriter.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "field" + i, descriptor, "TT" + i + ";", null).visitEnd();
|
|
238
|
+ optionInitSignatureBuilder.append("T").append(((GenericTypeID) types[i]).parameter.name).append(";");
|
|
239
|
+ optionWriter.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, "field" + i, descriptor, "T" + ((GenericTypeID) types[i]).parameter.name + ";", null).visitEnd();
|
208
|
240
|
}
|
209
|
241
|
optionInitDescBuilder.append(")V");
|
210
|
|
-
|
211
|
|
- JavaMethod constructorMethod = JavaMethod.getConstructor(optionTag.variantOptionClass, optionInitDescBuilder.toString(), JavaModifiers.PUBLIC);
|
212
|
|
- final JavaWriter initWriter = new JavaWriter(optionWriter, constructorMethod, variant, optionInitDescBuilder.toString(), null);
|
|
242
|
+ optionInitSignatureBuilder.append(")V");
|
|
243
|
+
|
|
244
|
+JavaMethod constructorMethod = JavaMethod.getConstructor(optionTag.variantOptionClass, optionInitDescBuilder.toString(), JavaModifiers.PUBLIC);
|
|
245
|
+ final JavaWriter initWriter = new JavaWriter(optionWriter, constructorMethod, variant, optionInitSignatureBuilder.toString(), null);
|
213
|
246
|
initWriter.start();
|
214
|
247
|
initWriter.loadObject(0);
|
215
|
248
|
initWriter.dup();
|
|
@@ -224,7 +257,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
224
|
257
|
initWriter.pop();
|
225
|
258
|
initWriter.ret();
|
226
|
259
|
initWriter.end();
|
227
|
|
-
|
|
260
|
+
|
228
|
261
|
//Denominator for switch-cases
|
229
|
262
|
JavaMethod denominator = JavaMethod.getVirtual(optionTag.variantOptionClass, "getDenominator", "()I", JavaModifiers.PUBLIC);
|
230
|
263
|
final JavaWriter getDenominator = new JavaWriter(optionWriter, denominator, null, null, null, "java/lang/Override");
|
|
@@ -232,7 +265,7 @@ public class JavaDefinitionVisitor implements DefinitionVisitor<byte[]> {
|
232
|
265
|
getDenominator.constant(option.ordinal);
|
233
|
266
|
getDenominator.returnInt();
|
234
|
267
|
getDenominator.end();
|
235
|
|
-
|
|
268
|
+
|
236
|
269
|
optionVisitor.end();
|
237
|
270
|
optionWriter.visitEnd();
|
238
|
271
|
final byte[] byteArray = optionWriter.toByteArray();
|