|
@@ -3,9 +3,91 @@ package org.openzen.zenscript.javabytecode.compiler;
|
3
|
3
|
|
4
|
4
|
import org.objectweb.asm.Label;
|
5
|
5
|
import org.objectweb.asm.Type;
|
|
6
|
+import org.openzen.zenscript.codemodel.expression.Expression;
|
|
7
|
+import org.openzen.zenscript.codemodel.expression.FunctionExpression;
|
|
8
|
+import org.openzen.zenscript.codemodel.expression.StorageCastExpression;
|
|
9
|
+import org.openzen.zenscript.codemodel.statement.ReturnStatement;
|
|
10
|
+
|
|
11
|
+import java.util.ArrayList;
|
|
12
|
+
|
|
13
|
+class ArrayInitializerHelper {
|
|
14
|
+
|
|
15
|
+ /**
|
|
16
|
+ * creates an int[] with the given array size locations and writes the code that gets them in the generated file.
|
|
17
|
+ * Uses an already present origin array (rectangular!)
|
|
18
|
+ *
|
|
19
|
+ * @param dimension the array's dim
|
|
20
|
+ * @param originArrayType the type of the original array
|
|
21
|
+ * @param originArrayLocation the location of the original array
|
|
22
|
+ * @param javaWriter the writer
|
|
23
|
+ * @return the size locations
|
|
24
|
+ */
|
|
25
|
+ static int[] getArraySizeLocationsProjected(int dimension, Type originArrayType, int originArrayLocation, JavaWriter javaWriter) {
|
|
26
|
+ int[] arraySizes;
|
|
27
|
+ final ArrayList<Integer> list = new ArrayList<>();
|
|
28
|
+ javaWriter.loadObject(originArrayLocation);
|
|
29
|
+ Type currentElementType = originArrayType;
|
|
30
|
+ for (int i = 0; i < dimension; i++) {
|
|
31
|
+ currentElementType = Type.getType(currentElementType.getDescriptor().substring(1));
|
|
32
|
+ final int location = javaWriter.local(int.class);
|
|
33
|
+ javaWriter.dup();
|
|
34
|
+ javaWriter.arrayLength();
|
|
35
|
+ javaWriter.storeInt(location);
|
|
36
|
+ list.add(location);
|
|
37
|
+
|
|
38
|
+ if (i < dimension - 1) {
|
|
39
|
+ javaWriter.iConst0();
|
|
40
|
+ javaWriter.arrayLoad(currentElementType);
|
|
41
|
+ }
|
|
42
|
+ }
|
|
43
|
+ javaWriter.pop();
|
|
44
|
+ arraySizes = new int[list.size()];
|
|
45
|
+ for (int i = 0; i < list.size(); i++) {
|
|
46
|
+ arraySizes[i] = list.get(i);
|
|
47
|
+ }
|
|
48
|
+ return arraySizes;
|
|
49
|
+ }
|
|
50
|
+
|
|
51
|
+ /**
|
|
52
|
+ * Creates an int[] with the given array size locations and writes the code that gets them in the generated file
|
|
53
|
+ * Uses the constructor arguments (sizes are expressions 0 .. dimension-1)
|
|
54
|
+ *
|
|
55
|
+ * @param dimension the array's dim
|
|
56
|
+ * @param arguments the arguments form the constructor
|
|
57
|
+ * @param visitor the visitor visiting them
|
|
58
|
+ * @return the size locations
|
|
59
|
+ */
|
|
60
|
+ static int[] getArraySizeLocationsFromConstructor(int dimension, Expression[] arguments, JavaExpressionVisitor visitor) {
|
|
61
|
+ final ArrayList<Integer> list = new ArrayList<>();
|
|
62
|
+ for (int i = 0; i < dimension; i++) {
|
|
63
|
+ final int location = visitor.javaWriter.local(int.class);
|
|
64
|
+ arguments[i].accept(visitor);
|
|
65
|
+ visitor.javaWriter.storeInt(location);
|
|
66
|
+ list.add(location);
|
|
67
|
+ }
|
|
68
|
+ int[] arraySizes = new int[list.size()];
|
|
69
|
+ for (int i = 0; i < list.size(); i++) {
|
|
70
|
+ arraySizes[i] = list.get(i);
|
|
71
|
+ }
|
|
72
|
+ return arraySizes;
|
|
73
|
+ }
|
6
|
74
|
|
7
|
|
-public class ArrayInitializerHelper {
|
8
|
|
- public static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int dim, int originArrayLocation, Type originArrayType, int functionLocation, Type functionType, Type currentArrayType) {
|
|
75
|
+ /**
|
|
76
|
+ * Writes the code for visiting a multidimensional array that is projected from an origin array.
|
|
77
|
+ * Accepts a function that will decide what to do with each value from the origin array
|
|
78
|
+ * When the function is executed, the value from the origin array will be on top of the stack and when it is finished the value on top should be what will be inserted into the array.
|
|
79
|
+ * After the function is completed the stack size must be the same as when it started (effectively replacing the item on top of the stack with the item that should be inserted.
|
|
80
|
+ * The function should not modify the other stacks.
|
|
81
|
+ *
|
|
82
|
+ * @param javaWriter the writer that will write the actual opcode
|
|
83
|
+ * @param sizeLocations the locations of the array dimension sizes sizeLocations.length == dim !!
|
|
84
|
+ * @param dim the array's dimensions, reduced during the recursions of the loop to find the innermost loop
|
|
85
|
+ * @param originArrayLocation The location of the origin array.
|
|
86
|
+ * @param originArrayType the type of the origin array. The element type needs to be assignable to the new array element type!
|
|
87
|
+ * @param currentArrayType The current type of the array, reduced during the recursions of the functions
|
|
88
|
+ * @param innermostFunction The function that will decide what to add to the array, needs to increase the stack size by one and may not touch the other stacks!
|
|
89
|
+ */
|
|
90
|
+ static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int dim, int originArrayLocation, Type originArrayType, Type currentArrayType, InnermostFunction innermostFunction) {
|
9
|
91
|
|
10
|
92
|
visitMultiDimArray(javaWriter, sizeLocations, dim, currentArrayType, (elementType, counterLocations) -> {
|
11
|
93
|
//Load origin array
|
|
@@ -18,25 +100,68 @@ public class ArrayInitializerHelper {
|
18
|
100
|
javaWriter.arrayLoad(modifiedOriginArrayType = Type.getType(modifiedOriginArrayType.getDescriptor().substring(1)));
|
19
|
101
|
}
|
20
|
102
|
|
21
|
|
- //Apply function here
|
22
|
|
- //javaWriter.loadObject(functionLocation);
|
23
|
|
- //javaWriter.swap();
|
|
103
|
+ innermostFunction.apply(elementType, counterLocations);
|
|
104
|
+
|
24
|
105
|
|
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
|
106
|
});
|
28
|
107
|
}
|
29
|
108
|
|
30
|
|
-
|
31
|
|
- public static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int dim, int defaultLocation, Type currentArrayType, int[] sizeLocations) {
|
|
109
|
+ /**
|
|
110
|
+ * Writes the code for visiting a multidimensional array with a default value.
|
|
111
|
+ * The variable at defaultLocation needs to be of or assignable to the resulting array element type.
|
|
112
|
+ *
|
|
113
|
+ * @param javaWriter the writer that will write the actual opcode
|
|
114
|
+ * @param sizeLocations the locations of the array dimension sizes sizeLocations.length == dim !!
|
|
115
|
+ * @param dim the array's dimensions, reduced during the recursions of the loop to find the innermost loop
|
|
116
|
+ * @param currentArrayType The current type of the array, reduced during the recursions of the functions
|
|
117
|
+ * @param defaultLocation The location of the default value. Needs to be of or assignable to elementType!
|
|
118
|
+ */
|
|
119
|
+ static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, int defaultLocation) {
|
32
|
120
|
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, (elementType, counterLocations) -> javaWriter.load(elementType, defaultLocation));
|
33
|
121
|
}
|
34
|
122
|
|
35
|
|
- public static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction){
|
|
123
|
+ /**
|
|
124
|
+ * Writes the code for visiting a multidimensional array.
|
|
125
|
+ * Accepts a function that will decide what value to insert into the array slots.
|
|
126
|
+ * When the function is finished, one additional item needs to have been added to the stack.
|
|
127
|
+ * The already present stacks may not be touched!
|
|
128
|
+ *
|
|
129
|
+ * @param javaWriter the writer that will write the actual opcode
|
|
130
|
+ * @param sizeLocations the locations of the array dimension sizes sizeLocations.length == dim !!
|
|
131
|
+ * @param dim the array's dimensions, reduced during the recursions of the loop to find the innermost loop
|
|
132
|
+ * @param currentArrayType The current type of the array, reduced during the recursions of the functions
|
|
133
|
+ * @param innermostFunction The function that will decide what to add to the array, needs to increase the stack size by one and may not touch the other stacks!
|
|
134
|
+ */
|
|
135
|
+ private static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
|
36
|
136
|
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, innermostFunction);
|
37
|
137
|
}
|
38
|
138
|
|
|
139
|
+ /**
|
|
140
|
+ * Checks if an expression can be inlined
|
|
141
|
+ *
|
|
142
|
+ * @param expression Expression to check for.
|
|
143
|
+ * @return can expression be inlined
|
|
144
|
+ */
|
|
145
|
+ static boolean canBeInlined(Expression expression) {
|
|
146
|
+ while (expression instanceof StorageCastExpression)
|
|
147
|
+ expression = ((StorageCastExpression) expression).value;
|
|
148
|
+
|
|
149
|
+ return expression instanceof FunctionExpression && ((FunctionExpression) expression).body instanceof ReturnStatement;
|
|
150
|
+ }
|
39
|
151
|
|
|
152
|
+ /**
|
|
153
|
+ * The function that is actually setting up the loops and naming the counter variables.
|
|
154
|
+ * Private because the other static methods provide the new int[] sizeLocations.
|
|
155
|
+ * Recursively creates a forLoop per array dimension and in the innermost loop, applies the given function.
|
|
156
|
+ * That function needs to add one stack and may not touch the existing stacks.
|
|
157
|
+ *
|
|
158
|
+ * @param javaWriter the writer that will write the actual opcode
|
|
159
|
+ * @param sizeLocations the locations of the array dimension sizes sizeLocations.length == dim !!
|
|
160
|
+ * @param counterLocations the locations of the for-Loop counter variables (will be filled by the function itself, counterLocations.length == dim !!
|
|
161
|
+ * @param dim the array's dimensions, reduced during the recursions of the loop to find the innermost loop
|
|
162
|
+ * @param currentArrayType The current type of the array, reduced during the recursions of the functions
|
|
163
|
+ * @param innermostFunction The function that will decide what to add to the array, needs to increase the stack size by one and may not touch the other stacks!
|
|
164
|
+ */
|
40
|
165
|
private static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
|
41
|
166
|
final Label begin = new Label();
|
42
|
167
|
final Label end = new Label();
|