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
}
}