Make progress on compiler posts

This commit is contained in:
2019-10-26 20:30:29 -07:00
parent 65b9f385cf
commit 7812b1064b
27 changed files with 1431 additions and 4 deletions

View File

@@ -20,9 +20,9 @@ our own stack, and whenever a graph-building function will want to modify
the stack, it will have to call library routines for our stack implementation:
```C
void stack_push(struct stack_s* s, struct node_s* n);
struct node_s* stack_slide(struct stack_s* s, size_t c);
/* other stack operation */
void stack_push(struct stack* s, struct node_s* n);
struct node_s* stack_slide(struct stack* s, size_t c);
/* other stack operations */
```
Furthermore, we observe that Unwind does a lot of the heavy lifting in our
@@ -41,4 +41,28 @@ while(1) {
```
In this implementation, Unwind is in charge. We won't need to insert
the Unwind operations at the end of our generated functions.
the Unwind operations at the end of our generated functions, and you
may have noticed we've already been following this strategy in our
implementation of the G-machine compilation.
We can start working on an implementation of the runtime right now,
beginning with the nodes:
{{< codelines "C++" "compiler/07/runtime.c" 5 46 >}}
We have a variety of different nodes that can be on the stack, but without
the magic of C++'s `vtable` and RTTI, we have to take care of the bookkeeping
ourselves. We add an enum, `node_tag`, which we will use to indicate what
type of node we're looking at. We also add a "base class" `node_base`, which
contains the fields that all nodes must contain (only `tag` at the moment).
We then add to the beginning of each node struct a member of type
`node_base`. With this, a pointer to a node struct can be interpreted as a pointer
to `node_base`, which is our lowest common denominator. To go back, we
check the `tag` of `node_base`, and cast the pointer appropriately. This way,
we mimic inheritance, in a very basic manner.
We also add an `alloc_node`, which allocates a region of memory big enough
to be any node. We do this because we sometimes mutate nodes (replacing
expressions with the results of their evaluation), changing their type.
We then want to be able to change a node without reallocating memory.
Since the biggest node we have is `node_app`, that's the one we choose.