Start of redesign

This commit is contained in:
2025-10-18 19:55:02 +11:00
parent c98f248245
commit 5fa47dc377
12 changed files with 140 additions and 202 deletions

View File

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

Binary file not shown.

Binary file not shown.

98
src/codegen.py Normal file
View 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()

View File

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

View File

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

View File

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

View File

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

View File

@@ -1 +1 @@
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
>>>>>,[>,]<[<]<<<<>>>>>[>]>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++><<<<<<<[<]<<<<>>>>>[>]>>>>>>+<<<<<<<[<]<<<<>>>>>[>]>>>>>>[<<<<<<<[<]<+<+>>>[>]>>>>>>-]<<<<<<<[<]<[>>[>]>>>>>>+<<<<<<<[<]<-]+<[>-<+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.--.+++.----------------.[-]]>[+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.-----.+++++++++++.+++++++.--------------.[-]]<<<

View File

@@ -1,2 +1,3 @@
var: str *7 = "Hello";
var2: str *5 = "World";
create str string 5 Hello
create var bool 1 true
print var