Execute Computer/Zero: Difference between revisions
Content added Content deleted
(Add Java) |
|||
Line 220: | Line 220: | ||
exec NOP 0 NOP 0 STP 0 NOP 0 LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 1 ADD 30 ADD 3 STA 1 LDA 0 ADD 30 ADD 3 STA 0 JMP 2 0 1 3 |
exec NOP 0 NOP 0 STP 0 NOP 0 LDA 3 SUB 29 BRZ 18 LDA 3 STA 29 BRZ 14 LDA 1 ADD 31 STA 1 JMP 2 LDA 0 ADD 31 STA 0 JMP 2 LDA 3 STA 29 LDA 1 ADD 30 ADD 3 STA 1 LDA 0 ADD 30 ADD 3 STA 0 JMP 2 0 1 3 |
||
0</lang> |
0</lang> |
||
=={{header|Java}}== |
|||
{{trans|Python}} |
|||
{{works with|Java|8}} |
|||
<lang python>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)); |
|||
} |
|||
} |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
4 |
|||
56 |
|||
55 |
|||
6 |
|||
0 |
|||
1 |
|||
255 |
|||
0 |
|||
</pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |