diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-29 11:09:25 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-29 11:09:25 +0200 |
commit | ba000c3e4589298bd62d91c7e42dbcf83c2b98e4 (patch) | |
tree | ae47e9f275f3187040074977db36fe7154da60fe | |
parent | c934ceda5e5a8f9d706b1f4e31f343e293e24f6d (diff) | |
download | bdl-ba000c3e4589298bd62d91c7e42dbcf83c2b98e4.tar.gz bdl-ba000c3e4589298bd62d91c7e42dbcf83c2b98e4.zip |
Update README
-rwxr-xr-x | README.md | 92 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 3 |
2 files changed, 63 insertions, 32 deletions
@@ -4,35 +4,69 @@ For some time I've been meaning to learn more about compilers and programming | |||
4 | language theory. And so I found myself again delving into a rabbit hole of | 4 | language theory. And so I found myself again delving into a rabbit hole of |
5 | wheel-reinvention for the purpose of fun and learning. | 5 | wheel-reinvention for the purpose of fun and learning. |
6 | 6 | ||
7 | The goals for this project are to build a programming language that can be | 7 | The language, `bdl` is inspired by `Scheme`, but it doesn't aim to be compatible |
8 | interpreted directly from a VM and with support for compilation to assembly | 8 | with it grammatically or in terms of behaviour. Instead, the core language is |
9 | (`x86_64` and/or `ARM (thumb or aarch64)`). It could make sense to output | 9 | much smaller and we will grow it organically as needed. As such, it is heavily |
10 | bytecode for LLVM to take advantage of the built in optimizations, but let's | 10 | in flux and not ready for any kind of production usage. |
11 | just go one step at a time. At the time I know some ARM assembly, but I'm not so | 11 | |
12 | versed in `x86_64` and know nothing of LLVM bytecode. | 12 | Currently `bdl` conforms with the grammar described below. It is a dynamically |
13 | 13 | typed language, garbage collected and supports lambdas, lexical scopes and | |
14 | I've chosen to implement a Lisp, perhaps a subset of Scheme. The syntax is not | 14 | closures. |
15 | so important for now, maybe in the future the compiler will take a different | 15 | |
16 | home-brew language, but hopefully this helps setting the fundamentals for | 16 | Up to [v0.7][v0.7] we were building a fully functional tree-walking interpreter. |
17 | a minimal working compiler. In principle, we could keep the internal | 17 | A writeup for the different building blocks can be found in [a series of |
18 | representation and language working as a lisp, but with a different external | 18 | articles][bdl-series] that go into great detail about the implementation and |
19 | syntax. | 19 | basic concepts behind the language. |
20 | 20 | ||
21 | The language should have built-in structures for dynamic arrays, hash tables, | 21 | From [v0.7][v0.7] to [v0.8][v0.8], we created a second interpreter |
22 | strings (and string views). It should be suitable for use in embedded systems | 22 | implementation. It was built by following along the second part of the [Crafting |
23 | and be linked seamlessly with other compiled objects. | 23 | Interpreters][crafting-interpreters] book. This reimagining of the project uses |
24 | 24 | a single-pass compiler to generate bytecode for an custom abstract virtual | |
25 | Accessing system resources, such as stdio or graphics could be done via function | 25 | machine. This interpreter is much faster than the tree-walking version and still |
26 | calls to the give APIs. This should help decouple the CPU logic from hardware, | 26 | supports closures, but it has no garbage collector and leaks memory. It was |
27 | hopefully facilitating porting programs to different platforms (GBA, Rasberry | 27 | a good learning exercise but the VM is too abstracted for my taste and I don't |
28 | Pi, etc.). | 28 | wish to maintain a half-baked implementation. |
29 | 29 | ||
30 | The current plan is to build a bootstrap interpreter in C that can be used to | 30 | Current development focuses on building from the fundamentals of previous |
31 | generate the self-hosted version of itself. I'll try to document the process | 31 | iterations to create a native compiler that could be used with multiple backends |
32 | here as best as I can. | 32 | for code generation (e.g. `LLVM`, `x86_64`/`aarch64` assembly, `uxn` bytecode, |
33 | 33 | etc.). One of the goals of this part is to have trivial `C` interop when | |
34 | The bootstrap implementation should be kept simple, since we can focus on | 34 | compiled natively, meaning it should be possible to call `bdl` code from `C` and |
35 | optimization once we have a self-hosting compiler. | 35 | `C` functions from `bdl` (though some wrappers may be necessary). |
36 | |||
37 | [bdl-series]: https://git.badd10de.dev/bdl/tag/?h=v0.7 | ||
38 | [v0.7]: https://git.badd10de.dev/bdl/tag/?h=v0.7 | ||
39 | [v0.8]: https://git.badd10de.dev/bdl/tag/?h=v0.8 | ||
40 | |||
41 | # Grammar | ||
42 | |||
43 | ``` | ||
44 | program : <statement>* EOF | ||
45 | |||
46 | <statement> : <definition> | <expression> | ||
47 | |||
48 | <definition> : ( def <symbol> <expression> ) | ||
49 | | ( fun ( <symbol>* ) <body> ) | ||
50 | ; | ||
51 | |||
52 | <expression> : <constant> | ||
53 | | ( lambda ( <symbol>* ) <body> ) | ||
54 | | ( if <expression> <expression> <expression> ) | ||
55 | | ( if <expression> <expression> ) | ||
56 | | ( set! <symbol> <expression> ) | ||
57 | | ( <expression> <expression>* ) | ||
58 | ; | ||
59 | |||
60 | <body> : <statement>* | ||
61 | |||
62 | <constant> : <bool> | <number> | <string> | <symbol> | ||
63 | |||
64 | <bool> : true | false | ||
65 | <number> : -?<digit>+ | ||
66 | <string> : " <character>+ " | ||
67 | <digit> : 0 | 1 | ... | 9 | ||
68 | <symbol> : <character>+ | ||
69 | ``` | ||
36 | 70 | ||
37 | # Resources | 71 | # Resources |
38 | 72 | ||
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 2e1c85b..d363958 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -14,9 +14,6 @@ | |||
14 | typedef struct CallFrame { | 14 | typedef struct CallFrame { |
15 | // Current code being run. | 15 | // Current code being run. |
16 | Closure *closure; | 16 | Closure *closure; |
17 | // Current program counter for this call. | ||
18 | // Ref to stack. Is this really needed? | ||
19 | // Object *locals; | ||
20 | // Return counter. | 17 | // Return counter. |
21 | u8 *rp; | 18 | u8 *rp; |
22 | // Starting point of the locals for this procedure. | 19 | // Starting point of the locals for this procedure. |