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. 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. 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. **IMPORTANT:** The number of bytes cannot be modified later.
Example: `create var *5 = "Hello"` Example: `create var bool 1 true`
## print var ## print var
Prints the value of `var` to the console, where `var` is a variable. Prints the value of `var` to the console, where `var` is a variable.
Example: `print var` 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
}
```

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): def error(message: str = "This is a bugged error message. Please report this issue."):
print(f"\033[91mError: \033[0m{message}") exit(f"\033[91mError: \033[0m{message}")
quit()

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 | # Note: cells in bf are | 0 | inputs | 0 | variables |
from sys import argv from sys import argv
from preprocess import preprocess from preprocess import preprocess
from eval import eval
from error import error from error import error
from codegen import generateCode
if (len(argv) < 3): if (len(argv) < 3):
print(f"Usage: python {argv[0]} file.basm file.bf") 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 # Pre-processing of the basm file, from preprocess.py
code = preprocess(content) code = preprocess(content)
# Variables and references offset: int = 5
bfcode: str = '>' * offset + ',[>,]<[<]' + '<' * (offset-1)
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
}
def find(str: str, char: str): def find(str: str, char: str):
if (char in str): if (char in str):
@@ -67,61 +37,9 @@ def find(str: str, char: str):
else: else:
return len(str) return len(str)
# Main loop print(code)
for line in code: for line in code:
keyword: str = line.keyword bfcode += generateCode(line, offset)
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 with open(argv[2], 'w') as f:
if ':' in keyword: print(f"{f.write(bfcode)} characters successfully compiled!")
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])

View File

@@ -1,45 +1,31 @@
class Line: def preprocess(code: str) -> list[list[str]]:
def __init__(self, keyword: str, argument: str): token : str = ''
self.keyword: str = keyword tokenise : list[list[str]] = [[]]
self.argument: str = argument
def preprocess(code: str) -> list[Line]:
token : str = ""
keyword : str = ""
tokenise : list[Line] = []
isString : bool = False isString : bool = False
isComment : bool = False isComment : bool = False
isKeyword : bool = True
for i in code: for i in code:
if i == "\n": if i == '\n':
isComment = False isComment = False
elif i == "#": if tokenise[-1] != []:
isComment = True if token != '':
tokenise[-1].append(token)
tokenise.append([])
token = ''
elif isComment: elif isComment:
pass pass
elif i == '"': elif i == '#':
isString = not(isString) isComment = True
elif (i != ' ') | isString:
token += i token += i
elif isString: if (i == '\"'):
token += i isString = not(isString)
elif (i == ';') | (i == '{') | (i == '}'): else:
if i != ';': tokenise[-1].append(token)
token += i
tokenise.append(Line(keyword, token))
token = '' token = ''
keyword = ''
isKeyword = True
elif (i != ' '):
if (i == '('):
isKeyword = False
if isKeyword: if token != '':
keyword += i tokenise[-1].append(token)
else: token = ''
token += i if tokenise[-1] == []:
tokenise = tokenise[:-1]
if (i == '='):
isKeyword = False
tokenise.append(Line(keyword, token))
return tokenise return tokenise

View File

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

View File

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