package org.reasm.m68k.assembly.internal; import javax.annotation.Nonnull; import org.reasm.AssemblyMessage; import org.reasm.Function; import org.reasm.StringValue; import org.reasm.Value; import org.reasm.ValueVisitor; import org.reasm.commons.messages.FunctionCannotBeConvertedToIntegerErrorMessage; import org.reasm.expressions.UnaryOperator; final class CardinalValueVisitor implements ValueVisitor<Void> { interface ErrorFactory { @Nonnull AssemblyMessage createMessage(); } private static final ErrorFactory DEFAULT_NEGATIVE_VALUE_ERROR_FACTORY = new ErrorFactory() { @Override public AssemblyMessage createMessage() { throw new RuntimeException("CardinalValueVisitor.negativeValueErrorFactory not initialized"); } }; @Nonnull private final M68KAssemblyContext context; private long value; @Nonnull private ErrorFactory negativeValueErrorFactory = DEFAULT_NEGATIVE_VALUE_ERROR_FACTORY; CardinalValueVisitor(@Nonnull M68KAssemblyContext context) { this.context = context; } @Override public Void visitFloat(double value) { return this.visitSignedInt((long) value); } @Override public Void visitFunction(Function value) { this.context.addTentativeMessage(new FunctionCannotBeConvertedToIntegerErrorMessage()); return null; } @Override public Void visitSignedInt(long value) { if (value < 0) { this.context.addTentativeMessage(this.negativeValueErrorFactory.createMessage()); } else { this.value = value; } return null; } @Override public Void visitString(String value) { // Pass the value through the unary plus operator to convert it to a real value. return Value.accept(UnaryOperator.UNARY_PLUS.apply(new StringValue(value), this.context.getEvaluationContext()), this); } @Override public Void visitUndetermined() { return null; } @Override public Void visitUnsignedInt(long value) { this.value = value; return null; } long getValue() { return this.value; } void reset(long value, @Nonnull ErrorFactory negativeValueErrorFactory) { this.value = value; this.negativeValueErrorFactory = negativeValueErrorFactory; } }