view interps/whirl/whirlinterp.py @ 6558:4ad4b893c806

<b_jonas> learn links are one of the very few HTML renderers that don\'t try to store a full document tree with heavyweight objects for each node just in case javascript wants to modify it later, so it\'s the only engine that can render those HTMLs that are automatically converted from a PDF and put each letter to a separate element.
author HackBot
date Thu, 14 Jan 2016 11:54:35 +0000
parents 859f9b4339e6
children
line wrap: on
line source

#!/usr/bin/env python
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()