I have recently started back up work on a compiler concept I’ve had for a while. A good example for the idea is seabass. My idea was to simply expand upon that, what is the most efficient way to make such a thing? Anyways checkout the markdown files in the repo on both branches to get a sort of understanding of it, due to recent circumstances I have mostly lost the design doc for it but the tl;dr is how do we make it easier to transform a language into an extension of the user? I’ve found that the easiest way to answer this is to try shit untill it works, this was a problem in the development of seabass where the author was doing more theory work than actual work
We can create entirely new behavior for the language like so
#lexer,add{
atok async
grammarFunc:
"async" :: tok "" async
}
ATTRIB(threaded)
HOOK(async) {
addattrib CURRENT_NODE threaded
validCases FN_NODE
}
codegen(FN_NODE,threaded) -> // as you can imagine just spits IR code to create a new thread, im too lazy to actually write that for an example
There’s another language I know called Racket that I’ve been meaning to learn which lets its users change the language to match the task you want to perform or problem that you want to solve. You might be able to glean something from looking at that compiler. I don’t know much about how it works myself.
I also decided to write both a brainfuck interpreter and transpiler in fien for funzies
Brainfuck interpreter for fun
#lexer,replace {
atok left
atok right
atok inc
atok dec
atok lbrack
atok rbrack
atok get
atok put
grammarFunc:
"<" :: tok "" left
">" :: tok "" right
"+" :: tok "" inc
"-" :: tok "" dec
"[" :: tok "" lbrack
"]" :: tok "" rbrack
"." :: tok "" put
"," :: tok "" get
}
let bytes:[30000] i8;
let index:int = 0;
HOOK(left) {
if index == 0 {
ret
}
index -= 1
}
HOOK(right) {
if index == 0 {
ret
}
index += 1
}
HOOK(inc) {
bytes[index] += 1
}
HOOK(dec) {
bytes[index] -= 1
}
HOOK(rbrack) {
if bytes[index] != 0 {
jmpback lbrack
}
}
HOOK(put) {
print bytes[index]
}
hook(get) {
bytes[index] = input
}
Brainfuck transpiler in fien
#lexer,replace {
atok left
atok right
atok inc
atok dec
atok lbrack
atok rbrack
atok get
atok put
grammarFunc:
"<" :: tok "" left
">" :: tok "" right
"+" :: tok "" inc
"-" :: tok "" dec
"[" :: tok "" lbrack
"]" :: tok "" rbrack
"." :: tok "" put
"," :: tok "" get
}
HOOK(left) {
addnode instruction left
}
HOOK(right) {
addnode instruction right
}
HOOK(inc) {
addnode instruction inc
}
HOOK(dec) {
addnode instruction dec
}
HOOK(lbrack) {
addnode container lbrack
}
HOOK(rbrack) {
stopContaining
addnode symbol rbrack
}
HOOK(put) {
addnode instruction print
}
hook(get) {
addnode(instruction,get)
}
fn codegen (tree:AST) -> string {
let output:String =
"int i = 0;
int[30000] p = {0};
void main () {\n"
let next_node:Node = tree.rootNode;
while next_node != null {
match next_node.attributes[0] {
left {
concat_str output "i--;\n"
}
right {
concat_str output "i++;\n"
}
inc {
concat_str output "p[i]++;\n"
}
dec {
concat_str output "p[i]--;\n"
}
lbrack {
concat_str output "while (p[i] != 0) {\n
}
rbrack {
concat_str output "}\n"
}
default {}
}
next_node = next_node.child
}
concat_str output "}"
ret output
}