|
@@ -1,7 +1,5 @@
|
1
|
1
|
package org.openzen.zenscript.javabytecode.compiler.definitions;
|
2
|
2
|
|
3
|
|
-import java.util.ArrayList;
|
4
|
|
-import java.util.List;
|
5
|
3
|
import org.objectweb.asm.ClassWriter;
|
6
|
4
|
import org.objectweb.asm.Label;
|
7
|
5
|
import org.objectweb.asm.Opcodes;
|
|
@@ -10,6 +8,7 @@ import org.openzen.zenscript.codemodel.FunctionParameter;
|
10
|
8
|
import org.openzen.zenscript.codemodel.HighLevelDefinition;
|
11
|
9
|
import org.openzen.zenscript.codemodel.Modifiers;
|
12
|
10
|
import org.openzen.zenscript.codemodel.definition.EnumDefinition;
|
|
11
|
+import org.openzen.zenscript.codemodel.expression.Expression;
|
13
|
12
|
import org.openzen.zenscript.codemodel.member.*;
|
14
|
13
|
import org.openzen.zenscript.javabytecode.JavaClassInfo;
|
15
|
14
|
import org.openzen.zenscript.javabytecode.JavaFieldInfo;
|
|
@@ -17,17 +16,25 @@ import org.openzen.zenscript.javabytecode.JavaMethodInfo;
|
17
|
16
|
import org.openzen.zenscript.javabytecode.JavaParameterInfo;
|
18
|
17
|
import org.openzen.zenscript.javabytecode.compiler.*;
|
19
|
18
|
|
|
19
|
+import java.util.List;
|
|
20
|
+
|
20
|
21
|
public class JavaMemberVisitor implements MemberVisitor<Void> {
|
21
|
22
|
|
22
|
23
|
private final ClassWriter writer;
|
23
|
|
- private final JavaClassInfo toClass;
|
24
|
|
- private final HighLevelDefinition definition;
|
25
|
|
- private final List<StaticInitializerMember> staticInitializers = new ArrayList<>();
|
|
24
|
+ private final JavaClassInfo toClass;
|
|
25
|
+ private final HighLevelDefinition definition;
|
|
26
|
+ private final JavaStatementVisitor clinitStatementVisitor;
|
|
27
|
+ private EnumDefinition enumDefinition = null;
|
26
|
28
|
|
27
|
29
|
public JavaMemberVisitor(ClassWriter writer, JavaClassInfo toClass, HighLevelDefinition definition) {
|
28
|
30
|
this.writer = writer;
|
29
|
|
- this.toClass = toClass;
|
30
|
|
- this.definition = definition;
|
|
31
|
+ this.toClass = toClass;
|
|
32
|
+ this.definition = definition;
|
|
33
|
+
|
|
34
|
+ final JavaWriter javaWriter = new JavaWriter(writer, new JavaMethodInfo(toClass, "<clinit>", "()V", 0), definition, null, null);
|
|
35
|
+ this.clinitStatementVisitor = new JavaStatementVisitor(javaWriter);
|
|
36
|
+ this.clinitStatementVisitor.start();
|
|
37
|
+ CompilerUtils.writeDefaultFieldInitializers(javaWriter, definition, true);
|
31
|
38
|
}
|
32
|
39
|
|
33
|
40
|
@Override
|
|
@@ -36,52 +43,52 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
|
36
|
43
|
//TODO calc signature
|
37
|
44
|
String signature = null;
|
38
|
45
|
final String descriptor = Type.getDescriptor(member.type.accept(JavaTypeClassVisitor.INSTANCE));
|
39
|
|
- writer.visitField(member.modifiers, member.name, descriptor, signature, null).visitEnd();
|
|
46
|
+ writer.visitField(CompilerUtils.calcAccess(member.modifiers), member.name, descriptor, signature, null).visitEnd();
|
40
|
47
|
member.setTag(JavaFieldInfo.class, new JavaFieldInfo(toClass, member.name, descriptor));
|
41
|
48
|
return null;
|
42
|
49
|
}
|
43
|
50
|
|
44
|
51
|
@Override
|
45
|
52
|
public Void visitConstructor(ConstructorMember member) {
|
46
|
|
- final boolean isEnum = definition instanceof EnumDefinition;
|
47
|
|
- String descriptor = CompilerUtils.calcDesc(member.header, isEnum);
|
48
|
|
- final JavaMethodInfo method = new JavaMethodInfo(toClass, "<init>", descriptor, isEnum ? Opcodes.ACC_PRIVATE : CompilerUtils.calcAccess(member.modifiers));
|
49
|
|
-
|
|
53
|
+ final boolean isEnum = definition instanceof EnumDefinition;
|
|
54
|
+ String descriptor = CompilerUtils.calcDesc(member.header, isEnum);
|
|
55
|
+ final JavaMethodInfo method = new JavaMethodInfo(toClass, "<init>", descriptor, isEnum ? Opcodes.ACC_PRIVATE : CompilerUtils.calcAccess(member.modifiers));
|
|
56
|
+
|
50
|
57
|
final Label constructorStart = new Label();
|
51
|
58
|
final Label constructorEnd = new Label();
|
52
|
59
|
final JavaWriter constructorWriter = new JavaWriter(writer, method, definition, CompilerUtils.calcSign(member.header, isEnum), null);
|
53
|
60
|
constructorWriter.label(constructorStart);
|
54
|
|
- CompilerUtils.tagConstructorParameters(member.header, isEnum);
|
|
61
|
+ CompilerUtils.tagConstructorParameters(member.header, isEnum);
|
55
|
62
|
for (FunctionParameter parameter : member.header.parameters) {
|
56
|
63
|
constructorWriter.nameVariable(
|
57
|
|
- parameter.getTag(JavaParameterInfo.class).index,
|
58
|
|
- parameter.name,
|
59
|
|
- constructorStart,
|
60
|
|
- constructorEnd,
|
61
|
|
- Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
|
|
64
|
+ parameter.getTag(JavaParameterInfo.class).index,
|
|
65
|
+ parameter.name,
|
|
66
|
+ constructorStart,
|
|
67
|
+ constructorEnd,
|
|
68
|
+ Type.getType(parameter.type.accept(JavaTypeClassVisitor.INSTANCE)));
|
62
|
69
|
}
|
63
|
|
-
|
|
70
|
+
|
64
|
71
|
final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(constructorWriter);
|
65
|
72
|
statementVisitor.start();
|
66
|
|
-
|
67
|
|
- if (!member.isConstructorForwarded()) {
|
68
|
|
- if (isEnum) {
|
69
|
|
- System.out.println("Writing enum constructor");
|
70
|
|
- constructorWriter.getVisitor().newLocal(Type.getType(String.class));
|
71
|
|
- constructorWriter.getVisitor().newLocal(Type.getType(int.class));
|
72
|
|
- constructorWriter.loadObject(0);
|
73
|
|
- constructorWriter.loadObject(1);
|
74
|
|
- constructorWriter.loadInt(2);
|
75
|
|
- constructorWriter.invokeSpecial(Type.getInternalName(Enum.class), "<init>", "(Ljava/lang/String;I)V");
|
76
|
|
- } else if (definition.superType == null) {
|
77
|
|
- System.out.println("Writing regular constructor");
|
78
|
|
- constructorWriter.load(Type.getType(Object.class), 0);
|
79
|
|
- constructorWriter.invokeSpecial(Type.getInternalName(Object.class), "<init>", "()V");
|
80
|
|
- }
|
81
|
|
-
|
82
|
|
- CompilerUtils.writeDefaultFieldInitializers(constructorWriter, definition, false);
|
83
|
|
- }
|
84
|
|
-
|
|
73
|
+
|
|
74
|
+ if (!member.isConstructorForwarded()) {
|
|
75
|
+ if (isEnum) {
|
|
76
|
+ System.out.println("Writing enum constructor");
|
|
77
|
+ constructorWriter.getVisitor().newLocal(Type.getType(String.class));
|
|
78
|
+ constructorWriter.getVisitor().newLocal(Type.getType(int.class));
|
|
79
|
+ constructorWriter.loadObject(0);
|
|
80
|
+ constructorWriter.loadObject(1);
|
|
81
|
+ constructorWriter.loadInt(2);
|
|
82
|
+ constructorWriter.invokeSpecial(Type.getInternalName(Enum.class), "<init>", "(Ljava/lang/String;I)V");
|
|
83
|
+ } else if (definition.superType == null) {
|
|
84
|
+ System.out.println("Writing regular constructor");
|
|
85
|
+ constructorWriter.load(Type.getType(Object.class), 0);
|
|
86
|
+ constructorWriter.invokeSpecial(Type.getInternalName(Object.class), "<init>", "()V");
|
|
87
|
+ }
|
|
88
|
+
|
|
89
|
+ CompilerUtils.writeDefaultFieldInitializers(constructorWriter, definition, false);
|
|
90
|
+ }
|
|
91
|
+
|
85
|
92
|
member.body.accept(statementVisitor);
|
86
|
93
|
constructorWriter.label(constructorEnd);
|
87
|
94
|
statementVisitor.end();
|
|
@@ -90,18 +97,18 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
|
90
|
97
|
|
91
|
98
|
@Override
|
92
|
99
|
public Void visitMethod(MethodMember member) {
|
93
|
|
- CompilerUtils.tagMethodParameters(member.header, member.isStatic());
|
94
|
|
-
|
|
100
|
+ CompilerUtils.tagMethodParameters(member.header, member.isStatic());
|
|
101
|
+
|
95
|
102
|
final boolean isAbstract = member.body == null || Modifiers.isAbstract(member.modifiers);
|
96
|
|
- int modifiers = (isAbstract ? Opcodes.ACC_ABSTRACT : 0)
|
97
|
|
- | (member.isStatic() ? Opcodes.ACC_STATIC : 0)
|
98
|
|
- | CompilerUtils.calcAccess(member.modifiers);
|
99
|
|
- final JavaMethodInfo method = new JavaMethodInfo(
|
100
|
|
- toClass,
|
101
|
|
- member.name,
|
102
|
|
- CompilerUtils.calcSign(member.header, false),
|
103
|
|
- modifiers);
|
104
|
|
-
|
|
103
|
+ int modifiers = (isAbstract ? Opcodes.ACC_ABSTRACT : 0)
|
|
104
|
+ | (member.isStatic() ? Opcodes.ACC_STATIC : 0)
|
|
105
|
+ | CompilerUtils.calcAccess(member.modifiers);
|
|
106
|
+ final JavaMethodInfo method = new JavaMethodInfo(
|
|
107
|
+ toClass,
|
|
108
|
+ member.name,
|
|
109
|
+ CompilerUtils.calcSign(member.header, false),
|
|
110
|
+ modifiers);
|
|
111
|
+
|
105
|
112
|
final Label methodStart = new Label();
|
106
|
113
|
final Label methodEnd = new Label();
|
107
|
114
|
final JavaWriter methodWriter = new JavaWriter(writer, method, definition, CompilerUtils.calcSign(member.header, false), null);
|
|
@@ -116,7 +123,7 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
|
116
|
123
|
|
117
|
124
|
if (!isAbstract) {
|
118
|
125
|
statementVisitor.start();
|
119
|
|
- member.body.accept(statementVisitor);
|
|
126
|
+ member.body.accept(statementVisitor);
|
120
|
127
|
methodWriter.label(methodEnd);
|
121
|
128
|
statementVisitor.end();
|
122
|
129
|
}
|
|
@@ -137,6 +144,23 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
|
137
|
144
|
|
138
|
145
|
@Override
|
139
|
146
|
public Void visitEnumConstant(EnumConstantMember member) {
|
|
147
|
+ writer.visitField(Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_ENUM, member.name, "L" + definition.name + ";", null, null).visitEnd();
|
|
148
|
+ final String internalName = member.constructor.type.accept(JavaTypeVisitor.INSTANCE).getInternalName();
|
|
149
|
+ final JavaWriter clinitWriter = clinitStatementVisitor.getJavaWriter();
|
|
150
|
+ clinitWriter.newObject(internalName);
|
|
151
|
+ clinitWriter.dup();
|
|
152
|
+ clinitWriter.constant(member.name);
|
|
153
|
+ clinitWriter.constant(member.value);
|
|
154
|
+ for (Expression argument : member.constructor.arguments.arguments) {
|
|
155
|
+ argument.accept(clinitStatementVisitor.expressionVisitor);
|
|
156
|
+ }
|
|
157
|
+
|
|
158
|
+ clinitWriter.invokeSpecial(internalName, "<init>", CompilerUtils.calcDesc(member.constructor.constructor.header, true));
|
|
159
|
+ clinitWriter.putStaticField(internalName, member.name, "L" + internalName + ";");
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+ enumDefinition = (EnumDefinition) member.definition;
|
|
163
|
+
|
140
|
164
|
return null;
|
141
|
165
|
}
|
142
|
166
|
|
|
@@ -170,30 +194,30 @@ public class JavaMemberVisitor implements MemberVisitor<Void> {
|
170
|
194
|
return null;
|
171
|
195
|
}
|
172
|
196
|
|
173
|
|
- @Override
|
174
|
|
- public Void visitStaticInitializer(StaticInitializerMember member) {
|
175
|
|
- staticInitializers.add(member);
|
176
|
|
- return null;
|
177
|
|
- }
|
178
|
|
-
|
179
|
|
- public void end() {
|
180
|
|
- final JavaMethodInfo method = new JavaMethodInfo(toClass, "<clinit>", "()V", 0);
|
181
|
|
-
|
182
|
|
- final Label constructorStart = new Label();
|
183
|
|
- final Label constructorEnd = new Label();
|
184
|
|
- final JavaWriter constructorWriter = new JavaWriter(writer, method, definition, null, null);
|
185
|
|
- constructorWriter.label(constructorStart);
|
186
|
|
-
|
187
|
|
- final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(constructorWriter);
|
188
|
|
- statementVisitor.start();
|
189
|
|
-
|
190
|
|
- CompilerUtils.writeDefaultFieldInitializers(constructorWriter, definition, true);
|
191
|
|
-
|
192
|
|
- for (StaticInitializerMember member : staticInitializers) {
|
193
|
|
- member.body.accept(statementVisitor);
|
194
|
|
- }
|
195
|
|
-
|
196
|
|
- constructorWriter.label(constructorEnd);
|
197
|
|
- statementVisitor.end();
|
198
|
|
- }
|
|
197
|
+ @Override
|
|
198
|
+ public Void visitStaticInitializer(StaticInitializerMember member) {
|
|
199
|
+ member.body.accept(clinitStatementVisitor);
|
|
200
|
+ return null;
|
|
201
|
+ }
|
|
202
|
+
|
|
203
|
+ public void end() {
|
|
204
|
+
|
|
205
|
+ if (enumDefinition != null) {
|
|
206
|
+ final JavaWriter clinitWriter = clinitStatementVisitor.getJavaWriter();
|
|
207
|
+ final List<EnumConstantMember> enumConstants = enumDefinition.getEnumConstants();
|
|
208
|
+ clinitWriter.constant(enumConstants.size());
|
|
209
|
+ clinitWriter.newArray(Type.getType("L" + definition.name + ";"));
|
|
210
|
+
|
|
211
|
+ for (EnumConstantMember enumConstant : enumConstants) {
|
|
212
|
+ clinitWriter.dup();
|
|
213
|
+ clinitWriter.constant(enumConstant.value);
|
|
214
|
+ clinitWriter.getStaticField(definition.name, enumConstant.name, "L" + definition.name + ";");
|
|
215
|
+ clinitWriter.arrayStore(Type.getType("L" + definition.name + ";"));
|
|
216
|
+ }
|
|
217
|
+ clinitWriter.putStaticField(definition.name, "$VALUES", "[L" + definition.name + ";");
|
|
218
|
+ }
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+ clinitStatementVisitor.end();
|
|
222
|
+ }
|
199
|
223
|
}
|