ソースを参照

WIP array initializers

kindlich 6年前
コミット
82a22a3d4f
この署名に対応する既知のキーがデータベースに存在しません

+ 89
- 0
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/ArrayInitializerHelper.java ファイルの表示

@@ -0,0 +1,89 @@
1
+package org.openzen.zenscript.javabytecode.compiler;
2
+
3
+
4
+import org.objectweb.asm.Label;
5
+import org.objectweb.asm.Type;
6
+
7
+public class ArrayInitializerHelper {
8
+	public static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, int originArrayLocation, Type originArrayType, int functionLocation, Type functionType, Type currentArrayType) {
9
+
10
+		visitMultiDimArray(javaWriter, sizeLocations, counterLocations, dim, currentArrayType, (elementType1, counterLocations1, sizeLocations1) -> {
11
+			//Load origin array
12
+			javaWriter.loadObject(originArrayLocation);
13
+
14
+			//Use arrayGets until we are at the element type
15
+			Type modifiedOriginArrayType = originArrayType;
16
+			for (final int location : counterLocations) {
17
+				javaWriter.loadInt(location);
18
+				javaWriter.arrayLoad(modifiedOriginArrayType = Type.getType(modifiedOriginArrayType.getDescriptor().substring(1)));
19
+			}
20
+
21
+			//Apply function here
22
+			//javaWriter.loadObject(functionLocation);
23
+			//javaWriter.swap();
24
+
25
+			//TODO invoke?
26
+			//javaWriter.invokeVirtual(new JavaMethod(JavaClass.fromInternalName("lambda1", JavaClass.Kind.CLASS), JavaMethod.Kind.INSTANCE, "accept", true, "(Ljava/lang/String;)Ljava/lang/String;", 0, false));
27
+		});
28
+	}
29
+
30
+
31
+	public static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int dim, int defaultLocation, Type currentArrayType, int[] sizeLocations) {
32
+		visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, (elementType, counterLocations, sizeLocations1) -> javaWriter.load(elementType, defaultLocation));
33
+	}
34
+
35
+
36
+	public static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
37
+		final Label begin = new Label();
38
+		final Label end = new Label();
39
+		javaWriter.label(begin);
40
+
41
+		final int currentArraySizeLocation = sizeLocations[sizeLocations.length - dim];
42
+		javaWriter.loadInt(currentArraySizeLocation);
43
+		final Type elementType = Type.getType(currentArrayType.getDescriptor().substring(1));
44
+		javaWriter.newArray(elementType);
45
+		//javaWriter.dup();
46
+
47
+		final int forLoopCounter = javaWriter.local(int.class);
48
+		javaWriter.iConst0();
49
+		javaWriter.storeInt(forLoopCounter);
50
+		counterLocations[counterLocations.length - dim] = forLoopCounter;
51
+
52
+
53
+		final Label loopStart = new Label();
54
+		final Label loopEnd = new Label();
55
+
56
+		javaWriter.label(loopStart);
57
+
58
+		javaWriter.loadInt(forLoopCounter);
59
+		javaWriter.loadInt(currentArraySizeLocation);
60
+		javaWriter.ifICmpGE(loopEnd);
61
+
62
+		//Loop content
63
+		javaWriter.dup();
64
+		javaWriter.loadInt(forLoopCounter);
65
+		if (dim == 1) {
66
+			innermostFunction.apply(elementType, counterLocations, sizeLocations);
67
+		} else {
68
+			visitMultiDimArray(javaWriter, sizeLocations, counterLocations, dim - 1, elementType, innermostFunction);
69
+		}
70
+		javaWriter.arrayStore(elementType);
71
+
72
+		//Return to the start
73
+		javaWriter.iinc(forLoopCounter);
74
+		javaWriter.goTo(loopStart);
75
+		javaWriter.label(loopEnd);
76
+		//javaWriter.pop();
77
+
78
+		//Naming the variables
79
+		javaWriter.nameVariable(forLoopCounter, "i" + dim, loopStart, loopEnd, Type.getType(int.class));
80
+
81
+		javaWriter.label(end);
82
+	}
83
+
84
+	@FunctionalInterface
85
+	public interface InnermostFunction {
86
+		void apply(Type elementType, int[] counterLocations, int[] sizeLocations);
87
+	}
88
+}
89
+

+ 134
- 81
JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java ファイルの表示

@@ -21,12 +21,9 @@ import org.openzen.zenscript.javashared.*;
21 21
 import java.io.FileOutputStream;
22 22
 import java.io.IOException;
23 23
 import java.lang.reflect.Modifier;
24
-import java.util.ArrayList;
25
-import java.util.Arrays;
26
-import java.util.Comparator;
27
-import java.util.StringJoiner;
24
+import java.util.*;
28 25
 
29
-public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
26
+public class JavaExpressionVisitor implements ExpressionVisitor<Void>, JavaNativeTranslator<Void> {
30 27
 	private static final JavaMethod BOOLEAN_PARSE = JavaMethod.getNativeStatic(JavaClass.BOOLEAN, "parseBoolean", "(Ljava/lang/String;)Z");
31 28
 	private static final JavaMethod BOOLEAN_TO_STRING = JavaMethod.getNativeStatic(JavaClass.BOOLEAN, "toString", "(Z)Ljava/lang/String;");
32 29
 	private static final JavaMethod BYTE_PARSE = JavaMethod.getNativeStatic(JavaClass.BYTE, "parseByte", "(Ljava/lang/String;)B");
@@ -293,7 +290,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
293 290
 					throw new UnsupportedOperationException("Unknown builtin comparator: " + expression.operator.getBuiltin());
294 291
 			}
295 292
 		} else {
296
-			if (!checkAndExecuteMethodInfo(expression.operator, expression.type))
293
+			if (!checkAndExecuteMethodInfo(expression.operator, expression.type, expression))
297 294
 				throw new IllegalStateException("Call target has no method info!");
298 295
 
299 296
 			expression.left.accept(this);
@@ -377,7 +374,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
377 374
 				argument.accept(this);
378 375
 			}
379 376
 
380
-			if (!checkAndExecuteMethodInfo(expression.member, expression.type))
377
+			if (!checkAndExecuteMethodInfo(expression.member, expression.type, expression))
381 378
 				throw new IllegalStateException("Call target has no method info!");
382 379
 
383 380
 			if (expression.member.getTarget().header.getReturnType().isGeneric())
@@ -921,7 +918,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
921 918
 
922 919
 		BuiltinID builtin = expression.member.getBuiltin();
923 920
 		if (builtin == null) {
924
-			if (!checkAndExecuteMethodInfo(expression.member, expression.type))
921
+			if (!checkAndExecuteMethodInfo(expression.member, expression.type, expression))
925 922
 				throw new IllegalStateException("Call target has no method info!");
926 923
 
927 924
 			return null;
@@ -1030,7 +1027,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
1030 1027
 
1031 1028
 		BuiltinID builtin = expression.member.member.builtin;
1032 1029
 		if (builtin == null) {
1033
-			if (!checkAndExecuteMethodInfo(expression.member, expression.type))
1030
+			if (!checkAndExecuteMethodInfo(expression.member, expression.type, expression))
1034 1031
 				throw new IllegalStateException("Call target has no method info!");
1035 1032
 
1036 1033
 			return null;
@@ -1832,7 +1829,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
1832 1829
 				javaWriter.getField(context.getJavaField(expression.getter));
1833 1830
 				return null;
1834 1831
 			}
1835
-			if (!checkAndExecuteMethodInfo(expression.getter, expression.type))
1832
+			if (!checkAndExecuteMethodInfo(expression.getter, expression.type, expression))
1836 1833
 				throw new IllegalStateException("Call target has no method info!");
1837 1834
 
1838 1835
 			return null;
@@ -3079,8 +3076,8 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3079 3076
 				javaWriter.label(begin);
3080 3077
 				final int defaultValueLocation = javaWriter.local(ASMElementType);
3081 3078
 
3082
-				if(builtin == BuiltinID.ARRAY_CONSTRUCTOR_SIZED) {
3083
-					if(CompilerUtils.isPrimitive(type.elementType.type))
3079
+				if (builtin == BuiltinID.ARRAY_CONSTRUCTOR_SIZED) {
3080
+					if (CompilerUtils.isPrimitive(type.elementType.type))
3084 3081
 						if (type.elementType.type == BasicTypeID.FLOAT) javaWriter.constant(0f);
3085 3082
 						else if (type.elementType.type == BasicTypeID.DOUBLE) javaWriter.constant(0D);
3086 3083
 						else javaWriter.iConst0();
@@ -3108,7 +3105,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3108 3105
 				}
3109 3106
 
3110 3107
 
3111
-				visitMultiDimArray(type.dimension, defaultValueLocation, ASMType, arraySizes);
3108
+				ArrayInitializerHelper.visitMultiDimArrayWithDefaultValue(javaWriter, type.dimension, defaultValueLocation, ASMType, arraySizes);
3112 3109
 
3113 3110
 
3114 3111
 				javaWriter.label(end);
@@ -3124,42 +3121,79 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3124 3121
 				ArrayTypeID type = (ArrayTypeID) expression.type.type;
3125 3122
 
3126 3123
 				if (type.dimension == 1) {
3127
-
3128
-
3129 3124
 					// array = new T[arguments[0]]
3130 3125
 					// lambda = arguments[1]
3131 3126
 					// for (int i = 0; i < array.length; i++)
3132 3127
 					//    array[i] = lambda.invoke(i);
3133 3128
 					//
3134 3129
 					// NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
3135
-
3136
-					// TODO: implement in bytecode
3137
-
3138
-					return;
3130
+					throw new UnsupportedOperationException("Not yet supported!");
3139 3131
 				} else {
3140 3132
 					// TODO: implement
3141 3133
 					throw new UnsupportedOperationException("Not yet supported!");
3142 3134
 				}
3143 3135
 			}
3144 3136
 			case ARRAY_CONSTRUCTOR_PROJECTED: {
3137
+
3138
+
3145 3139
 				ArrayTypeID type = (ArrayTypeID) expression.type.type;
3146 3140
 
3147
-				if (type.dimension == 1) {
3148
-					// original = arguments[0] (this is an array)
3149
-					// projector = arguments[1] (this is a lambda with 1 parameter)
3150
-					// array = new T[original.length]
3151
-					// for (int i = 0; i < array.length; i++)
3152
-					//    array[i] = projector(original[i]);
3153
-					//
3154
-					// NOTE: arguments[1] can be a FunctionExpression; this can be optimized by running it inline
3141
+				final Label begin = new Label();
3142
+				final Label end = new Label();
3155 3143
 
3156
-					// TODO: implement in bytecode
3144
+				javaWriter.label(begin);
3145
+				expression.arguments.arguments[0].accept(this); //Origin array
3146
+				final Type originArrayType = context.getType(expression.arguments.arguments[0].type);
3147
+				final int originArrayLocation = javaWriter.local(originArrayType);
3148
+				javaWriter.storeObject(originArrayLocation);
3157 3149
 
3158
-					return;
3159
-				} else {
3160
-					// TODO: implement
3161
-					throw new UnsupportedOperationException("Not yet supported!");
3150
+
3151
+				expression.arguments.arguments[1].accept(this); //Projection Function
3152
+				final Type functionType = context.getType(expression.arguments.arguments[1].type);
3153
+				final int functionLocation = javaWriter.local(functionType);
3154
+				javaWriter.storeObject(functionLocation);
3155
+
3156
+				int[] variableCounterLocations = new int[type.dimension];
3157
+				Type destinationArrayType = context.getType(expression.type);
3158
+
3159
+
3160
+				final int[] arraySizes;
3161
+				{
3162
+					final ArrayList<Integer> list = new ArrayList<>();
3163
+					javaWriter.loadObject(originArrayLocation);
3164
+					Type currentElementType = originArrayType;
3165
+					for (int i = 0; i < type.dimension; i++) {
3166
+						currentElementType = Type.getType(currentElementType.getDescriptor().substring(1));
3167
+						final int location = javaWriter.local(int.class);
3168
+						javaWriter.dup();
3169
+						javaWriter.arrayLength();
3170
+						javaWriter.storeInt(location);
3171
+						list.add(location);
3172
+
3173
+						if (i < type.dimension - 1) {
3174
+							javaWriter.iConst0();
3175
+							javaWriter.arrayLoad(currentElementType);
3176
+						}
3177
+					}
3178
+					javaWriter.pop();
3179
+					arraySizes = new int[list.size()];
3180
+					for (int i = 0; i < list.size(); i++) {
3181
+						arraySizes[i] = list.get(i);
3182
+					}
3183
+				}
3184
+
3185
+
3186
+				ArrayInitializerHelper.visitProjected(javaWriter, arraySizes, variableCounterLocations, type.dimension, originArrayLocation, originArrayType, functionLocation, functionType, destinationArrayType);
3187
+
3188
+				javaWriter.label(end);
3189
+
3190
+				//naming the variables
3191
+				javaWriter.nameVariable(functionLocation, "projectionFunction", begin, end, functionType);
3192
+				for (int i = 0; i < arraySizes.length; i++) {
3193
+					javaWriter.nameVariable(arraySizes[i], "size" + (arraySizes.length - i), begin, end, Type.getType(int.class));
3162 3194
 				}
3195
+				return;
3196
+
3163 3197
 			}
3164 3198
 			case ARRAY_CONSTRUCTOR_PROJECTED_INDEXED: {
3165 3199
 				ArrayTypeID type = (ArrayTypeID) expression.type.type;
@@ -3279,52 +3313,6 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3279 3313
 		throw new UnsupportedOperationException("Unknown builtin constructor: " + builtin);
3280 3314
 	}
3281 3315
 
3282
-	private void visitMultiDimArray(int dim, int defaultLocation, Type currentArrayType, int[] sizeLocations) {
3283
-		final Label begin = new Label();
3284
-		final Label end = new Label();
3285
-		javaWriter.label(begin);
3286
-
3287
-		final int currentArraySizeLocation = sizeLocations[sizeLocations.length - dim];
3288
-		javaWriter.loadInt(currentArraySizeLocation);
3289
-		final Type elementType = Type.getType(currentArrayType.getDescriptor().substring(1));
3290
-		javaWriter.newArray(elementType);
3291
-		//javaWriter.dup();
3292
-
3293
-		final int forLoopCounter = javaWriter.local(int.class);
3294
-		javaWriter.iConst0();
3295
-		javaWriter.storeInt(forLoopCounter);
3296
-
3297
-
3298
-		final Label loopStart = new Label();
3299
-		final Label loopEnd = new Label();
3300
-
3301
-		javaWriter.label(loopStart);
3302
-
3303
-		javaWriter.loadInt(forLoopCounter);
3304
-		javaWriter.loadInt(currentArraySizeLocation);
3305
-		javaWriter.ifICmpGE(loopEnd);
3306
-
3307
-		//Loop content
3308
-		javaWriter.dup();
3309
-		javaWriter.loadInt(forLoopCounter);
3310
-		if (dim == 1) {
3311
-			javaWriter.load(elementType, defaultLocation);
3312
-		} else {
3313
-			visitMultiDimArray(dim - 1, defaultLocation, elementType, sizeLocations);
3314
-		}
3315
-		javaWriter.arrayStore(elementType);
3316
-
3317
-		//Return to the start
3318
-		javaWriter.iinc(forLoopCounter);
3319
-		javaWriter.goTo(loopStart);
3320
-		javaWriter.label(loopEnd);
3321
-		//javaWriter.pop();
3322
-
3323
-		//Naming the variables
3324
-		javaWriter.nameVariable(forLoopCounter, "i" + dim, loopStart, loopEnd, Type.getType(int.class));
3325
-
3326
-		javaWriter.label(end);
3327
-	}
3328 3316
 
3329 3317
 	@Override
3330 3318
 	public Void visitNull(NullExpression expression) {
@@ -3374,7 +3362,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3374 3362
 	public Void visitPostCall(PostCallExpression expression) {
3375 3363
 		expression.target.accept(this);
3376 3364
 		javaWriter.dup(context.getType(expression.type));
3377
-		if (!checkAndExecuteMethodInfo(expression.member, expression.type))
3365
+		if (!checkAndExecuteMethodInfo(expression.member, expression.type, expression))
3378 3366
 			throw new IllegalStateException("Call target has no method info!");
3379 3367
 
3380 3368
 		return null;
@@ -3465,7 +3453,7 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3465 3453
 				return null;
3466 3454
 			}
3467 3455
 
3468
-			if (!checkAndExecuteMethodInfo(expression.getter, expression.type))
3456
+			if (!checkAndExecuteMethodInfo(expression.getter, expression.type, expression))
3469 3457
 				throw new IllegalStateException("Call target has no method info!");
3470 3458
 
3471 3459
 			return null;
@@ -3645,13 +3633,16 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3645 3633
 	}
3646 3634
 
3647 3635
 	//Will return true if a JavaMethodInfo.class tag exists, and will compile that tag
3648
-	private boolean checkAndExecuteMethodInfo(DefinitionMemberRef member, StoredType resultType) {
3636
+	@SuppressWarnings({"Raw", "unchecked"})
3637
+	private boolean checkAndExecuteMethodInfo(DefinitionMemberRef member, StoredType resultType, Expression expression) {
3649 3638
 		JavaMethod methodInfo = context.getJavaMethod(member);
3650 3639
 		if (methodInfo == null)
3651 3640
 			return false;
3652 3641
 
3653 3642
 		if (methodInfo.kind == JavaMethod.Kind.STATIC) {
3654 3643
 			getJavaWriter().invokeStatic(methodInfo);
3644
+		} else if (methodInfo.kind == JavaMethod.Kind.COMPILED) {
3645
+			Objects.requireNonNull(methodInfo.translation).translate(expression, this);
3655 3646
 		} else {
3656 3647
 			getJavaWriter().invokeVirtual(methodInfo);
3657 3648
 		}
@@ -3679,4 +3670,66 @@ public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3679 3670
 			getJavaWriter().getField(fieldInfo);
3680 3671
 		}
3681 3672
 	}
3673
+
3674
+	@Override
3675
+	public Void isEmptyAsLengthZero(Expression value) {
3676
+		return null;
3677
+	}
3678
+
3679
+	@Override
3680
+	public Void listToArray(CastExpression value) {
3681
+		//value.target.accept(this);
3682
+		javaWriter.iConst0();
3683
+		final Type type = context.getType(((ArrayTypeID) value.type.type).elementType);
3684
+		javaWriter.newArray(type);
3685
+		final JavaMethod toArray = new JavaMethod(JavaClass.COLLECTION, JavaMethod.Kind.INSTANCE, "toArray", true, "([Ljava/lang/Object;)[Ljava/lang/Object;", 0, true);
3686
+		javaWriter.invokeInterface(toArray);
3687
+		javaWriter.checkCast(context.getType(value.type));
3688
+		return null;
3689
+	}
3690
+
3691
+	@Override
3692
+	public Void containsAsIndexOf(Expression target, Expression value) {
3693
+		return null;
3694
+	}
3695
+
3696
+	@Override
3697
+	public Void sorted(Expression value) {
3698
+		return null;
3699
+	}
3700
+
3701
+	@Override
3702
+	public Void sortedWithComparator(Expression value, Expression comparator) {
3703
+		return null;
3704
+	}
3705
+
3706
+	@Override
3707
+	public Void copy(Expression value) {
3708
+		return null;
3709
+	}
3710
+
3711
+	@Override
3712
+	public Void copyTo(CallExpression call) {
3713
+		return null;
3714
+	}
3715
+
3716
+	@Override
3717
+	public Void stringToAscii(Expression value) {
3718
+		return null;
3719
+	}
3720
+
3721
+	@Override
3722
+	public Void stringToUTF8(Expression value) {
3723
+		return null;
3724
+	}
3725
+
3726
+	@Override
3727
+	public Void bytesAsciiToString(Expression value) {
3728
+		return null;
3729
+	}
3730
+
3731
+	@Override
3732
+	public Void bytesUTF8ToString(Expression value) {
3733
+		return null;
3734
+	}
3682 3735
 }

+ 49
- 23
ScriptingExample/scripts/arrays.zs ファイルの表示

@@ -1,23 +1,49 @@
1
-val a  = new int[](3, 10);
2
-
3
-for i in a {
4
-	println(i);
5
-}
6
-
7
-println(a[1]);
8
-
9
-
10
-val multiDim = new int[,,](1,2,3, 130);
11
-println(multiDim[0,1,2]);
12
-
13
-val t = multiDim;
14
-
15
-
16
-val b = new int[](3);
17
-for i in b {
18
-	println(i);
19
-}
20
-
21
-
22
-val c = new int[,,](1,2,3);
23
-println(c[0,1,2]);
1
+//val a  = new int[](3, 10);
2
+//
3
+//for i in a {
4
+//	println(i);
5
+//}
6
+//
7
+//println(a[1]);
8
+////
9
+////
10
+//val multiDim = new int[,,](1,2,3, 130);
11
+//println(multiDim[0,1,2]);
12
+//
13
+//val t = multiDim;
14
+////
15
+////
16
+//val b = new int[](3);
17
+//for i in b {
18
+//	println(i);
19
+//}
20
+//
21
+//
22
+//val c = new int[,,](1,2,3);
23
+//println(c[0,1,2]);
24
+////
25
+////
26
+////val d = new string[,,](5,5,5, "HelloWorld");
27
+////println(d[2,2,2]);
28
+//
29
+//
30
+////val e = new int[](a, value => value);
31
+//
32
+//
33
+//var projection = (value => value) as function(value as string`borrow) as string;
34
+//val e = new string[](5, "HelloWorld");
35
+//val f = new string[]<string>(e, projection);
36
+//var projection = (value => value) as function(value as string`borrow) as string;
37
+//val a = new string[](5, "HelloWorld");
38
+//val b = new string[]<string>(a, projection);
39
+
40
+val d = new string[,,](5,5,5, "HelloWorld");
41
+
42
+var projection = (value => "" + value) as function(value as string`borrow) as string;
43
+val e = new string[,,]<string>(d, projection);
44
+
45
+
46
+val a = new string[](5, "HelloWorld");
47
+val b = new string[]<string>(a, projection);
48
+
49
+println(e[0,0,0]);

読み込み中…
キャンセル
保存