The purpose of this first, ungraded assignment is to get familiar with the L3 language 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 for the course ask the TAs for help.
The next step is to set up the git repository – see the Getting Started – Repository page. which will store all your assignment files. The repository interface lets you add ssh keys to the interface, show the latest commits, execute all tests (both public and private tests) and finally deliver a version for grading, once all tests pass.
The first two assignments are individual assignments. This means that for now you are only allowed to create groups of one person each (even if the repository allows you to create larger ones!). Later, when group assignments begin, you will be asked to merge groups with another person.
Note: The stubs for each assignment will be provided in a branch named AssignmentX. You should still submit commits with your master branch.
Now you should have cloned your repository and should have found a compiler directory:
$ cd acc2016-groupXX $ cd 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 acc2016-groupXX directory. It should load a project called l3-compiler, as described here.
Now, run the program examples/hello.l3. This can be done in two ways:
- using Eclipse (as described here), 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 implemented” error (with a long stacktrace). Your next task is to add the missing pieces to the syntactic sugar translation. Navigate to the bottom of file src/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.
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 tests, which verify the trees you generate (L3DesugaringWhitebox.scala) and blackbox tests, which check 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 ??? instead of the expected output. Fill in the correct tree so the test suite passes. Maybe now is another good time 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.ml3 ../examples/printint.l3 [info] Running l3.Main ../library/lib.ml3 ../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/integers.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 and int->char-digit. 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, local tests should be passing and all examples should be running fine. Now it’s time to make a final git commit.
You can test with the full test suite online, from the git repository. But keep in mind test tokens are not ulimited! Once the full test suite passes, you can mark the commit as a deliverable for the assignment. Don’t worry about marking as deliverable — you can do it as many times as you need it. 🙂
For more information on tests, test tokens and marking a commit as deliverable have a look at Getting Started – Repository.
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 you 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 will now need to specify that the project needs to be compiled with the Java 8 library. In the Package Explorer on the left, right-click on your project and go to Properties-> Java build path -> Add library -> JRE system library. Click on alternate JRE -> Installed JREs -> Add, and navigate to the home directory of your Java 8 installation.
You can now build and run the L3 compiler / interpreter directly in Eclipse. If you get errors regarding the econding of the source files while building the project, you have to make the project encoding as UTF-8 in the project properties -> resource menu. For running (or debugging) create a new Run Configuration of type Scala Application and specify l3.Main as main class. You have to specify one ore more source files as the arguments (../examples/hello.l3 is a good start).
You can also run the test suite from within Eclipse. For the first assignment, you have two test suites:
- l3.test.L3DesugaringWhitebox tests the trees that are output from your transformation
- l3.test.L3DesugaringBlackbox tests the transformation based on running the resulting program (blackbox test cannot be executed in Eclipse, only in sbt)
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.