package scotch.compiler.syntax.value; import static scotch.compiler.syntax.builder.BuilderUtil.require; import java.util.Optional; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; 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.builder.SyntaxBuilder; import scotch.compiler.syntax.pattern.PatternReducer; import scotch.compiler.text.SourceLocation; import scotch.symbol.FieldSignature; import scotch.symbol.Symbol; import scotch.compiler.syntax.type.Type; @EqualsAndHashCode(callSuper = false) @ToString(exclude = "sourceLocation") public class ConstantReference extends Value { public static Builder builder() { return new Builder(); } @Getter private final SourceLocation sourceLocation; private final Symbol symbol; private final Symbol dataType; private final FieldSignature constantField; @Getter private final Type type; @java.beans.ConstructorProperties({ "sourceLocation", "symbol", "dataType", "constantField", "type" }) ConstantReference(SourceLocation sourceLocation, Symbol symbol, Symbol dataType, FieldSignature constantField, Type type) { this.sourceLocation = sourceLocation; this.symbol = symbol; this.dataType = dataType; this.constantField = constantField; this.type = type; } @Override public Value accumulateDependencies(DependencyAccumulator state) { return this; } @Override public Value accumulateNames(NameAccumulator state) { return this; } @Override public IntermediateValue generateIntermediateCode(IntermediateGenerator state) { return state.constantReference(symbol, dataType, constantField); } @Override public Value bindMethods(TypeChecker typeChecker) { return this; } @Override public Value bindTypes(TypeChecker typeChecker) { return withType(typeChecker.generate(type)); } @Override public Value checkTypes(TypeChecker typeChecker) { return this; } @Override public Value defineOperators(OperatorAccumulator state) { return this; } @Override public Value parsePrecedence(PrecedenceParser state) { return this; } @Override public Value qualifyNames(NameQualifier state) { return this; } @Override public Value reducePatterns(PatternReducer reducer) { return this; } @Override public Value withType(Type type) { return new ConstantReference(sourceLocation, symbol, dataType, constantField, type); } public static class Builder implements SyntaxBuilder<ConstantReference> { private Optional<SourceLocation> sourceLocation = Optional.empty(); private Optional<Symbol> symbol = Optional.empty(); private Optional<Symbol> dataType = Optional.empty(); private Optional<Type> type = Optional.empty(); private Optional<FieldSignature> constantField = Optional.empty(); private Builder() { // intentionally empty } @Override public ConstantReference build() { return new ConstantReference( require(sourceLocation, "Source location"), require(symbol, "Symbol"), require(dataType, "Data type"), require(constantField, "Constant field"), require(type, "Type") ); } public Builder withConstantField(FieldSignature constantField) { this.constantField = Optional.of(constantField); return this; } public Builder withDataType(Symbol dataType) { this.dataType = Optional.of(dataType); return this; } @Override public Builder withSourceLocation(SourceLocation sourceLocation) { this.sourceLocation = Optional.of(sourceLocation); return this; } public Builder withSymbol(Symbol symbol) { this.symbol = Optional.of(symbol); return this; } public Builder withType(Type type) { this.type = Optional.of(type); return this; } } }