Welcome to the last common assignment for the Amy compiler. At this point, we are finally done with the frontend: we have translated source programs to ASTs and have checked that all correctness conditions hold for our program. We are finally ready to generate code for our program. In our case the target language will be WebAssembly.
For simplicity, we will not use a browser, but execute the resulting WebAssembly bytecode directly using
p, it will generate four different files under the
p.watis the wasm output of the compiler in text format. You can use this representation to debug your generated code.
p.wasmis the binary output of the compiler. This is what
nodejswill use. To translate to the binary format, we use the
wat2wasmtool provided by the WebAssembly developers. For your convenience we have included it in the
bindirectory of the skeleton. Note that this tool performs a purely mechanical translation and thus its output (for instance,
p.wasm) corresponds to a binary representation of
To run the program, simply type
- After you install, run
npm install deasyncat the directory you plan to run
amyc, i.e. the toplevel directory of the compiler.
- Make sure the
wat2wasmexecutable is visible, i.e. it is in the system path or you are at the toplevel of the
WebAssembly and Amy
Look at this presentation for the main concepts of how to translate Amy programs to WebAssembly.
You can find the annotated compiler output to the concat example here.
The assignment code
The code for the assignment is divided into two directories:
wasm for the modelling of the WebAssembly framework, and
codegen for Amy-specific code generation. There is a lot of code here, but your task is only to implement code generation for Amy expressions within
wasm/Instructions.scalaprovides types that describe a subset of WebAssembly instructions. It also provides a type
Codeto describe sequences of instructions. You can chain multiple instructions or
Codeobjects together to generate a longer
wasm/Function.scaladescribes a wasm function.
LocalsHandleris an object which will create fresh indexes for local variables as needed.
Functioncontains a field called
- The only way to create a
Function.apply. Its last argument is a function from a
Code. The reason for this unusual choice is to make sure the Function object is instantiated with the number of local variables that will be requested from the LocalsHandler. To see how it is used, you can look in
codegen/Utils.scala(but you won't have to use it directly).
wasm/ModulePrinter.scaladescribe a wasm module, which you can think of as a set of functions and the corresponding module headers.
codegen/Utils.scalacontains a few utility functions (which you should use!) and implementations of the built-in functions of Amy. Use the built-ins as examples.
codegen/CodeGen.scalais the focus of the assignment. It contains code to translate Amy modules, functions and expressions to wasm code. It is a pipeline and returns a wasm Module.
codegen/CodePrinter.scalais a Pipeline which will print output files from the wasm module.
The cgExpr function
The focus of this assignment is the
cgExpr function, which takes an expression and generates a
Code object. It also takes two additional arguments: (1) a
LocalsHandler which you can use to get a new slot for a local when you encounter a local variable or you need a temporary variable for your computation. (2) a map
Identifiers to locals slots, i.e. indices, in the wasm world. For example, if
locals contains a pair
i → 4, we know that
get_local 4 in wasm will push the value of i to the stack. Notice how
locals is instantiated with the function parameters in
As usual, you can find the skeleton for this lab on Courseware. After merging it with your existing work, the structure of your project
src directory should be as follows:
amyc ├── Main.scala (updated) │ ├── analyzer │ ├── SymbolTable.scala │ ├── NameAnalyzer.scala │ └── TypeChecker.scala │ ├── ast │ ├── Identifier.scala │ ├── Printer.scala │ └── TreeModule.scala │ ├── codegen (new) │ ├── CodeGen.scala │ ├── CodePrinter.scala │ └── Utils.scala │ ├── parsing │ ├── ASTConstructor.scala │ ├── ASTConstructorLL1.scala │ ├── Parser.scala │ ├── Lexer.scala │ └── Tokens.scala │ ├── utils │ ├── AmycFatalError.scala │ ├── Context.scala │ ├── Document.scala │ ├── Pipeline.scala │ ├── Position.scala │ ├── Reporter.scala │ └── UniqueCounter.scala │ └── wasm (new) ├── Function.scala ├── Instructions.scala ├── ModulePrinter.scala └── Module.scala
You have four weeks to complete this assignment.
Deadline: Tuesday, December 18th, 23:59
Please use the Courseware interface to submit your solution and get some preliminary feedback from our automated tests.