Skip to content

Commit

Permalink
Fix boxing of generics in generic method and constructor calls + fix …
Browse files Browse the repository at this point in the history
…constructor calls on generic classes
  • Loading branch information
stanhebben committed Mar 15, 2024
1 parent 3ae11ff commit df2f4ce
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
import org.openzen.zenscript.javashared.*;

import java.util.Collections;
import java.util.concurrent.atomic.AtomicInteger;

public class JavaMethodBytecodeCompiler implements JavaMethodCompiler<Void> {
private static final JavaNativeMethod BOOLEAN_TO_STRING = JavaNativeMethod.getNativeStatic(JavaClass.BOOLEAN, "toString", "(Z)Ljava/long/String;");

public static final JavaNativeMethod OBJECT_HASHCODE = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "hashCode", "()I");
public static final JavaNativeMethod OBJECT_EQUALS = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "equals", "(Ljava/lang/Object)Z");
public static final JavaNativeMethod OBJECT_EQUALS = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "equals", "(Ljava/lang/Object;)Z");
public static final JavaNativeMethod OBJECT_CLONE = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "clone", "()Ljava/lang/Object;");
private static final JavaNativeMethod OBJECTS_TOSTRING = JavaNativeMethod.getNativeStatic(new JavaClass("java.util", "Objects", JavaClass.Kind.CLASS), "toString", "(Ljava/lang/Object;)Ljava/lang/String;");
private static final JavaNativeMethod BYTE_PARSE = JavaNativeMethod.getNativeStatic(JavaClass.BYTE, "parseByte", "(Ljava/lang/String;)B");
Expand Down Expand Up @@ -102,12 +103,12 @@ public class JavaMethodBytecodeCompiler implements JavaMethodCompiler<Void> {
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([FII)[F");
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([DII)[D");
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([CII)[C");
private static final JavaNativeMethod ARRAYS_EQUALS_OBJECTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Ljava/lang/Object[Ljava/lang/Object)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_OBJECTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_BOOLS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Z[Z)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_BYTES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([B[B)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_SHORTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([S[S)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_INTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([I[I)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([L[L)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([J[J)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([F[F)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([D[D)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([C[C)Z");
Expand All @@ -116,7 +117,7 @@ public class JavaMethodBytecodeCompiler implements JavaMethodCompiler<Void> {
private static final JavaNativeMethod ARRAYS_HASHCODE_BYTES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([B)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_SHORTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([S)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_INTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([I)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([L)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([J)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([F)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([D)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([C)I");
Expand Down Expand Up @@ -147,12 +148,17 @@ public JavaMethodBytecodeCompiler(JavaWriter javaWriter, JavaExpressionVisitor e
public Void nativeConstructor(JavaNativeMethod method, TypeID type, CallArguments arguments) {
javaWriter.newObject(method.cls);
javaWriter.dup();
for (Expression argument : arguments.arguments) {
argument.accept(expressionVisitor);
}
AtomicInteger typeArguments = new AtomicInteger(0);
if (method.compile) {
handleTypeArguments(method, arguments);
type.asDefinition().ifPresent(definitionType -> {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
typeArguments.set(definitionType.typeArguments.length);
for (TypeID typeParameter : definitionType.typeArguments) {
typeParameter.accept(javaWriter, javaTypeExpressionVisitor);
}
});
}
handleArguments(typeArguments.get(), method, arguments);
javaWriter.invokeSpecial(method);
return null;
}
Expand All @@ -165,9 +171,7 @@ public Void nativeVirtualMethod(JavaNativeMethod method, TypeID returnType, Expr

@Override
public Void nativeStaticMethod(JavaNativeMethod method, TypeID returnType, CallArguments arguments) {
for (Expression argument : arguments.arguments) {
argument.accept(expressionVisitor);
}
handleArguments(arguments.typeArguments.length, method, arguments);
if (method.compile) {
handleTypeArguments(method, arguments);
}
Expand Down Expand Up @@ -200,16 +204,24 @@ public Void nativeStaticMethod(JavaNativeMethod method, TypeID returnType, CallA
@Override
public Void nativeSpecialMethod(JavaNativeMethod method, TypeID returnType, Expression target, CallArguments arguments) {
target.accept(expressionVisitor);
for (Expression argument : arguments.arguments) {
argument.accept(expressionVisitor);
}
handleArguments(arguments.typeArguments.length, method, arguments);
if (method.compile) {
handleTypeArguments(method, arguments);
}
javaWriter.invokeSpecial(method);
return null;
}

private void handleArguments(int typeArguments, JavaNativeMethod method, CallArguments arguments) {
for (int index = 0; index < arguments.arguments.length; index++) {
Expression argument = arguments.arguments[index];
argument.accept(expressionVisitor);
if (!method.primitiveArguments[typeArguments + index]) {
argument.type.accept(argument.type, boxingTypeVisitor);
}
}
}

private void handleTypeArguments(JavaNativeMethod method, CallArguments arguments) {
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
if (arguments.typeArguments.length != method.typeParameterArguments.length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

public class JavaBuiltinModule {
public static final JavaNativeMethod OBJECT_HASHCODE = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "hashCode", "()I");
public static final JavaNativeMethod OBJECT_EQUALS = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "equals", "(Ljava/lang/Object)Z");
public static final JavaNativeMethod OBJECT_EQUALS = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "equals", "(Ljava/lang/Object;)Z");
public static final JavaNativeMethod OBJECT_CLONE = JavaNativeMethod.getNativeVirtual(JavaClass.OBJECT, "clone", "()Ljava/lang/Object;");
private static final JavaNativeMethod OBJECTS_TOSTRING = JavaNativeMethod.getNativeStatic(new JavaClass("java.util", "Objects", JavaClass.Kind.CLASS), "toString", "(Ljava/lang/Object;)Ljava/lang/String;");
private static final JavaNativeMethod BYTE_PARSE = JavaNativeMethod.getNativeStatic(JavaClass.BYTE, "parseByte", "(Ljava/lang/String;)B");
Expand Down Expand Up @@ -102,12 +102,12 @@ public class JavaBuiltinModule {
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([FII)[F");
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([DII)[D");
private static final JavaNativeMethod ARRAYS_COPY_OF_RANGE_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "copyOfRange", "([CII)[C");
private static final JavaNativeMethod ARRAYS_EQUALS_OBJECTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Ljava/lang/Object[Ljava/lang/Object)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_OBJECTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Ljava/lang/Object;[Ljava/lang/Object;)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_BOOLS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([Z[Z)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_BYTES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([B[B)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_SHORTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([S[S)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_INTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([I[I)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([L[L)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([J[J)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([F[F)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([D[D)Z");
private static final JavaNativeMethod ARRAYS_EQUALS_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "equals", "([C[C)Z");
Expand All @@ -116,7 +116,7 @@ public class JavaBuiltinModule {
private static final JavaNativeMethod ARRAYS_HASHCODE_BYTES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([B)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_SHORTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([S)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_INTS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([I)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([L)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_LONGS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([J)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_FLOATS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([F)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_DOUBLES = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([D)I");
private static final JavaNativeMethod ARRAYS_HASHCODE_CHARS = JavaNativeMethod.getNativeStatic(JavaClass.ARRAYS, "hashCode", "([C)I");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.openzen.zenscript.codemodel.expression.Expression;
import org.openzen.zenscript.codemodel.type.TypeID;

import java.util.Arrays;

/**
* @author Hoofdgebruiker
*/
Expand All @@ -21,6 +23,7 @@ public class JavaNativeMethod implements JavaMethod {
public final int modifiers; // these are Java modifiers!
public final boolean genericResult;
public final boolean[] typeParameterArguments;
public final boolean[] primitiveArguments;

public JavaNativeMethod(JavaClass cls, Kind kind, String name, boolean compile, String descriptor, int modifiers, boolean genericResult) {
this(cls, kind, name, compile, descriptor, modifiers, genericResult, new boolean[0]);
Expand All @@ -41,6 +44,7 @@ public JavaNativeMethod(JavaClass cls, Kind kind, String name, boolean compile,
this.modifiers = modifiers;
this.genericResult = genericResult;
this.typeParameterArguments = typeParameterArguments;
this.primitiveArguments = determinePrimitiveArguments(descriptor);
}

public static JavaNativeMethod getConstructor(JavaClass cls, String descriptor, int modifiers) {
Expand Down Expand Up @@ -134,4 +138,35 @@ public enum Kind {
CONSTRUCTOR,
COMPILED
}

private static boolean[] determinePrimitiveArguments(String descriptor) {
try {
boolean[] result = new boolean[descriptor.length()];
int index = 0;
for (int i = 1; i < descriptor.length(); i++) {
if (descriptor.charAt(i) == ')')
break;

char c = descriptor.charAt(i);
if (c == 'L') {
while (descriptor.charAt(i) != ';')
i++;
result[index++] = false;
} else if (c == '[') {
while (descriptor.charAt(i) == '[')
i++;
if (descriptor.charAt(i) == 'L') {
while (descriptor.charAt(i) != ';')
i++;
}
result[index++] = false;
} else {
result[index++] = true;
}
}
return Arrays.copyOf(result, index);
} catch (StringIndexOutOfBoundsException ex) {
throw new IllegalArgumentException("Invalid descriptor: " + descriptor, ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#output: Jimmy
#output: 19

public class Duad<A, B> {
public var a as A : get;
public var b as B : get;
public this(a as A, b as B) {
this.a = a;
this.b = b;
}
}

public function duadExample(name as string, age as int) as Duad<string, int> {
return new Duad<string, int>(name, age);
}

var jimmy = duadExample("Jimmy", 19);

println(jimmy.a);
println(jimmy.b);
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#output: 1
#output: test

var item_values = {} as int[string];
item_values["box"] = 1;
item_values["test"] = 9;
println(item_values["box"]);

var value_items = {} as string[int];
value_items[1] = "box";
value_items[9] = "test";
println(value_items[9]);

This file was deleted.

0 comments on commit df2f4ce

Please sign in to comment.