Commit 9e1be396 authored by Wastl's avatar Wastl

Add wimp mode

parent 43c4be3d
......@@ -5,18 +5,27 @@ import sys, getopt
from collections import Iterator
is_iterator = lambda x: isinstance(x, Iterator)
def skip(it, n):
for i in xrange(n): next(it, None)
class ObCodeError(Exception): pass
class Ob(object):
def __init__(self, children=(), line=None, flat=None): # Be sure not to pass a wrong flat value
self.children = tuple(children)
self.line = line
if flat: self.flat = flat
if isinstance(children, type(self)):
self.children = children.children
self.flat = children.flat
if line is None: self.line = children.line
else: self.line = line
else:
self.flat = []
for ob in self.children:
self.flat.append(len(ob))
self.flat.extend(ob.flat)
self.children = tuple(children)
self.line = line
if flat: self.flat = flat
else:
self.flat = []
for ob in self.children:
self.flat.append(len(ob))
self.flat.extend(ob.flat)
def __hash__(self): return hash(tuple(self.flat))
def __eq__(lhs, rhs): return type(lhs) == type(rhs) and lhs.flat == rhs.flat
def __ne__(lhs, rhs): return not (lhs == rhs)
......@@ -31,12 +40,13 @@ class Ob(object):
def is_packed(code):
return code and ord(code[0]) & 0x80
def parse(code):
def parse(code, wimp=False):
if is_packed(code): return unpack(code)
ob_stack = []
curr_ob = []
line = 1
for char in code:
enum = enumerate(code)
for i, char in enum:
if char == '(':
ob_stack.append(curr_ob)
curr_ob = []
......@@ -48,6 +58,46 @@ def parse(code):
else: raise ObCodeError("Unbalanced brackets (line %d)" % line)
elif char == '\n':
line += 1
elif wimp:
if code[i:i+3] == 'NOP':
curr_ob.append(Ob(NOP, line))
skip(enum, 3)
elif code[i:i+4] == 'PUSH':
curr_ob.append(Ob(PUSH, line))
skip(enum, 4)
elif code[i:i+5] == 'STORE':
curr_ob.append(Ob(STORE, line))
skip(enum, 5)
elif code[i:i+4] == 'LOAD':
curr_ob.append(Ob(LOAD, line))
skip(enum, 4)
elif code[i:i+5] == 'WHILE':
curr_ob.append(Ob(WHILE, line))
skip(enum, 5)
elif code[i:i+5] == 'USING':
curr_ob.append(Ob(USING, line))
skip(enum, 5)
elif code[i:i+3] == 'END':
curr_ob.append(Ob(END, line))
skip(enum, 3)
elif code[i:i+4] == 'SWAP':
curr_ob.append(Ob(SWAP, line))
skip(enum, 4)
elif code[i:i+3] == 'OUT':
curr_ob.append(Ob(OUT, line))
skip(enum, 3)
elif code[i:i+2] == 'IN':
curr_ob.append(Ob(IN, line))
skip(enum, 2)
elif code[i:i+3] == 'CAT':
curr_ob.append(Ob(CAT, line))
skip(enum, 3)
elif code[i:i+3] == 'DEF':
curr_ob.append(Ob(DEF, line))
skip(enum, 3)
elif code[i:i+3] == 'DUP':
curr_ob.extend((Ob(STORE,line), Ob(LOAD,line), Ob(LOAD,line)))
skip(enum, 3)
if ob_stack: raise ObCodeError("Unbalanced brackets (EOF)")
if len(curr_ob) != 1: raise ObCodeError("Didn't find exactly one object")
return curr_ob[0]
......@@ -69,14 +119,14 @@ def pack(ob):
big = pack_to_num(ob, 0L)
if len(ob) > 1:
while big & 1: big >>= 1
debug("Program number is %x" % big)
result = ""
while big:
char = big & 0xff
big >>= 8
if not big:
if char & 0x80: result = chr(0x80)+chr(char)+result
else: result = chr(char | 0x80)+result
else: result = chr(char)+result
if big: result = chr(char)+result
elif char & 0x80: result = chr(0x80)+chr(char)+result
else: result = chr(char | 0x80)+result
return result
def pack_to_num(ob, num):
......@@ -161,9 +211,9 @@ def execute_object(code, input_gen, out_fun, debug, output, stacks, curr_stack,
stack = list(curr_stack.pop())
stacks.append(curr_stack)
curr_stack = stack
debug("USING %s" % ', '.join(str(ob) for ob in stack))
debug("USING [%s]" % ', '.join(str(ob) for ob in stack))
elif ob == END:
debug("END %s" % ', '.join(str(ob) for ob in curr_stack))
debug("END [%s]" % ', '.join(str(ob) for ob in curr_stack))
ob = Ob(curr_stack)
if stacks:
curr_stack = stacks.pop()
......@@ -178,9 +228,10 @@ def execute_object(code, input_gen, out_fun, debug, output, stacks, curr_stack,
curr_stack.append(ob2)
elif ob == OUT:
stack_depth(curr_stack, ob)
char = curr_stack.pop()
debug("OUT %d [%s]"%(len(char),char))
char = unichr(len(char))
ob = curr_stack.pop()
char = len(ob) % 0xff
debug("OUT %d [%s]"%(char,ob))
char = chr(char)
out_fun(char)
output += char
elif ob == IN:
......@@ -211,28 +262,33 @@ def stack_depth(stack, ob, req=1):
if __name__ == '__main__':
def usage():
print >> sys.stderr, """\
Synopsis: %s [-pdh] [-e <program> | <file>]
Synopsis: %s [-pdwh] [-e <program> | <file>]
Options:
-p
-p, --pack
Pack/unpack the code and print to STDOUT.
-d
-d, --debug
Print debugging information while executing
-w, --wimp, --wimpy
Replace names of instructions by the correct instructions at
parse time and add the DUP keyword which equals STORE LOAD LOAD
-e <program>
Use the given program instead of file/STDIN.
-h
-h, -?, --help
Print this help and exit""" % sys.argv[0]
sys.exit()
try:
try: opts, args = getopt.getopt(sys.argv[1:], 'dpe:h?', ['help', 'pack', 'debug'])
try: opts, args = getopt.getopt(sys.argv[1:], 'dpwe:h?', ['help', 'wimp', 'wimpy', 'pack', 'debug'])
except getopt.GetoptError: usage()
code = None
do_pack = False
debug = lambda x: None
wimp = False
for opt, val in opts:
if opt == '-p' or opt == '--pack': do_pack = True
elif opt == '-d' or opt == '--debug': debug = lambda x: sys.stderr.write(x+'\n')
elif opt == '-w' or opt == '--wimp' or opt == '--wimpy': wimp = True
elif opt == '-e': code = val
elif opt == '-h' or opt == '-?' or opt == '--help': usage()
if code is None:
......@@ -243,7 +299,7 @@ Options:
else: code = sys.stdin.read()
if do_pack:
if is_packed(code): print unpack(code)
else: sys.stdout.write(pack(parse(code)))
else: execute(code, lambda: sys.stdin.read(1), lambda x: sys.stdout.write(x), debug)
else: sys.stdout.write(pack(parse(code, wimp)))
else: execute(parse(code, wimp), lambda: sys.stdin.read(1), lambda x: (sys.stdout.write(x), sys.stdout.flush()), debug)
except ObCodeError as err: print >> sys.stderr, err
except KeyboardInterrupt: print >> sys.stderr, "Interrupted"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment