Very simple cases of function resolution are supported

This commit is contained in:
Andrey Breslav
2011-02-21 15:30:55 +03:00
parent 986e703fad
commit 0dd7118678
12 changed files with 98 additions and 29 deletions
@@ -122,7 +122,8 @@ public class ClassDescriptorResolver {
AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()), AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()),
valueParameter.getName(), valueParameter.getName(),
TypeResolver.INSTANCE.resolveType(parameterScope, typeReference), TypeResolver.INSTANCE.resolveType(parameterScope, typeReference),
valueParameter.getDefaultValue() != null valueParameter.getDefaultValue() != null,
false // TODO : varargs
); );
// TODO : Default values??? // TODO : Default values???
@@ -29,5 +29,5 @@ public interface JetScope {
Type getThisType(); Type getThisType();
@NotNull @NotNull
OverloadDomain getOverloadDomain(Type receiverType, String referencedName); OverloadDomain getOverloadDomain(@Nullable Type receiverType, @NotNull String referencedName);
} }
@@ -46,7 +46,7 @@ public class JetScopeAdapter implements JetScope {
@NotNull @NotNull
@Override @Override
public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
return scope.getOverloadDomain(receiverType, referencedName); return scope.getOverloadDomain(receiverType, referencedName);
} }
} }
@@ -40,7 +40,7 @@ public abstract class JetScopeImpl implements JetScope {
@NotNull @NotNull
@Override @Override
public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
return OverloadDomain.EMPTY; return receiverType.getMemberScope().getOverloadDomain(null, referencedName);
} }
} }
@@ -55,7 +55,9 @@ public class SubstitutingScope implements JetScope {
@NotNull @NotNull
@Override @Override
public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
throw new UnsupportedOperationException(); // TODO final OverloadDomain workerDomain = workerScope.getOverloadDomain(receiverType, referencedName);
// TODO: !!!
return workerDomain;
} }
} }
@@ -65,7 +65,7 @@ public class WritableFunctionGroup implements FunctionGroup {
private FunctionDescriptor substituteFunctionDescriptor(List<Type> typeArguments, FunctionDescriptor functionDescriptor) { private FunctionDescriptor substituteFunctionDescriptor(List<Type> typeArguments, FunctionDescriptor functionDescriptor) {
return new FunctionDescriptor( return new FunctionDescriptor(
// TODO : substitute // TODO : substitute
functionDescriptor.getAttributes(), functionDescriptor.getAttributes(),
functionDescriptor.getName(), functionDescriptor.getName(),
Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable Collections.<TypeParameterDescriptor>emptyList(), // TODO : questionable
@@ -4,10 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import java.util.Collection; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* @author abreslav * @author abreslav
@@ -71,7 +68,7 @@ public class WritableScope implements JetScope {
@NotNull @NotNull
@Override @Override
public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
final FunctionGroup functionGroup = getFunctionGroups().get(referencedName); final FunctionGroup functionGroup = getFunctionGroups().get(referencedName);
if (functionGroup == null) { if (functionGroup == null) {
return OverloadDomain.EMPTY; return OverloadDomain.EMPTY;
@@ -85,7 +82,55 @@ public class WritableScope implements JetScope {
return null; return null;
} }
throw new UnsupportedOperationException(); List<FunctionDescriptor> applicable = new ArrayList<FunctionDescriptor>();
descLoop:
for (FunctionDescriptor descriptor : possiblyApplicableFunctions) {
// ASSERT: type arguments are figured out and substituted by this time!!!
assert descriptor.getTypeParameters().isEmpty();
List<ValueParameterDescriptor> parameters = descriptor.getUnsubstitutedValueParameters();
if (parameters.size() >= positionedValueArgumentTypes.size()) {
// possibly, some default values
// possibly, nothing passed to a vararg
// possibly, a single value passed to a vararg
// possibly an array/list/etc passed as a whole vararg
for (int i = 0, positionedValueArgumentTypesSize = positionedValueArgumentTypes.size(); i < positionedValueArgumentTypesSize; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
// TODO : handle vararg cases here
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
} else {
// vararg
int nonVarargs = parameters.size() - 1;
for (int i = 0; i < nonVarargs; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
Type parameterType = parameters.get(i).getType();
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
continue descLoop;
}
}
Type varArgType = parameters.get(nonVarargs).getType();
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
Type argumentType = positionedValueArgumentTypes.get(i);
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, varArgType)) {
continue descLoop;
}
}
}
applicable.add(descriptor);
}
if (applicable.size() == 0) {
return null;
} else if (applicable.size() == 1) {
return applicable.get(0).getUnsubstitutedReturnType();
} else {
throw new UnsupportedOperationException();
}
} }
@Override @Override
@@ -45,7 +45,7 @@ public class ErrorType {
@NotNull @NotNull
@Override @Override
public OverloadDomain getOverloadDomain(Type receiverType, String referencedName) { public OverloadDomain getOverloadDomain(Type receiverType, @NotNull String referencedName) {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
} }
}; };
@@ -1,7 +1,6 @@
package org.jetbrains.jet.lang.types; package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.TypeResolver;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -84,7 +83,8 @@ public class FunctionDescriptor extends MemberDescriptorImpl {
unsubstitutedValueParameter.getAttributes(), unsubstitutedValueParameter.getAttributes(),
unsubstitutedValueParameter.getName(), unsubstitutedValueParameter.getName(),
TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE), TypeSubstitutor.INSTANCE.substitute(context, unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE),
unsubstitutedValueParameter.hasDefaultValue() unsubstitutedValueParameter.hasDefaultValue(),
unsubstitutedValueParameter.isVararg()
)); ));
} }
return result; return result;
@@ -303,13 +303,24 @@ public class JetTypeChecker {
// result[0] = overloadDomain.getReturnTypeForNamedArguments(typeArguments, valueArguments, functionLiteralArgument); // result[0] = overloadDomain.getReturnTypeForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
} else { } else {
throw new UnsupportedOperationException(); // TODO List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
// List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>(); for (JetArgument argument : valueArguments) {
// for (JetArgument argument : valueArguments) { positionedValueArguments.add(argument.getArgumentExpression());
// positionedValueArguments.add(argument.getArgumentExpression()); }
// } positionedValueArguments.addAll(functionLiteralArguments);
// positionedValueArguments.addAll(functionLiteralArguments);
// result[0] = overloadDomain.getReturnTypeForPositionedArguments(typeArguments, positionedValueArguments); List<Type> types = new ArrayList<Type>();
for (JetTypeProjection projection : typeArguments) {
// TODO : check that there's no projection
types.add(TypeResolver.INSTANCE.resolveType(scope, projection.getTypeReference()));
}
List<Type> valueArgumentTypes = new ArrayList<Type>();
for (JetExpression valueArgument : positionedValueArguments) {
valueArgumentTypes.add(getType(scope, valueArgument, false));
}
result[0] = overloadDomain.getReturnTypeForPositionedArguments(types, valueArgumentTypes);
} }
} }
@@ -622,6 +633,11 @@ public class JetTypeChecker {
throw new UnsupportedOperationException(); // TODO throw new UnsupportedOperationException(); // TODO
} }
public boolean isConvertibleTo(Type actual, Type expected) {
// TODO
return isSubtypeOf(actual, expected);
}
public boolean isSubtypeOf(Type subtype, Type supertype) { public boolean isSubtypeOf(Type subtype, Type supertype) {
if (!supertype.isNullable() && subtype.isNullable()) { if (!supertype.isNullable() && subtype.isNullable()) {
return false; return false;
@@ -7,10 +7,12 @@ import java.util.List;
*/ */
public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl implements ValueParameterDescriptor { public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl implements ValueParameterDescriptor {
private final boolean hasDefaultValue; private final boolean hasDefaultValue;
private final boolean isVararg;
public ValueParameterDescriptorImpl(List<Attribute> attributes, String name, Type type, boolean hasDefaultValue) { public ValueParameterDescriptorImpl(List<Attribute> attributes, String name, Type type, boolean hasDefaultValue, boolean isVararg) {
super(attributes, name, type); super(attributes, name, type);
this.hasDefaultValue = hasDefaultValue; this.hasDefaultValue = hasDefaultValue;
this.isVararg = isVararg;
} }
@Override @Override
@@ -25,6 +27,6 @@ public class ValueParameterDescriptorImpl extends PropertyDescriptorImpl impleme
@Override @Override
public boolean isVararg() { public boolean isVararg() {
throw new UnsupportedOperationException(); // TODO return isVararg;
} }
} }
@@ -320,7 +320,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
public void testOverloads() throws Exception { public void testOverloads() throws Exception {
assertType("new Functions<String>().f()", "Unit"); assertType("new Functions<String>().f()", "Unit");
assertType("new Functions<String>().f(1)", "Int"); assertType("new Functions<String>().f(1)", "Int");
assertType("new Functions<String>().f(1d)", "Any"); assertType("new Functions<String>().f(1d)", (String) null);
assertType("new Functions<Double>().f(())", "Double");
assertType("new Functions<Double>().f(1d)", "Any");
} }
// public void testImplicitConversions() throws Exception { // public void testImplicitConversions() throws Exception {
@@ -402,8 +404,8 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
Project project = getProject(); Project project = getProject();
JetExpression jetExpression = JetChangeUtil.createExpression(project, expression); JetExpression jetExpression = JetChangeUtil.createExpression(project, expression);
Type type = JetTypeChecker.INSTANCE.getType(scope, jetExpression, false); Type type = JetTypeChecker.INSTANCE.getType(scope, jetExpression, false);
Type expectedType = makeType(expectedTypeStr); Type expectedType = expectedTypeStr == null ? null : makeType(expectedTypeStr);
assertTrue(type + " != " + expectedType, TypeImpl.equalTypes(type, expectedType)); assertEquals(expectedType, type);
} }
private static Type makeType(String typeStr) { private static Type makeType(String typeStr) {
@@ -431,6 +433,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
"fun f() : Unit {} " + "fun f() : Unit {} " +
"fun f(a : Int) : Int {} " + "fun f(a : Int) : Int {} " +
"fun f(a : T) : Any {} " + "fun f(a : T) : Any {} " +
"fun f(a : Unit) : T {} " +
"}" "}"
}; };