Create variables
This commit is contained in:
@@ -1,18 +1,11 @@
|
|||||||
|
## Work in Progress
|
||||||
|
|
||||||
To create a comment, begin a line with a hash (#) symbol, like python.
|
To create a comment, begin a line with a hash (#) symbol, like python.
|
||||||
|
|
||||||
So far, the supported types are `bool` and `string`.
|
Create a string: `string name value bytes`
|
||||||
|
|
||||||
## create name type bytes value
|
Create a boolean: `bool name value`
|
||||||
|
|
||||||
Creates the variable "var" with a set number of bytes allocated to it, and initialises its value.
|
Create an integer: `int name value`
|
||||||
**IMPORTANT:** The number of bytes cannot be modified later.
|
|
||||||
|
|
||||||
Example: `create var bool 1 true`
|
**Note**: A string of dynamic length can be created by setting the bytes to -1.
|
||||||
|
|
||||||
To set a variable to an input byte, use: `create var string 1 i[idx]`.
|
|
||||||
|
|
||||||
## print var
|
|
||||||
|
|
||||||
Prints the value of `var` to the console, where `var` is a variable.
|
|
||||||
|
|
||||||
Example: `print var`
|
|
||||||
19
readme.md
19
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 our test programs.
|
||||||
196
src/codegen.py
196
src/codegen.py
@@ -2,115 +2,121 @@ from error import error
|
|||||||
import math as m
|
import math as m
|
||||||
|
|
||||||
class Variable:
|
class Variable:
|
||||||
def __init__(self, name: str, bytes: int, startByte: int, type: int):
|
def __init__(self, name: str, bytes: int, type: int):
|
||||||
self.name: str = name
|
self.name: str = name
|
||||||
self.bytes: int = bytes
|
self.bytes: int = bytes
|
||||||
self.startByte: int = startByte
|
|
||||||
self.type: int = type
|
self.type: int = type
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"[{self.name}, {self.bytes}, {self.startByte}, {self.type}]"
|
return f"[{self.name}, {self.bytes}, {self.type}]"
|
||||||
|
|
||||||
variables: list[Variable] = []
|
variables: list[Variable] = []
|
||||||
bytesum: int = 0
|
bytesum: int = 0
|
||||||
|
|
||||||
types = {
|
|
||||||
"bool": 0,
|
|
||||||
"string": 1,
|
|
||||||
"int": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
bool = {
|
bool = {
|
||||||
"true": 1,
|
"true": 1,
|
||||||
"false": 0,
|
"false": 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
def generateCode(line: list[str], offset: int) -> str:
|
def generateCode(line: list[str], offset: int) -> str:
|
||||||
try:
|
|
||||||
bytesum = variables[-1].startByte + variables[-1].bytes
|
|
||||||
except IndexError:
|
|
||||||
bytesum = 0
|
|
||||||
keyword = line[0]
|
keyword = line[0]
|
||||||
if keyword == 'create':
|
if keyword == 'bool':
|
||||||
if len(line) != 5:
|
if len(line) != 3:
|
||||||
error(f"Create command requires 4 arguments (got {len(line)-1})")
|
error(f'Bool command requires 2 arguments (got {len(line)-1})')
|
||||||
name = line[1]
|
variables.append(Variable(line[1], 1, 0))
|
||||||
try:
|
if line[2] == 'true':
|
||||||
type = types[line[2]]
|
returnval = '>' * offset + '[>]'
|
||||||
except KeyError:
|
for var in variables[:-1]:
|
||||||
error(f"Invalid type: {line[2]}")
|
if var.bytes >= 0:
|
||||||
quit()
|
returnval += '>' * (var.bytes+1)
|
||||||
bytes = int(line[3])
|
elif var.bytes == -1:
|
||||||
value = line[4]
|
returnval += '>[>]'
|
||||||
|
else:
|
||||||
if type == 0:
|
error()
|
||||||
variables.append(Variable(name, bytes, bytesum, type))
|
returnval += '>+<'
|
||||||
if (value == 'true'):
|
for var in reversed(variables[:-1]):
|
||||||
return '>' * offset + '[>]' + '>' * (bytesum + 1) + '+' + '<' * (bytesum + 1) + '<[<]' + '<' * (offset - 1)
|
if var.bytes >= 0:
|
||||||
elif (value == 'false'):
|
returnval += '<' * (var.bytes+1)
|
||||||
return ''
|
elif var.bytes == -1:
|
||||||
else:
|
returnval += '<[<]'
|
||||||
error(f'Invalid bool: {value}')
|
else:
|
||||||
elif type == 1:
|
error()
|
||||||
if value[0] == value[-1] == '"':
|
returnval += '<[<]' + '<' * (offset-1)
|
||||||
value = value[1:-1]
|
|
||||||
variables.append(Variable(name, bytes, bytesum, type))
|
|
||||||
returnval = '>' * offset + '[>]' + '>' * (bytesum + 1)
|
|
||||||
for i in range(bytes):
|
|
||||||
try:
|
|
||||||
returnval += '+' * ord(value[i]) + '>'
|
|
||||||
except IndexError:
|
|
||||||
returnval += '>'
|
|
||||||
returnval += '<' * (bytes+bytesum+2) + '[<]' + '<' * (offset - 1)
|
|
||||||
return returnval
|
|
||||||
elif (value[:2] == 'i[') & (value[-1] == ']'):
|
|
||||||
try:
|
|
||||||
validx: int = int(value[2:-1])
|
|
||||||
except ValueError:
|
|
||||||
error(f'Invalid input index: {value[2:-1]}')
|
|
||||||
quit()
|
|
||||||
variables.append(Variable(name, bytes, bytesum, type))
|
|
||||||
returnval = '>' * (offset + validx)
|
|
||||||
returnval += '[[>]' + '>' * (bytesum+1) + '+' + '<' * (bytesum+2) + '[<]<+' + '>' * (validx+2) + '-]'
|
|
||||||
returnval += '<[<]<[' + '>' * (validx+2) + '+<[<]<-]<<<'
|
|
||||||
|
|
||||||
return returnval
|
|
||||||
else:
|
|
||||||
error(f"Invalid string: {value}")
|
|
||||||
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()
|
|
||||||
|
|
||||||
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
|
return returnval
|
||||||
elif var.type == 1:
|
elif line[2] == 'false':
|
||||||
return '>' * offset + '[>]' + '>' * (var.startByte + 1) + '.>' * var.bytes + '<' * (var.startByte+var.bytes+2) + '[<]' + '<' * (offset - 1)
|
return ''
|
||||||
else:
|
else:
|
||||||
error('Type not yet supported')
|
error(f"Invalid bool: {line[2]}")
|
||||||
quit()
|
elif keyword == 'string':
|
||||||
else:
|
if len(line) != 4:
|
||||||
error(f"Invalid token: {keyword}")
|
error(f'String command requires 3 arguments (got {len(line)-1})')
|
||||||
quit()
|
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) + '>'
|
||||||
|
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 = int(line[2]) % 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:
|
||||||
|
returnval += '+' * 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
|
||||||
|
error()
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
def error(message: str = "This is a bugged error message. Please report this issue."):
|
def error(message: str = "This is a bugged error message. Please report this issue."):
|
||||||
exit(f"\033[91mError: \033[0m{message}")
|
exit(f"\033[91mError: \033[0m{message}")
|
||||||
|
|
||||||
|
def warn(message: str):
|
||||||
|
print(f"\033[33mWarning: {message}")
|
||||||
@@ -31,11 +31,7 @@ code = preprocess(content)
|
|||||||
offset: int = 5
|
offset: int = 5
|
||||||
bfcode: str = '>' * offset + ',[>,]<[<]' + '<' * (offset-1)
|
bfcode: str = '>' * offset + ',[>,]<[<]' + '<' * (offset-1)
|
||||||
|
|
||||||
def find(str: str, char: str):
|
open(argv[2], 'w').write('')
|
||||||
if (char in str):
|
|
||||||
return str.find(char)
|
|
||||||
else:
|
|
||||||
return len(str)
|
|
||||||
|
|
||||||
for line in code:
|
for line in code:
|
||||||
bfcode += generateCode(line, offset)
|
bfcode += generateCode(line, offset)
|
||||||
|
|||||||
@@ -1,2 +1,8 @@
|
|||||||
create i3 string 1 i[3]
|
bool var true
|
||||||
print i3
|
bool var2 false
|
||||||
|
string str1 -1 "Hell"
|
||||||
|
bool var3 true
|
||||||
|
int num1 -1736671613
|
||||||
|
int num2 9182364129
|
||||||
|
string str2 5 "World!"
|
||||||
|
bool var4 true
|
||||||
Reference in New Issue
Block a user