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