2025-10-11 16:59:05 +11:00
|
|
|
from email.charset import UNKNOWN8BIT
|
2025-10-10 14:19:07 +11:00
|
|
|
import os
|
2025-10-10 08:28:12 +11:00
|
|
|
import math as m
|
2025-10-06 10:50:14 +11:00
|
|
|
from sys import argv
|
|
|
|
file = open(argv[1]).readlines();
|
2025-10-11 16:59:05 +11:00
|
|
|
bfcode: str = ""
|
2025-10-06 12:52:38 +11:00
|
|
|
variables = []
|
2025-10-06 18:33:53 +11:00
|
|
|
varbytes = []
|
2025-10-10 14:19:07 +11:00
|
|
|
braces = []
|
|
|
|
conditions = []
|
|
|
|
|
2025-10-11 11:11:14 +11:00
|
|
|
types = {
|
|
|
|
"int": 2,
|
|
|
|
"string": 3,
|
|
|
|
"bool": 4,
|
|
|
|
}
|
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
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
|
2025-10-10 08:28:12 +11:00
|
|
|
|
2025-10-11 16:59:05 +11:00
|
|
|
def removeChar(str: str, char: str) -> str:
|
2025-10-06 11:11:27 +11:00
|
|
|
ans = ""
|
2025-10-06 10:50:14 +11:00
|
|
|
for i in str:
|
|
|
|
if (i != char):
|
|
|
|
ans += i
|
|
|
|
return ans
|
|
|
|
|
2025-10-11 16:59:05 +11:00
|
|
|
def removeEnd(string: str) -> str:
|
2025-10-06 10:50:14 +11:00
|
|
|
ans = ""
|
|
|
|
for i in range(len(string)-1):
|
|
|
|
ans += string[i]
|
|
|
|
return ans
|
|
|
|
|
2025-10-11 16:59:05 +11:00
|
|
|
def sign(num: float) -> int:
|
2025-10-10 08:28:12 +11:00
|
|
|
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)
|
|
|
|
|
2025-10-11 15:20:12 +11:00
|
|
|
filewrite()
|
2025-10-06 10:50:14 +11:00
|
|
|
for i in file:
|
2025-10-10 08:28:12 +11:00
|
|
|
while (i[0] == " "):
|
|
|
|
i = i.split(" ", 1)[1]
|
2025-10-11 11:11:14 +11:00
|
|
|
|
|
|
|
module = i.split(" ")[0]
|
2025-10-10 08:28:12 +11:00
|
|
|
if (i[0] == "#"):
|
|
|
|
# Skip line if it is a comment
|
|
|
|
pass
|
|
|
|
# Create command
|
|
|
|
elif (i.split(" ")[0] == "create"):
|
2025-10-06 11:11:27 +11:00
|
|
|
if (i[len(i)-1] == "\n"):
|
2025-10-11 16:59:05 +11:00
|
|
|
i = removeEnd(i)
|
2025-10-06 10:50:14 +11:00
|
|
|
bfcode += ">>>>>>>>>>>>[[>>]>>]"
|
|
|
|
|
2025-10-06 11:11:27 +11:00
|
|
|
bytes = int(removeChar(i.split("*", 1)[1].split("=", 1)[0], " "))
|
2025-10-06 18:33:53 +11:00
|
|
|
varbytes.append(bytes)
|
2025-10-06 10:50:14 +11:00
|
|
|
|
|
|
|
a = i.split("=", 1)[1]
|
|
|
|
if (a[0] == " "):
|
|
|
|
a = a.split(" ", 1)[1]
|
|
|
|
|
2025-10-11 11:11:14 +11:00
|
|
|
# Get type
|
2025-10-10 08:28:12 +11:00
|
|
|
try:
|
|
|
|
a = int(a)
|
|
|
|
type = "int"
|
|
|
|
except ValueError:
|
|
|
|
if ((a[0] == "\"") & (a[len(a)-1] == "\"")):
|
|
|
|
type = "string"
|
|
|
|
elif (a == "true") | (a == "false"):
|
|
|
|
type = "bool"
|
2025-10-11 11:11:14 +11:00
|
|
|
elif (a.split("*")[0][:5] == "input"):
|
|
|
|
type = "input"
|
2025-10-06 10:50:14 +11:00
|
|
|
|
|
|
|
if (type == "string"):
|
|
|
|
a = a.split("\"", 1)[1]
|
2025-10-11 16:59:05 +11:00
|
|
|
a = removeEnd(a)
|
2025-10-06 10:50:14 +11:00
|
|
|
for j in range(bytes):
|
|
|
|
bfcode += "+++>"
|
|
|
|
if (j < len(a)):
|
|
|
|
bfcode += "+" * ord(a[j]) + ">"
|
2025-10-06 18:33:53 +11:00
|
|
|
else:
|
|
|
|
bfcode += ">"
|
2025-10-10 08:28:12 +11:00
|
|
|
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)
|
2025-10-06 12:52:38 +11:00
|
|
|
|
2025-10-10 08:28:12 +11:00
|
|
|
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 += "<<[[<<]<<]<<<<<<<<"
|
|
|
|
|
2025-10-06 12:52:38 +11:00
|
|
|
variables.append(i.split(" ")[1].split("*")[0])
|
|
|
|
|
2025-10-11 11:11:14 +11:00
|
|
|
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 += "<<[[<<]<<]<<<<<<<<"
|
|
|
|
|
2025-10-06 12:52:38 +11:00
|
|
|
elif (i.split(" ")[0] == "print"):
|
|
|
|
a = i.split(" ", 1)[1]
|
|
|
|
if a[len(a)-1] == "\n":
|
2025-10-11 16:59:05 +11:00
|
|
|
a = removeEnd(a)
|
2025-10-06 12:52:38 +11:00
|
|
|
if (a in variables):
|
|
|
|
bfcode += ">>>>>>>>>>>>"
|
2025-10-06 18:33:53 +11:00
|
|
|
for j in range(variables.index(a)):
|
2025-10-06 12:52:38 +11:00
|
|
|
bfcode += "[>>]>>"
|
2025-10-10 08:28:12 +11:00
|
|
|
|
2025-10-06 12:52:38 +11:00
|
|
|
bfcode += "[>.>]<<[[<<]<<]<<<<<<<<++++++++++.[-]"
|
|
|
|
else:
|
|
|
|
raise NameError(f"Could not find variable {a}")
|
2025-10-10 08:28:12 +11:00
|
|
|
|
|
|
|
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 += "[<]>"
|
2025-10-06 18:33:53 +11:00
|
|
|
|
|
|
|
elif (i.split(" ")[0] == "set"):
|
|
|
|
a = i.split(" ")[1]
|
|
|
|
if a[len(a)-1] == "\n":
|
2025-10-11 16:59:05 +11:00
|
|
|
a = removeEnd(a)
|
2025-10-06 18:33:53 +11:00
|
|
|
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]
|
2025-10-10 14:19:07 +11:00
|
|
|
type = None
|
2025-10-06 18:33:53 +11:00
|
|
|
if (val[len(val)-1] == "\n"):
|
2025-10-11 16:59:05 +11:00
|
|
|
val = removeEnd(val)
|
2025-10-06 18:33:53 +11:00
|
|
|
if (val[0] == "\"") & (val[len(val)-1] == "\""):
|
|
|
|
val = val.split("\"", 1)[1]
|
2025-10-11 16:59:05 +11:00
|
|
|
val = removeEnd(val)
|
2025-10-06 18:33:53 +11:00
|
|
|
type = "string"
|
2025-10-10 14:19:07 +11:00
|
|
|
elif (val == "true") | (val == "false"):
|
|
|
|
type = "bool"
|
|
|
|
|
2025-10-06 18:33:53 +11:00
|
|
|
if (type == "string"):
|
|
|
|
for j in range(varbytes[variables.index(a)]):
|
|
|
|
bfcode += "+++>"
|
|
|
|
if (j >= len(val)):
|
|
|
|
bfcode += ">"
|
|
|
|
else:
|
|
|
|
bfcode += "+" * ord(val[j]) + ">"
|
2025-10-10 08:28:12 +11:00
|
|
|
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 + ">"
|
2025-10-10 14:19:07 +11:00
|
|
|
elif (type == "bool"):
|
|
|
|
bfcode += "++++>"
|
|
|
|
if (val == "true"):
|
|
|
|
bfcode += "+"
|
|
|
|
bfcode += ">"
|
|
|
|
else:
|
|
|
|
raise TypeError("Could not find variable type")
|
2025-10-06 18:33:53 +11:00
|
|
|
bfcode += "<<[[<<]<<]<<<<<<<<"
|
2025-10-11 18:07:46 +11:00
|
|
|
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]}")
|
2025-10-11 16:59:05 +11:00
|
|
|
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 + ">"
|
2025-10-11 18:07:46 +11:00
|
|
|
if "\"" in i:
|
|
|
|
replace = ord(i.split("=", 1)[1].split("\"")[1])
|
|
|
|
else:
|
|
|
|
replace = int(i.split("=", 1)[1].lstrip().rstrip())
|
|
|
|
bfcode += "[-]" + "+" * replace
|
2025-10-11 16:59:05 +11:00
|
|
|
bfcode += "<[[<<]<<]<<<<<<<<"
|
|
|
|
else:
|
|
|
|
raise NameError(f"Could not find variable {a.split("[")[0]}")
|
2025-10-06 18:33:53 +11:00
|
|
|
else:
|
|
|
|
raise NameError(f"Could not find variable {a}")
|
2025-10-06 12:52:38 +11:00
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
elif (i.split(" ")[0] == "if") | (i.split(" ")[0] == "while"):
|
|
|
|
braces.append(i.split(" ")[0])
|
|
|
|
|
2025-10-10 08:28:12 +11:00
|
|
|
# Argument must be boolean
|
|
|
|
if not ('{' in i):
|
2025-10-11 11:11:14 +11:00
|
|
|
raise SyntaxError(f"Expected {{ in {module} statement")
|
2025-10-10 08:28:12 +11:00
|
|
|
a = removeChar(i.split(" ", 1)[1].split("{")[0], " ")
|
2025-10-11 11:11:14 +11:00
|
|
|
|
|
|
|
# input is bool
|
|
|
|
bflen = len(bfcode)
|
2025-10-10 08:28:12 +11:00
|
|
|
if (a in variables):
|
|
|
|
bfcode += ">>>>>>>>>>>>"
|
|
|
|
bfcode += "[>>]>>" * (variables.index(a))
|
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
|
2025-10-10 08:28:12 +11:00
|
|
|
bfcode += ">[>+>+<<-]>[<+>-]>[-<<<"
|
|
|
|
bfcode += "[[<<]<<]"
|
|
|
|
bfcode += "+>>>>"
|
|
|
|
bfcode += "[>>]>>" * (variables.index(a))
|
|
|
|
bfcode += ">>>]"
|
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
bfcode += "<<<" + "[<<]<<" * (variables.index(a)+1)
|
|
|
|
bfcode += "[<<<<<<<<+>>>>>>>>-]<<<<<<<<"
|
2025-10-11 11:11:14 +11:00
|
|
|
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) + "-]"
|
2025-10-10 14:19:07 +11:00
|
|
|
|
2025-10-11 11:11:14 +11:00
|
|
|
# Move copy to start
|
2025-10-11 15:20:12 +11:00
|
|
|
bfcode += "<["
|
|
|
|
if (var1 > 0):
|
|
|
|
bfcode += "[<<]<<" * (var1) + "+>>>>" + "[>>]>>" * (var1-1) + ">>" * varbytes[var1-1] + "-]"
|
|
|
|
else:
|
|
|
|
bfcode += "[<<+>>-]]"
|
2025-10-11 11:11:14 +11:00
|
|
|
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) + "-]"
|
2025-10-11 15:20:12 +11:00
|
|
|
bfcode += "<["
|
|
|
|
if (var2 > 0):
|
|
|
|
bfcode += "[<<]<<" * (var2) + "+>>>>" + "[>>]>>" * (var2-1) + ">>" * varbytes[var2-1] + "-]"
|
|
|
|
else:
|
|
|
|
bfcode += "[<<+>>-]"
|
2025-10-11 11:11:14 +11:00
|
|
|
bfcode += "<<" + "[<<]<<" * (var2) + "[<<<<<<<+>>>>>>>-]<<<<<<<"
|
|
|
|
bfcode += "[<->-]+<[>-]>[>]<<[-]>[<+>-]<"
|
2025-10-10 08:28:12 +11:00
|
|
|
|
|
|
|
else:
|
|
|
|
raise NameError(f"Could not find variable {a}")
|
2025-10-11 11:11:14 +11:00
|
|
|
|
|
|
|
conditions.append(bfcode[-(len(bfcode)-bflen):])
|
|
|
|
bfcode += "[[-]"
|
2025-10-10 08:28:12 +11:00
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
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()
|
2025-10-10 08:28:12 +11:00
|
|
|
|
|
|
|
# No command
|
2025-10-06 12:52:38 +11:00
|
|
|
elif ((i != "\n") & (i != "")):
|
|
|
|
raise ValueError(f"Invalid Command")
|
2025-10-06 10:50:14 +11:00
|
|
|
|
2025-10-10 14:19:07 +11:00
|
|
|
print("Successfully compiled!")
|
2025-10-10 08:28:12 +11:00
|
|
|
filewrite()
|