Execute Computer/Zero: Difference between revisions

Content added Content deleted
No edit summary
Line 1,785: Line 1,785:
1
1
255
255
0
</pre>

=={{header|jq}}==
'''Adapted from [[#Wren|Wren]]'''
{{works with|jq}}
'''Also works with gojq, the Go implementation of jq'''

This entry assumes all the programs have been placed in a text file
in which each program takes the form of a header followed
by the instructions, one per line.

The header is assumed to have the form:
<pre>
; title
</pre>
<syntaxhighlight lang="jq">
### 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
</syntaxhighlight>
'''Program file - scrollable window''' (programs.txt)
<div style="overflow:scroll; height:400px;">
<pre>
; 2+2
LDA 3
ADD 4
STP
2
2

; 7 * 8
LDA 12
ADD 10
STA 12
LDA 11
SUB 13
STA 11
BRZ 8
JMP 0
LDA 12
STP
8
7
0
1

; finonacci
LDA 14
STA 15
ADD 13
STA 14
LDA 15
STA 13
LDA 16
SUB 17
BRZ 11
STA 16
JMP 0
LDA 14
STP
1
1
0
8
1

; linkedList
LDA 13
ADD 15
STA 5
ADD 16
STA 7
NOP
STA 14
NOP
BRZ 11
STA 15
JMP 0
LDA 14
STP
LDA 0
0
28
1
0
0
0
6
0
2
26
5
20
3
30
1
22
4
24

; prisoner
0
0
STP
NOP
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 0
ADD 30
ADD 3
STA 0
LDA 1
ADD 30
ADD 3
STA 1
JMP 2
0
1
3
</pre>
</div>

{{output}}
'''Invocation:''' jq -nR -f execute-computer-zero.jq programs.txt
<pre>
"; 2+2"
4
"; 7 * 8"
56
"; finonacci"
55
"; linkedList"
6
"; prisoner"
0
0
</pre>
</pre>