Skip to content

Commit

Permalink
Merge pull request #196 from UQuark/advanced-control-flow
Browse files Browse the repository at this point in the history
add JAB instruction & MOV labels support
  • Loading branch information
fnuecke authored Apr 15, 2024
2 parents 0f72925 + d6f9ea3 commit 3f2deee
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ private static void parseInstruction(final Matcher matcher, final MachineState s
builder.put(JumpLessThanZeroInstruction.NAME, new LabelInstructionEmitter(JumpLessThanZeroInstruction::new));
builder.put(JumpNotZeroInstruction.NAME, new LabelInstructionEmitter(JumpNotZeroInstruction::new));
builder.put(JumpRelativeInstruction.NAME, new TargetOrImmediateInstructionEmitter(JumpRelativeInstruction::new, JumpRelativeImmediateInstruction::new));
builder.put(JumpAbsoluteInstruction.NAME, new TargetOrImmediateInstructionEmitter(JumpAbsoluteInstruction::new, JumpAbsoluteImmediateInstruction::new));

// Data transfer.
builder.put(MoveInstruction.NAME, new MoveInstructionEmitter());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,20 @@ static Object checkTargetOrNumber(String name, final int lineNumber, final Map<S
}
}
}
static Object checkTargetOrNumberOrLabel(String name, final int lineNumber, final Map<String, String> defines, final int start, final int end) throws ParseException {
name = defines.getOrDefault(name, name);
try {
final Target target = Enum.valueOf(Target.class, name);
if (!Target.VALID_TARGETS.contains(target)) {
throw new ParseException(Strings.MESSAGE_PARAMETER_INVALID, lineNumber, start, end);
}
return target;
} catch (final IllegalArgumentException ex) {
try {
return Integer.decode(name).shortValue();
} catch (final NumberFormatException ignored) {
return name;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
package li.cil.tis3d.common.module.execution.compiler.instruction;

import li.cil.tis3d.common.module.execution.MachineState;
import li.cil.tis3d.common.module.execution.compiler.ParseException;
import li.cil.tis3d.common.module.execution.compiler.Strings;
import li.cil.tis3d.common.module.execution.compiler.Validator;
import li.cil.tis3d.common.module.execution.instruction.Instruction;
import li.cil.tis3d.common.module.execution.instruction.MoveImmediateInstruction;
import li.cil.tis3d.common.module.execution.instruction.MoveInstruction;
import li.cil.tis3d.common.module.execution.instruction.MoveLabelInstruction;
import li.cil.tis3d.common.module.execution.target.Target;

import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

public final class MoveInstructionEmitter extends AbstractInstructionEmitter {
private static void validateLabel(final MachineState state, final String label, final Matcher matcher, final int lineNumber) throws ParseException {
if (!state.labels.containsKey(label)) {
throw new ParseException(Strings.MESSAGE_LABEL_NOT_FOUND, lineNumber, matcher.start("arg1"), matcher.end("arg1"));
}
}

@Override
public Instruction compile(final Matcher matcher, final int lineNumber, final Map<String, String> defines, final List<Validator> validators) throws ParseException {
final Object src = checkTargetOrNumber(checkArg(lineNumber, matcher, "arg1", "name"),
final Object src = checkTargetOrNumberOrLabel(checkArg(lineNumber, matcher, "arg1", "name"),
lineNumber, defines, matcher.start("arg1"), matcher.end("arg1"));
final Target dst = checkTarget(checkArg(lineNumber, matcher, "arg2", "arg1"),
lineNumber, defines, matcher.start("arg2"), matcher.end("arg2"));
Expand All @@ -24,6 +33,10 @@ public Instruction compile(final Matcher matcher, final int lineNumber, final Ma
return new MoveInstruction(target, dst);
} else if (src instanceof final Short value) {
return new MoveImmediateInstruction(value, dst);
} else if (src instanceof String){
final String label = checkArg(lineNumber, matcher, "arg1", "name");
validators.add(state -> validateLabel(state, label, matcher, lineNumber));
return new MoveLabelInstruction(label, dst);
} else {
throw new AssertionError();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package li.cil.tis3d.common.module.execution.instruction;

import li.cil.tis3d.common.module.execution.Machine;
import li.cil.tis3d.common.module.execution.target.Target;
import li.cil.tis3d.common.module.execution.target.TargetInterface;

public class JumpAbsoluteImmediateInstruction implements Instruction {
private final short pc;

public JumpAbsoluteImmediateInstruction(final short pc) {
this.pc = pc;
}

@Override
public void step(final Machine machine) {
machine.getState().pc = pc;
}

@Override
public String toString() {
return JumpAbsoluteInstruction.NAME + " " + pc;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package li.cil.tis3d.common.module.execution.instruction;

import li.cil.tis3d.common.module.execution.Machine;
import li.cil.tis3d.common.module.execution.target.Target;
import li.cil.tis3d.common.module.execution.target.TargetInterface;

public class JumpAbsoluteInstruction implements Instruction {
public static final String NAME = "JAB";

private final Target source;

public JumpAbsoluteInstruction(final Target source) {
this.source = source;
}

@Override
public void step(final Machine machine) {
final TargetInterface sourceInterface = machine.getInterface(source);

if (!sourceInterface.isReading()) {
sourceInterface.beginRead();
}
if (sourceInterface.canTransfer()) {
machine.getState().pc = sourceInterface.read();
}
}

@Override
public String toString() {
return NAME + " " + source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package li.cil.tis3d.common.module.execution.instruction;

import li.cil.tis3d.common.module.execution.Machine;
import li.cil.tis3d.common.module.execution.target.Target;
import li.cil.tis3d.common.module.execution.target.TargetInterface;

public class MoveLabelInstruction extends AbstractMoveInstruction {
private final String label;

public MoveLabelInstruction(final String label, final Target destination) {
super(destination);
this.label = label;
}

@Override
public void step(final Machine machine) {
final TargetInterface destinationInterface = machine.getInterface(destination);
int addr = machine.getState().labels.get(label);

if (!destinationInterface.isWriting()) {
if (destinationInterface.beginWrite((short) addr)) {
machine.getState().pc++;
}
}
}

@Override
public String toString() {
return MoveInstruction.NAME + " " + label + " " + destination;
}
}

0 comments on commit 3f2deee

Please sign in to comment.