- Get everything installed (see this section)
- Write your program in program.wkt
- Run make
- Start your server (see Getting Server Running)
- Click the run button, or enter input (for readbyte programs) and then click run
- The output of the program should display under the run button
Make sure you have the following installed:
- racket
- WABT (see this section below)
- node/npm
npm install
cd server
node index.js
- navigate to http://localhost:3000
- Write some wacket (for example, into
program.wkt
) make program.wat
(optional)make program.wasm
- In the frontend, enter any input and click
Run
.
Run make tests/{folder}/{number}.wasm
to compile to main.wasm
in the server/
folder, which can then be run
from the frontend.
Kind of error | What it means | Who is most likely responsible |
---|---|---|
Compile errors that start with read: |
wacket syntax error | programmer |
Compile errors that start with WAT parse error: |
compiler has generated a poorly formed wat AST, or the pretty printer is non-comprehensive | compiler writer |
Compile errors that include contract violation (or other racket errors) |
compiler has an error in it | compiler writer |
Compile errors that cite .wat files (eg: ....wat:20:10: error: ) |
wat generated by the pretty printer is malformed | compiler writer |
Runtime errors (the frontend says RUNTIME ERROR ) |
the wacket code written has some error in it | programmer |
JavaScript runtime errors, that don't say RUNTIME ERROR in the frontend |
the wasm code generated an unexpected runtime error | compiler writer |
We need to write to .wat
which is the WebAssembly Text format. From there we can use wat2wasm to turn that into the actual assembly code which can run in the browser.
- find the ast for our representation at the bottom of the readme, or in
wat/ast.rkt
- wat boolean representation
- true: 1 (i32)
- false: 0 (i32)
- Understanding WebAssembly text format
- Info on Text Format from the WebAssembly GitHub repo (this gets very spec-y)
- WebAssembly Spec PDF (contains the same information as the link above, but is useful because ctrl-F works over all the subpages)
- wat s-expression-syntax
- wat examples (see also our own
watexamples/
directory)
- Info from Mozilla
- WABT: The WebAssembly Binary Toolkit
- Think of this as our version of nasm
- Can install from a package manager (e.g.
sudo apt install wabt
)
Our runtime system is written in JavaScript, which can interface with compiled WASM bidirectionally. There is a minimal HTML file to act as an interface to the runtime system. This must be exposed to localhost with a web server, because modern browsers don't allow for accessing arbitrary files in the filesystem.
We'll be aiming to implement all the features present in Loot, the reduced version of Racket created in class already. This should allow for the re-use of much of the compiler infrastructure, like the lexer, parser, and AST.
They start with #lang wacket
. This caused my syntax checker to tell me:
standard-module-name-resolver: collection not found
for module path: wacket/lang/reader
collection: "wacket/lang"
in collection directories:
/home/chris/.racket/8.4/collects
/usr/share/racket/collects/
To fix this problem, I navigated to /usr/share/racket/collects/
and ran the command sudo ln -s racket/ wacket
.
This tricks the syntax checker because it looks at /usr/share/racket/collects/wacket
, but it's really just a symbolic link to /usr/share/racket/collects/racket
.
Alternatively, your syntax checker may fail to do anything at all, because of the unrecognized .wkt
file extension.
- Case
- Cond
- Pattern Matching
- Tail recursion
- Lambdas with arbitrary signatures
- update the wat AST in the README to reflect more recent changes
- More detailed RTS printing for heap structures
- Arity checking
- Pretty printer
- Makefile
- Integers
- Prim1
- If
- types
- Cons
- Box
- Prim2
- Functions
- Lets
- Prim0
- IO
- Strings
- Vectors
- Lambdas with one argument
Note: [list of Things] may be empty in this representation.
Note 2: This is not up to date. See
wat/ast.rkt
for the most up to date AST.
type Module = (Module [list of Definitions])
type Definition = Import
| Export
| Func
| Start
type Start = (Start funcname)
;; imports have a 2 level namespace: module then function
type Import = (Import modulename funcname FuncSignature)
;; name is what the RTS will see, ExportFuncSignature is what we use internally
type Export = (Export name ExportFuncSignature)
type ExportFuncSignature = (ExportFuncSignature name)
type Func = (Func FuncSignature [list of Locals] Body)
type FuncSignature = (FuncSignature name? [list of Params] Result?)
type Param = (Param name? Type)
type Result = (Result Type)
type Local = (Local name? Type)
type Type = i32
| i64
| f32
| f64
type Body = (Body [list of Instructions])
type Instruction = (Inst name [list of Instructions])
| Const
type Const = (Const v)
An instance of memory in WASM is allocated in blocks of 64KB of storage, so a single block should be more than enough for Wacket.
I found this article to have
the best (and really only) example of manipulating memory in .wat
files.
Instead of rbx
, we will use the global variable defined by heap-name
to store the next available address on the
heap. This is a global variable with the internal name generated by (gensym 'heap)
.
Some specifics to note:
- Addressing must be done with
i32
. Practically, this isn't an issue, since indexing must start at 0, but it's simply another thing to keep in mind. - Becuase the heap is a byte array, each value still occupies 8 "positions" on the heap, so we need to increment the heap pointer by 8 each time. This means the logic is actually pretty much the same as in racket.
- Just like in class, the cons cell starts with the
cdr
and is followed by thecar
8 bytes later. - The
StoreHeap
struct requires the address to be on WASM's stack beforehand. This is so thecar
andcdr
can be stored right next to each other in memory.