Laboratory assignment · 1 October

Lab 8: VM Translator, Part II

Extend the Project 7 translator into a full VM-to-Hack translator by adding program flow, function calling, return handling, multi-file translation, and bootstrap code.

Back to course home

Objective and contract

Complete the VM translator

Retain every Project 7 feature and add the remaining VM commands.

Contract

Translate complete VM programs into Hack assembly

The generated assembly must conform to the VM specification and produce the results required by the supplied CPU-emulator tests and compare files.

Extend
The Python VMTranslator.py developed for Project 7.
Add
label, goto, if-goto, function, call, and return.
File input
Translate one Xxx.vm file into one Xxx.asm file.
Directory input
Translate every .vm file in directory Xxx into one combined Xxx.asm program.

Implementation plan

Build it in two stages

Unit-test program flow before adding stack frames and function calls.

Stage I

Program flow

Implement the VM branching commands:

  • label labelName
  • goto labelName
  • if-goto labelName

Ensure labels are scoped so that identically named labels in different functions do not collide.

Stage II

Functions and bootstrap

Implement:

  • function functionName nVars
  • call functionName nArgs
  • return
  • Translation of all .vm files in one directory
  • Bootstrap code that sets SP=256 and calls Sys.init

Test programs

Follow the supplied test progression

Each test isolates a new layer of translator behavior.

Program flow

BasicLoop

Computes 1+2+...+n and pushes the result. Tests goto and if-goto.

Program flow

FibonacciSeries

Stores the first n Fibonacci numbers in memory. This is the more demanding branching and array-access test.

Functions

SimpleFunction

Performs a calculation and returns the result. It is the first focused test of function and return.

Functions and bootstrap

FibonacciElement

A full recursive-call test. Compile the entire directory containing Main.vm and Sys.vm into one FibonacciElement.asm file.

Statics and multi-file input

StaticsTest

Tests static variables belonging to different VM files. Compile the entire directory into one StaticsTest.asm file.

Do not translate the files in a multi-file program separately. FibonacciElement and StaticsTest must each produce one combined assembly file from the complete directory.

Function-call state

What the generated assembly must preserve

A function call must be able to return to the caller with its memory-segment view restored.

On call

Create the callee's frame

  • Push a unique return address.
  • Save the caller's LCL, ARG, THIS, and THAT.
  • Reposition ARG for the callee's arguments.
  • Set LCL=SP and jump to the called function.
On return

Restore the caller's frame

  • Recover the return address from the current frame.
  • Move the return value to argument 0.
  • Restore SP immediately above the return value.
  • Restore THAT, THIS, ARG, and LCL, then jump to the return address.

Initialization

Know when bootstrap code is expected

The tests deliberately introduce bootstrap responsibilities gradually.

First three
BasicLoop, FibonacciSeries, and SimpleFunction use test scripts that manually provide the initialization they need.
Last two
FibonacciElement and StaticsTest expect your generated program to contain bootstrap code.
Bootstrap
Set SP to 256 and generate the equivalent of call Sys.init 0.

Testing and debugging

Test every stage before continuing

Use the VM emulator to understand behavior and the CPU emulator to test generated assembly.

For each test program

  1. Run the program in the VM emulator with XxxVME.tst to understand its intended behavior.
  2. Translate the required .vm file—or the complete directory for a multi-file program—into one .asm file.
  3. Inspect the generated assembly for syntax, label-scope, stack-frame, and control-flow errors.
  4. Run the assembly on the CPU emulator using Xxx.tst.
  5. Compare the result with Xxx.cmp. Correct the translator and regenerate the assembly if the test fails.

Implement in the supplied order. Later programs depend on earlier features, so skipping directly to recursion or multi-file translation makes failures much harder to diagnose.