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