Finish readme and add pngs
This commit is contained in:
parent
01e43dfba0
commit
143301f3d4
99
README.md
99
README.md
@ -91,4 +91,103 @@ translate individual asm-files and does not search a directory.
|
||||
Load the resulting hack file into the CPU emulator to verify that the
|
||||
assembler works correctly.
|
||||
|
||||
## Project 7/8: VM Translator
|
||||
|
||||
At this point, we have finished the hardware part of our computer and can
|
||||
program it via the Hack assembly language. Of course, a higher-level programming
|
||||
language is desirable to write programs more comfortably. Therefore, our goal
|
||||
is to implement the high-level programming language *Jack* and compile it down
|
||||
into Hack assembly.
|
||||
|
||||
We use a two-step compilation process. First, we translate the Jack code into VM
|
||||
code, which we then translate further into Hack assembly. The goal of projects 7
|
||||
and 8 is to implement the VM translator in a programming language of our choice.
|
||||
Even though Python is my primary language, and I would have been faster using
|
||||
it, I decided to opt for Rust, a language that I hadn't used before. Rust comes
|
||||
with a flourishing eco-system and static typing that came in handy for this
|
||||
project.
|
||||
|
||||
My VM translator ended up with just under 900 lines of code. A considerable part
|
||||
of that is the template Hack assembly code that the translator fills with
|
||||
registers and addresses. I would have opted for the Jinja2 templating language
|
||||
in Python, but instead, I used in-code strings combined with "format!\". While
|
||||
this looks ugly at times, it avoids external dependencies. The approach is okay
|
||||
for this course, but a template engine would have been desirable for a
|
||||
real-world project.
|
||||
|
||||
To run the VM translator, switch into the `./vm_translator directory` and
|
||||
execute `cargo build`. You can then execute
|
||||
`./vm_translator/target/debug/vm_translator` on one of the example projects in
|
||||
`./projects/08`.
|
||||
|
||||
I was happy with my choice to learn Rust even though I spent too much time
|
||||
figuring out trivial things like how to read a file.
|
||||
|
||||
## Project 9: High-Level Language
|
||||
|
||||
With the VM translator in place, it is now time to understand the high-level
|
||||
Jack languaged by implementing a project. I decided to implement a 1D cellular
|
||||
automation in `./projects/09/CellAutomaton1D`. To run the program first compile
|
||||
the project by running `./tool/JackCompiler.sh ./projects/09/CellAutomaton1D`.
|
||||
Then, start the Virtual Machine Emulator and open the project. Make sure to
|
||||
select the directory `CellAutomaton1D` and not one of the VM files.
|
||||
|
||||
![A 1D cellular automaton on the Hack computer](gifs/automaton_drawing.png)
|
||||
|
||||
The program consists of two parts. First, you configure the initial population
|
||||
using Vim key bindings, and then the program simulates the selected rule. You
|
||||
have the option to pause and single step the simulation.
|
||||
|
||||
![The menu for the automaton](gifs/automaton_menu.png)
|
||||
|
||||
I have also implemented Vim syntax highlighting for the jack programming
|
||||
language. The best thing is that Vim yells at you when you forgot one of
|
||||
the keywords, like let or do. And you will forget them all the time.
|
||||
Simple put [jack.vim](vim/jack.vim) into your Vim's syntax
|
||||
directory, and you should be good to go.
|
||||
|
||||
![Jack syntax highlighting in Vim](gifs/vim_jack_syntax.png)
|
||||
|
||||
## Project 10/11: Compiler
|
||||
|
||||
With a solid understanding of the Jack programming language, we are now ready to
|
||||
implement the compiler. I opted for Rust again and had a great time. The
|
||||
directory `jack_analyzer` contains the tokenizer and parser, which outputs an
|
||||
XML syntax tree. In project 11, we use the analyzer to generate VM code. The
|
||||
resulting Rust project is in the directory `jack_compiler`. To compile the
|
||||
project, change into the directory and execute `cargo build`.
|
||||
|
||||
You can now recompile the cellular automaton by running the following command:
|
||||
|
||||
~~~
|
||||
./jack_compiler/target/debug/jack_compiler projects/09/CellAutomaton1D
|
||||
~~~
|
||||
|
||||
I honestly was happy with my decision to opt for Rust again. While the project
|
||||
would undoubtedly have been manageable in Python, static typing made it so much
|
||||
easier to cover all cases for keywords and tokens. The compiler has a little
|
||||
over 1000 lines of code. That sounds pretty decent.
|
||||
|
||||
![Number of source code lines for the compiler](gifs/compiler_loc.png)
|
||||
|
||||
## Project 12: The Operating System
|
||||
|
||||
With the compiler in place, the last step is implementing the OS functionality
|
||||
that previously came from the Virtual Machine Emulator. In particular, there is
|
||||
a library for string handling, memory management, array handling, math
|
||||
(multiplication and division), and display routines to draw characters and
|
||||
geometric forms.
|
||||
|
||||
I particularly enjoy seeing how much effort goes into simple routines like
|
||||
multiplication and division. Of course, as a high-level programmer, you take
|
||||
these operations for granted but getting into the details of how to implement
|
||||
them is rewarding. I still learned a lot, even for this last project.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Nand to Tetris is one of my favorite classes of all time. I highly recommend it
|
||||
to everybody who works in computer science and feels like they only partially
|
||||
understand how a computer works. I certainly got many new insights throughout
|
||||
the course, and I learned a new programming language, Rust, which I should use
|
||||
more often over Python.
|
||||
|
||||
|
BIN
gifs/automaton_drawing.png
Normal file
BIN
gifs/automaton_drawing.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
BIN
gifs/automaton_menu.png
Normal file
BIN
gifs/automaton_menu.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.0 KiB |
BIN
gifs/compiler_loc.png
Normal file
BIN
gifs/compiler_loc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
gifs/vim_jack_syntax.png
Normal file
BIN
gifs/vim_jack_syntax.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 54 KiB |
78
vim/jack.vim
Normal file
78
vim/jack.vim
Normal file
@ -0,0 +1,78 @@
|
||||
if exists("b:current_syntax")
|
||||
finish
|
||||
endif
|
||||
|
||||
syntax match jackError "\v^\s*[A-Za-z_]+"
|
||||
|
||||
syntax match jackIdentifier "\v<Math>"
|
||||
syntax match jackIdentifier "\v<String>"
|
||||
syntax match jackIdentifier "\v<Array>"
|
||||
syntax match jackIdentifier "\v<Output>"
|
||||
syntax match jackIdentifier "\v<Screen>"
|
||||
syntax match jackIdentifier "\v<Keyboard>"
|
||||
syntax match jackIdentifier "\v<Memory>"
|
||||
syntax match jackIdentifier "\v<Sys>"
|
||||
|
||||
syntax match jackKeyword "\v\s*<class>"
|
||||
syntax match jackFunction "\v\s*<constructor>"
|
||||
syntax match jackFunction "\v\s*<method>"
|
||||
syntax match jackFunction "\v\s*<function>"
|
||||
|
||||
syntax match jackType "\v<int>"
|
||||
syntax match jackType "\v<boolean>"
|
||||
syntax match jackType "\v<char>"
|
||||
syntax match jackType "\v<void>"
|
||||
|
||||
syntax match jackKeyword "\v\s*<var>"
|
||||
syntax match jackKeyword "\v\s*<static>"
|
||||
syntax match jackKeyword "\v\s*<field>"
|
||||
|
||||
syntax match jackConditional "\v\s*<let>"
|
||||
syntax match jackConditional "\v\s*<do>"
|
||||
syntax match jackConditional "\v\s*<if>"
|
||||
syntax match jackConditional "\v\s*<else>"
|
||||
syntax match jackConditional "\v\s*<while>"
|
||||
syntax match jackConditional "\v\s*<return>"
|
||||
|
||||
syntax match jackConstant "\v<true>"
|
||||
syntax match jackConstant "\v<false>"
|
||||
syntax match jackConstant "\v<null>"
|
||||
|
||||
syntax match jackKeyword "\v<this>"
|
||||
|
||||
syntax match jackOperator "\v\+"
|
||||
syntax match jackOperator "\v-"
|
||||
syntax match jackOperator "\v\*"
|
||||
syntax match jackOperator "\v/"
|
||||
syntax match jackOperator "\v\&"
|
||||
syntax match jackOperator "\v\|"
|
||||
syntax match jackOperator "\v\~"
|
||||
syntax match jackOperator "\v\<"
|
||||
syntax match jackOperator "\v\>"
|
||||
|
||||
syntax match jackNumber "\v<([1-9][0-9]*|[0-9])>"
|
||||
syntax region jackString start=/\v"/ skip=/\v\\./ end=/\v"/
|
||||
|
||||
syntax match jackTodo "\vTODO:?" contained
|
||||
syntax match jackTodo "\vFIXME:?" contained
|
||||
syntax match jackTodo "\vXXX:?" contained
|
||||
|
||||
syntax match jackComment "\v//.*$" contains=jackTodo
|
||||
syntax region jackComment start="\v/\*\*" end="\v\*/" contains=jackTodo
|
||||
syntax region jackComment start="\v/\*" end="\v\*/" contains=jackTodo
|
||||
|
||||
highlight link jackError Error
|
||||
highlight link jackIdentifier Identifier
|
||||
highlight link jackString String
|
||||
highlight link jackComment Comment
|
||||
highlight link jackTodo Todo
|
||||
highlight link jackFunction Function
|
||||
highlight link jackConditional Conditional
|
||||
highlight link jackType Type
|
||||
highlight link jackConstant Constant
|
||||
highlight link jackOperator Operator
|
||||
highlight link jackKeyword Keyword
|
||||
highlight link jackString String
|
||||
highlight link jackNumber Number
|
||||
|
||||
let b:current_syntax = "jack"
|
Loading…
Reference in New Issue
Block a user