package scotch.symbol.type; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; import static scotch.symbol.Symbol.symbol; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import com.google.common.collect.ImmutableList; import scotch.symbol.Symbol; import scotch.util.Pair; public class TypeDescriptors { public static ConstructorTypeDescriptor ctor(TypeDescriptor head, TypeDescriptor tail) { return new ConstructorTypeDescriptor(head, tail); } public static FunctionTypeDescriptor fn(TypeDescriptor argument, TypeDescriptor result) { return new FunctionTypeDescriptor(argument, result); } public static TypeDescriptor instance(Symbol symbol, TypeDescriptor descriptor) { return new InstanceTypeDescriptor(symbol, descriptor); } public static SumTypeDescriptor sum(String name) { return sum(name, emptyList()); } public static SumTypeDescriptor sum(String name, TypeDescriptor... parameters) { return sum(name, asList(parameters)); } public static SumTypeDescriptor sum(String name, List<? extends TypeDescriptor> parameters) { return sum(symbol(name), parameters); } public static SumTypeDescriptor sum(Symbol symbol, List<? extends TypeDescriptor> parameters) { return new SumTypeDescriptor(symbol, parameters); } public static VariableTypeDescriptor t(int offset) { return var("t" + offset); } public static VariableTypeDescriptor var(String name) { return var(name, ImmutableList.of()); } public static VariableTypeDescriptor var(String name, Collection<?> context) { return new VariableTypeDescriptor(name, toSymbols(context)); } @SuppressWarnings("unchecked") private static Set<Symbol> toSymbols(Collection<?> context) { return context.stream() .map(item -> item instanceof String ? symbol((String) item) : (Symbol) item) .collect(Collectors.toSet()); } protected static int sort(Pair<VariableTypeDescriptor, Symbol> left, Pair<VariableTypeDescriptor, Symbol> right) { return left.into((t1, s1) -> right.into((t2, s2) -> { int result = t1.getName().compareTo(t2.getName()); if (result != 0) { return result; } return s1.compareTo(s2); })); } private TypeDescriptors() { // intentionally empty } }