package nl.utwente.viskell.haskell.type;
import java.util.LinkedList;
import java.util.List;
public class TypeApp extends ConcreteType {
/*
* The Type of function part of of type application, usually some type constructor
*/
private final Type typeFun;
/*
* The Type of argument part of a type application
*/
private final Type typeArg;
/** The set of constraints attached to this type application that can not yet be propagated further. */
private ConstraintSet constraints;
TypeApp(Type typeFun, Type typearg) {
this.typeFun = typeFun;
this.typeArg = typearg;
this.constraints = new ConstraintSet();
}
public Type getTypeFun() {
return this.typeFun;
}
public Type getTypeArg() {
return this.typeArg;
}
protected ConstraintSet getConstraint() {
return this.constraints;
}
/**
* Remove all constraints from this type application, to be used only after all are satisfied.
*/
protected void clearConstraints() {
this.constraints = new ConstraintSet();
}
/**
* Extends the constraint set with extra set of constraints.
* @param constraints set to be added to the type application
*/
protected void extendConstraints(ConstraintSet constraints) {
this.constraints.addExtraConstraint(constraints);
}
@Override
public String prettyPrint(int fixity) {
List<Type> chain = this.asFlattenedAppChain();
Type ftype = chain.remove(0);
if (this.constraints.hasConstraints()) {
String apptype = ftype.prettyPrintAppChain(9, chain);
return this.constraints.prettyPrintWith(apptype, fixity);
} else {
return ftype.prettyPrintAppChain(fixity, chain);
}
}
public final List<Type> asFlattenedAppChain(){
final LinkedList<Type> chain = new LinkedList<>();
Type type = this;
while (type instanceof TypeApp) {
TypeApp ta = (TypeApp) type;
chain.addFirst(ta.typeArg);
type = ta.typeFun;
}
chain.addFirst(type);
return chain;
}
@Override
public TypeApp getFresh(TypeScope scope) {
return new TypeApp(this.typeFun.getFresh(scope), this.typeArg.getFresh(scope));
}
@Override
public Type getConcrete() {
return new TypeApp(this.typeFun.getConcrete(), this.typeArg.getConcrete());
}
@Override
public boolean containsOccurenceOf(TypeVar tvar) {
return this.typeFun.containsOccurenceOf(tvar) || this.typeArg.containsOccurenceOf(tvar);
}
@Override
public String toString() {
if (this.constraints.hasConstraints()) {
return String.format("(%s:%s @ %s)", this.constraints, this.typeFun, this.typeArg);
} else {
return String.format("(%s @ %s)", this.typeFun, this.typeArg);
}
}
}