|
@@ -1,6 +1,7 @@
|
1
|
1
|
package org.openzen.zenscript.javabytecode.compiler;
|
2
|
2
|
|
3
|
|
-import org.openzen.zenscript.javashared.JavaParameterInfo;
|
|
3
|
+import org.openzen.zenscript.javashared.*;
|
|
4
|
+
|
4
|
5
|
import java.util.Arrays;
|
5
|
6
|
import java.util.Comparator;
|
6
|
7
|
import java.util.StringJoiner;
|
|
@@ -13,7 +14,6 @@ import org.openzen.zenscript.codemodel.expression.*;
|
13
|
14
|
import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
|
14
|
15
|
import org.openzen.zenscript.codemodel.member.ref.DefinitionMemberRef;
|
15
|
16
|
import org.openzen.zenscript.codemodel.member.ref.FieldMemberRef;
|
16
|
|
-import org.openzen.zenscript.codemodel.statement.ReturnStatement;
|
17
|
17
|
import org.openzen.zenscript.codemodel.type.*;
|
18
|
18
|
import org.openzen.zenscript.codemodel.type.member.BuiltinID;
|
19
|
19
|
import org.openzen.zenscript.javabytecode.*;
|
|
@@ -24,12 +24,6 @@ import java.lang.reflect.Modifier;
|
24
|
24
|
import org.openzen.zenscript.codemodel.type.storage.BorrowStorageTag;
|
25
|
25
|
import org.openzen.zenscript.codemodel.type.storage.StorageTag;
|
26
|
26
|
import org.openzen.zenscript.codemodel.type.storage.UniqueStorageTag;
|
27
|
|
-import org.openzen.zenscript.javashared.JavaClass;
|
28
|
|
-import org.openzen.zenscript.javashared.JavaCompiledModule;
|
29
|
|
-import org.openzen.zenscript.javashared.JavaField;
|
30
|
|
-import org.openzen.zenscript.javashared.JavaMethod;
|
31
|
|
-import org.openzen.zenscript.javashared.JavaTypeUtils;
|
32
|
|
-import org.openzen.zenscript.javashared.JavaVariantOption;
|
33
|
27
|
|
34
|
28
|
public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
|
35
|
29
|
private static final JavaMethod BOOLEAN_PARSE = JavaMethod.getNativeStatic(JavaClass.BOOLEAN, "parseBoolean", "(Ljava/lang/String;)Z");
|
|
@@ -96,6 +90,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
|
96
|
90
|
private static final JavaField CHARACTER_MIN_VALUE = new JavaField(JavaClass.CHARACTER, "MIN_VALUE", "C");
|
97
|
91
|
private static final JavaField CHARACTER_MAX_VALUE = new JavaField(JavaClass.CHARACTER, "MAX_VALUE", "C");
|
98
|
92
|
private static final JavaMethod CHARACTER_TO_STRING = JavaMethod.getNativeStatic(JavaClass.CHARACTER, "toString", "(C)Ljava/lang/String;");
|
|
93
|
+ private static final JavaMethod STRING_INIT_CHARACTERS = JavaMethod.getNativeConstructor(JavaClass.STRING, "([C)V");
|
99
|
94
|
private static final JavaMethod STRING_COMPARETO = JavaMethod.getNativeVirtual(JavaClass.STRING, "compareTo", "(Ljava/lang/String;)I");
|
100
|
95
|
private static final JavaMethod STRING_CONCAT = JavaMethod.getNativeVirtual(JavaClass.STRING, "concat", "(Ljava/lang/String;)Ljava/lang/String;");
|
101
|
96
|
private static final JavaMethod STRING_CHAR_AT = JavaMethod.getNativeVirtual(JavaClass.STRING, "charAt", "(I)C");
|
|
@@ -109,6 +104,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
|
109
|
104
|
private static final JavaMethod ENUM_COMPARETO = JavaMethod.getNativeVirtual(JavaClass.ENUM, "compareTo", "(Ljava/lang/Enum;)I");
|
110
|
105
|
private static final JavaMethod ENUM_NAME = JavaMethod.getNativeVirtual(JavaClass.ENUM, "name", "()Ljava/lang/String;");
|
111
|
106
|
private static final JavaMethod ENUM_ORDINAL = JavaMethod.getNativeVirtual(JavaClass.ENUM, "ordinal", "()I");
|
|
107
|
+ private static final JavaMethod HASHMAP_INIT = JavaMethod.getNativeConstructor(JavaClass.HASHMAP, "()V");
|
112
|
108
|
private static final JavaMethod MAP_GET = JavaMethod.getNativeVirtual(JavaClass.MAP, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
|
113
|
109
|
private static final JavaMethod MAP_PUT = JavaMethod.getNativeVirtual(JavaClass.MAP, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
|
114
|
110
|
private static final JavaMethod MAP_CONTAINS_KEY = JavaMethod.getNativeVirtual(JavaClass.MAP, "containsKey", "(Ljava/lang/Object;)Z");
|
|
@@ -2128,8 +2124,13 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
|
2128
|
2124
|
|
2129
|
2125
|
@Override
|
2130
|
2126
|
public Void visitNew(NewExpression expression) {
|
|
2127
|
+ if (expression.constructor.getBuiltin() != null) {
|
|
2128
|
+ visitBuiltinConstructor(expression);
|
|
2129
|
+ return null;
|
|
2130
|
+ }
|
|
2131
|
+
|
2131
|
2132
|
JavaMethod method = context.getJavaMethod(expression.constructor);
|
2132
|
|
- javaWriter.newObject(method.cls.internalName);
|
|
2133
|
+ javaWriter.newObject(method.cls);
|
2133
|
2134
|
javaWriter.dup();
|
2134
|
2135
|
|
2135
|
2136
|
for (Expression argument : expression.arguments.arguments) {
|
|
@@ -2140,6 +2141,130 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
|
2140
|
2141
|
return null;
|
2141
|
2142
|
}
|
2142
|
2143
|
|
|
2144
|
+ private void visitBuiltinConstructor(NewExpression expression) {
|
|
2145
|
+ switch (expression.constructor.getBuiltin()) {
|
|
2146
|
+ case STRING_CONSTRUCTOR_CHARACTERS:
|
|
2147
|
+ javaWriter.newObject(JavaClass.STRING);
|
|
2148
|
+ javaWriter.dup();
|
|
2149
|
+ expression.arguments.arguments[0].accept(this);
|
|
2150
|
+ javaWriter.invokeSpecial(STRING_INIT_CHARACTERS);
|
|
2151
|
+ return;
|
|
2152
|
+ case ASSOC_CONSTRUCTOR:
|
|
2153
|
+ case GENERICMAP_CONSTRUCTOR: {
|
|
2154
|
+ javaWriter.newObject(JavaClass.HASHMAP);
|
|
2155
|
+ javaWriter.dup();
|
|
2156
|
+ javaWriter.invokeSpecial(HASHMAP_INIT);
|
|
2157
|
+ return;
|
|
2158
|
+ }
|
|
2159
|
+ case ARRAY_CONSTRUCTOR_SIZED: {
|
|
2160
|
+ ArrayTypeID type = (ArrayTypeID) expression.type.type;
|
|
2161
|
+ if (type.dimension == 1) {
|
|
2162
|
+ // new T[arguments[0]]
|
|
2163
|
+ expression.arguments.arguments[0].accept(this);
|
|
2164
|
+ javaWriter.newArray(context.getType(type.elementType));
|
|
2165
|
+ return;
|
|
2166
|
+ } else {
|
|
2167
|
+ // TODO: implement multidimensional arrays
|
|
2168
|
+ throw new UnsupportedOperationException("Not yet supported!");
|
|
2169
|
+ }
|
|
2170
|
+ }
|
|
2171
|
+ case ARRAY_CONSTRUCTOR_INITIAL_VALUE: {
|
|
2172
|
+ ArrayTypeID type = (ArrayTypeID) expression.type.type;
|
|
2173
|
+
|
|
2174
|
+ if (type.dimension == 1) {
|
|
2175
|
+ // array = new T[arguments[0]]
|
|
2176
|
+ // value = arguments[1]
|
|
2177
|
+ // for (int i = 0; i < array.length; i++)
|
|
2178
|
+ // array[i] = value;
|
|
2179
|
+
|
|
2180
|
+ expression.arguments.arguments[0].accept(this); // array size
|
|
2181
|
+ javaWriter.newArray(context.getType(type.elementType));
|
|
2182
|
+
|
|
2183
|
+ int i = javaWriter.local(int.class);
|
|
2184
|
+ javaWriter.iConst0();
|
|
2185
|
+ javaWriter.storeInt(i);
|
|
2186
|
+
|
|
2187
|
+ Type valueType = context.getType(expression.arguments.arguments[1].type);
|
|
2188
|
+
|
|
2189
|
+ expression.arguments.arguments[1].accept(this); // initializer value
|
|
2190
|
+ javaWriter.store(valueType, i);
|
|
2191
|
+
|
|
2192
|
+ // TODO: implement in bytecode
|
|
2193
|
+ return;
|
|
2194
|
+ } else {
|
|
2195
|
+ // TODO: implement
|
|
2196
|
+ throw new UnsupportedOperationException("Not yet supported!");
|
|
2197
|
+ }
|
|
2198
|
+ }
|
|
2199
|
+ case ARRAY_CONSTRUCTOR_LAMBDA: {
|
|
2200
|
+ ArrayTypeID type = (ArrayTypeID) expression.type.type;
|
|
2201
|
+
|
|
2202
|
+ if (type.dimension == 1) {
|
|
2203
|
+ // array = new T[arguments[0]]
|
|
2204
|
+ // lambda = arguments[1]
|
|
2205
|
+ // for (int i = 0; i < array.length; i++)
|
|
2206
|
+ // array[i] = lambda.invoke(i);
|
|
2207
|
+ //
|
|
2208
|
+ // NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
|
|
2209
|
+
|
|
2210
|
+ // TODO: implement in bytecode
|
|
2211
|
+
|
|
2212
|
+ return;
|
|
2213
|
+ } else {
|
|
2214
|
+ // TODO: implement
|
|
2215
|
+ throw new UnsupportedOperationException("Not yet supported!");
|
|
2216
|
+ }
|
|
2217
|
+ }
|
|
2218
|
+ case ARRAY_CONSTRUCTOR_PROJECTED: {
|
|
2219
|
+ ArrayTypeID type = (ArrayTypeID) expression.type.type;
|
|
2220
|
+
|
|
2221
|
+ if (type.dimension == 1) {
|
|
2222
|
+ // original = arguments[0] (this is an array)
|
|
2223
|
+ // projector = arguments[1] (this is a lambda with 1 parameter)
|
|
2224
|
+ // array = new T[original.length]
|
|
2225
|
+ // for (int i = 0; i < array.length; i++)
|
|
2226
|
+ // array[i] = projector(original[i]);
|
|
2227
|
+ //
|
|
2228
|
+ // NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
|
|
2229
|
+
|
|
2230
|
+ // TODO: implement in bytecode
|
|
2231
|
+
|
|
2232
|
+ return;
|
|
2233
|
+ } else {
|
|
2234
|
+ // TODO: implement
|
|
2235
|
+ throw new UnsupportedOperationException("Not yet supported!");
|
|
2236
|
+ }
|
|
2237
|
+ }
|
|
2238
|
+ case ARRAY_CONSTRUCTOR_PROJECTED_INDEXED: {
|
|
2239
|
+ ArrayTypeID type = (ArrayTypeID) expression.type.type;
|
|
2240
|
+
|
|
2241
|
+ if (type.dimension == 1) {
|
|
2242
|
+ // original = arguments[0] (this is an array)
|
|
2243
|
+ // projector = arguments[1] (this is a lambda with 2 parameters)
|
|
2244
|
+ // array = new T[original.length]
|
|
2245
|
+ // for (int i = 0; i < array.length; i++)
|
|
2246
|
+ // array[i] = projector(i, original[i]);
|
|
2247
|
+ //
|
|
2248
|
+ // NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
|
|
2249
|
+
|
|
2250
|
+ // TODO: implement in bytecode
|
|
2251
|
+
|
|
2252
|
+ return;
|
|
2253
|
+ } else {
|
|
2254
|
+ // TODO: implement
|
|
2255
|
+ throw new UnsupportedOperationException("Not yet supported!");
|
|
2256
|
+ }
|
|
2257
|
+ }
|
|
2258
|
+ case CLASS_DEFAULT_CONSTRUCTOR:
|
|
2259
|
+ javaWriter.newObject(context.getInternalName(expression.type));
|
|
2260
|
+ javaWriter.dup();
|
|
2261
|
+ javaWriter.invokeSpecial(context.getJavaMethod(expression.constructor));
|
|
2262
|
+ return;
|
|
2263
|
+ }
|
|
2264
|
+
|
|
2265
|
+ throw new UnsupportedOperationException("Unknown builtin constructor: " + expression.constructor.getBuiltin());
|
|
2266
|
+ }
|
|
2267
|
+
|
2143
|
2268
|
@Override
|
2144
|
2269
|
public Void visitNull(NullExpression expression) {
|
2145
|
2270
|
if (!expression.type.isBasic(BasicTypeID.NULL) && expression.type.type.withoutOptional() == BasicTypeID.USIZE)
|