FunctorSubtypingViolation.java
package com.mackenziehigh.autumn.lang.compiler.utils;
import autumn.lang.DefinedFunctor;
import com.google.common.base.Preconditions;
import com.mackenziehigh.autumn.lang.compiler.typesystem.design.IMethod;
import com.mackenziehigh.autumn.lang.compiler.typesystem.design.IVariableType;
/**
* An instance of this class is used to indicate why one functor-type cannot subtype another.
*
* @author Mackenzie High
*/
public final class FunctorSubtypingViolation
{
public final IMethod lower;
public final IMethod upper;
/**
* Sole Constructor.
*
* @param lower is the type of the invoke(*) method in the subclass.
* @param upper is the type of the invoke(*) method in the superclass.
*/
FunctorSubtypingViolation(final IMethod lower,
final IMethod upper)
{
Preconditions.checkNotNull(lower);
Preconditions.checkNotNull(upper);
assert lower.getOwner().isSubtypeOf(upper.getOwner());
assert lower.getName().equals("invoke");
assert upper.getName().equals("invoke");
assert lower.getOwner().isSubtypeOf(lower.getOwner().getTypeFactory().fromClass(DefinedFunctor.class));
assert upper.getOwner().isSubtypeOf(upper.getOwner().getTypeFactory().fromClass(DefinedFunctor.class));
this.lower = lower;
this.upper = upper;
}
/**
* The lengths of the methods parameter-lists must be the same.
*
* @return true, if this violation was caused by differing numbers of parameters.
*/
public boolean isParameterLengthViolation()
{
return lower.getParameters().size() != upper.getParameters().size();
}
/**
* Each parameter in the lower method must be a subtype of the equivalent parameter
* in the upper method.
*
* @return true, if this violation was caused by mismatched parameters.
*/
public boolean isParameterTypeViolation()
{
for (int i = 0; i < lower.getParameters().size() && i < upper.getParameters().size(); i++)
{
final IVariableType param1 = lower.getParameters().get(i).getType();
final IVariableType param2 = upper.getParameters().get(i).getType();
if (param1.isSubtypeOf(param2) == false)
{
return true; // Violation Detected
}
}
return false; // No Violation Detected
}
/**
* The return-type of the lower method must be subtype of the upper method's return-type.
*
* @return true, if this violation is a result of a covariance violation.
*/
public boolean isReturnTypeViolation()
{
return !lower.getReturnType().isSubtypeOf(upper.getReturnType());
}
}