Start of redesign
This commit is contained in:
		| @@ -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 | ||||
| } | ||||
| ``` | ||||
| Example: `print var` | ||||
							
								
								
									
										
											BIN
										
									
								
								src/__pycache__/codegen.cpython-313.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/__pycache__/codegen.cpython-313.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										98
									
								
								src/codegen.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/codegen.py
									
									
									
									
									
										Normal file
									
								
							| @@ -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() | ||||
| @@ -1,3 +1,2 @@ | ||||
| def error(message: str): | ||||
|     print(f"\033[91mError: \033[0m{message}") | ||||
|     quit() | ||||
| def error(message: str = "This is a bugged error message. Please report this issue."): | ||||
|     exit(f"\033[91mError: \033[0m{message}") | ||||
							
								
								
									
										21
									
								
								src/eval.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								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() | ||||
							
								
								
									
										98
									
								
								src/main.py
									
									
									
									
									
								
							
							
						
						
									
										98
									
								
								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]) | ||||
|     bfcode += generateCode(line, offset) | ||||
|      | ||||
| with open(argv[2], 'w') as f: | ||||
|     print(f"{f.write(bfcode)} characters successfully compiled!") | ||||
| @@ -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 | ||||
							
								
								
									
										2
									
								
								test.bf
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								test.bf
									
									
									
									
									
								
							| @@ -1 +1 @@ | ||||
| ++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. | ||||
| >>>>>,[>,]<[<]<<<<>>>>>[>]>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++><<<<<<<[<]<<<<>>>>>[>]>>>>>>+<<<<<<<[<]<<<<>>>>>[>]>>>>>>[<<<<<<<[<]<+<+>>>[>]>>>>>>-]<<<<<<<[<]<[>>[>]>>>>>>+<<<<<<<[<]<-]+<[>-<+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.--.+++.----------------.[-]]>[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.-----.+++++++++++.+++++++.--------------.[-]]<<< | ||||
| @@ -1,2 +1,3 @@ | ||||
| var: str *7 = "Hello"; | ||||
| var2: str *5 = "World"; | ||||
| create str string 5 Hello | ||||
| create var bool 1 true | ||||
| print var | ||||
		Reference in New Issue
	
	Block a user