Compare commits
	
		
			18 Commits
		
	
	
		
			91f090dc12
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e853195cc3 | |||
| 4bcbc6c650 | |||
| 5e9c2273a9 | |||
| 976e9dfaa0 | |||
| 89065711ce | |||
| 9ad3bdbc92 | |||
| 176c07151a | |||
| 1ceecbb99e | |||
| 0710369871 | |||
| 5fa47dc377 | |||
| c98f248245 | |||
| 333a1241e8 | |||
| 74494711f6 | |||
| ea8d651171 | |||
| f2336c8463 | |||
| ea55468a10 | |||
| 11f708a9fd | |||
| 937cdfa3ef | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					src/__pycache__
 | 
				
			||||||
 | 
					test.bf
 | 
				
			||||||
@@ -1,32 +0,0 @@
 | 
				
			|||||||
To create a comment, begin a line with a hash (#) symbol, like python.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## create var *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"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 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.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example: `set var = "World"`
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## if bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Runs code if a boolean is true.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Example: 
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
create *1 bool = true
 | 
					 | 
				
			||||||
if bool {
 | 
					 | 
				
			||||||
  set var = "BASM!"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
							
								
								
									
										21
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								readme.md
									
									
									
									
									
								
							@@ -2,6 +2,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
BrainAssembly is a language that compiles to Brainfuck. Similar to Assembly languages, it has simple syntax, and is designed to make Brainfuck easier to write code for. Heavily inspired by Ground. Enjoy!
 | 
					BrainAssembly is a language that compiles to Brainfuck. Similar to Assembly languages, it has simple syntax, and is designed to make Brainfuck easier to write code for. Heavily inspired by Ground. Enjoy!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Features
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Simple syntax: The language is designed to be very simple, and a framework for larger projects. This also means that the syntax is quite easy to learn.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**NOTE:** Due to the current lack of optimisation in the compiled code, we recommend an optimising intepreter such as [this one](https://copy.sh/brainfuck).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To run:
 | 
					To run:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- First clone this repository and install python.
 | 
					- First clone this repository and install python.
 | 
				
			||||||
@@ -10,10 +16,21 @@ git clone https://chookspace.com/DiamondNether90/BrainAssembly
 | 
				
			|||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Next, run the following command to compile a .basm file to Brainfuck:
 | 
					- Next, run the following command to compile a .basm file to Brainfuck:
 | 
				
			||||||
```
 | 
					```bash
 | 
				
			||||||
python3 src/main.py path/to/file.basm path/to/file.bf
 | 
					python3 src/main.py path/to/file.basm path/to/file.bf
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
(Replace path/to/file.basm with the actual path to your desired .basm file, and replace path/to/file.bf with where you want the compiled file to be created.)
 | 
					(Replace path/to/file.basm with the actual path to your desired .basm file, and replace path/to/file.bf with where you want the compiled file to be created.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This will create or replace the contents of path/to/file.bf with the compiled BrainAssembly code.
 | 
					This will create or replace the contents of path/to/file.bf with the compiled BrainAssembly code.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Test the compiler with our in-built test programs!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can access our test programs in the test folder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example:
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					python src/main.py tests/create.basm test.bf
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This will create a Brainfuck file named test.bf that contains the compiled code of the 'create' test program.
 | 
				
			||||||
							
								
								
									
										387
									
								
								src/codegen.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								src/codegen.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,387 @@
 | 
				
			|||||||
 | 
					from error import error, warn
 | 
				
			||||||
 | 
					import math as m
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					class Variable:
 | 
				
			||||||
 | 
					    def __init__(self, name: str, bytes: int, type: int):
 | 
				
			||||||
 | 
					        self.name: str = name
 | 
				
			||||||
 | 
					        self.bytes: int = bytes
 | 
				
			||||||
 | 
					        self.type: int = type
 | 
				
			||||||
 | 
					    def __repr__(self) -> str:
 | 
				
			||||||
 | 
					        return f"[{self.name}, {self.bytes}, {self.type}]"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					variables: list[Variable] = []
 | 
				
			||||||
 | 
					bytesum: int = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool = {
 | 
				
			||||||
 | 
					    "true": 1,
 | 
				
			||||||
 | 
					    "false": 0,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getIndex(name: str) -> int:
 | 
				
			||||||
 | 
					    varnames = []
 | 
				
			||||||
 | 
					    for var in variables:
 | 
				
			||||||
 | 
					        varnames.append(var.name)
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        return varnames.index(name)
 | 
				
			||||||
 | 
					    except IndexError:
 | 
				
			||||||
 | 
					        return -1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def generateCode(line: list[str], offset: int) -> str:
 | 
				
			||||||
 | 
					    keyword = line[0]
 | 
				
			||||||
 | 
					    if keyword == 'bool':
 | 
				
			||||||
 | 
					        if len(line) != 3:
 | 
				
			||||||
 | 
					            error(f'Bool command requires 2 arguments (got {len(line)-1})')
 | 
				
			||||||
 | 
					        variables.append(Variable(line[1], 1, 0))
 | 
				
			||||||
 | 
					        if line[2] == 'true':
 | 
				
			||||||
 | 
					            returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					            for var in variables[:-1]:
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '>[>]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '>+<'
 | 
				
			||||||
 | 
					            for var in reversed(variables[:-1]):
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '<[<]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					            return returnval
 | 
				
			||||||
 | 
					        elif line[2] == 'false':
 | 
				
			||||||
 | 
					            return ''
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            error(f"Invalid bool: {line[2]}")
 | 
				
			||||||
 | 
					    elif keyword == 'string':
 | 
				
			||||||
 | 
					        if len(line) != 4:
 | 
				
			||||||
 | 
					            error(f'String command requires 3 arguments (got {len(line)-1})')
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            variables.append(Variable(line[1], int(line[2]), 1))
 | 
				
			||||||
 | 
					        except ValueError:
 | 
				
			||||||
 | 
					            error(f'Unexpected bytes for string: {line[2]}')
 | 
				
			||||||
 | 
					        returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        for var in variables[:-1]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes + 1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error('Cannot have negative byte count (excluding -1)')
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '>'
 | 
				
			||||||
 | 
					        # Normal string
 | 
				
			||||||
 | 
					        if line[3][0] == line[3][-1] == '"':
 | 
				
			||||||
 | 
					            line[3] = line[3][1:-1]
 | 
				
			||||||
 | 
					            if (len(line[3]) > int(line[2])) & (line[2] != '-1'):
 | 
				
			||||||
 | 
					                line[3] = line[3][:(int(line[2])-len(line[3]))]
 | 
				
			||||||
 | 
					            for char in line[3]:
 | 
				
			||||||
 | 
					                returnval += '+' * ord(char) + '>'
 | 
				
			||||||
 | 
					            for char in range(int(line[2])-len(line[3])):
 | 
				
			||||||
 | 
					                returnval += '>'
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            error(f'Invalid string: {line[3]}')
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        # Return to start
 | 
				
			||||||
 | 
					        for var in reversed(variables):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes + 1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'int':
 | 
				
			||||||
 | 
					        if len(line) != 3:
 | 
				
			||||||
 | 
					            error(f'Int requires 2 arguments (got {len(line)-1})')
 | 
				
			||||||
 | 
					        variables.append(Variable(line[1], 4, 2))
 | 
				
			||||||
 | 
					        returnval: str = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        for var in variables[:-1]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        returnval += '>'
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            input = int(line[2])
 | 
				
			||||||
 | 
					            if abs(input) > 4294967295:
 | 
				
			||||||
 | 
					                warn(f'Input {line[2]} is too large for int. Overflowing...')
 | 
				
			||||||
 | 
					            input %= 4294967296
 | 
				
			||||||
 | 
					        except ValueError:
 | 
				
			||||||
 | 
					            error(f'Invalid integer: {line[2]}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        values: list[int] = []
 | 
				
			||||||
 | 
					        for i in reversed(range(4)):
 | 
				
			||||||
 | 
					            values.append(m.floor(input/(256**i)))
 | 
				
			||||||
 | 
					            input -= values[-1] * (256**i)
 | 
				
			||||||
 | 
					        for num in values:
 | 
				
			||||||
 | 
					            if num < 128:
 | 
				
			||||||
 | 
					                returnval += '+' * num + '>'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                returnval += '-' * (256-num) + '>'
 | 
				
			||||||
 | 
					        returnval += '<<<<<'
 | 
				
			||||||
 | 
					        for var in reversed(variables[:-1]):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes + 1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'print':
 | 
				
			||||||
 | 
					        if len(line) != 2:
 | 
				
			||||||
 | 
					            error(f'Print command requires 1 argument (got {len(line)-1})')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        idx = getIndex(line[1])
 | 
				
			||||||
 | 
					        if idx != -1:
 | 
				
			||||||
 | 
					            for var in variables[:idx]:
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '>[>]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            var = variables[idx]
 | 
				
			||||||
 | 
					            if var.type != 1:
 | 
				
			||||||
 | 
					                error(f'Can\'t print {var.name}: Invalid type')
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' + '.>' * var.bytes + '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[.>]' + '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            for var in reversed(variables[:idx]):
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '<[<]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            error(f'{line[1]} is not a variable')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'inc':
 | 
				
			||||||
 | 
					        if len(line) != 2:
 | 
				
			||||||
 | 
					            error(f'Inc command requires 1 argument (got {len(line)-1})')    
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        idx = getIndex(line[1])
 | 
				
			||||||
 | 
					        if variables[idx].type != 2:
 | 
				
			||||||
 | 
					            error(f'Cannot increment {line[1]}: Invalid type')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        for var in variables[:idx]:
 | 
				
			||||||
 | 
					            if var.bytes > 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes + 1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        # Increment logic        
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        The logic in pseudo-python is like this:
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            byte[3]++
 | 
				
			||||||
 | 
					            carry = 1
 | 
				
			||||||
 | 
					            if byte[3] != 0:
 | 
				
			||||||
 | 
					                carry = 0
 | 
				
			||||||
 | 
					            if carry == 1:
 | 
				
			||||||
 | 
					                byte[2]++
 | 
				
			||||||
 | 
					                if byte[2] != 0:
 | 
				
			||||||
 | 
					                    carry = 0
 | 
				
			||||||
 | 
					                if carry == 1:
 | 
				
			||||||
 | 
					                    byte[1]++
 | 
				
			||||||
 | 
					                    if byte[1] != 0:
 | 
				
			||||||
 | 
					                        carry = 0
 | 
				
			||||||
 | 
					                    if carry == 1:
 | 
				
			||||||
 | 
					                        byte[0]++
 | 
				
			||||||
 | 
					                        carry = 0
 | 
				
			||||||
 | 
					        '''
 | 
				
			||||||
 | 
					        # Carry will be stored to the immediate right of cells
 | 
				
			||||||
 | 
					        # byte[3]++; carry = 1
 | 
				
			||||||
 | 
					        returnval += '>>>>+>+'
 | 
				
			||||||
 | 
					        # If byte[3] != 0: carry = 0
 | 
				
			||||||
 | 
					        returnval += '<[>-<[<<<<+>>>>-]]<<<<[>>>>+<<<<-]>>>>'
 | 
				
			||||||
 | 
					        # If carry == 1
 | 
				
			||||||
 | 
					        returnval += '>['
 | 
				
			||||||
 | 
					        # byte[2]++
 | 
				
			||||||
 | 
					        returnval += '<<+'
 | 
				
			||||||
 | 
					        # if byte[2] != 0: carry = 0
 | 
				
			||||||
 | 
					        returnval += '[>>-<<[<<<+>>>-]]'
 | 
				
			||||||
 | 
					        returnval += '<<<[>>>+<<<-]>>>'
 | 
				
			||||||
 | 
					        # if carry == 1
 | 
				
			||||||
 | 
					        returnval += '>>['
 | 
				
			||||||
 | 
					        # byte[1]++
 | 
				
			||||||
 | 
					        returnval += '<<<+'
 | 
				
			||||||
 | 
					        # if byte[1] != 0: carry = 0
 | 
				
			||||||
 | 
					        returnval += '[>>>-<<<[<<+>>-]]<<[>>+<<-]>>'
 | 
				
			||||||
 | 
					        # if carry == 1
 | 
				
			||||||
 | 
					        returnval += '>>>['
 | 
				
			||||||
 | 
					        # byte[0]++; carry = 0
 | 
				
			||||||
 | 
					        returnval += '<<<<+>>>>-]]]'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # Return to start
 | 
				
			||||||
 | 
					        returnval += '<<<<<'
 | 
				
			||||||
 | 
					        for var in reversed(variables[:idx]):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'equal':
 | 
				
			||||||
 | 
					        if len(line) != 4:
 | 
				
			||||||
 | 
					            error(f'Equal command requires 3 arguments (got {len(line)-1})')
 | 
				
			||||||
 | 
					        returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        idx = getIndex(line[1])
 | 
				
			||||||
 | 
					        for var in variables[:idx]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        returnval += '>'
 | 
				
			||||||
 | 
					        for i in range(4):
 | 
				
			||||||
 | 
					            returnval += '[-'
 | 
				
			||||||
 | 
					            returnval += '>' * (4-i)
 | 
				
			||||||
 | 
					            for var in variables[(idx+1):]:
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '>[>]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '>' * (i+1) + '+' + '<' * (i+1)
 | 
				
			||||||
 | 
					            for var in reversed(variables[(idx+1):]):
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '<[<]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '<<<<<+' + '>' * (i+1) + ']'
 | 
				
			||||||
 | 
					            returnval += '<' * (i+1) + '[' + '>' * (i+1) + '+' + '<' * (i+1) + '-]' + '>' * (i+2)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        # Copy the above, but subtract from duplicate
 | 
				
			||||||
 | 
					        idx2 = getIndex(line[2])
 | 
				
			||||||
 | 
					        for var in variables[(idx+1):idx2]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '>'
 | 
				
			||||||
 | 
					        for i in range(4):
 | 
				
			||||||
 | 
					            returnval += '[-'
 | 
				
			||||||
 | 
					            returnval += '>' * (4-i)
 | 
				
			||||||
 | 
					            for var in variables[(idx2+1):]:
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '>[>]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '>' * (i+1) + '-' + '<' * (i+1)
 | 
				
			||||||
 | 
					            for var in reversed(variables[(idx2+1):]):
 | 
				
			||||||
 | 
					                if var.bytes >= 0:
 | 
				
			||||||
 | 
					                    returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					                elif var.bytes == -1:
 | 
				
			||||||
 | 
					                    returnval += '<[<]'
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    error()
 | 
				
			||||||
 | 
					            returnval += '<<<<<+' + '>' * (i+1) + ']'
 | 
				
			||||||
 | 
					            returnval += '<' * (i+1) + '[' + '>' * (i+1) + '+' + '<' * (i+1) + '-]' + '>' * (i+2)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        for var in variables[(idx2+1):]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        returnval += '>[<+>[-]]>[<<+>>[-]]>[<<<+>>>[-]]>[<<<<+>>>>[-]]<<<+<[>-<[-]]'
 | 
				
			||||||
 | 
					        for var in reversed(variables):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '<[<]' + '<' * (offset-1)
 | 
				
			||||||
 | 
					        variables.append(Variable(line[3], 1, 0))
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'if':
 | 
				
			||||||
 | 
					        if len(line) != 2:
 | 
				
			||||||
 | 
					            error(f'If command requires 1 argument (got {len(line)-1})')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        returnval = '>' * offset + '[>]'
 | 
				
			||||||
 | 
					        idx = getIndex(line[1])
 | 
				
			||||||
 | 
					        for var in variables[:idx]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        returnval += '>[<+>->+<]<[>+<-]>>[<<'
 | 
				
			||||||
 | 
					        for var in reversed(variables[:idx]):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '<[<]<+>>[>]'
 | 
				
			||||||
 | 
					        for var in variables[:idx]:
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '>' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '>[>]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '>>-]<<'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        for var in reversed(variables[:idx]):
 | 
				
			||||||
 | 
					            if var.bytes >= 0:
 | 
				
			||||||
 | 
					                returnval += '<' * (var.bytes+1)
 | 
				
			||||||
 | 
					            elif var.bytes == -1:
 | 
				
			||||||
 | 
					                returnval += '<[<]'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                error()
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					        returnval += '<[<]<[' + '<' * (offset-2) + '+' + '>' * (offset-2) + '-]' + '<' * (offset-2) + '[-'
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return returnval
 | 
				
			||||||
 | 
					    elif keyword == 'end':
 | 
				
			||||||
 | 
					        if len(line) != 2:
 | 
				
			||||||
 | 
					            error(f'End command requires 2 arguments (got {len(line)-1})')
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        if line[1] == 'if':
 | 
				
			||||||
 | 
					            return ']'
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            error(f'Invalid argument for end: {line[1]}')
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        error(f'Invalid keyword: {line[0]}')
 | 
				
			||||||
							
								
								
									
										5
									
								
								src/error.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/error.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					def error(message: str = "This is a bugged error message. Please report this issue."):
 | 
				
			||||||
 | 
					    exit(f"\033[91mError: \033[0m{message}")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					def warn(message: str):
 | 
				
			||||||
 | 
					    print(f"\033[33mWarning: {message}\033[0m")
 | 
				
			||||||
							
								
								
									
										267
									
								
								src/main.py
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								src/main.py
									
									
									
									
									
								
							@@ -1,237 +1,40 @@
 | 
				
			|||||||
from signal import Sigmasks
 | 
					# Hopefully this code is actually decent lol
 | 
				
			||||||
import string
 | 
					# Note: cells in bf are | 0 | inputs | 0 | variables |
 | 
				
			||||||
import math as m
 | 
					 | 
				
			||||||
from sys import argv
 | 
					from sys import argv
 | 
				
			||||||
file = open(argv[1]).readlines();
 | 
					from preprocess import preprocess
 | 
				
			||||||
bfcode = ""
 | 
					from error import error
 | 
				
			||||||
variables = []
 | 
					from codegen import generateCode
 | 
				
			||||||
varbytes = []
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def removeChar(str, char):
 | 
					if (len(argv) < 3):
 | 
				
			||||||
    ans = ""
 | 
					    print(f"Usage: python {argv[0]} file.basm file.bf")
 | 
				
			||||||
    for i in str:
 | 
					    quit()
 | 
				
			||||||
        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):
 | 
					# Check if correct argument count
 | 
				
			||||||
    if num < 0:
 | 
					if (len(argv) != 3) | (argv[1][-5:] != ".basm") | (argv[2][-3:] != ".bf"):
 | 
				
			||||||
        return -1
 | 
					    print(f"Usage: python {argv[0]} file.basm file.bf")
 | 
				
			||||||
    elif num == 0:
 | 
					    quit()
 | 
				
			||||||
        return 0
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        return 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def filewrite():
 | 
					# Get contents of files
 | 
				
			||||||
    with open(argv[2], "w") as file:
 | 
					try:
 | 
				
			||||||
        file.write(bfcode)
 | 
					    with open(argv[1], 'r') as file:
 | 
				
			||||||
        
 | 
					        content : str = file.read()
 | 
				
			||||||
filewrite()
 | 
					except FileNotFoundError:
 | 
				
			||||||
for i in file:
 | 
					    error(f"File '{argv[1]}' not found.")
 | 
				
			||||||
    while (i[0] == " "):
 | 
					    quit()
 | 
				
			||||||
        i = i.split(" ", 1)[1]
 | 
					except IOError:
 | 
				
			||||||
    if (i[0] == "#"):
 | 
					    error(f"Cannot read file '{argv[1]}'.")
 | 
				
			||||||
        # Skip line if it is a comment
 | 
					    quit()
 | 
				
			||||||
        pass
 | 
					
 | 
				
			||||||
    # Create command
 | 
					# Pre-processing of the basm file, from preprocess.py
 | 
				
			||||||
    elif (i.split(" ")[0] == "create"):
 | 
					code = preprocess(content)
 | 
				
			||||||
        if (i[len(i)-1] == "\n"):
 | 
					
 | 
				
			||||||
            i = removeEnd(i, 1)
 | 
					offset: int = 5
 | 
				
			||||||
        bfcode += ">>>>>>>>>>>>[[>>]>>]"
 | 
					bfcode: str = '>' * offset + ',[>,]<[<]' + '<' * (offset-1)
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        bytes = int(removeChar(i.split("*", 1)[1].split("=", 1)[0], " "))
 | 
					open(argv[2], 'w').write('')
 | 
				
			||||||
        varbytes.append(bytes)
 | 
					
 | 
				
			||||||
        
 | 
					for line in code:
 | 
				
			||||||
        a = i.split("=", 1)[1]
 | 
					    bfcode += generateCode(line, offset)
 | 
				
			||||||
        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"):
 | 
					with open(argv[2], 'w') as f:
 | 
				
			||||||
        a = i.split(" ", 1)[1]
 | 
					    print(f"{f.write(bfcode)} characters successfully compiled!")
 | 
				
			||||||
        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]
 | 
					 | 
				
			||||||
            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"
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            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 + ">"
 | 
					 | 
				
			||||||
            bfcode += "<<[[<<]<<]<<<<<<<<"
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise NameError(f"Could not find variable {a}")
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
    elif (i.split(" ")[0] == "if"):
 | 
					 | 
				
			||||||
        # Argument must be boolean
 | 
					 | 
				
			||||||
        if not ('{' in i):
 | 
					 | 
				
			||||||
            raise SyntaxError(f"Expected {{ in if statement")
 | 
					 | 
				
			||||||
        a = removeChar(i.split(" ", 1)[1].split("{")[0], " ")
 | 
					 | 
				
			||||||
        if (a in variables):
 | 
					 | 
				
			||||||
            bfcode += ">>>>>>>>>>>>"
 | 
					 | 
				
			||||||
            bfcode += "[>>]>>" * (variables.index(a))
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            bfcode += ">[>+>+<<-]>[<+>-]>[-<<<"
 | 
					 | 
				
			||||||
            bfcode += "[[<<]<<]"
 | 
					 | 
				
			||||||
            bfcode += "+>>>>"
 | 
					 | 
				
			||||||
            bfcode += "[>>]>>" * (variables.index(a))
 | 
					 | 
				
			||||||
            bfcode += ">>>]"
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            bfcode += "<<<<<<<[<<<<<<<<+>>>>>>>>-]<<<<<<<<"
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            bfcode += "[-"
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise NameError(f"Could not find variable {a}")
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
    elif (i == "}"):
 | 
					 | 
				
			||||||
        bfcode += "]"
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    # No command
 | 
					 | 
				
			||||||
    elif ((i != "\n") & (i != "")):
 | 
					 | 
				
			||||||
        raise ValueError(f"Invalid Command")
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
print("DONE!")
 | 
					 | 
				
			||||||
filewrite()
 | 
					 | 
				
			||||||
							
								
								
									
										31
									
								
								src/preprocess.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/preprocess.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					def preprocess(code: str) -> list[list[str]]:
 | 
				
			||||||
 | 
					    token : str = ''
 | 
				
			||||||
 | 
					    tokenise : list[list[str]] = [[]]
 | 
				
			||||||
 | 
					    isString : bool = False
 | 
				
			||||||
 | 
					    isComment : bool = False
 | 
				
			||||||
 | 
					    for i in code:
 | 
				
			||||||
 | 
					        if i == '\n':
 | 
				
			||||||
 | 
					            isComment = False
 | 
				
			||||||
 | 
					            if token != '':
 | 
				
			||||||
 | 
					                tokenise[-1].append(token)
 | 
				
			||||||
 | 
					            if tokenise[-1]:
 | 
				
			||||||
 | 
					                tokenise.append([])
 | 
				
			||||||
 | 
					                token = ''
 | 
				
			||||||
 | 
					        elif isComment:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        elif i == '#':
 | 
				
			||||||
 | 
					            isComment = True
 | 
				
			||||||
 | 
					        elif (i != ' ') | isString:
 | 
				
			||||||
 | 
					            token += i
 | 
				
			||||||
 | 
					            if (i == '\"'):
 | 
				
			||||||
 | 
					                isString = not(isString)
 | 
				
			||||||
 | 
					        elif token != '':
 | 
				
			||||||
 | 
					            tokenise[-1].append(token)
 | 
				
			||||||
 | 
					            token = ''
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					    if token != '':
 | 
				
			||||||
 | 
					        tokenise[-1].append(token)
 | 
				
			||||||
 | 
					        token = ''
 | 
				
			||||||
 | 
					    if tokenise[-1] == []:
 | 
				
			||||||
 | 
					        tokenise = tokenise[:-1]
 | 
				
			||||||
 | 
					    return tokenise
 | 
				
			||||||
							
								
								
									
										30
									
								
								syntax.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								syntax.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					## Work in Progress
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To create a comment, begin a line with a hash (#) symbol, like python.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create a string: `string name value bytes`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create a boolean: `bool name value`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Create an integer: `int name value`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Note**: A string of dynamic length can be created by setting the bytes to -1.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Print a string: `print name`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Increment an int: `inc name`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Check if two numbers are equal, and store the result in `cond`: `equal num1 num2 cond`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If statement: 
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					if bool
 | 
				
			||||||
 | 
					    # Code here
 | 
				
			||||||
 | 
					end if
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example program (prints "Hello, World"):
 | 
				
			||||||
 | 
					```py
 | 
				
			||||||
 | 
					string var 13 "Hello, world!" # Or -1 bytes for a dynamic string
 | 
				
			||||||
 | 
					print var
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										1
									
								
								test.bf
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								test.bf
									
									
									
									
									
								
							@@ -1 +0,0 @@
 | 
				
			|||||||
>>>>>>>>>>>>[[>>]>>]++++>+><<[[<<]<<]<<<<<<<<>>>>>>>>>>>>[[>>]>>]+++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++><<[[<<]<<]<<<<<<<<>>>>>>>>>>>>>[>+>+<<-]>[<+>-]>[-<<<[[<<]<<]+>>>>>>>]<<<<<<<[<<<<<<<<+>>>>>>>>-]<<<<<<<<[->>>>>>>>>>>>[>>]>>[-]>[-]><<+++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++><<[[<<]<<]<<<<<<<<]
 | 
					 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
create bool *1 = true
 | 
					 | 
				
			||||||
create string *1 = "A"
 | 
					 | 
				
			||||||
if bool {
 | 
					 | 
				
			||||||
    set string = "B"
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										13
									
								
								tests/test.basm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/test.basm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					int num1 796
 | 
				
			||||||
 | 
					string str1 -1 "Hello, world!"
 | 
				
			||||||
 | 
					int num2 795
 | 
				
			||||||
 | 
					string str2 -1 "World, hello?"
 | 
				
			||||||
 | 
					equal num1 num2 cond
 | 
				
			||||||
 | 
					if cond
 | 
				
			||||||
 | 
					    print str1
 | 
				
			||||||
 | 
					end if
 | 
				
			||||||
 | 
					inc num2
 | 
				
			||||||
 | 
					equal num1 num2 cond2
 | 
				
			||||||
 | 
					if cond2
 | 
				
			||||||
 | 
					    print str2
 | 
				
			||||||
 | 
					end if
 | 
				
			||||||
		Reference in New Issue
	
	Block a user