Create variables

This commit is contained in:
2025-10-24 20:32:51 +11:00
parent 176c07151a
commit 9ad3bdbc92
6 changed files with 139 additions and 118 deletions

View File

@@ -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`

View File

@@ -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.

View File

@@ -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)
elif var.bytes == -1:
returnval += '<[<]'
else:
error()
returnval += '<[<]' + '<' * (offset-1)
return returnval
elif line[2] == 'false':
return '' return ''
else: else:
error(f'Invalid bool: {value}') error(f"Invalid bool: {line[2]}")
elif type == 1: elif keyword == 'string':
if value[0] == value[-1] == '"': if len(line) != 4:
value = value[1:-1] error(f'String command requires 3 arguments (got {len(line)-1})')
variables.append(Variable(name, bytes, bytesum, type))
returnval = '>' * offset + '[>]' + '>' * (bytesum + 1)
for i in range(bytes):
try: try:
returnval += '+' * ord(value[i]) + '>' variables.append(Variable(line[1], int(line[2]), 1))
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: except ValueError:
error(f'Invalid input index: {value[2:-1]}') error(f'Unexpected bytes for string: {line[2]}')
quit() returnval = '>' * offset + '[>]'
variables.append(Variable(name, bytes, bytesum, type)) for var in variables[:-1]:
returnval = '>' * (offset + validx) if var.bytes >= 0:
returnval += '[[>]' + '>' * (bytesum+1) + '+' + '<' * (bytesum+2) + '[<]<+' + '>' * (validx+2) + '-]' returnval += '>' * (var.bytes + 1)
returnval += '<[<]<[' + '>' * (validx+2) + '+<[<]<-]<<<' elif var.bytes == -1:
returnval += '>[>]'
return returnval
else: else:
error(f"Invalid string: {value}") error('Cannot have negative byte count (excluding -1)')
elif type == 2:
# I hate integers
error('Integers are not yet implemented')
else:
error(f"Type {type} not yet implemented")
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() error()
quit() returnval += '<[<]' + '<' * (offset-1)
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 keyword == 'int':
return '>' * offset + '[>]' + '>' * (var.startByte + 1) + '.>' * var.bytes + '<' * (var.startByte+var.bytes+2) + '[<]' + '<' * (offset - 1) 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: else:
error('Type not yet supported') error()
quit() 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: else:
error(f"Invalid token: {keyword}") error()
quit() returnval += '<[<]' + '<' * (offset-1)
return returnval
error()

View File

@@ -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}")

View File

@@ -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)

View File

@@ -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