76 lines
2.0 KiB
Plaintext
76 lines
2.0 KiB
Plaintext
### Utility
|
|
def trim: sub("^ +";"") | sub(" +$";"");
|
|
|
|
### Computer/Zero
|
|
def NOP: 0;
|
|
def LDA: 1;
|
|
def STA: 2;
|
|
def ADD: 3;
|
|
def SUB: 4;
|
|
def BRZ: 5;
|
|
def JMP: 6;
|
|
def STP: 7;
|
|
|
|
def ops: {"NOP": NOP, "LDA": LDA, "STA": STA, "ADD": ADD,
|
|
"SUB": SUB, "BRZ": BRZ, "JMP": JMP, "STP": STP};
|
|
|
|
# Input: the program in the form of an array of strings,
|
|
# each string corresponding to an input line of the form
|
|
# "INSTR N" or "N"
|
|
# Output: an array of integers
|
|
def load:
|
|
map([splits(" *")] as $split
|
|
| $split[0] as $instr
|
|
| (if ($split|length == 2) then $split[1]|tonumber
|
|
else 0
|
|
end) as $addr
|
|
| if ops[$instr]
|
|
then ops[$instr] * 32 + $addr
|
|
else try ($instr|tonumber) catch 0
|
|
end );
|
|
|
|
# input: an array as produced by `load`
|
|
def interp:
|
|
{ acc: 0, pc: 0, mem: .}
|
|
| until(.break;
|
|
(.mem[.pc] % 32) as $addr
|
|
| ((.mem[.pc] - $addr) / 32) as $instr
|
|
| .pc += 1
|
|
| if $instr == LDA then .acc = .mem[$addr]
|
|
elif $instr == STA then .mem[$addr] = .acc
|
|
elif $instr == ADD then .acc += .mem[$addr]
|
|
| if .acc > 255 then .acc += -256 else . end
|
|
elif $instr == SUB then .acc += (- .mem[$addr])
|
|
| if .acc < 0 then .acc += 256 else . end
|
|
elif $instr == BRZ
|
|
then if .acc == 0 then .pc = $addr else . end
|
|
elif $instr == JMP then .pc = $addr
|
|
else .
|
|
end
|
|
| .break = $instr == STP or .pc > 31 )
|
|
| .acc;
|
|
|
|
# Assume the input file consists of several programs, each structured as:
|
|
# ; program name
|
|
# one instruction per line
|
|
#
|
|
def task:
|
|
def init: map_values(null);
|
|
|
|
foreach (inputs, null) as $line ({};
|
|
if $line == null then .program = .buffer
|
|
elif $line[0:1] == ";" then init | .title = $line
|
|
else ($line|trim) as $line
|
|
| if $line == "" then .program = .buffer | .buffer = []
|
|
else .buffer += [$line]
|
|
end
|
|
end)
|
|
| .title as $title
|
|
| .program
|
|
| if length == 0 then empty
|
|
else
|
|
$title, (load|interp)
|
|
end ;
|
|
|
|
task
|