Add finishing touches to code for part 6 of compiler series
This commit is contained in:
@@ -168,6 +168,10 @@ first define C++ structs for the instructions of the G-machine:
|
||||
|
||||
{{< codeblock "C++" "compiler/06/instruction.hpp" >}}
|
||||
|
||||
I omit the implementation of the various (trivial) `print` methods in this post;
|
||||
as always, you can look at the full project source code, which is
|
||||
freely available for each post in the series.
|
||||
|
||||
We can now envision a method on the `ast` struct that takes an environment
|
||||
(just like our compilation scheme takes the environment \\(\\rho\\\)),
|
||||
and compiles the `ast`. Rather than returning a vector
|
||||
@@ -282,7 +286,7 @@ struct, called `type_data`:
|
||||
|
||||
When we create types from `definition_data`, we tag the corresponding constructors:
|
||||
|
||||
{{< codelines "C++" "compiler/06/definition.cpp" 35 51 >}}
|
||||
{{< codelines "C++" "compiler/06/definition.cpp" 53 69 >}}
|
||||
|
||||
Ah, but adding constructor info to the type doesn't solve the problem.
|
||||
Once we performed type checking, we don't keep
|
||||
@@ -339,7 +343,7 @@ of a node. Here's a sample implementation from `ast_binop`:
|
||||
|
||||
And here's the implementation of `definition::resolve` on `definition_defn`:
|
||||
|
||||
{{< codelines "C++" "compiler/06/definition.cpp" 31 33 >}}
|
||||
{{< codelines "C++" "compiler/06/definition.cpp" 32 42 >}}
|
||||
|
||||
Finally, we call `resolve` at the end `typecheck_program` in `main.cpp`:
|
||||
|
||||
@@ -348,7 +352,7 @@ Finally, we call `resolve` at the end `typecheck_program` in `main.cpp`:
|
||||
At last, we're ready to implement the code for compiling `ast_case`.
|
||||
Here it is, in all its glory:
|
||||
|
||||
{{< codelines "C++" "compiler/06/ast.cpp" 178 224 >}}
|
||||
{{< codelines "C++" "compiler/06/ast.cpp" 178 230 >}}
|
||||
|
||||
There's a lot to unpack here. First of all, just like we said in the compilation
|
||||
scheme, we want to build and evaluate the expression that's being analyzed.
|
||||
@@ -399,4 +403,51 @@ After we're done with all the branches, we also check for non-exhaustive pattern
|
||||
since otherwise we could run into runtime errors. With this, the case expression,
|
||||
and the last of the AST nodes, can be compiled.
|
||||
|
||||
We also add a `compile` method to definitions, since they contain
|
||||
our AST nodes. The method is empty for `defn_data`, and
|
||||
looks as follows for `definition_defn`:
|
||||
|
||||
{{< codelines "C++" "compiler/06/definition.cpp" 44 51 >}}
|
||||
|
||||
Finally, we make a function in our `main.cpp` file to compile
|
||||
all the definitions:
|
||||
|
||||
{{< codelines "C++" "compiler/06/main.cpp" 45 56 >}}
|
||||
|
||||
In this method, we also include some extra
|
||||
output to help us see the result of our compilation. Since
|
||||
at the moment, only the `definition_defn` program has to
|
||||
be compiled, we try cast all definitions to it, and if
|
||||
we succeed, we print them out.
|
||||
|
||||
Let's try it all out! For the below sample program:
|
||||
|
||||
{{< rawblock "compiler/06/examples/works1.txt" >}}
|
||||
|
||||
Our compiler produces the following new output:
|
||||
```
|
||||
PushInt(6)
|
||||
PushInt(320)
|
||||
PushGlobal(plus)
|
||||
MkApp()
|
||||
MkApp()
|
||||
|
||||
Push(1)
|
||||
Push(1)
|
||||
PushGlobal(+)
|
||||
MkApp()
|
||||
MkApp()
|
||||
```
|
||||
|
||||
The first sequence of instructions is clearly `main`. It creates
|
||||
an application of `plus` to `320`, and then applies that to
|
||||
`6`, which results in `plus 320 6`, which is correct. The
|
||||
second sequence of instruction pushes the parameter that
|
||||
sits on offset 1 from the top of the stack (`y`). It then
|
||||
pushes a parameter from the same offset again, but this time,
|
||||
since `y` was previously pushed on the stack, `x` is now
|
||||
in that position, so `x` is pushed onto the stack.
|
||||
Finally, `+` is pushed, and the application
|
||||
`(+) x y` is created, which is equivalent to `x+y`.
|
||||
|
||||
{{< todo >}}Backport bugfix in case's typecheck{{< /todo >}}
|
||||
|
||||
Reference in New Issue
Block a user