Make sure you have the following installed:
npm install
cd server
node index.js
program.wkt
)make program.wat
(optional)make program.wasm
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.
wat/ast.rkt
watexamples/
directory)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.
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:
i32
. Practically, this isn't an issue, since indexing must start at 0, but it's
simply another thing to keep in mind.cdr
and is followed by the car
8 bytes later.StoreHeap
struct requires the address to be on WASM's stack beforehand. This is so the car
and cdr
can be
stored right next to each other in memory.