ECS 09 - Getting up and running.

The recommended first step in starting out on this project is to make sure that you will be able to successfully compile and run your program once you've written it. This has proven to be a bit of a challenge for some because of a few of subtle points regarding the tools. So hopefully this "guide" to getting the "Square" example project running will help.

The four steps (Step 0 through Step 3) for compiling and running a Jack Program are in section 9.5 of the text.

Follow them!

That concludes this guide. Have a nice day.

Seriously, though. While there are some subtle gotchas that we'll get to, most people that have had problems have not even read this section of the text and instead figured out by trial and error how to invoke the compiler but failed to copy the vm code for the operating system into the directory thinking (not unreasonably) that all of the files necessary to run the example project would have already been located in the example directory. Step 0 of the process explictly tells you how to do this. For the "Square" example project, simply copy them into the "\09\Square" directory.

Step 1 of the process is one that few people have difficulties with. Put all of your .jack source code files into the same directory as you put the OS .vm files. For the "Square" example project, this is already done for you, of course. One point to note when you start writing your own files -- you MUST have a file named "Main.jack" and, in turn, it MUST have a function named main() that takes no arguments and returns nothing (i.e., is a "void function").

Here is the first subtle point about Jack. In Section 9.2.6 of the text it states, "Thus, a class that implements a type must contain at least one constructor." It is easy to draw the conclusion that this means that every class has to have a constructor subroutine. Yet if you examine the Main class in the "Square" project, you will see that it has no constructor. What gives? The key is the phrase "that implements a type", meaning that you can instantiate objects of that class. If the particular class is not meant to ever have instantiated objects, then you don't need a constructor -- the term "constructor" was coined because it is a function that constructs and instance of an object of that class. An example of a class that wouldn't implement a type would be a utility class that consists of useful functions that only act on the data passed to them and, perhaps, maintains some class-wide data (but no instance data). As long as there is no data that is specific to a particular instance of a class, there is no need to ever cosntruct instances of that class. It should not be surprising to discover that if a class does not contain a constructor, it also cannot contain any methods (i.e., member functions), since methods have to be associated with a specific instance of that class.

So now we move on to Step 2, actually compiling the code. The instructions simply recommend that the supplied Jack compiler be applied to the program directory. That's fine, but no details of how to access the Jack compiler or how to apply it to a directory are provided. So let's take a look at that. Finding the Jack compiler isn't too difficult since it is located in the same directory that the other tools, such as the assembler and emulators are in. It is called JackCompiler.(bat|sh). Up to this point, you have been able to just run the batch file (or shell script) and it launched a GUI that you interacted with from there.

If you try to run the batch file (from this point on the discussion will be specific to the behavior on a Windows machine, though the behavior on Linux/Mac are likely very similar) it opens a command window, appears to try to do something, and then closes. Not very useful or informative. So let's open a command window and run the batch file from the command line and see what happens; at least then we should be able to see what it attempted to do and any messages that were output to the console. Assuming it ran, you probably saw what amounts to a spash screen and a couple of messages. The first says that usage instructions and tips can be found in the relevant book chapters. Well, that's certainly debatable; but the second message says that the usage is "java JackCompiler ". Thus we know that it is expecting a directory or filename supplied as a command line argument, which means that (short of having more information) we need to run the compiler from a command prompt.

But this brings up the question of where we run it from. Do we run it from the directory the compiler is located in and supply a path to the directory containing the project, or do we run it from the directory containing our project (i.e., the project's parent directory) by supplying a path to the compiler? Let's try it both ways.

In my case, I tried using a relative path to the project as follows:

c:\CSM\CSCI410\nand2tetris\tools>JackCompiler ..\..\work\09\Square

This worked just fine.

I then tried running it from the \work\09 directory as follows:

This produced the following result:

c:\CSM\CSCI410\work\09>..\..\nand2tetris\tools\JackCompiler Square
Could not find file or directory: Square


The key to why it failed is contained on the final line -- the directory has been changed to the directory that the compiler is located in. By looking at the JackCompiler.bat file, we see that before it runs the compiler, it issues the command cd %0\... The %0 is a batch file parameter (remember that we are talking Windows here) that is the name of the batch file that was run. The \.. then makes this refer to the directory in which this batch file is located. The reason this is done is because the JackCompiler (which is a Java program) needs to have this anchor in order for the Java Runtime Environment to be able to find its component parts. As a result, copying the bat file to your project's parent directory will not work.

So are we stuck with having to go to the \tools directory and run the compiler from there by supplying a path back to the project we want to compile? Yes and no. Yes, that is the effect that we have to produce, but no, we don't have to manually do it. We are computer scientists, after all, and we believe in being lazy and writing programs that do the grunt work for us when possible. So let's write our own batch file that we can run from our ECS project directory (the \09 directory, in this case) and have it work. Since we are lazy, let's give it a simple name such as jc.bat so that we can use it as follows:

c:\CSM\CSCI410\work\09>jc Square

Notice that after running the batch file we are left in the same directory we started. The batch file that accomplishes this is very simple:

@echo off
SET ECStools = C:\CSM\CSCI410\Nand2Tetris\tools
SET OriginalDirectory = %CD%
CALL %ECStools%\JackCompiler %OriginalDirectory%\%1
cd %OriginalDirectory%

The first SET stores the path to the compiler in an environment variable (that is only used in this batch file) while the second stores the current directory in another environment variable. The CALL invokes the compiler building up the same string that we previously typed manually. The final line changes the current directory back to the original directory.

If you wanted to, instead of copying this batch file into every directory that has Jack projects in it, you could put it someplace convenient (your own version of a "tools" directory) and add that directory to the Path environment variable. Then you can run it from anywhere.

That brings us to Step 3, the final step, actually running the program in the VM emulator. As you already know If you've already used this as part of ECS 07 and ECS 08, you launch it the same way you did prior tools such as the assembler and emulators, namely by double clicking on the batch file name in the \tools directory (Windows) to launch a GUI. To load the program you can either load a single .vm file or an entire directory. Since you need to load an entire directory, you need to be sure that you choose the directory and not one of the .vm files that's in that directory. Once loaded, if you run the program you will almost certainly discover that it is extremely slow, even if you move the speed bar all the way to Fast. The reason is that, by default, the emulator animates the program flow of the code. You want to set Animate to "No animation" and then run it. You also need to have the View set to "Screen", but this is the default. At this point you will likely find that you actually need to slow down the program, perhaps even all the way to Slow, to get something that is comfortable to interact with.

Blog entry information

Last update

More entries in General

More entries from WBahn

Share this entry