package typing;
import java.util.Set;
import java.util.TreeSet;
/**
* Function types.
*
* @author Benedikt Meurer
* @version $Id$
*/
public final class ArrowType extends MonoType {
/**
* Allocates a new function type with <code>t1</code> as
* argument type and <code>t2</code> as return type.
*
* @param t1 the monomorphic argument type.
* @param t2 the monomorphic return type.
*/
public ArrowType(MonoType t1, MonoType t2) {
this.t1 = t1;
this.t2 = t2;
}
/**
* {@inheritDoc}
*
* For the {@link ArrowType} class, <code>true</code> will be
* returned if either the operand or the return type contains
* a type variable of the given <code>name</code>.
*
* @see typing.Type#containsFreeTypeVariable(java.lang.String)
*/
@Override
public final boolean containsFreeTypeVariable(String name) {
return (this.t1.containsFreeTypeVariable(name) || this.t2.containsFreeTypeVariable(name));
}
/**
* {@inheritDoc}
*
* @see typing.Type#free()
*/
@Override
public final Set<String> free() {
// determine the free type variables for
// the type components of the arrow type
Set<String> freeT1 = this.t1.free();
Set<String> freeT2 = this.t2.free();
// check if one of the sets is empty
if (freeT1 == Type.EMPTY_SET)
return freeT2;
else if (freeT2 == Type.EMPTY_SET)
return freeT1;
// merge the sets into a new set
TreeSet<String> free = new TreeSet<String>();
free.addAll(freeT1);
free.addAll(freeT2);
return free;
}
/**
* Returns the monomorphic argument type.
*
* @return the monomorphic argument type.
*/
public MonoType getT1() {
return this.t1;
}
/**
* Returns the monomorphic return type.
*
* @return the monomorphic return type.
*/
public MonoType getT2() {
return this.t2;
}
/**
* {@inheritDoc}
*
* @see typing.Type#substitute(typing.Substitution)
*/
@Override
MonoType substitute(Substitution s) {
// apply the substitution to both types
MonoType t1 = this.t1.substitute(s);
MonoType t2 = this.t2.substitute(s);
// check if anything changed, otherwise
// we can reuse the existing object
if (t1 != this.t1 || t2 != this.t2)
return new ArrowType(t1, t2);
else
return this;
}
/**
* Returns <code>true</code> if <code>obj</code> is an
* <code>ArrowType</code>, which is equal to this
* arrow type.
*
* @param obj another object.
*
* @return <code>true</code> if equal.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof ArrowType) {
ArrowType arrowType = (ArrowType)obj;
return (this.t1.equals(arrowType.t1) && this.t2.equals(arrowType.t2));
}
else {
return false;
}
}
/**
* Returns the string representation of the arrow type.
*
* @return the string representation of the arrow type.
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "(" + this.t1 + " \u2192 " + this.t2 + ")";
}
/**
* The arrow type for <code>int -> int -> int</code>.
*/
public static final ArrowType INT_INT_INT = new ArrowType(PrimitiveType.INT, new ArrowType(PrimitiveType.INT, PrimitiveType.INT));
/**
* The arrow type for <code>int -> int -> bool</code>.
*/
public static final ArrowType INT_INT_BOOL = new ArrowType(PrimitiveType.INT, new ArrowType(PrimitiveType.INT, PrimitiveType.BOOL));
// member attributes
private MonoType t1;
private MonoType t2;
}