package org.reasm.m68k.assembly.internal;
import java.io.IOException;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;
import org.reasm.Value;
import org.reasm.ValueToBooleanVisitor;
import org.reasm.m68k.messages.UntilWithoutDoErrorMessage;
/**
* The <code>UNTIL</code> directive.
*
* @author Francis Gagné
*/
@Immutable
class UntilDirective extends Mnemonic {
@Nonnull
static final UntilDirective UNTIL = new UntilDirective();
private UntilDirective() {
}
@Override
void assemble(M68KAssemblyContext context) throws IOException {
context.sizeNotAllowed();
final Object blockState = context.getParentBlock();
if (blockState instanceof DoBlockState) {
final DoBlockState doBlockState = (DoBlockState) blockState;
// The UNTIL directive is assembled on every iteration.
// Parse the condition operand on the first iteration only.
if (!doBlockState.parsedCondition) {
if (context.requireNumberOfOperands(1)) {
doBlockState.conditionExpression = parseExpressionOperand(context, 0);
}
doBlockState.parsedCondition = true;
}
final Value condition;
if (doBlockState.conditionExpression != null) {
condition = doBlockState.conditionExpression.evaluate(context.getEvaluationContext());
} else {
condition = null;
}
final Boolean result = Value.accept(condition, ValueToBooleanVisitor.INSTANCE);
if (result == null || result.booleanValue()) {
// Stop the iteration.
doBlockState.hasNextIteration = false;
}
} else {
context.addMessage(new UntilWithoutDoErrorMessage());
}
}
}