Curlyfrick/Interpreter

From Esolang
Jump to navigation Jump to search
Back to Curlyfrick
#Curlyfrick Interpreter
#Absolutely no rights reserved


import math 
'''


OpCode | What | Psuedo
0001 | Print Value | PRINT val
0010 | Print Variable | PRINT VAR
0011 | Store value in var | VAR val
0100 | Increment variable ptr | INC PTR val
0101 | Decrement variable ptr | DEC PTR val
0110 | Input Variable | INPUT var
0111 | If condition | IF var
1000 | While loop | WHILE var
1001 | Comment | //
1010 | End statement | END
1011 | Increment variable | INC val
1100 | Decrement variable | DEC val
1101 | Print value as char | PRINT CHR(val)
1110 | Print var as char | PRINT CHR(VAR)
1111 | Zero the value of var | VAR 0
'''


# Opcode made of {}s and " "s
# Value made of {}s, and +-*/%~!√^

CMD = "cmd"
VAL = "val"

OPS = {
    "...{}" : "OUT",
    "..{}." : "OUTV",
    "..{}{}": "STR",
    ".{}.." : "INC PTR",
    ".{}.{}": "DEC PTR",
    ".{}{}.": "PUT",
    ".{}{}{}": "IF",
    "{}..." : "WHILE",
    "{}..{}": "//",
    "{}.{}.": "END",
    "{}.{}{}": "INC",
    "{}{}..": "DEC",
    "{}{}.{}": "OUT CHR",
    "{}{}{}.": "OUTV CHR",
    "{}{}{}{}": "VAR 0"
}

def brackets_to_expr(src):
    src = src.replace("^", "**")
    src = src.replace("√", "math.sqrt(")
    src = src.replace("{}", "1")

    return eval(src)
    

def ast(code):
    bricks = []
    
    for line in code:
        try:
            op, data = line.split("\t")
        except:
            continue
        if op not in OPS:
            continue
        bricks.append({"cmd" : OPS[op], "val" : brackets_to_expr(data)})

    return bricks
        

class Interpreter():
    def __init__(self, code):
        self.registers = []
        self.program = code
        self.raw = ast(self.program)
        self.vp = 0 #variable pointer
        self.ip = 0 #instruction pointer
        self.do_skip = False
        self.jumps = []
        
    def execute(self, num_vars):
        self.registers = [0]*num_vars
        while self.ip < len(self.raw):
            cmd = self.raw[self.ip]
            if self.do_skip:
                if cmd[CMD] == "END":
                    self.do_skip = False
                else:
                    self.ip += 1
                    continue
                
            if cmd[CMD] == "OUT":
                print(cmd[VAL], end="")

            elif cmd[CMD] == "OUTV":
                print(self.registers[self.vp], end="")

            elif cmd[CMD] == "STR":
                registers[self.vp] = cmd[VAL]

            elif cmd[CMD] == "INC PTR":
                self.vp = (self.vp + cmd[VAL]) % len(self.registers)

            elif cmd[CMD] == "DEC PTR":
                self.vp = (self.vp - cmd[VAL]) % len(self.registers)

            elif cmd[CMD] == "PUT":
                temp = input(">")
                try:
                    self.registers[self.vp] = int(temp)
                except:
                    self.registers[self.vp] = temp

            elif cmd[CMD] == "INC":
                if type(registers[self.vp]) is str:
                    temp = ""

                    for char in registers[self.vp]:
                        temp += chr(ord(char) + cmd[VAL])

                    self.registers[self.vp] = temp

                else:
                    self.registers[self.vp] += cmd[VAL]

            elif cmd[CMD] == "DEC":
                if type(self.registers[self.vp]) is str:
                    temp = ""

                    for char in self.registers[self.vp]:
                        temp += chr(ord(char) - cmd[VAL])

                    self.registers[self.vp] = temp

                else:
                    self.registers[self.vp] -= 1

            elif cmd[CMD] == "OUT CHR":
                print(chr(cmd[VAL]), end="")

            elif cmd[CMD] == "OUTV CHR":
                if type(self.registers[self.vp]) is str:
                    print(self.registers[self.vp], end="")
                else:
                    print(ord(self.registers[self.vp]), end="")

            elif cmd[CMD] == "VAR 0":
                self.registers[self.vp] = 0

            elif cmd[CMD] == "IF":
                if not self.registers[self.vp]:
                    self.do_skip = True

            elif cmd[CMD] == "WHILE":
                if self.registers[self.vp]:
                    self.jumps.append(self.ip)
                else:
                    self.do_skip = True

            elif cmd[CMD] == "END":
                if len(self.jumps):
                    if self.registers[self.vp]:
                        self.ip = self.jumps[-1]
                    else:
                        self.jumps.pop()

            self.ip += 1

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument("file", help="The location of the cf file to open")
    parser.add_argument("-v","--vars",
                        help="The number of variables in the regs",
                        type=int)

    args = parser.parse_args()

    try:
        file = open(args.file)
    except:
        print("File not found")
        exit()

    code = file.read()
    code = code.strip("\n").split("\n")

    x = Interpreter(code)

    if args.vars:
        x.execute(args.var)
    else:
        x.execute(30000)
    print()