Skip to content

Commit

Permalink
Fix creation of generic arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
stanhebben committed Mar 15, 2024
1 parent df2f4ce commit 3d3c7f0
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public CastedEval(ExpressionCompiler compiler, CodePosition position, TypeID typ
public CastedExpression of(Expression value) {
if (value.type.equals(type) || type == BasicTypeID.UNDETERMINED)
return new CastedExpression(CastedExpression.Level.EXACT, value);
if (value.type.isInvalid())
return CastedExpression.invalid(value);

ResolvedType resolvedTargetType = compiler.resolve(type);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,15 @@ public ResolvedType resolve(TypeID[] typeArguments) {
if (baseType.hasDefaultValue()) {
members.constructor(new MethodInstance(
BuiltinMethodSymbol.ARRAY_CONSTRUCTOR_SIZED,
new FunctionHeader(VOID, indexGetParameters),
new FunctionHeader(type, indexGetParameters),
type));
}

FunctionParameter[] initialValueConstructorParameters = new FunctionParameter[dimension + 1];
for (int i = 0; i < dimension; i++)
initialValueConstructorParameters[i] = new FunctionParameter(USIZE);
initialValueConstructorParameters[dimension] = new FunctionParameter(baseType);
FunctionHeader initialValueConstructorHeader = new FunctionHeader(VOID, initialValueConstructorParameters);
FunctionHeader initialValueConstructorHeader = new FunctionHeader(type, initialValueConstructorParameters);
members.constructor(new MethodInstance(BuiltinMethodSymbol.ARRAY_CONSTRUCTOR_INITIAL_VALUE, initialValueConstructorHeader, type));

FunctionParameter[] lambdaConstructorParameters = new FunctionParameter[dimension + 1];
Expand All @@ -152,7 +152,7 @@ public ResolvedType resolve(TypeID[] typeArguments) {

FunctionHeader lambdaConstructorFunction = new FunctionHeader(baseType, indexGetParameters);
lambdaConstructorParameters[dimension] = new FunctionParameter(new FunctionTypeID(lambdaConstructorFunction));
FunctionHeader lambdaConstructorHeader = new FunctionHeader(VOID, lambdaConstructorParameters);
FunctionHeader lambdaConstructorHeader = new FunctionHeader(type, lambdaConstructorParameters);
members.constructor(new MethodInstance(BuiltinMethodSymbol.ARRAY_CONSTRUCTOR_LAMBDA, lambdaConstructorHeader, type));

FunctionParameter[] indexSetParameters = new FunctionParameter[dimension + 1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
import org.openzen.zenscript.codemodel.expression.Expression;
import org.openzen.zenscript.codemodel.type.ArrayTypeID;
import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
import org.openzen.zenscript.javashared.JavaClass;
import org.openzen.zenscript.javashared.JavaNativeMethod;

import java.util.ArrayList;

class ArrayInitializerHelper {
private static final JavaNativeMethod ARRAY_NEWINSTANCE = JavaNativeMethod.getNativeStatic(JavaClass.ARRAY, "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;");

private final JavaBytecodeContext context;

public ArrayInitializerHelper(JavaBytecodeContext context) {
this.context = context;
}

/**
* Creates an int[] with the given array size locations and writes the code that gets them in the generated file
Expand Down Expand Up @@ -43,8 +54,8 @@ static int[] getArraySizeLocationsFromConstructor(int dimension, Expression[] ar
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
* @param defaultLocation The location of the default value. Needs to be of or assignable to elementType!
*/
static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, int defaultLocation) {
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, (elementType, counterLocations) -> javaWriter.load(elementType, defaultLocation));
void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, ArrayTypeID arrayType, int defaultLocation) {
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, arrayType, (elementType, counterLocations) -> javaWriter.load(elementType, defaultLocation));
}

/**
Expand All @@ -60,15 +71,23 @@ static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] size
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
* @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!
*/
static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, Type currentArrayType, ArrayTypeID arrayType, InnermostFunction innermostFunction) {
final Label begin = new Label();
final Label end = new Label();
javaWriter.label(begin);

final int currentArraySizeLocation = sizeLocations[sizeLocations.length - dim];
javaWriter.loadInt(currentArraySizeLocation);

final Type elementType = Type.getType(currentArrayType.getDescriptor().substring(1));
javaWriter.newArray(elementType);
if (arrayType.elementType.isGeneric()) {
arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
javaWriter.loadInt(currentArraySizeLocation);
javaWriter.invokeStatic(ARRAY_NEWINSTANCE);
javaWriter.checkCast(context.getInternalName(arrayType));
} else {
javaWriter.loadInt(currentArraySizeLocation);
javaWriter.newArray(elementType);
}
//javaWriter.dup();

final int forLoopCounter = javaWriter.local(int.class);
Expand All @@ -92,7 +111,7 @@ static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[]
if (dim == 1) {
innermostFunction.apply(elementType, counterLocations);
} else {
visitMultiDimArray(javaWriter, sizeLocations, counterLocations, dim - 1, elementType, innermostFunction);
visitMultiDimArray(javaWriter, sizeLocations, counterLocations, dim - 1, elementType, arrayType, innermostFunction);
}
javaWriter.arrayStore(elementType);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ public Void visitAndAnd(AndAndExpression expression) {
public Void visitArray(ArrayExpression expression) {
Type type = context.getType(expression.arrayType.elementType);
if (expression.arrayType.elementType.isGeneric()) {

expression.arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
javaWriter.constant(expression.expressions.length);
javaWriter.invokeStatic(ARRAY_NEWINSTANCE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,13 @@ public Void builtinConstructor(BuiltinMethodSymbol method, TypeID type, CallArgu


final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsFromConstructor(arrayType.dimension, arguments, expressionVisitor);
ArrayInitializerHelper.visitMultiDimArrayWithDefaultValue(javaWriter, arraySizes, arrayType.dimension, ASMType, defaultValueLocation);
new ArrayInitializerHelper(context).visitMultiDimArrayWithDefaultValue(javaWriter, arraySizes, arrayType.dimension, ASMType, arrayType, defaultValueLocation);

javaWriter.label(end);
return null;
}
case ARRAY_CONSTRUCTOR_LAMBDA: {
ArrayTypeID arrayType = (ArrayTypeID) type;

//Labels
final Label begin = new Label();
Expand All @@ -301,7 +302,7 @@ public Void builtinConstructor(BuiltinMethodSymbol method, TypeID type, CallArgu
final Type ASMElementType = context.getType(type);
final int dimension = ((ArrayTypeID) type).dimension;
final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsFromConstructor(dimension, arguments, expressionVisitor);
ArrayInitializerHelper.visitMultiDimArray(javaWriter, arraySizes, new int[dimension], dimension, ASMElementType, (elementType, counterLocations) -> {
new ArrayInitializerHelper(context).visitMultiDimArray(javaWriter, arraySizes, new int[dimension], dimension, ASMElementType, arrayType, (elementType, counterLocations) -> {
arguments[dimension].accept(expressionVisitor);
for (int counterLocation : counterLocations) {
javaWriter.loadInt(counterLocation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,9 @@ public Void visitVariant(VariantDefinition variant) {
}

private void visitClassCompiled(HighLevelDefinition definition, boolean startsEmpty, JavaClass.Kind kind) {
for (TypeParameter typeParameter : definition.typeParameters) {
class_.module.module.setTypeParameterInfo(typeParameter, new JavaTypeParameterInfo(-1));
}

JavaNativeClass nativeClass = class_.getContext().getJavaNativeClass(definition);
JavaClass cls = class_.getContext().getJavaClass(definition);

if (nativeClass == null) {
visitClassMembers(definition, startsEmpty);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.openzen.zenscript.codemodel.HighLevelDefinition;
import org.openzen.zenscript.codemodel.annotations.NativeTag;
import org.openzen.zenscript.codemodel.definition.*;
import org.openzen.zenscript.codemodel.generic.TypeParameter;
import org.openzen.zenscript.codemodel.identifiers.TypeSymbol;
import org.openzen.zenscript.codemodel.member.IDefinitionMember;
import org.openzen.zenscript.codemodel.member.ImplementationMember;
Expand Down Expand Up @@ -363,6 +364,16 @@ private JavaClass visitClassCompiled(HighLevelDefinition definition, boolean sta
module.context.setJavaNativeClass(definition, nativeClass);
}

for (int typeParameterIndex = 0; typeParameterIndex < definition.typeParameters.length; typeParameterIndex++) {
TypeParameter typeParameter = definition.typeParameters[typeParameterIndex];
final JavaNativeField field = new JavaNativeField(cls,
"typeOf" + typeParameter.name,
"Ljava/lang/Class;",
"Ljava/lang/Class<T" + typeParameter.name + ";>;"
);
module.module.setTypeParameterInfo(typeParameter, new JavaTypeParameterInfo(typeParameterIndex + 1, field));
}

if (definition.getSuperType() != null) {
definition.getSuperType().asDefinition().ifPresent(definitionTypeID -> compiling.addDependency(definitionTypeID.definition));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#output: 0
#output: x

class ArrayFactory<T> {
public newInstance(length: int): T[] {
return new T[length];
public newInstance(length: int, defaultValue: T): T[] {
return new T[](length, defaultValue);
}
}

var a = new ArrayFactory<int>();
var b = a.newInstance(10);
var a = new ArrayFactory<string>();
var b = a.newInstance(10, "x");
println(b[1]);

0 comments on commit 3d3c7f0

Please sign in to comment.