Skip to content

Commit 58bbc6a

Browse files
authored
Merge pull request #123 from ZenCodeLang/bugfix/expansion_generic_signature_2
Bugfix/expansion generic signature 2
2 parents 094886f + 1cc9c7b commit 58bbc6a

File tree

12 files changed

+376
-164
lines changed

12 files changed

+376
-164
lines changed

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/ArrayTypeID.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ public ArrayTypeID(GlobalTypeRegistry registry, TypeID elementType, int dimensio
2828
this.normalized = elementType.getNormalized() == elementType ? this : registry.getArray(elementType.getNormalized(), dimension);
2929
}
3030

31+
public TypeID removeOneDimension() {
32+
return dimension > 1 ? new ArrayTypeID(elementType, dimension - 1) : elementType;
33+
}
34+
3135
@Override
3236
public Expression getDefaultValue() {
3337
return new ArrayExpression(CodePosition.UNKNOWN, Expression.NONE, this);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package org.openzen.zenscript.javabytecode.compiler;
2+
3+
import org.objectweb.asm.Type;
4+
import org.openzen.zenscript.codemodel.type.ArrayTypeID;
5+
import org.openzen.zenscript.codemodel.type.GenericTypeID;
6+
import org.openzen.zenscript.codemodel.type.TypeID;
7+
import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
8+
import org.openzen.zenscript.javashared.JavaClass;
9+
import org.openzen.zenscript.javashared.JavaMethod;
10+
11+
public class ArrayHelperType {
12+
13+
private final TypeID elementType;
14+
private final JavaBytecodeContext context;
15+
16+
public ArrayHelperType(TypeID elementType, JavaBytecodeContext context) {
17+
this.elementType = elementType;
18+
this.context = context;
19+
}
20+
21+
22+
public ArrayHelperType getWithOneDimensionLess() {
23+
ArrayTypeID arrayTypeID = ((ArrayTypeID) elementType);
24+
return new ArrayHelperType(arrayTypeID.removeOneDimension(), context);
25+
}
26+
27+
public void newArray(JavaWriter javaWriter) {
28+
if(elementType instanceof GenericTypeID) {
29+
30+
elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
31+
javaWriter.swap();
32+
final JavaClass arrayClass = JavaClass.fromInternalName("java/lang/reflect/Array", JavaClass.Kind.CLASS);
33+
javaWriter.invokeStatic(JavaMethod.getStatic(arrayClass, "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;", 0));
34+
javaWriter.checkCast("[Ljava/lang/Object;");
35+
} else {
36+
javaWriter.newArray(context.getType(elementType));
37+
}
38+
}
39+
40+
public Type getASMElementType() {
41+
return context.getType(elementType);
42+
}
43+
}

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/ArrayInitializerHelper.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static int[] getArraySizeLocationsFromConstructor(int dimension, Expression[] ar
8686
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
8787
* @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!
8888
*/
89-
static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int dim, int originArrayLocation, Type originArrayType, Type currentArrayType, InnermostFunction innermostFunction) {
89+
static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int dim, int originArrayLocation, Type originArrayType, ArrayHelperType currentArrayType, InnermostFunction innermostFunction) {
9090

9191
visitMultiDimArray(javaWriter, sizeLocations, dim, currentArrayType, (elementType, counterLocations) -> {
9292
//Load origin array
@@ -115,8 +115,8 @@ static void visitProjected(JavaWriter javaWriter, int[] sizeLocations, int dim,
115115
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
116116
* @param defaultLocation The location of the default value. Needs to be of or assignable to elementType!
117117
*/
118-
static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, int defaultLocation) {
119-
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, (elementType, counterLocations) -> javaWriter.load(elementType, defaultLocation));
118+
static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] sizeLocations, int dim, ArrayHelperType currentArrayType, int defaultLocation) {
119+
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, (elementType, counterLocations) -> javaWriter.load(elementType.getASMElementType(), defaultLocation));
120120
}
121121

122122
/**
@@ -131,7 +131,7 @@ static void visitMultiDimArrayWithDefaultValue(JavaWriter javaWriter, int[] size
131131
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
132132
* @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!
133133
*/
134-
private static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
134+
private static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int dim, ArrayHelperType currentArrayType, InnermostFunction innermostFunction) {
135135
visitMultiDimArray(javaWriter, sizeLocations, new int[dim], dim, currentArrayType, innermostFunction);
136136
}
137137

@@ -158,15 +158,15 @@ static boolean canBeInLined(Expression expression) {
158158
* @param currentArrayType The current type of the array, reduced during the recursions of the functions
159159
* @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!
160160
*/
161-
static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, Type currentArrayType, InnermostFunction innermostFunction) {
161+
static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[] counterLocations, int dim, ArrayHelperType currentArrayType, InnermostFunction innermostFunction) {
162162
final Label begin = new Label();
163163
final Label end = new Label();
164164
javaWriter.label(begin);
165165

166166
final int currentArraySizeLocation = sizeLocations[sizeLocations.length - dim];
167167
javaWriter.loadInt(currentArraySizeLocation);
168-
final Type elementType = Type.getType(currentArrayType.getDescriptor().substring(1));
169-
javaWriter.newArray(elementType);
168+
final ArrayHelperType elementType = currentArrayType.getWithOneDimensionLess();
169+
elementType.newArray(javaWriter);
170170
//javaWriter.dup();
171171

172172
final int forLoopCounter = javaWriter.local(int.class);
@@ -192,7 +192,7 @@ static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[]
192192
} else {
193193
visitMultiDimArray(javaWriter, sizeLocations, counterLocations, dim - 1, elementType, innermostFunction);
194194
}
195-
javaWriter.arrayStore(elementType);
195+
javaWriter.arrayStore(elementType.getASMElementType());
196196

197197
//Return to the start
198198
javaWriter.iinc(forLoopCounter);
@@ -212,7 +212,7 @@ static void visitMultiDimArray(JavaWriter javaWriter, int[] sizeLocations, int[]
212212

213213
@FunctionalInterface
214214
public interface InnermostFunction {
215-
void apply(Type elementType, int[] counterLocations);
215+
void apply(ArrayHelperType elementType, int[] counterLocations);
216216
}
217217
}
218218

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaExpressionVisitor.java

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.openzen.zenscript.codemodel.CompareType;
99
import org.openzen.zenscript.codemodel.FunctionParameter;
1010
import org.openzen.zenscript.codemodel.annotations.NativeTag;
11+
import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
1112
import org.openzen.zenscript.codemodel.expression.*;
1213
import org.openzen.zenscript.codemodel.expression.switchvalue.VariantOptionSwitchValue;
1314
import org.openzen.zenscript.codemodel.generic.TypeParameter;
@@ -431,6 +432,9 @@ public Void visitCall(CallExpression expression) {
431432
if (!checkAndExecuteMethodInfo(expression.member, expression.type, expression))
432433
throw new IllegalStateException("Call target has no method info!");
433434

435+
if (expression.member.getTarget().header.getReturnType().isGeneric())
436+
javaWriter.checkCast(context.getType(expression.type));
437+
434438
return null;
435439
}
436440

@@ -1230,8 +1234,26 @@ private void handleTypeArguments(FunctionalMemberRef member, CallArguments argum
12301234
JavaMethod methodInfo = context.getJavaMethod(member);
12311235

12321236
if (methodInfo.compile) {
1233-
if (typeParameters.size() == arguments.typeArguments.length) {
1237+
if (typeParameters.size() == (member.getTarget().definition.getNumberOfGenericParameters() + arguments.typeArguments.length)) {
12341238
final JavaTypeExpressionVisitor javaTypeExpressionVisitor = new JavaTypeExpressionVisitor(context);
1239+
1240+
// Try to load all type parameters of "this" to the stack, if an expansion
1241+
if (member.getTarget().definition instanceof ExpansionDefinition) {
1242+
if (((ExpansionDefinition) member.getTarget().definition).target instanceof ArrayTypeID
1243+
&& member.getOwnerType() instanceof ArrayTypeID) {
1244+
//FIXME: Dirty hack until we get this to work better
1245+
// Problem: How can we get the TypeParameters of e.g. T[] when all info we have uses the filled in type info?
1246+
final TypeID elementType = ((ArrayTypeID) member.getOwnerType()).elementType;
1247+
elementType.accept(javaWriter, javaTypeExpressionVisitor);
1248+
} else {
1249+
for (int i = 0; i < member.getTarget().definition.getNumberOfGenericParameters(); i++) {
1250+
1251+
javaWriter.aConstNull(); // TODO: Replace with actual class
1252+
javaWriter.checkCast("java/lang/Class");
1253+
}
1254+
}
1255+
}
1256+
12351257
for (TypeID typeArgument : arguments.typeArguments) {
12361258
typeArgument.accept(javaWriter, javaTypeExpressionVisitor);
12371259
}
@@ -2683,7 +2705,7 @@ private void visitBuiltinConstructor(NewExpression expression) {
26832705
case ARRAY_CONSTRUCTOR_INITIAL_VALUE: {
26842706
ArrayTypeID type = (ArrayTypeID) expression.type;
26852707

2686-
final Type ASMType = context.getType(expression.type);
2708+
final ArrayHelperType ASMType = new ArrayHelperType(type, context);
26872709
final Type ASMElementType = context.getType(type.elementType);
26882710

26892711
final Label begin = new Label();
@@ -2715,7 +2737,7 @@ private void visitBuiltinConstructor(NewExpression expression) {
27152737
final Label end = new Label();
27162738
javaWriter.label(begin);
27172739

2718-
final Type ASMElementType = context.getType(expression.type);
2740+
final ArrayHelperType ASMElementType = new ArrayHelperType(expression.type, context);
27192741
final int dimension = ((ArrayTypeID) expression.type).dimension;
27202742
final int[] arraySizes = ArrayInitializerHelper.getArraySizeLocationsFromConstructor(dimension, expression.arguments.arguments, this);
27212743
ArrayInitializerHelper.visitMultiDimArray(javaWriter, arraySizes, new int[dimension], dimension, ASMElementType, (elementType, counterLocations) -> {
@@ -2742,7 +2764,7 @@ private void visitBuiltinConstructor(NewExpression expression) {
27422764
final Type originArrayType = context.getType(expression.arguments.arguments[0].type);
27432765
final int originArrayLocation = javaWriter.local(originArrayType);
27442766
javaWriter.storeObject(originArrayLocation);
2745-
Type destinationArrayType = context.getType(expression.type);
2767+
ArrayHelperType destinationArrayType = new ArrayHelperType(type, context);
27462768

27472769
final boolean indexed = builtin == BuiltinID.ARRAY_CONSTRUCTOR_PROJECTED_INDEXED;
27482770
final boolean canBeInLined = ArrayInitializerHelper.canBeInLined(expression.arguments.arguments[1]);
@@ -3509,8 +3531,8 @@ public Void isEmptyAsLengthZero(Expression value) {
35093531
public Void listToArray(CastExpression value) {
35103532
//value.target.accept(this);
35113533
javaWriter.iConst0();
3512-
final Type type = context.getType(((ArrayTypeID) value.type).elementType);
3513-
javaWriter.newArray(type);
3534+
final ArrayHelperType arrayHelperType = new ArrayHelperType(((ArrayTypeID)value.type).elementType, context);
3535+
arrayHelperType.newArray(javaWriter);
35143536
final JavaMethod toArray = new JavaMethod(JavaClass.COLLECTION, JavaMethod.Kind.INSTANCE, "toArray", true, "([Ljava/lang/Object;)[Ljava/lang/Object;", 0, true);
35153537
javaWriter.invokeInterface(toArray);
35163538
javaWriter.checkCast(context.getType(value.type));

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/JavaWriter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ public void constant(Object value) {
199199
visitor.visitLdcInsn(value);
200200
}
201201

202+
public void constant(Class<?> cls) {
203+
constant(Type.getType(cls));
204+
}
205+
202206
public void constantClass(JavaClass cls) {
203207
visitor.visitLdcInsn(Type.getObjectType(cls.internalName));
204208
}

JavaBytecodeCompiler/src/main/java/org/openzen/zenscript/javabytecode/compiler/definitions/JavaExpansionMemberVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ public Void visitMethod(MethodMember member) {
130130

131131

132132
final int index = methodSignature1.lastIndexOf('(') + 1;
133-
methodSignature = methodSignature1.substring(0, index) + expandedClassSignature + typeParamSigBuilder.toString() + methodSignature1.substring(index);
134-
methodDescriptor = "(" + expandedClassDescriptor + typeParamDescBuilder.toString() + context.getMethodDescriptor(member.header).substring(1);
133+
methodSignature = methodSignature1.substring(0, index) + expandedClassSignature + typeParamSigBuilder + methodSignature1.substring(index);
134+
methodDescriptor = "(" + expandedClassDescriptor + typeParamDescBuilder + context.getMethodDescriptor(member.header).substring(1);
135135
} else {
136136
methodSignature = context.getMethodSignature(member.header);
137137
methodDescriptor = context.getMethodDescriptor(member.header);

JavaShared/src/main/java/org/openzen/zenscript/javashared/JavaContext.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,16 +523,17 @@ public JavaSynthesizedClass getRange(RangeTypeID type) {
523523
*/
524524
public String getMethodDescriptor(FunctionHeader header, boolean isEnumConstructor, String expandedType) {
525525
StringBuilder descBuilder = new StringBuilder("(");
526+
527+
//TODO: Put this earlier? We'd need to agree on one...
528+
if (expandedType != null)
529+
descBuilder.append(expandedType);
530+
526531
for (int i = 0; i < header.getNumberOfTypeParameters(); i++)
527532
descBuilder.append("Ljava/lang/Class;");
528533

529534
if (isEnumConstructor)
530535
descBuilder.append("Ljava/lang/String;I");
531536

532-
//TODO: Put this earlier? We'd need to agree on one...
533-
if (expandedType != null)
534-
descBuilder.append(expandedType);
535-
536537
for (FunctionParameter parameter : header.parameters) {
537538
descBuilder.append(getDescriptor(parameter.type));
538539
}
@@ -552,4 +553,8 @@ public String getMethodDescriptorConstructor(FunctionHeader header, DefinitionMe
552553
public GlobalTypeRegistry getRegistry() {
553554
return registry;
554555
}
556+
557+
public boolean isGenericOrContainsGenericParameters(TypeID typeID) {
558+
return typeID.accept(new JavaTypeCheckIfGenericVisitor());
559+
}
555560
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package org.openzen.zenscript.javashared;
2+
3+
import org.openzen.zenscript.codemodel.type.*;
4+
5+
import java.util.Arrays;
6+
7+
public class JavaTypeCheckIfGenericVisitor implements TypeVisitor<Boolean> {
8+
@Override
9+
public Boolean visitBasic(BasicTypeID basic) {
10+
return false;
11+
}
12+
13+
@Override
14+
public Boolean visitArray(ArrayTypeID array) {
15+
return array.elementType.accept(this);
16+
}
17+
18+
@Override
19+
public Boolean visitAssoc(AssocTypeID assoc) {
20+
return assoc.keyType.accept(this) || assoc.valueType.accept(this);
21+
}
22+
23+
@Override
24+
public Boolean visitGenericMap(GenericMapTypeID map) {
25+
return true;
26+
}
27+
28+
@Override
29+
public Boolean visitIterator(IteratorTypeID iterator) {
30+
return true; //ToDo, is that right?
31+
}
32+
33+
@Override
34+
public Boolean visitFunction(FunctionTypeID function) {
35+
return function.header.typeParameters.length > 0
36+
|| function.header.getReturnType().accept(this)
37+
|| Arrays.stream(function.header.parameters).anyMatch(functionParameter -> functionParameter.type.accept(this));
38+
}
39+
40+
@Override
41+
public Boolean visitDefinition(DefinitionTypeID definition) {
42+
return definition.isGeneric();
43+
}
44+
45+
@Override
46+
public Boolean visitGeneric(GenericTypeID generic) {
47+
return true;
48+
}
49+
50+
@Override
51+
public Boolean visitRange(RangeTypeID range) {
52+
return range.baseType.accept(this);
53+
}
54+
55+
@Override
56+
public Boolean visitOptional(OptionalTypeID type) {
57+
return type.baseType.accept(this);
58+
}
59+
}

JavaShared/src/main/java/org/openzen/zenscript/javashared/prepare/JavaPrepareExpansionMethodVisitor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.openzen.zenscript.codemodel.definition.ExpansionDefinition;
1313
import org.openzen.zenscript.codemodel.member.*;
1414
import org.openzen.zenscript.codemodel.type.BasicTypeID;
15-
import org.openzen.zenscript.codemodel.type.GenericTypeID;
1615
import org.openzen.zenscript.javashared.*;
1716

1817
/**
@@ -170,7 +169,7 @@ private void visitFunctional(DefinitionMember member, FunctionHeader header, Str
170169
true,
171170
descriptor,
172171
JavaModifiers.getJavaModifiers(member.getEffectiveModifiers()),
173-
header.getReturnType() instanceof GenericTypeID,
172+
context.isGenericOrContainsGenericParameters(header.getReturnType()),
174173
header.useTypeParameters());
175174
}
176175
}

0 commit comments

Comments
 (0)