Files
BrainAssembly/src/codegen.py

164 lines
5.4 KiB
Python
Raw Normal View History

2025-10-28 14:48:11 +11:00
from error import error, warn
2025-10-18 19:55:02 +11:00
import math as m
class Variable:
2025-10-24 20:32:51 +11:00
def __init__(self, name: str, bytes: int, type: int):
2025-10-18 19:55:02 +11:00
self.name: str = name
self.bytes: int = bytes
self.type: int = type
def __repr__(self) -> str:
2025-10-24 20:32:51 +11:00
return f"[{self.name}, {self.bytes}, {self.type}]"
2025-10-18 19:55:02 +11:00
variables: list[Variable] = []
bytesum: int = 0
bool = {
"true": 1,
"false": 0,
}
def generateCode(line: list[str], offset: int) -> str:
keyword = line[0]
2025-10-24 20:32:51 +11:00
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})')
2025-10-18 19:55:02 +11:00
try:
2025-10-24 20:32:51 +11:00
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 += '>[>]'
2025-10-18 19:55:02 +11:00
else:
2025-10-24 20:32:51 +11:00
error('Cannot have negative byte count (excluding -1)')
2025-10-20 10:38:15 +11:00
2025-10-24 20:32:51 +11:00
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) + '>'
2025-10-18 19:55:02 +11:00
else:
2025-10-24 20:32:51 +11:00
error(f'Invalid string: {line[3]}')
2025-10-18 19:55:02 +11:00
2025-10-24 20:32:51 +11:00
# 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)
2025-10-18 19:55:02 +11:00
2025-10-28 14:48:11 +11:00
return returnval
elif keyword == 'print':
if len(line) != 2:
error(f'Print command requires 1 argument (got {len(line)-1})')
returnval = '>' * offset + '[>]'
varnames = []
for var in variables:
varnames.append(var.name)
if line[1] in varnames:
idx = varnames.index(line[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')
2025-10-24 20:32:51 +11:00
return returnval
error()