package nl.utwente.viskell.haskell.type; import java.util.ArrayList; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; public class TypeScope { /** * Offset for the creation of globally unique type variable names. */ static int tvOffset = 0; /** * Lookup table by textual name for type variable within this scope */ private HashMap<String, TypeVar> vars; /** * The mapping between known type instances and their related fresh type variables */ private IdentityHashMap<TypeVar.TypeInstance, TypeVar> staleToFresh; public TypeScope() { this.vars = new HashMap<>(); this.staleToFresh = new IdentityHashMap<>(); } /** * Looks up a type variable by name in this scope or constructs a new one if it doesn't exists yet. * @param name The textual representation of the type variable. * @return TypeVar that is (now) associated with the name */ public TypeVar getVar(String name) { if (this.vars.containsKey(name)) { return this.vars.get(name); } TypeVar var = new TypeVar(name, false); this.vars.put(name, var); return var; } /** * Helper method that add an extra constraint to an type variable, for use in parsing types. * @param name The textual representation of the type variable. * @param typeClass The constraint to be added to the type variable. */ public void introduceConstraint(String name, TypeClass typeClass) { TypeVar var = this.getVar(name); var.introduceConstraint(typeClass); } /** * Convenience helper method for testing, combining getVar and introduceConstraint. */ public TypeVar getVarTC(String name, TypeClass... classes) { TypeVar var = this.getVar(name); for (TypeClass tc : classes) { var.introduceConstraint(tc); } return var; } /** * This internal method should only be called from the TypeVar in the argument */ protected TypeVar pickFreshTypeVar(TypeVar var) { return var.pickFreshTypeVarInstance(this.staleToFresh); } /** * Produces a new type variable with a unique name. * @param prefix A string to prepend to the unique name. * @return The new type variable */ public static TypeVar unique(String prefix) { return new TypeVar(prefix + "___" + Integer.toHexString(tvOffset++), true); } /** * Helper method to get all type variables (instances) used in a type * @param type to inspect for type variables * @return the list of typevar instances */ protected static List<TypeVar.TypeInstance> gatherAllTypeVarInsts(Type type) { TypeScope scope = new TypeScope(); type.getFresh(scope); return new ArrayList<>(scope.staleToFresh.keySet()); } @Override public String toString() { return "TypeScope [vars=" + vars + ", staleToFresh=" + staleToFresh + "]"; } }