Quellcode durchsuchen

Adding support for builtin constructors

Stan Hebben vor 6 Jahren
Ursprung
Commit
06e3a0c203

+ 134
- 9
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java Datei anzeigen

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

+ 7
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java Datei anzeigen

@@ -851,6 +851,13 @@ public class JavaWriter {
851 851
         visitor.visitTypeInsn(NEW, internalName);
852 852
     }
853 853
 
854
+    public void newObject(JavaClass cls) {
855
+        if (debug)
856
+            System.out.println("newObject " + cls.internalName);
857
+
858
+        visitor.visitTypeInsn(NEW, cls.internalName);
859
+    }
860
+
854 861
     public void goTo(Label lbl) {
855 862
         if (debug)
856 863
             System.out.println("goTo " + getLabelName(lbl));

Laden…
Abbrechen
Speichern