from email.charset import UNKNOWN8BIT import os import math as m from sys import argv file = open(argv[1]).readlines(); bfcode: str = "" variables = [] varbytes = [] braces = [] conditions = [] types = { "int": 2, "string": 3, "bool": 4, } def find_file(filename, root_dir): for dirpath, dirnames, filenames in os.walk(root_dir): if filename in filenames: return os.path.join(dirpath, filename) return None def removeChar(str: str, char: str) -> str: ans = "" for i in str: if (i != char): ans += i return ans def removeEnd(string: str) -> str: ans = "" for i in range(len(string)-1): ans += string[i] return ans def sign(num: float) -> int: if num < 0: return -1 elif num == 0: return 0 else: return 1 def filewrite(): with open(argv[2], "w") as file: file.write(bfcode) filewrite() for i in file: while (i[0] == " "): i = i.split(" ", 1)[1] module = i.split(" ")[0] if (i[0] == "#"): # Skip line if it is a comment pass # Create command elif (i.split(" ")[0] == "create"): if (i[len(i)-1] == "\n"): i = removeEnd(i) bfcode += ">>>>>>>>>>>>[[>>]>>]" bytes = int(removeChar(i.split("*", 1)[1].split("=", 1)[0], " ")) varbytes.append(bytes) a = i.split("=", 1)[1] if (a[0] == " "): a = a.split(" ", 1)[1] # Get type try: a = int(a) type = "int" except ValueError: if ((a[0] == "\"") & (a[len(a)-1] == "\"")): type = "string" elif (a == "true") | (a == "false"): type = "bool" elif (a.split("*")[0][:5] == "input"): type = "input" if (type == "string"): a = a.split("\"", 1)[1] a = removeEnd(a) for j in range(bytes): bfcode += "+++>" if (j < len(a)): bfcode += "+" * ord(a[j]) + ">" else: bfcode += ">" elif (type == "int"): tempint = [sign(a)] a = abs(a) tempbytes = m.floor(m.log2(a)/8) a = a % (256 ** (bytes - 1)) for j in range(bytes - 1): if (a == 0): modulus = 1 else: modulus = 256 ** (bytes - j - 2) tempint.append(m.floor(a / modulus)) a -= modulus * m.floor(a/modulus) for j in tempint: bfcode += "++>" bfcode += "+" * j + ">" elif type == "bool": if (bytes == 1): bfcode += "++++>" + "+" * (a == "true") + ">" else: raise MemoryError("Booleans can only be made as 1 byte data.") else: raise TypeError("Could not find argument type") bfcode += "<<[[<<]<<]<<<<<<<<" variables.append(i.split(" ")[1].split("*")[0]) elif (module == "input"): var = removeChar(i.split(" ", 1)[1].split("*")[0], " ") bytes = int(removeChar(i.split("*")[1].split("=")[0], " ")) variables.append(var) varbytes.append(bytes) bfcode += ">>>>>>>>>>>>[[>>]>>]" # Get type type = removeChar(i.split("=", 1)[1].split("*")[0], " ") inputbytes = int(removeChar(i.split("*", 2)[2], " ")) for j in range(bytes): bfcode += "+" * types[type] + ">" if (j < inputbytes): bfcode += "," bfcode += ">" bfcode += "<<[[<<]<<]<<<<<<<<" elif (i.split(" ")[0] == "print"): a = i.split(" ", 1)[1] if a[len(a)-1] == "\n": a = removeEnd(a) if (a in variables): bfcode += ">>>>>>>>>>>>" for j in range(variables.index(a)): bfcode += "[>>]>>" bfcode += "[>.>]<<[[<<]<<]<<<<<<<<++++++++++.[-]" else: raise NameError(f"Could not find variable {a}") elif (i.split(" ")[0] == "printnum"): varnum = variables.index(i.split(" ", 1)[1]) bfcode += ">>>>>>>>>>>>" for j in range(varnum): bfcode += "[>>]>>" for j in range(varbytes[varnum]): # Go to correct cell bfcode += ">>" * j + ">" # Create Copy bfcode += "[" + "<<" * (j+1) + "+<+>" + ">>" * (j+1) + "-]" bfcode += "<<" * j + "<" bfcode += "<<[" + ">>" * (j+1) + ">+" + "<<" * (j+1) + "<-]>" # Move copy to end bfcode += "[->" for k in range(len(variables)-varnum+j): bfcode += "[>>]>>" bfcode += "+<<<<" for k in range(len(variables)-varnum+j): bfcode += "[<<]<<" bfcode += ">>>]>" for k in range(len(variables)-varnum+j): bfcode += "[>>]>>" # Split up digits (modulo copied from https://esolangs.org/wiki/Brainfuck_algorithms#Modulo) bfcode += ">>++++++++++<<" bfcode += "[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]" # MODULO bfcode += "++>[-]>[-]>[<<+>>-]>>>++++++++++<<" bfcode += "[->+>-[>+>>]>[+[-<+>]>+>>]<<<<<<]" # MODULO bfcode += "++<<++>>>[-]>[-]>[<<<<+>>>>-]>[<<<+>>>-]" # Return to start bfcode += "<<<<" bfcode += "[<<]<<" * (j+1) bfcode += "[<]>" elif (i.split(" ")[0] == "set"): a = i.split(" ")[1] if a[len(a)-1] == "\n": a = removeEnd(a) if (a in variables): bfcode += ">>>>>>>>>>>>" for j in range(variables.index(a)): bfcode += "[>>]>>" for j in range(varbytes[variables.index(a)]): bfcode += "[-]>[-]>" for j in range(varbytes[variables.index(a)]): bfcode += "<<" # Get type val = i.split("=", 1)[1].split(" ", 1)[1] type = None if (val[len(val)-1] == "\n"): val = removeEnd(val) if (val[0] == "\"") & (val[len(val)-1] == "\""): val = val.split("\"", 1)[1] val = removeEnd(val) type = "string" elif (val == "true") | (val == "false"): type = "bool" if (type == "string"): for j in range(varbytes[variables.index(a)]): bfcode += "+++>" if (j >= len(val)): bfcode += ">" else: bfcode += "+" * ord(val[j]) + ">" elif (type == "int"): bytes = varbytes[variables.index(a)] a = int(val) tempint = [sign(a)] a = abs(a) tempbytes = m.floor(m.log2(a)/8) a = a % (256 ** (bytes - 1)) for j in range(bytes - 1): if (a == 0): modulus = 1 else: modulus = 256 ** (bytes - j - 2) tempint.append(m.floor(a / modulus)) a -= modulus * m.floor(a/modulus) for j in tempint: bfcode += "++>" bfcode += "+" * j + ">" elif (type == "bool"): bfcode += "++++>" if (val == "true"): bfcode += "+" bfcode += ">" else: raise TypeError("Could not find variable type") bfcode += "<<[[<<]<<]<<<<<<<<" elif "+=" in i: if a.split("[")[0] in variables: var = a.split("[")[0] idx = int(a.split("[")[1].split("]")[0]) bfcode += ">>>>>>>>>>>>" + "[>>]>>" * variables.index(var) + ">>" * idx + ">" bfcode += "+" * int(removeChar(i.split("+=")[1], " ")) bfcode += "<[[<<]<<]<<<<<<<<" else: raise NameError(f"Could not find variable {a.split("[")[0]}") elif "-=" in i: if a.split("[")[0] in variables: var = a.split("[")[0] idx = int(a.split("[")[1].split("]")[0]) bfcode += ">>>>>>>>>>>>" + "[>>]>>" * variables.index(var) + ">>" * idx + ">" bfcode += "-" * int(removeChar(i.split("-=")[1], " ")) bfcode += "<[[<<]<<]<<<<<<<<" else: raise NameError(f"Could not find variable {a.split("[")[0]}") elif "=" in i: if a.split("[")[0] in variables: var = a.split("[")[0] idx = int(a.split("[")[1].split("]")[0]) bfcode += ">>>>>>>>>>>>" + "[>>]>>" * variables.index(var) + ">>" * idx + ">" if "\"" in i: replace = ord(i.split("=", 1)[1].split("\"")[1]) else: replace = int(i.split("=", 1)[1].lstrip().rstrip()) bfcode += "[-]" + "+" * replace bfcode += "<[[<<]<<]<<<<<<<<" else: raise NameError(f"Could not find variable {a.split("[")[0]}") else: raise NameError(f"Could not find variable {a}") elif (i.split(" ")[0] == "if") | (i.split(" ")[0] == "while"): braces.append(i.split(" ")[0]) # Argument must be boolean if not ('{' in i): raise SyntaxError(f"Expected {{ in {module} statement") a = removeChar(i.split(" ", 1)[1].split("{")[0], " ") # input is bool bflen = len(bfcode) if (a in variables): bfcode += ">>>>>>>>>>>>" bfcode += "[>>]>>" * (variables.index(a)) bfcode += ">[>+>+<<-]>[<+>-]>[-<<<" bfcode += "[[<<]<<]" bfcode += "+>>>>" bfcode += "[>>]>>" * (variables.index(a)) bfcode += ">>>]" bfcode += "<<<" + "[<<]<<" * (variables.index(a)+1) bfcode += "[<<<<<<<<+>>>>>>>>-]<<<<<<<<" elif ("==" in a): # if input is equal arg1 = i.split("if ")[1].split("==")[0].lstrip().rstrip() arg2 = i.split("==", 1)[1].lstrip().rstrip() try: var1 = variables.index(arg1.split("[")[0]) except: raise NameError(f"Could not find variable {arg1.split("[")[0]}") idx1 = int(arg1.split("[")[1].split("]")[0]) try: var2 = variables.index(arg2.split("[")[0]) except: raise NameError(f"Could not find variable {arg2.split("[")[0]}") idx2 = int(arg2.split("[")[1].split("]")[0]) # Get first data bfcode += ">>>>>>>>>>>>" bfcode += "[>>]>>" * var1 bfcode += ">>" * idx1 + ">" # Create Copy bfcode += "[<" + "<<" * (idx1+1) + "+>+>" + ">>" * idx1 + ">-]" bfcode += "<" + "<<" * (idx1+1) + ">[" + ">>" * (idx1+1) + "+" + "<<" * (idx1+1) + "-]" # Move copy to start bfcode += "<[" if (var1 > 0): bfcode += "[<<]<<" * (var1) + "+>>>>" + "[>>]>>" * (var1-1) + ">>" * varbytes[var1-1] + "-]" else: bfcode += "[<<+>>-]]" bfcode += "<<" + "[<<]<<" * (var1) + "[<<<<<<<<+>>>>>>>>-]<<<<<<<<" # Get second data by copying the above bfcode += ">>>>>>>>>>>>" bfcode += "[>>]>>" * var2 bfcode += ">>" * idx2 + ">" bfcode += "[<" + "<<" * (idx2+1) + "+>+>" + ">>" * idx2 + ">-]" bfcode += "<" + "<<" * (idx2+1) + ">[" + ">>" * (idx2+1) + "+" + "<<" * (idx2+1) + "-]" bfcode += "<[" if (var2 > 0): bfcode += "[<<]<<" * (var2) + "+>>>>" + "[>>]>>" * (var2-1) + ">>" * varbytes[var2-1] + "-]" else: bfcode += "[<<+>>-]" bfcode += "<<" + "[<<]<<" * (var2) + "[<<<<<<<+>>>>>>>-]<<<<<<<" bfcode += "[<->-]+<[>-]>[>]<<[-]>[<+>-]<" else: raise NameError(f"Could not find variable {a}") conditions.append(bfcode[-(len(bfcode)-bflen):]) bfcode += "[[-]" elif (removeChar(removeChar(i, " "), "\n") == "}"): if (braces[len(braces)-1] == "if"): bfcode += "]" elif (braces[len(braces)-1] == "while"): bfcode += f"{conditions[-1]}]" else: raise SyntaxError("How on earth did you get here") braces.pop() conditions.pop() # No command elif ((i != "\n") & (i != "")): raise ValueError(f"Invalid Command") print("Successfully compiled!") filewrite()