Subleq/subleq.py
Jump to navigation
Jump to search
This is a public domain interpreter and simple assembler for Subleq, written in Python 3. It can assemble and run the Hello, world! example on the Subleq article.
#!/usr/bin/env python3
import sys
class Subleq:
def __init__(self):
self.mem = []
def assemble(self, source_text):
labels = self.collect_labels(source_text)
self.write_contents(source_text, labels)
def collect_labels(self, source_text):
labels = {}
def label_it(s, addr):
if ':' in s:
label, contents = s.split(':')
labels[label] = addr
addr = 0
for line in source_text.split("\n"):
line = line.strip()
if not line or line.startswith('#'):
continue
[a, b, c] = line.split()
label_it(a, addr)
label_it(b, addr + 1)
label_it(c, addr + 2)
addr += 3
return labels
def write_contents(self, source_text, labels):
def write_it(v, addr):
if ':' in v:
label, contents = v.split(':')
v = contents
if v in labels:
v = labels[v]
if v == '?+1':
v = addr + 3
self.mem.append(int(v))
addr = 0
for line in source_text.split("\n"):
line = line.strip()
if not line or line.startswith('#'):
continue
[a, b, c] = line.split()
write_it(a, addr)
write_it(b, addr)
write_it(c, addr)
addr += 3
def dump_triples(self, f):
addr = 0
while addr < len(self.mem):
a = self.mem[addr]
b = self.mem[addr + 1] if addr + 1 < len(self.mem) else 0
c = self.mem[addr + 2] if addr + 2 < len(self.mem) else 0
f.write('{} {} {}\n'.format(a, b, c))
addr += 3
def load_triples(self, f):
for line in f:
a, b, c = line.split()
self.mem.append(int(a))
self.mem.append(int(b))
self.mem.append(int(c))
def run(self, trace=False):
pc = 0
while pc >= 0:
a = self.mem[pc]
b = self.mem[pc + 1]
c = self.mem[pc + 2]
if trace:
print('pc={}, a={}, b={}, c={}'.format(pc, a, b, c))
at_a = self.mem[a]
if b >= 0:
at_b = self.mem[b]
result = at_b - at_a
self.mem[b] = result
elif b == -1:
sys.stdout.write(chr(at_a))
result = 0
if result <= 0:
pc = c
else:
pc += 3
def main(args):
if len(args) == 3 and args[0] == 'assemble':
subleq = Subleq()
subleq.assemble(open(args[1], 'r').read())
with open(args[2], 'w') as f:
subleq.dump_triples(f)
elif len(args) == 2 and args[0] == 'run':
subleq = Subleq()
with open(args[1], 'r') as f:
subleq.load_triples(f)
subleq.run()
elif len(args) == 2 and args[0] == 'trace':
subleq = Subleq()
with open(args[1], 'r') as f:
subleq.load_triples(f)
subleq.run(trace=True)
else:
print('usage: subleq.py assemble in.subleqasm out.triples | run in.triples | trace in.triples')
sys.exit(1)
if __name__ == '__main__':
main(sys.argv[1:])