package scotch.compiler.syntax.value;
import static java.util.stream.Collectors.toList;
import static scotch.compiler.syntax.value.WithArguments.withoutArguments;
import static scotch.util.Either.left;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import scotch.compiler.analyzer.DependencyAccumulator;
import scotch.compiler.analyzer.NameAccumulator;
import scotch.compiler.analyzer.OperatorAccumulator;
import scotch.compiler.analyzer.PrecedenceParser;
import scotch.compiler.analyzer.NameQualifier;
import scotch.compiler.analyzer.TypeChecker;
import scotch.compiler.intermediate.IntermediateGenerator;
import scotch.compiler.intermediate.IntermediateValue;
import scotch.compiler.syntax.pattern.PatternReducer;
import scotch.compiler.syntax.scope.Scope;
import scotch.compiler.text.SourceLocation;
import scotch.util.Either;
import scotch.util.Pair;
import scotch.symbol.Operator;
import scotch.symbol.Symbol;
import scotch.compiler.syntax.type.SumType;
import scotch.compiler.syntax.type.Type;
public abstract class Value {
Value() {
// intentionally empty
}
public abstract Value accumulateDependencies(DependencyAccumulator state);
public abstract Value accumulateNames(NameAccumulator state);
public Optional<Value> asInitializer(Initializer initializer, TypeChecker state) {
Value checkedValue = checkTypes(state);
if (checkedValue.getType() instanceof SumType) {
return Optional.of(new CopyInitializer(
initializer.getSourceLocation(),
checkedValue,
initializer.getFields().stream()
.map(field -> field.checkTypes(state))
.collect(toList())));
} else {
throw new UnsupportedOperationException(); // TODO
}
}
public Optional<Pair<Identifier, Operator>> asOperator(Scope scope) {
return Optional.empty();
}
public abstract Value bindMethods(TypeChecker typeChecker);
public abstract Value bindTypes(TypeChecker typeChecker);
public abstract Value checkTypes(TypeChecker typeChecker);
public Value collapse() {
return this;
}
public abstract Value defineOperators(OperatorAccumulator state);
public Either<Value, List<Value>> destructure() {
return left(this);
}
@Override
public abstract boolean equals(Object o);
public boolean equalsBeta(Value o) {
return false;
}
public abstract IntermediateValue generateIntermediateCode(IntermediateGenerator state);
public abstract SourceLocation getSourceLocation();
public Optional<Symbol> getTag() {
return Optional.empty();
}
public abstract Type getType();
@Override
public abstract int hashCode();
public boolean isOperator(Scope scope) {
return false;
}
public Value mapTags(Function<Value, Value> mapper) {
throw new UnsupportedOperationException();
}
public abstract Value parsePrecedence(PrecedenceParser state);
public String prettyPrint() {
return "[" + getClass().getSimpleName() + "]";
}
public abstract Value qualifyNames(NameQualifier state);
public abstract Value reducePatterns(PatternReducer reducer);
public Value reTag(Value value) {
return value.getTag().map(this::withTag).orElse(this);
}
@Override
public abstract String toString();
public Value unwrap() {
return this;
}
public WithArguments withArguments() {
return withoutArguments(this);
}
public Value withTag(Symbol tag) {
throw new UnsupportedOperationException(getClass().getName()); // TODO
}
public abstract Value withType(Type type);
}