Skip to content

Commit c9407d9

Browse files
committed
Fix generic expansions and handling of generic array return types
1 parent b1d89fa commit c9407d9

20 files changed

Lines changed: 113 additions & 29 deletions

File tree

CodeModel/src/main/java/org/openzen/zenscript/codemodel/FunctionHeader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ public boolean isSimilarTo(FunctionHeader other) {
328328
public FunctionHeader instanceForCall(CallArguments arguments) {
329329
if (arguments.getNumberOfTypeArguments() > 0) {
330330
Map<TypeParameter, TypeID> typeParameters = TypeID.getMapping(this.typeParameters, arguments.typeArguments);
331-
return instance(new GenericMapper(typeParameters));
331+
return instance(new GenericMapper(typeParameters, arguments.expansionTypeArguments));
332332
} else {
333333
return this;
334334
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/GenericMapper.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@
1414

1515
public class GenericMapper {
1616

17-
public static final GenericMapper EMPTY = new GenericMapper(Collections.emptyMap());
17+
public static final GenericMapper EMPTY = new GenericMapper(Collections.emptyMap(), TypeID.NONE);
1818

1919
private final Map<TypeParameter, TypeID> mapping;
20+
private final TypeID[] expansionTypeArguments;
2021

21-
public GenericMapper(Map<TypeParameter, TypeID> mapping) {
22+
public GenericMapper(Map<TypeParameter, TypeID> mapping, TypeID[] expansionTypeArguments) {
2223
if (mapping == null)
2324
throw new IllegalArgumentException();
2425

2526
this.mapping = mapping;
27+
this.expansionTypeArguments = expansionTypeArguments;
2628
}
2729

2830
public static GenericMapper create(TypeParameter[] typeParameters, TypeID[] typeArguments) {
@@ -33,11 +35,11 @@ public static GenericMapper create(TypeParameter[] typeParameters, TypeID[] type
3335
for (int i = 0; i < typeParameters.length; i++) {
3436
mapping.put(typeParameters[i], typeArguments[i]);
3537
}
36-
return new GenericMapper(mapping);
38+
return new GenericMapper(mapping, TypeID.NONE);
3739
}
3840

3941
public static GenericMapper single(TypeParameter parameter, TypeID argument) {
40-
return new GenericMapper(Collections.singletonMap(parameter, argument));
42+
return new GenericMapper(Collections.singletonMap(parameter, argument), TypeID.NONE);
4143
}
4244

4345
public Map<TypeParameter, TypeID> getMapping() {
@@ -74,7 +76,7 @@ public FieldInstance map(FieldSymbol field) {
7476
}
7577

7678
public MethodInstance map(TypeID target, MethodSymbol method) {
77-
return new MethodInstance(method, map(method.getHeader()), target);
79+
return new MethodInstance(method, map(method.getHeader()), target, expansionTypeArguments);
7880
}
7981

8082
public GenericMapper getInner(Map<TypeParameter, TypeID> mapping) {
@@ -87,14 +89,14 @@ public GenericMapper getInner(Map<TypeParameter, TypeID> mapping) {
8789
resultMap.put(typeParameter, type);
8890
});
8991

90-
return new GenericMapper(resultMap);
92+
return new GenericMapper(resultMap, expansionTypeArguments);
9193
}
9294

9395
public GenericMapper getInner(TypeParameter[] parameters) {
9496
Map<TypeParameter, TypeID> resultMap = new HashMap<>(this.mapping);
9597
for (TypeParameter parameter : parameters)
9698
resultMap.put(parameter, new GenericTypeID(parameter));
97-
return new GenericMapper(resultMap);
99+
return new GenericMapper(resultMap, expansionTypeArguments);
98100
}
99101

100102
@Override

CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/CompileContext.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.openzen.zenscript.codemodel.type.member.ExpandedResolvedType;
2222

2323
import java.util.*;
24+
import java.util.stream.Stream;
2425

2526
public class CompileContext extends AbstractTypeBuilder implements TypeResolver {
2627
private final ZSPackage rootPackage;
@@ -93,8 +94,9 @@ public ResolvedType resolve(TypeID type) {
9394
if (mapping == null)
9495
continue;
9596

97+
TypeID[] expansionTypeArguments = Stream.of(expansion.typeParameters).map(mapping::get).toArray(TypeID[]::new);
9698
MemberSet.Builder resolution = MemberSet.create();
97-
GenericMapper mapper = new GenericMapper(mapping);
99+
GenericMapper mapper = new GenericMapper(mapping, expansionTypeArguments);
98100
for (IDefinitionMember member : expansion.members)
99101
member.registerTo(type, resolution, mapper);
100102

CodeModel/src/main/java/org/openzen/zenscript/codemodel/compilation/MatchedCallArguments.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.openzen.zenscript.codemodel.expression.CallArguments;
88
import org.openzen.zenscript.codemodel.expression.Expression;
99
import org.openzen.zenscript.codemodel.generic.TypeParameter;
10+
import org.openzen.zenscript.codemodel.identifiers.instances.MethodInstance;
1011
import org.openzen.zenscript.codemodel.type.ArrayTypeID;
1112
import org.openzen.zenscript.codemodel.type.BasicTypeID;
1213
import org.openzen.zenscript.codemodel.type.TypeID;
@@ -109,9 +110,12 @@ private static CallArguments match(
109110
TypeID[] typeArguments,
110111
CompilingExpression... arguments
111112
) {
113+
TypeID[] expansionTypeArguments = method.asMethod().map(MethodInstance::getExpansionTypeArguments).orElse(TypeID.NONE);
114+
112115
if (!method.getHeader().accepts(arguments.length))
113116
return new CallArguments(
114117
CastedExpression.Level.INVALID,
118+
expansionTypeArguments,
115119
typeArguments,
116120
Expression.NONE);
117121

@@ -124,7 +128,7 @@ private static CallArguments match(
124128

125129
// create a mapping with everything found so far
126130
// NOTE - this means that inference is sensitive to order of parameters
127-
GenericMapper mapper = new GenericMapper(typeArgumentMap);
131+
GenericMapper mapper = new GenericMapper(typeArgumentMap, expansionTypeArguments);
128132

129133
// now try to infer type arguments from the arguments
130134
for (int i = 0; i < arguments.length; i++) {
@@ -152,7 +156,7 @@ private static CallArguments match(
152156
}
153157
if (hasUnknowns) {
154158
// TODO: improve type inference
155-
return new CallArguments(CastedExpression.Level.INVALID, typeArguments, Expression.NONE);
159+
return new CallArguments(CastedExpression.Level.INVALID, TypeID.NONE, typeArguments, Expression.NONE);
156160
}
157161

158162
typeArguments = typeArguments2;
@@ -195,6 +199,6 @@ private static CallArguments match(
195199
cArguments[cArguments.length - 1] = compiler.at(position).newArray(new ArrayTypeID(variadicType), varargArguments.toArray(Expression.NONE));
196200
levelNormalCall = levelVarargCall;
197201
}
198-
return new CallArguments(levelNormalCall, typeArguments, cArguments);
202+
return new CallArguments(levelNormalCall, expansionTypeArguments, typeArguments, cArguments);
199203
}
200204
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/expression/CallArguments.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,44 @@ public class CallArguments {
77
public static final CallArguments EMPTY = new CallArguments(Expression.NONE);
88

99
public final CastedExpression.Level level;
10+
public final TypeID[] expansionTypeArguments;
1011
public final TypeID[] typeArguments;
1112
public final Expression[] arguments;
1213

1314
public CallArguments(Expression... arguments) {
1415
this.level = CastedExpression.Level.EXACT;
16+
this.expansionTypeArguments = TypeID.NONE;
1517
this.typeArguments = TypeID.NONE;
1618
this.arguments = arguments;
1719
}
1820

19-
public CallArguments(TypeID[] typeArguments, Expression[] arguments) {
21+
public CallArguments(TypeID[] expansionTypeArguments, TypeID[] typeArguments, Expression[] arguments) {
2022
if (typeArguments == null)
2123
typeArguments = TypeID.NONE;
2224
if (arguments == null)
2325
throw new IllegalArgumentException("Arguments cannot be null!");
2426

2527
this.level = CastedExpression.Level.EXACT;
28+
this.expansionTypeArguments = expansionTypeArguments;
2629
this.typeArguments = typeArguments;
2730
this.arguments = arguments;
2831
}
2932

30-
public CallArguments(CastedExpression.Level level, TypeID[] typeArguments, Expression[] arguments) {
33+
public CallArguments(CastedExpression.Level level, TypeID[] expansionTypeArguments, TypeID[] typeArguments, Expression[] arguments) {
3134
if (typeArguments == null)
3235
typeArguments = TypeID.NONE;
3336
if (arguments == null)
3437
throw new IllegalArgumentException("Arguments cannot be null!");
3538

3639
this.level = level;
40+
this.expansionTypeArguments = expansionTypeArguments;
3741
this.typeArguments = typeArguments;
3842
this.arguments = arguments;
3943
}
4044

4145
public CallArguments(TypeID... dummy) {
4246
this.level = CastedExpression.Level.EXACT;
47+
this.expansionTypeArguments = TypeID.NONE;
4348
this.typeArguments = TypeID.NONE;
4449
this.arguments = new Expression[dummy.length];
4550
for (int i = 0; i < dummy.length; i++)
@@ -50,7 +55,7 @@ public CallArguments bind(Expression target) {
5055
Expression[] newArguments = new Expression[arguments.length + 1];
5156
newArguments[0] = target;
5257
System.arraycopy(arguments, 0, newArguments, 1, arguments.length);
53-
return new CallArguments(typeArguments, newArguments);
58+
return new CallArguments(level, expansionTypeArguments, typeArguments, newArguments);
5459
}
5560

5661
public int getNumberOfTypeArguments() {
@@ -59,6 +64,6 @@ public int getNumberOfTypeArguments() {
5964

6065
public CallArguments transform(ExpressionTransformer transformer) {
6166
Expression[] tArguments = Expression.transform(arguments, transformer);
62-
return tArguments == arguments ? this : new CallArguments(level, typeArguments, tArguments);
67+
return tArguments == arguments ? this : new CallArguments(level, expansionTypeArguments, typeArguments, tArguments);
6368
}
6469
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/identifiers/instances/MethodInstance.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,27 @@ public class MethodInstance implements InstanceCallableMethod, StaticCallableMet
1717
public final MethodSymbol method;
1818
private final FunctionHeader header;
1919
private final TypeID target;
20+
private final TypeID[] expansionTypeArguments;
2021

2122
public MethodInstance(MethodSymbol method) {
2223
this.method = method;
2324
this.header = method.getHeader();
2425
this.target = method.getTargetType();
26+
this.expansionTypeArguments = TypeID.NONE;
2527
}
2628

2729
public MethodInstance(MethodSymbol method, FunctionHeader header, TypeID target) {
2830
this.method = method;
2931
this.header = header;
3032
this.target = target;
33+
this.expansionTypeArguments = TypeID.NONE;
34+
}
35+
36+
public MethodInstance(MethodSymbol method, FunctionHeader header, TypeID target, TypeID[] expansionTypeArguments) {
37+
this.method = method;
38+
this.header = header;
39+
this.target = target;
40+
this.expansionTypeArguments = expansionTypeArguments;
3141
}
3242

3343
public TypeID getTarget() {
@@ -66,4 +76,8 @@ public Expression call(ExpressionBuilder builder, CallArguments arguments) {
6676
public boolean isImplicit() {
6777
return method.getModifiers().isImplicit();
6878
}
79+
80+
public TypeID[] getExpansionTypeArguments() {
81+
return expansionTypeArguments;
82+
}
6983
}

CodeModel/src/main/java/org/openzen/zenscript/codemodel/type/builtin/GenericMapTypeSymbol.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public ResolvedType resolve(TypeID[] typeArguments) {
8282
Map<TypeParameter, TypeID> parameterFilled = new HashMap<>();
8383
parameterFilled.put(PARAMETER, typeArguments[0]);
8484
parameterFilled.put(VALUE, value);
85-
GenericMapper mapper = new GenericMapper(parameterFilled);
85+
GenericMapper mapper = new GenericMapper(parameterFilled, TypeID.NONE);
8686

8787
TypeID valueType = mapper.map(value);
8888

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ public static boolean isLarge(TypeID type) {
3636
return type == BasicTypeID.DOUBLE || type == BasicTypeID.LONG || type == BasicTypeID.ULONG;
3737
}
3838

39+
private boolean isGenericReturn(TypeID type) {
40+
return type.isGeneric() || type.asArray().map(array -> isGenericReturn(type)).orElse(false);
41+
}
42+
3943
public static int calcAccess(Modifiers modifiers) {
4044
int out = 0;
4145
if (modifiers.isStatic())

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.openzen.zenscript.javashared.expressions.JavaFunctionInterfaceCastExpression;
2424
import org.openzen.zenscript.javashared.types.JavaFunctionalInterfaceTypeID;
2525

26+
import java.lang.reflect.Array;
2627
import java.lang.reflect.Method;
2728
import java.lang.reflect.Modifier;
2829
import java.util.*;
@@ -31,6 +32,7 @@
3132

3233
public class JavaExpressionVisitor implements ExpressionVisitor<Void> {
3334
private static final JavaNativeMethod MAP_PUT = JavaNativeMethod.getInterface(JavaClass.MAP, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
35+
private static final JavaNativeMethod ARRAY_NEWINSTANCE = JavaNativeMethod.getNativeStatic(JavaClass.ARRAY, "newInstance", "(Ljava/lang/Class;I)Ljava/lang/Object;");
3436
private static final MethodID CONSTRUCTOR = MethodID.staticOperator(OperatorType.CONSTRUCTOR);
3537

3638
final JavaWriter javaWriter;
@@ -108,9 +110,17 @@ public Void visitAndAnd(AndAndExpression expression) {
108110

109111
@Override
110112
public Void visitArray(ArrayExpression expression) {
111-
javaWriter.constant(expression.expressions.length);
112-
Type type = context.getType(((ArrayTypeID) expression.type).elementType);
113-
javaWriter.newArray(type);
113+
Type type = context.getType(expression.arrayType.elementType);
114+
if (expression.arrayType.elementType.isGeneric()) {
115+
116+
expression.arrayType.elementType.accept(javaWriter, new JavaTypeExpressionVisitor(context));
117+
javaWriter.constant(expression.expressions.length);
118+
javaWriter.invokeStatic(ARRAY_NEWINSTANCE);
119+
javaWriter.checkCast(context.getInternalName(expression.arrayType));
120+
} else {
121+
javaWriter.constant(expression.expressions.length);
122+
javaWriter.newArray(type);
123+
}
114124
for (int i = 0; i < expression.expressions.length; i++) {
115125
javaWriter.dup();
116126
javaWriter.constant(i);

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ private void handleTypeArguments(JavaNativeMethod method, CallArguments argument
202202
if (arguments.typeArguments.length != method.typeParameterArguments.length)
203203
throw new IllegalArgumentException("Number of type parameters doesn't match");
204204

205+
for (int i = 0; i < arguments.expansionTypeArguments.length; i++) {
206+
arguments.expansionTypeArguments[i].accept(javaWriter, javaTypeExpressionVisitor);
207+
}
205208
for (int i = 0; i < arguments.typeArguments.length; i++) {
206209
if (method.typeParameterArguments[i])
207210
arguments.typeArguments[i].accept(javaWriter, javaTypeExpressionVisitor);

0 commit comments

Comments
 (0)