[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Whirl Interpreter



Hey everyone.
I just got finished writing an interpreter for the esoteric language called Whirl (linky: http://www.bigzaphod.org/whirl/ )
I was thinking about writing a graphical version of the interpreter as well.
Does anyone see anything wrong with my code that would be more easily done a different way before
I start writing the graphical version?
Just wondering if I have developed any bad coding habits I didn't know about.
Be honest please!
-Luke
#!/usr/local/bin/python
"""
Whirlinterp.py - an interpreter for the esoteric language Whirl (found at http://bigzaphod.org/whirl)
Copyright (C) 2006 Luke Paireepinart

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
"""

import sys
global OPS,MEMORY,PC, MC
OPS = []
PC = 0
MC = 0
MEMORY = [0]
class OpRing:
    def __init__(self):
        self.currentop = 0
        self.opring = ["NOOP","EXIT","ONE","ZERO","LOAD","STORE","PADD","DADD","LOGIC","IF","INTIO","ASCIO"]
        self.val = 0
        self.direction = 0
        pass
    def ROTATE(s):
        if s.direction == 0:
            s.currentop = (s.currentop + 1) % 12
        elif s.direction == 1:
            s.currentop = (s.currentop -1) % 12
        else:
            print "Error in ROTATE.  self.direction not 0/1."
    def FLIP(s):
        s.direction = s.direction ^ 1
        return s.direction
    def EXEC(self):
        global MEMORY,MC,PC,OPS
        t = self.opring[self.currentop]
        
        if   t == "NOOP":
            pass
        
        elif t == "EXIT":
            return "EXIT"
        
        elif t == "ONE":
            self.val = 1
            
        elif t == "ZERO":
            self.val = 0

        elif t == "LOAD":
            self.val = MEMORY[MC]

        elif t == "STORE":
            MEMORY[MC] = self.val
        
        elif t == "PADD":
            PC += self.val - 1
            if PC < -1:
                PC = -1
            elif len(OPS) < PC:
                return "EXIT"
            

        elif t == "DADD":
            MC += self.val
            if MC < 0:
                MC = 0
            while len(MEMORY) <= MC:
                MEMORY.append(0)

        elif t == "LOGIC":
            if MEMORY[MC] == 0:
                self.val = 0
            else:
                self.val = (self.val and 1)

        elif t == "IF":
            if MEMORY[MC] != 0:
                PC += (self.val-1)
                if PC < -1:
                    PC = -1
                elif len(OPS) < PC:
                    return "EXIT"

        elif t == "INTIO":
            if self.val == 0:
                MEMORY[MC] = int(raw_input("Please enter an integer: "))
            else:
                return MEMORY[MC]
        elif t == "ASCIO":
            if self.val == 0:
                MEMORY[MC] = raw_input("Please enter a character: ")[0]
            else:
                try:
                    return chr(MEMORY[MC])
                except TypeError:
                    return MEMORY[MC]
    def GETCURRENTOP(self):
        return self.opring[self.currentop]

class MathRing:
    global MEMORY,PC, MC
    def __init__(self):
        self.opring = ["NOOP","LOAD","STORE","ADD","MULT","DIV","ZERO","<",">","=","NOT","NEG"]
        self.val = 0
        self.currentop = 0
        self.direction = 0
    def ROTATE(s):
        if s.direction == 0:
            s.currentop = (s.currentop + 1) % 12
        elif s.direction == 1:
            s.currentop = (s.currentop -1) % 12
        else:
            print "Error in ROTATE.  self.direction not 0/1."
    def FLIP(s):
        s.direction = s.direction ^ 1
        return s.direction
    def EXEC(self):
        t = self.opring[self.currentop]
        
        if   t == "NOOP":
            pass
        
        elif t == "LOAD":
            self.val = MEMORY[MC]

        elif t == "STORE":
            MEMORY[MC] = self.val
        
        elif t == "ADD":
            self.val += MEMORY[MC]
            
        elif t == "MULT":
            self.val *= MEMORY[MC]
        
        elif t == "DIV":
            if MEMORY[MC] != 0:
                self.val /= MEMORY[MC]
            else:
                print "Attempted to divide by zero.  Value in Math Ring unchanged."
                
        elif t == "ZERO":
            self.val = 0

        elif t == "<":
            self.val = (self.val < MEMORY[MC])

        elif t == ">":
            self.val = (self.val > MEMORY[MC])
            
        elif t == "=":
            self.val = (self.val == MEMORY[MC])

        elif t == "NOT":
            self.val = (self.val == 0)

        elif t == "NEG":
            self.val *= -1

def main():
    global OPS,MEMORY,PC, MC

    opring = OpRing()
    mathring = MathRing()
    rings = {"OPRING":opring,"MATHRING":mathring}
    if len(sys.argv) < 2:
        print "Must specify a filename as the argument. eg: python whirlinterp.py filename.txt"
        raise SystemExit
    filename = sys.argv[1]
    f = file(filename,'r')
    text = f.readlines()
    f.close()
    for line in text:
        for char in line:
            if char in ['0','1']:
                OPS.append(char)
    previousop = 3
    current = "OPRING"
    outputtext = ""
    while PC < len(OPS):
        if OPS[PC] == "0":
            rings[current].FLIP()
            if previousop == 0:
                text = rings[current].EXEC()
                if text == "EXIT":
                    print outputtext
                    raise SystemExit
                elif text != None:
                    try:
                        sys.stdout.write(text)
                    except TypeError:
                        sys.stdout.write(str(text))
                
                if current == "OPRING":
                    current = "MATHRING"
                elif current == "MATHRING":
                    current = "OPRING"
                    
                previousop = 1
            else:
                previousop = 0
 
        elif OPS[PC] == "1":
            rings[current].ROTATE()
            previousop = 1
        PC += 1
    print outputtext

if __name__ == "__main__":
    main()