The purpose of this first, ungraded assignment is to get familiar with the language L3 and the existing code base of the L3 compiler and interpreter. Although the assignment itself is not graded, you should take it seriously, as it guides you through the L3 code base and it explains how to set up the tools that will make code development efficient. This assignment will require completing 5 steps:
- Set up the Infrastructure (as discussed in the Getting Started page)
- Provide the Desugaring Implementation for the L3 Compiler
- Provide Three Test Cases for the Desugaring
- Implement a Function in the L3 Library
- Submit the Assignment
The first step of this assignment is to set up your environment, as described in the Getting Started – Tools page. If you have any trouble installing the tools or running the virtual machine for the course ask the TA for help.
The next step is to decide on a group and announce it to the TA. Once the group is formed, you will be given access to a git repository where you will be able to store all your assignment files. The repostiory interface lets you add ssh keys to the interface, shows the latest commits, let you execute all tests (both public and private tests) and finally deliver a version for grading, once all tests pass.
So, go ahead and make groups of two students and let the TA know. When you have a group id, you can follow the instructions on the Getting Started – Repository page to clone the assignment source.
Now you should have cloned your repository and should have found an l3 directory. The compiler is located in l3/compiler.
$ cd acc2013-groupXX $ cd l3/compiler $ sbt compile $ sbt eclipse
After running sbt eclipse you should be able to load the project in Eclipse using File > Import… and General > Existing Projects into Workspace and point Eclipse to the l3 directory. It should load a project called l3-compiler.
Now, run the program examples/hello.l3 together with the provided L3 standard library. This can be done either using Eclipse, by indicating the main class l3.Main with the argument “../examples/hello.l3” or using sbt:
$ sbt "run ../examples/hello.l3" [info] Loading project definition from ... [info] Set current project to l3-compiler (in build file:...) [info] Running l3.Main ../examples/hello.l3 [error] (run-main) scala.NotImplementedError: an implementation is missing
You will notice that it fails with a “not yet implemented” runtime exception (with a long stacktrace). Your next task is to add the missing pieces to the syntactic sugar translation. Navigate to the bottom of file compiler/l3/L3Parser.scala. You will notice that some methods are implemented in terms of a ??? method, which throws a runtime exception. Rewrite those method bodies according to the rewrite rules on the slides shown in this week’s lecture.
Once you provided implementations for sBegin and sFun in src/l3/L3Parser.scala you should be able to run the hello.l3 example. Now implement all the other desugaring methods. Remeber that as you work you can also use the git repository for storing intermediate results. So when you reached a milestone, go ahead and commit the results, so your colleague can pick them up.
As you are developing the desugaring, it would be good to verify your implementation. For this assignment, you have tests that make sure your desugaring is correct. There are two categories of tests: whitebox testing, which verifies the trees you generate (L3DesugaringWhitebox.scala) and blackbox testing, which checks the output of running the compiled program (L3DesugaringBlackbox.scala). To run the tests, it is easiest to navigate to the l3.test package in the test/ directory and open up one of the files. Then from the Run menu select Run As > Scala JUnit Test. You can also use sbt:
$ sbt test [info] Test run started ... [error] Failed: : Total 21, Failed 3, Errors 0, Passed 18, Skipped 0 ...
Even with a perfect implementation the last three whitebox tests will fail. Your next task is to complete the test suite so all tests pass. To do this, have a look at methods testSAnd, testSOr and testSNot in test/l3/test/L3DesugaringWhitebox.scala. They contain ??? as the expected tree. Fill in the correct tree so the test suite passes. Maybe now is another good point to commit.
Once you are done with the desugaring and all tests pass, run printint.l3 and enter a number when asked to.
> run ../library/lib.l3 ../examples/printint.l3 [info] Running l3.Main ../library/lib.l3 ../examples/printint.l3 Enter a number: 12 You entered [success] Total time: 2 s, completed Feb 15, 2013 4:03:13 AM
You will notice that it cannot print the number you have entered: it is missing a library function int-print that accepts a number and prints it to the console. Your last task is to add the body of int-print in library/lib.l3 such that it prints the correct output. Make sure it prints a given number to the base of 10 and that it can handle negative numbers as well. Hint: implement it recursively in terms of char-print. Modify printint.l3 so that it prints the number you have entered and verify that it runs correctly.
At this point everything should be working: compiler code should be ready, tests should be passing and all examples should be running fine. Now it’s time to make a final git commit. You can assign any commit as a deliverable for the assignment and also run remote tests to confirm everything works correctly. Don’t worry about marking as deliverable and running tests — you can do it as many times as you need it, just make sure you have your best version marked as deliverable when the deadline comes. 🙂
Simple Build Tool performs a series of tasks for you:
- manages dependecies of your project (you will see it “downloading the Internet” the first time run it)
- compiles your project
- runs the main class of your project
- runs the test suite
- creates eclipse project files
- packages your project for submission
Sbt can work in two modes: as a command-line tool, invoked with
$ sbt <task>
and as a console:
$ sbt ... [info] Set current project to acc-1 (in build file:/...) > <task> ... >
Both the console and the command line have a series of common useful tasks:
- compile will compile your project
- run <args> will run the main class of your project
- eclipse create eclipse project files so you can import the project in Eclipse
- test run the test suite
- test-only <test> run a single test
- package create a jar file with the classes
- package-src creates a jar file with the source files
- update refreshes the dependencies (“downloads the Internet” again)
Preceeding any of the task with “~” (tilda, no quotes) will run the task each time you change a file:
$ sbt '~test-only my.Test' # quotes are necessary to prevent the shell from expanding ~ to /home/$USER ... 1. Waiting for source changes... (press enter to interrupt)
In order to work on the compiler in Eclipse you need to create the Eclipse project files. It is easiest to do using sbt:
$ sbt eclipse
Don’t worry about the errors shown by sbt — it is set to download source archives for all the projects the compiler depends on — and some of the source archives are not available, but this will not affect the Eclipse functionality.
To add the project in Eclipse, from the File menu, choose Import.. and then General > Existing Projects into Workspace. For the root directory, pick the directory where you unpacked the exercise sources. Eclipse should locate the l3-compiler project that sbt created and import it.
You can now build and run the L3 compiler / interpreter directly in Eclipse. For running (or debugging) create a new Run Configuration of type Scala Application and specify l3.Main as main class. You can specify a source file as the argument (../examples/hello.l3 is a good start) or leave the arguments empty so the compiler expects the source code to be entered in the console.
You can also run the test suite from within Eclipse. For the first assignment, you have two test suites:
- l3.test.L3DesugaringBlackbox tests the transformation based on running the resulting program
- l3.test.L3DesugaringWhitebox tests the trees that are output from your transformation
To run a test suite, you can use either sbt test or navigate to the test suite source file (in the test directory), open the test suite file and choose Run > Run as > Scala JUnit Test from the menu.
A good video on using Eclipse can be found on the ScalaIDE main page.