Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
305
Task/Execute-Computer-Zero/Java/execute-computer-zero.java
Normal file
305
Task/Execute-Computer-Zero/Java/execute-computer-zero.java
Normal file
|
|
@ -0,0 +1,305 @@
|
|||
import static java.lang.Math.floorMod;
|
||||
import static java.lang.Math.min;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ComputerZero {
|
||||
|
||||
private static final int MEM = 32;
|
||||
|
||||
private static final int NOP = 0;
|
||||
private static final int LDA = 1;
|
||||
private static final int STA = 2;
|
||||
private static final int ADD = 3;
|
||||
private static final int SUB = 4;
|
||||
private static final int BRZ = 5;
|
||||
private static final int JMP = 6;
|
||||
private static final int STP = 7;
|
||||
|
||||
private static final Map<String, Integer> OPCODES = Stream.of(
|
||||
new SimpleEntry<>("NOP", NOP),
|
||||
new SimpleEntry<>("LDA", LDA),
|
||||
new SimpleEntry<>("STA", STA),
|
||||
new SimpleEntry<>("ADD", ADD),
|
||||
new SimpleEntry<>("SUB", SUB),
|
||||
new SimpleEntry<>("BRZ", BRZ),
|
||||
new SimpleEntry<>("JMP", JMP),
|
||||
new SimpleEntry<>("STP", STP))
|
||||
.collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));
|
||||
|
||||
private static final Pattern RE_INSTRUCTION = Pattern.compile(
|
||||
"\\s*" +
|
||||
"(?:(?<label>\\w+):)?" +
|
||||
"\\s*" +
|
||||
String.format("(?<opcode>%s)?", String.join("|", OPCODES.keySet())) +
|
||||
"\\s*" +
|
||||
"(?<argument>\\w+)?" +
|
||||
"\\s*" +
|
||||
"(?:;(?<comment>.+))?");
|
||||
|
||||
public static class ComputerZeroException extends RuntimeException {
|
||||
public ComputerZeroException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Instruction {
|
||||
String opcode;
|
||||
String argument;
|
||||
|
||||
public Instruction(String opcode, String argument) {
|
||||
this.opcode = opcode;
|
||||
this.argument = argument;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Assembly {
|
||||
public Iterable<Instruction> instructions;
|
||||
public Map<String, Integer> labels;
|
||||
|
||||
public Assembly(Iterable<Instruction> instructions, Map<String, Integer> labels) {
|
||||
this.instructions = instructions;
|
||||
this.labels = labels;
|
||||
}
|
||||
}
|
||||
|
||||
public static Assembly parse(String assembly) {
|
||||
ArrayList<Instruction> instructions = new ArrayList<Instruction>();
|
||||
HashMap<String, Integer> labels = new HashMap<String, Integer>();
|
||||
int lineNumber = 0;
|
||||
|
||||
for (String line : assembly.split("\\R")) {
|
||||
Matcher matcher = RE_INSTRUCTION.matcher(line);
|
||||
|
||||
if (!matcher.matches()) {
|
||||
throw new ComputerZeroException(String.format("%s %d", line, lineNumber));
|
||||
}
|
||||
|
||||
if (matcher.group("label") != null) {
|
||||
labels.put(matcher.group("label"), lineNumber);
|
||||
}
|
||||
|
||||
instructions.add(new Instruction(matcher.group("opcode"), matcher.group("argument")));
|
||||
lineNumber++;
|
||||
}
|
||||
|
||||
return new Assembly(instructions, labels);
|
||||
}
|
||||
|
||||
public static Integer[] compile(Assembly assembly) {
|
||||
ArrayList<Integer> bytecode = new ArrayList<Integer>();
|
||||
|
||||
for (Instruction instruction : assembly.instructions) {
|
||||
int argument;
|
||||
if (instruction.argument == null) {
|
||||
argument = 0;
|
||||
} else if (instruction.argument.matches("\\d+")) {
|
||||
argument = Integer.parseInt(instruction.argument);
|
||||
} else {
|
||||
argument = assembly.labels.getOrDefault(instruction.argument, 0);
|
||||
}
|
||||
|
||||
if (instruction.opcode != null) {
|
||||
bytecode.add(OPCODES.get(instruction.opcode) << 5 | argument);
|
||||
} else {
|
||||
bytecode.add(argument);
|
||||
}
|
||||
}
|
||||
|
||||
return bytecode.toArray(new Integer[0]);
|
||||
}
|
||||
|
||||
public static int run(Integer[] bytecode) {
|
||||
int accumulator = 0;
|
||||
int instruction_pointer = 0;
|
||||
Integer[] memory = new Integer[MEM];
|
||||
Arrays.fill(memory, 0);
|
||||
System.arraycopy(bytecode, 0, memory, 0, min(MEM, bytecode.length));
|
||||
|
||||
vm: while (instruction_pointer < MEM) {
|
||||
int operation = memory[instruction_pointer] >> 5;
|
||||
int argument = memory[instruction_pointer] & 0b11111;
|
||||
instruction_pointer++;
|
||||
|
||||
switch (operation) {
|
||||
case NOP:
|
||||
continue;
|
||||
case LDA:
|
||||
accumulator = memory[argument];
|
||||
break;
|
||||
case STA:
|
||||
memory[argument] = accumulator;
|
||||
break;
|
||||
case ADD:
|
||||
accumulator = floorMod(accumulator + memory[argument], 256);
|
||||
break;
|
||||
case SUB:
|
||||
accumulator = floorMod(accumulator - memory[argument], 256);
|
||||
break;
|
||||
case BRZ:
|
||||
if (accumulator == 0) {
|
||||
instruction_pointer = argument;
|
||||
}
|
||||
break;
|
||||
case JMP:
|
||||
instruction_pointer = argument;
|
||||
break;
|
||||
case STP:
|
||||
break vm;
|
||||
default:
|
||||
throw new ComputerZeroException(
|
||||
String.format("error: %d %d", operation, argument));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
public static int run(String source) {
|
||||
return run(compile(parse(source)));
|
||||
}
|
||||
|
||||
public static final List<String> TEST_CASES = Arrays.asList(
|
||||
String.join("\n",
|
||||
" LDA x",
|
||||
" ADD y ; accumulator = x + y",
|
||||
" STP",
|
||||
"x: 2",
|
||||
"y: 2"),
|
||||
String.join("\n",
|
||||
"loop: LDA prodt",
|
||||
" ADD x",
|
||||
" STA prodt",
|
||||
" LDA y",
|
||||
" SUB one",
|
||||
" STA y",
|
||||
" BRZ done",
|
||||
" JMP loop",
|
||||
"done: LDA prodt ; to display it",
|
||||
" STP",
|
||||
"x: 8",
|
||||
"y: 7",
|
||||
"prodt: 0",
|
||||
"one: 1"),
|
||||
String.join("\n",
|
||||
"loop: LDA n",
|
||||
" STA temp",
|
||||
" ADD m",
|
||||
" STA n",
|
||||
" LDA temp",
|
||||
" STA m",
|
||||
" LDA count",
|
||||
" SUB one",
|
||||
" BRZ done",
|
||||
" STA count",
|
||||
" JMP loop",
|
||||
"done: LDA n ; to display it",
|
||||
" STP",
|
||||
"m: 1",
|
||||
"n: 1",
|
||||
"temp: 0",
|
||||
"count: 8 ; valid range: 1-11",
|
||||
"one: 1"),
|
||||
String.join("\n",
|
||||
"start: LDA load",
|
||||
" ADD car ; head of list",
|
||||
" STA ldcar",
|
||||
" ADD one",
|
||||
" STA ldcdr ; next CONS cell",
|
||||
"ldcar: NOP",
|
||||
" STA value",
|
||||
"ldcdr: NOP",
|
||||
" BRZ done ; 0 stands for NIL",
|
||||
" STA car",
|
||||
" JMP start",
|
||||
"done: LDA value ; CAR of last CONS",
|
||||
" STP",
|
||||
"load: LDA 0",
|
||||
"value: 0",
|
||||
"car: 28",
|
||||
"one: 1",
|
||||
" ; order of CONS cells",
|
||||
" ; in memory",
|
||||
" ; does not matter",
|
||||
" 6",
|
||||
" 0 ; 0 stands for NIL",
|
||||
" 2 ; (CADR ls)",
|
||||
" 26 ; (CDDR ls) -- etc.",
|
||||
" 5",
|
||||
" 20",
|
||||
" 3",
|
||||
" 30",
|
||||
" 1 ; value of (CAR ls)",
|
||||
" 22 ; points to (CDR ls)",
|
||||
" 4",
|
||||
" 24"),
|
||||
String.join("\n",
|
||||
"p: 0 ; NOP in first round",
|
||||
"c: 0",
|
||||
"start: STP ; wait for p's move",
|
||||
"pmove: NOP",
|
||||
" LDA pmove",
|
||||
" SUB cmove",
|
||||
" BRZ same",
|
||||
" LDA pmove",
|
||||
" STA cmove ; tit for tat",
|
||||
" BRZ cdeft",
|
||||
" LDA c ; p defected, c did not",
|
||||
" ADD three",
|
||||
" STA c",
|
||||
" JMP start",
|
||||
"cdeft: LDA p",
|
||||
" ADD three",
|
||||
" STA p",
|
||||
" JMP start",
|
||||
"same: LDA pmove",
|
||||
" STA cmove ; tit for tat",
|
||||
" LDA p",
|
||||
" ADD one",
|
||||
" ADD pmove",
|
||||
" STA p",
|
||||
" LDA c",
|
||||
" ADD one",
|
||||
" ADD pmove",
|
||||
" STA c",
|
||||
" JMP start",
|
||||
"cmove: 0 ; co-operate initially",
|
||||
"one: 1",
|
||||
"three: 3 "),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"SUB 4",
|
||||
"STP 0",
|
||||
" 0",
|
||||
" 255"),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"SUB 4",
|
||||
"STP 0",
|
||||
" 0",
|
||||
" 1"),
|
||||
String.join("\n",
|
||||
"LDA 3",
|
||||
"ADD 4",
|
||||
"STP 0",
|
||||
" 1",
|
||||
" 255")
|
||||
|
||||
);
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (String source : TEST_CASES) {
|
||||
System.out.println(run(source));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue