diff --git a/docs/syntax.md b/docs/syntax.md index 85f6cc5..706d64f 100644 --- a/docs/syntax.md +++ b/docs/syntax.md @@ -1,59 +1,16 @@ To create a comment, begin a line with a hash (#) symbol, like python. -## create var *bytes = Value +So far, the supported types are `bool` and `string`. + +## create name type bytes value Creates the variable "var" with a set number of bytes allocated to it, and initialises its value. **IMPORTANT:** The number of bytes cannot be modified later. -Example: `create var *5 = "Hello"` +Example: `create var bool 1 true` ## print var Prints the value of `var` to the console, where `var` is a variable. -Example: `print var` - -## set var = Value - -Changes the value of an already created value. - -Examples: -``` -set var = "World" -set var[0] = "w" -``` - -## input var *bytes = type *ibytes - -Creates a new variable that is `bytes` long, that reads the first `ibytes` of input. - -Example: `input str *5 = string *3` (3 bytes of input, remaining 2 bytes are left blank) - -## if bool - -Runs code if a boolean is true. - -Example: -``` -# If a boolean is true -if bool { - set str = "Hello" -} - -# If second byte of var and third byte of var are equal -if var[1] == var[2] { - set bool = true -} -``` - -## while bool - -Runs code until a boolean is false - -Example: -``` -create bool *1 = true -while bool { - # Loops forever because bool is never false -} -``` \ No newline at end of file +Example: `print var` \ No newline at end of file diff --git a/src/__pycache__/codegen.cpython-313.pyc b/src/__pycache__/codegen.cpython-313.pyc new file mode 100644 index 0000000..f6d54e2 Binary files /dev/null and b/src/__pycache__/codegen.cpython-313.pyc differ diff --git a/src/__pycache__/error.cpython-313.pyc b/src/__pycache__/error.cpython-313.pyc index b3ffc11..8a51ddc 100644 Binary files a/src/__pycache__/error.cpython-313.pyc and b/src/__pycache__/error.cpython-313.pyc differ diff --git a/src/__pycache__/eval.cpython-313.pyc b/src/__pycache__/eval.cpython-313.pyc index b7965f4..c5072fc 100644 Binary files a/src/__pycache__/eval.cpython-313.pyc and b/src/__pycache__/eval.cpython-313.pyc differ diff --git a/src/__pycache__/preprocess.cpython-313.pyc b/src/__pycache__/preprocess.cpython-313.pyc index 2f170a7..6ba5c17 100644 Binary files a/src/__pycache__/preprocess.cpython-313.pyc and b/src/__pycache__/preprocess.cpython-313.pyc differ diff --git a/src/codegen.py b/src/codegen.py new file mode 100644 index 0000000..6e8db5a --- /dev/null +++ b/src/codegen.py @@ -0,0 +1,98 @@ +from error import error +import math as m + +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}]" + +variables: list[Variable] = [] +bytesum: int = 0 + +types = { + "bool": 0, + "string": 1, + "int": 2, +} + +bool = { + "true": 1, + "false": 0, +} + +def generateCode(line: list[str], offset: int) -> str: + try: + bytesum = variables[-1].startByte + variables[-1].bytes + except IndexError: + bytesum = 0 + keyword = line[0] + if keyword == 'create': + if len(line) != 5: + error(f"Create command requires 4 arguments (got {len(line)-1})") + name = line[1] + try: + type = types[line[2]] + except KeyError: + error(f"Invalid type: {line[2]}") + quit() + bytes = int(line[3]) + value = line[4] + + if type == 0: + variables.append(Variable(name, bytes, bytesum, type)) + if (value == 'true'): + return '>' * offset + '[>]' + '>' * (bytesum + 1) + '+' + '<' * (bytesum + 1) + '<[<]' + '<' * (offset - 1) + elif (value == 'false'): + return '' + else: + error(f'Invalid bool: {value}') + elif type == 1: + variables.append(Variable(name, bytes, bytesum, type)) + returnval: str = '>' * offset + '[>]' + '>' * (bytesum + 1) + for i in range(bytes): + returnval += '+' * ord(value[i]) + '>' + returnval += '<' * (bytes+bytesum+2) + '[<]' + '<' * (offset - 1) + return returnval + elif type == 2: + # I hate integers + error('Integers are not yet implemented') + else: + error(f"Type {type} not yet implemented") + + error() + quit() + elif keyword == 'print': + if len(line) != 2: + error(f"Print command requires 1 argument (got {len(line)-1})") + + # Find value of variable + var: Variable | str = '' + for v in variables: + if v.name == line[1]: + var = v + + if var == '': + error(f'Could not find variable {line[1]}') + quit() + + print(var.startByte) + if var.type == 0: + # Create copy + returnval = '>' * offset + '[>]' + '>' * (var.startByte + 1) + '[' + '<' * (var.startByte+2) + '[<]<+<+>>>' + '[>]>' + '>' * var.startByte + '-]' + '<' * (var.startByte + 2) + '[<]<' + '[>>[>]' + '>' * (var.startByte + 1) + '+' + '<' * (var.startByte + 2) + '[<]<-]' + # If true + returnval += '+<[>-<' + '+' * 115 + '.--.+++.----------------.[-]' + ']' + # else false + returnval += '>[' + '+' * 101 + '.-----.+++++++++++.+++++++.--------------.[-]' + ']<<<' + return returnval + elif var.type == 1: + return '>' * offset + '[>]' + '>' * (var.startByte + 1) + '.>' * var.bytes + '<' * (var.startByte+var.bytes+2) + '[<]' + '<' * (offset - 1) + else: + error('Type not yet supported') + quit() + else: + error(f"Invalid token: {keyword}") + quit() \ No newline at end of file diff --git a/src/error.py b/src/error.py index bc95f7d..4a0f3df 100644 --- a/src/error.py +++ b/src/error.py @@ -1,3 +1,2 @@ -def error(message: str): - print(f"\033[91mError: \033[0m{message}") - quit() \ No newline at end of file +def error(message: str = "This is a bugged error message. Please report this issue."): + exit(f"\033[91mError: \033[0m{message}") \ No newline at end of file diff --git a/src/eval.py b/src/eval.py index bc77a2f..e69de29 100644 --- a/src/eval.py +++ b/src/eval.py @@ -1,21 +0,0 @@ -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() \ No newline at end of file diff --git a/src/main.py b/src/main.py index ef28100..0d06c72 100644 --- a/src/main.py +++ b/src/main.py @@ -2,8 +2,8 @@ # Note: cells in bf are | 0 | inputs | 0 | variables | from sys import argv from preprocess import preprocess -from eval import eval from error import error +from codegen import generateCode if (len(argv) < 3): print(f"Usage: python {argv[0]} file.basm file.bf") @@ -28,38 +28,8 @@ except IOError: # 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, - "ref": 3, -} - -bool = { - "false": 0, - "true": 1 -} +offset: int = 5 +bfcode: str = '>' * offset + ',[>,]<[<]' + '<' * (offset-1) def find(str: str, char: str): if (char in str): @@ -67,61 +37,9 @@ def find(str: str, char: str): else: return len(str) -# Main loop +print(code) for line in code: - keyword: str = line.keyword - argument: str = line.argument - if (keyword == ''): - pass - elif (keyword[-1] == '='): - keyword = keyword[:-1] - try: - bytes: int = int(keyword[find(keyword, '*')+1:]) - except: - bytes = 0 - keyword = keyword[:find(keyword, '*')] - - vartype: int - if ':' in keyword: - try: - vartype = types[keyword[keyword.find(':')+1:]] - keyword = keyword[:keyword.find(':')] - except KeyError: - error(f"Cannot find type {keyword[keyword.find(':')+1:]}") - else: - 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}") - -print(bfcode) -print(variables[0]) \ No newline at end of file + bfcode += generateCode(line, offset) + +with open(argv[2], 'w') as f: + print(f"{f.write(bfcode)} characters successfully compiled!") \ No newline at end of file diff --git a/src/preprocess.py b/src/preprocess.py index 81b6958..2c3d1e4 100644 --- a/src/preprocess.py +++ b/src/preprocess.py @@ -1,45 +1,31 @@ -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] = [] +def preprocess(code: str) -> list[list[str]]: + token : str = '' + tokenise : list[list[str]] = [[]] isString : bool = False - isComment : bool = False - isKeyword : bool = True + isComment : bool = False for i in code: - if i == "\n": + if i == '\n': isComment = False - elif i == "#": - isComment = True + if tokenise[-1] != []: + if token != '': + tokenise[-1].append(token) + tokenise.append([]) + token = '' elif isComment: pass - elif i == '"': - isString = not(isString) + elif i == '#': + isComment = True + elif (i != ' ') | isString: token += i - elif isString: - token += i - elif (i == ';') | (i == '{') | (i == '}'): - if i != ';': - token += i - tokenise.append(Line(keyword, token)) + if (i == '\"'): + isString = not(isString) + else: + tokenise[-1].append(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)) + + if token != '': + tokenise[-1].append(token) + token = '' + if tokenise[-1] == []: + tokenise = tokenise[:-1] return tokenise \ No newline at end of file diff --git a/test.bf b/test.bf index e0a8381..c7f6fa0 100644 --- a/test.bf +++ b/test.bf @@ -1 +1 @@ -++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. \ No newline at end of file +>>>>>,[>,]<[<]<<<<>>>>>[>]>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++><<<<<<<[<]<<<<>>>>>[>]>>>>>>+<<<<<<<[<]<<<<>>>>>[>]>>>>>>[<<<<<<<[<]<+<+>>>[>]>>>>>>-]<<<<<<<[<]<[>>[>]>>>>>>+<<<<<<<[<]<-]+<[>-<+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.--.+++.----------------.[-]]>[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.-----.+++++++++++.+++++++.--------------.[-]]<<< \ No newline at end of file diff --git a/tests/create.basm b/tests/create.basm index 7edf1d6..656dfea 100644 --- a/tests/create.basm +++ b/tests/create.basm @@ -1,2 +1,3 @@ -var: str *7 = "Hello"; -var2: str *5 = "World"; \ No newline at end of file +create str string 5 Hello +create var bool 1 true +print var \ No newline at end of file