Execute Computer/Zero: Difference between revisions

julia example
(J)
(julia example)
Line 75:
exec assemble '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';'NOP 0';'NOP 1';'NOP 3'
0</lang>
 
=={{header|Julia}}==
<lang ruby>mutable struct ComputerZero
ip::Int
ram::Vector{UInt8}
accum::UInt8
isready::Bool
end
function ComputerZero(program)
memory = zeros(UInt8, 32)
for i in 1:min(32, length(program))
memory[i] = program[i]
end
return ComputerZero(1, memory, 0, true)
end
 
NOP(c) = (c.ip = mod1(c.ip + 1, 32))
LDA(c) = (c.accum = c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
STA(c) = (c.ram[c.ram[c.ip] & 0b00011111 + 1] = c.accum; c.ip = mod1(c.ip + 1, 32))
ADD(c) = (c.accum += c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
SUB(c) = (c.accum -= c.ram[c.ram[c.ip] & 0b00011111 + 1]; c.ip = mod1(c.ip + 1, 32))
BRZ(c) = (c.ip = (c.accum == 0) ? c.ram[c.ip] & 0b00011111 + 1 : mod1(c.ip + 1, 32))
JMP(c) = (c.ip = c.ram[c.ip] & 0b00011111 + 1)
STP(c) = (println("Program completed with accumulator value $(c.accum).\n"); c.isready = false)
 
const step = [NOP, LDA, STA, ADD, SUB, BRZ, JMP, STP]
const instructions = ["NOP", "LDA", "STA", "ADD", "SUB", "BRZ", "JMP", "STP"]
const assemblywords = Dict(s => i - 1 for (i, s) in pairs(instructions))
 
function run(compzero::ComputerZero)
while compzero.isready
instruction = compzero.ram[compzero.ip]
opcode = instruction >> 5 + 1
#println("op ", instructions[opcode])
step[opcode](compzero)
opcode == 8 && break
end
end
run(program::Vector) = run(ComputerZero(program))
 
function compile(text::String)
bin, lines = UInt8[], 0
for line in strip.(split(text, "\n"))
lines += 1
if isempty(line)
push!(bin, 0)
elseif (m = match(r"(\w\w\w)\s+(\d\d?)", line)) != nothing
push!(bin, UInt8((assemblywords[m.captures[1]] << 5) | parse(UInt8, m.captures[2])))
elseif (m = match(r"(\w\w\w)", line)) != nothing
push!(bin, UInt8(assemblywords[m.match] << 5))
elseif (m = match(r"\d\d?", line)) != nothing
push!(bin, parse(UInt8, m.match))
else
error("Compilation error in at line $lines: error parsing <$line>")
end
end
println("Compiled $lines lines.")
return bin
end
 
 
const testprograms = [
"""
LDA 3
ADD 4
STP
2
2
""",
"""
LDA 12
ADD 10
STA 12
LDA 11
SUB 13
STA 11
BRZ 8
JMP 0
LDA 12
STP
8
7
0
1
""",
"""
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
""",
"""
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
 
 
 
6
0
2
26
5
20
3
30
1
22
4
24
""",
"""
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
"""
]
 
for t in testprograms
run(compile(t))
end
</lang>{{out}}
<pre>
Compiled 6 lines.
Program completed with accumulator value 4.
 
Compiled 15 lines.
Program completed with accumulator value 56.
 
Compiled 19 lines.
Program completed with accumulator value 55.
 
Compiled 33 lines.
Program completed with accumulator value 6.
 
Compiled 33 lines.
Program completed with accumulator value 0.
</pre>
 
=={{header|Wren}}==
4,104

edits