Undo literally everything lol

This commit is contained in:
2025-10-16 13:21:27 +11:00
parent 333a1241e8
commit c98f248245
13 changed files with 184 additions and 356 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
src/error.py Normal file
View File

@@ -0,0 +1,3 @@
def error(message: str):
print(f"\033[91mError: \033[0m{message}")
quit()

21
src/eval.py Normal file
View File

@@ -0,0 +1,21 @@
from error import error
def eval(type: int, arg: str) -> list[str | int]:
if (type == 0):
if (arg == 'true'):
return ['true']
elif (arg == 'false'):
return ['false']
else:
error(f'Invalid bool: {arg}')
quit()
elif type == 1:
rval: list[str | int] = []
for i in arg.split('+'):
if (i[0] == i[-1] == '\"'):
rval.append(i[1:-1])
else:
error(f'Invalid token: {arg}')
return rval
else:
error(f'\'{type}\' type not yet implemented')
quit()

View File

@@ -1,367 +1,127 @@
from email.charset import UNKNOWN8BIT
import os
import math as m
# Hopefully this code is actually decent lol
# Note: cells in bf are | 0 | inputs | 0 | variables |
from sys import argv
file = open(argv[1]).readlines();
bfcode: str = ""
variables = []
varbytes = []
braces = []
conditions = []
from preprocess import preprocess
from eval import eval
from error import error
if (len(argv) < 3):
print(f"Usage: python {argv[0]} file.basm file.bf")
quit()
# Check if correct argument count
if (len(argv) != 3) | (argv[1][-5:] != ".basm") | (argv[2][-3:] != ".bf"):
print(f"Usage: python {argv[0]} file.basm file.bf")
quit()
# Get contents of files
try:
with open(argv[1], 'r') as file:
content : str = file.read()
except FileNotFoundError:
error(f"File '{argv[1]}' not found.")
quit()
except IOError:
error(f"Cannot read file '{argv[1]}'.")
quit()
# Pre-processing of the basm file, from preprocess.py
code = preprocess(content)
# Variables and references
class Reference:
def __init__(self, name: str, value: list[str], type: str):
self.name : str = name
self.value : list[str] = value
self.type : str = type
class Variable:
def __init__(self, name: str, bytes: int, startByte: int, type: int):
self.name: str = name
self.bytes: int = bytes
self.startByte: int = startByte
self.type: int = type
def __repr__(self) -> str:
return f"[{self.name}, {self.bytes}, {self.startByte}, {self.type}]"
bfcode: str = '>,[>,]<[<]'
variables: list[Variable | Reference] = []
bytesum: int = 0
types = {
"bool": 0,
"str": 1,
"int": 2,
"string": 3,
"bool": 4,
"ref": 3,
}
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
bool = {
"false": 0,
"true": 1
}
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
def find(str: str, char: str):
if (char in str):
return str.find(char)
else:
return 1
return len(str)
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
# Main loop
for line in code:
keyword: str = line.keyword
argument: str = line.argument
if (keyword == ''):
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
elif (keyword[-1] == '='):
keyword = keyword[:-1]
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 += "<<[[<<]<<]<<<<<<<<"
bytes: int = int(keyword[find(keyword, '*')+1:])
except:
bytes = 0
keyword = keyword[:find(keyword, '*')]
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()
vartype: int
if ':' in keyword:
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 += "[<->-]+<[>-]>[>]<<[-]>[<+>-]<"
vartype = types[keyword[keyword.find(':')+1:]]
keyword = keyword[:keyword.find(':')]
except KeyError:
error(f"Cannot find type {keyword[keyword.find(':')+1:]}")
else:
raise NameError(f"Could not find variable {a}")
vartype = 3
if (keyword in (var.name for var in variables)):
print("Double up?")
else:
# Create new variables
bfcode += ">[>]>" + '>' * bytesum
if (vartype == 0):
# Booleans
if (bytes == 0):
bytes = 1
variables.append(Variable(keyword, int(bytes), bytesum, 0))
bfcode += '+' * bool[eval(0, argument)[0]] + '<' * bytesum + '<<[<]'
bytesum += bytes
elif (vartype == 1):
# Strings
if (bytes == 0):
error("None/Invalid Byte Declaration")
variables.append(Variable(keyword, bytes, bytesum, 1))
print(bytes)
bytesum += bytes
value: list[str] = eval(1, argument)
for a in value:
print(a)
if (type(a) == str):
for b in a:
bfcode += '+' * ord(b) + '>'
else:
error(f"Invalid token: {a}")
bfcode += '<' * bytesum + '<<[<]'
else:
error(f"Invalid token: {keyword}")
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()
print(bfcode)
print(variables[0])

45
src/preprocess.py Normal file
View File

@@ -0,0 +1,45 @@
class Line:
def __init__(self, keyword: str, argument: str):
self.keyword: str = keyword
self.argument: str = argument
def preprocess(code: str) -> list[Line]:
token : str = ""
keyword : str = ""
tokenise : list[Line] = []
isString : bool = False
isComment : bool = False
isKeyword : bool = True
for i in code:
if i == "\n":
isComment = False
elif i == "#":
isComment = True
elif isComment:
pass
elif i == '"':
isString = not(isString)
token += i
elif isString:
token += i
elif (i == ';') | (i == '{') | (i == '}'):
if i != ';':
token += i
tokenise.append(Line(keyword, token))
token = ''
keyword = ''
isKeyword = True
elif (i != ' '):
if (i == '('):
isKeyword = False
if isKeyword:
keyword += i
else:
token += i
if (i == '='):
isKeyword = False
tokenise.append(Line(keyword, token))
return tokenise

0
src/tokenise.py Normal file
View File

View File

@@ -0,0 +1 @@
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.

View File

@@ -1,4 +1,2 @@
create var *5 = "Hello"
create var2 *5 = "World"
set var[1] = "E"
set var2[2] -= 1
var: str *7 = "Hello";
var2: str *5 = "World";