import os import string import math as m from sys import argv file = open(argv[1]).readlines(); bfcode = "" variables = [] varbytes = [] braces = [] conditions = [] 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, char): ans = "" for i in str: if (i != char): ans += i return ans def removeEnd(string, num): ans = "" for i in range(len(string)-1): ans += string[i] return ans def ord2(char): if (len(char) == 1): return ord(char) elif (len(char == 0)): return(0) def sign(num): 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) for i in file: while (i[0] == " "): i = i.split(" ", 1)[1] 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, 1) 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" if (type == "string"): a = a.split("\"", 1)[1] a = removeEnd(a, 1) 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 (i.split(" ")[0] == "print"): a = i.split(" ", 1)[1] if a[len(a)-1] == "\n": a = removeEnd(a, 1) 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, 1) 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, 1) if (val[0] == "\"") & (val[len(val)-1] == "\""): val = val.split("\"", 1)[1] val = removeEnd(val, 1) 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 += "<<[[<<]<<]<<<<<<<<" 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("Expected { in if statement") a = removeChar(i.split(" ", 1)[1].split("{")[0], " ") if (a in variables): bflen = len(bfcode) bfcode += ">>>>>>>>>>>>" bfcode += "[>>]>>" * (variables.index(a)) bfcode += ">[>+>+<<-]>[<+>-]>[-<<<" bfcode += "[[<<]<<]" bfcode += "+>>>>" bfcode += "[>>]>>" * (variables.index(a)) bfcode += ">>>]" bfcode += "<<<" + "[<<]<<" * (variables.index(a)+1) bfcode += "[<<<<<<<<+>>>>>>>>-]<<<<<<<<" conditions.append(bfcode[-(len(bfcode)-bflen):]) bfcode += "[-" else: raise NameError(f"Could not find variable {a}") 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 != "")): print(i) raise ValueError(f"Invalid Command") print("Successfully compiled!") filewrite()