package scotch.symbol.type;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import com.google.common.collect.ImmutableList;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import scotch.symbol.Symbol;
import scotch.util.Pair;
@EqualsAndHashCode(callSuper = false)
public class SumTypeDescriptor extends TypeDescriptor {
@Getter private final Symbol symbol;
@Getter private final List<TypeDescriptor> parameters;
SumTypeDescriptor(Symbol symbol, List<? extends TypeDescriptor> parameters) {
this.symbol = symbol;
this.parameters = ImmutableList.copyOf(parameters);
}
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
@Override
public Set<Symbol> getContext() {
return parameters.stream()
.map(TypeDescriptor::getContext)
.flatMap(Set::stream)
.collect(toSet());
}
@Override
public TypeDescriptor mapVariables(Function<TypeDescriptor, TypeDescriptor> function) {
return new SumTypeDescriptor(symbol, parameters.stream()
.map(parameter -> parameter.mapVariables(function))
.collect(toList()));
}
@Override
protected Set<Pair<VariableTypeDescriptor, Symbol>> gatherContext_() {
return parameters.stream()
.flatMap(parameter -> parameter.gatherContext_().stream())
.collect(toSet());
}
@Override
protected String toParenthesizedString() {
return toString_();
}
@Override
protected String toString_() {
if (symbol.isTuple()) {
return "(" + parameters.stream().map(TypeDescriptor::toString_).collect(joining(", ")) + ")";
} else if (symbol.isList()) {
return "[" + parameters.stream().map(TypeDescriptor::toString_).collect(joining(", ")) + "]";
} else if (parameters.isEmpty()) {
return symbol.getSimpleName();
} else {
return symbol.getSimpleName() + " " + parameters.stream().map(TypeDescriptor::toString_).collect(joining(" "));
}
}
}