You may do this assignment in OCaml, Python, JavaScript, Haskell or Ruby. You must use be graded on a different language for each of PA2 - PA5.
You may work in a team of two people for this assignment. You may work in a team for any or all subsequent programming assignments. You do not need to keep the same teammate. The course staff are not responsible for finding you a willing teammate. However, you must still satisfy the language breadth requirement (i.e., you must be graded on a different language for each of PA2 - PA5).
You will also write additional code to unserialize the AST produced by the parser stage and to serialize the class map, implementation map, parent map, and annotated AST produced by your semantic analysis.
class Main inherits IO { main() : Object { out_string("Hello, world.\n" + 16777216) -- adding string + int !? } ; } ;
Example error report output:
ERROR: 3: Type-Check: arithmetic on String Int instead of Ints
Semantic checks are unordered — if a program contains two or more errors, you may indicate whichever you like. You can infer from this that all of our test cases will contain at most one error.
A .cl-type file consists of four sections:
Simply output the four sections in order, one after the other.
We will now describe exactly what to output for the class and implementation maps. The general idea and notation (one string per line, recursive descent) are the same as in PA3.
Note that you must output information about all classes and methods defined in the program as well as all base classes (and their methods). Do not just print out "classes actually used" or "methods actually called" or something like that. Output all classes and methods -- no optimizations or shortcuts!
That's it for the output specification. Here's some example input:
class Main inherits IO { my_attribute : Int <- 5 ; main() : Object { out_string("Hello, world.\n") } ; } ;
Example .cl-type class map output -- with comments:
class_map
6 number of classes
Bool note: includes predefined base
classes
0
IO
0
Int
0
Main
1 our Main has 1 attribute
initializer
my_attribute named "my_attribute"
Int with type Int
2 -- initializer expression line number
Int -- initializer expression type (see
above: this is an expression annotated with a type)
-- do not emit types for the PA4c Checkpoint!
integer -- initializer expression kind
5 -- which interger constant is it?
Object
0
String
0
Example .cl-type implementation map output -- with comments:
implementation_map
6 six classes
Bool first is Bool
3 - it has three methods
abort - first is abort()
0 -- abort has 0 formal arguments
Object -- name of parent class from
which Bool inherits abort()
0 -- abort's body expression starts
o line 0
Object -- abort's body expression
has type Object
internal -- abort's body is
an internal kind of expression (i.e., a system call; see above)
Object.abort -- extra detail on
abort's body expression
copy - second of Bool's three
methods is copy()
0 -- copy has 0 formal arguments
Object -- name of parent class from
which Bool inherits copy()
0 -- copy's body expression starts
on line 0
SELF_TYPE -- copy's body
expression has type SELF_TYPE
internal -- copy's body is
an internal kind of expression (i.e., a system call; see above)
Object.copy -- extra detail on
copy's body expression
... many lines skipped
Main another class is Main
8 - it has 8 methods
... many lines skipped ...
main - one of Main's methods is
main()
0 -- main has 0 formal arguments
Main -- the name of the class where
Main.main() is defined
4 -- the body expression of Main.main starts on line 4
SELF_TYPE -- the body expression
of Main.main has type SELF_TYPE
self_dispatch -- the body
of Main.main() is a self_dispatch kind of expression
... many lines skipped ...
Example .cl-type parent map output -- with comments:
parent_map
5 there are five classes with
parents (Object is the sixth class)
Bool Bool's parent ...
Object ... is Object.
IO IO's parent ...
Object ... is Object.
Int Int's parent ...
Object ... is Object.
Main Main's parent ...
IO ... is IO.
String String's parent. ..
Object ... is Object.
Writing the rote code to output a .cl-type text file given an AST may take a bit of time but it should not be difficult; our reference implementation does it in 35 lines and cleaves closely to the structure given above. Reading in the AST is similarly straightforward; our reference implementation does it in 171 lines.
$ cool --parse file.cl $ cool --out reference --type file.cl $ my-checker file.cl-ast $ diff -b -B -E -w file.cl-type reference.cl-type
You should implement all of the typing rules in the Reference Manual. There are also a number of other rules and corner cases you have to check (e.g., no class can inherit from Int, you cannot redefine a class, you cannot have an attribute named self, etc.). They are sprinkled throughout the manual. Check everything you possibly can.
Because PA4 involves spitting out parts of the AST in a similar format to PA3, there is a slight synergy to doing PA3 and PA4 in the same language. It's not major, though, and the vast majority of your effort in PA4 will be centered on type checking (rather than output formatting).
The goal of PA4t is to leave you with a high-quality test suite of Cool programs that you can use to evaluate your own PA4 type checker. Writing a type checker requires you to consider many corner cases when reading the formal and informal typing rules in the Cool Reference Manual. While you you can check for correct "positive" behavior by comparing your typechecker's output to the reference compiler's output on existing "good" Cool programs, it is comparatively harder to check for "negative" behavior (i.e., correctly reporting ill-typed Cool programs).
If you fail to construct a rich test suite of syntactically-valid but semantically-invalid programs you will face a frustrating series of "you fail held-out negative test x" reports for PA4 proper, which can turn into unproductive guessing games. Because students often report that this is frustrating (even though it is, shall we say, infinitely more realistic than making all of the post-deployment tests visible in advance), the PA4t preliminary testing exercise provides a structured means to help you get started with the constuction of a rich test suite.
The course staff have produced 20 variants of the reference compiler, each with a secret intentionally-introduced defect related to type-checking. A high-quality test suite is one that reveals each introduced defect by showing a difference between the behavior of the true reference compiler and the corresponding buggy verison. You desire a high-quality test suite to help you gain confidence in your own PA4 submission.
For PA4t, you must produce syntactically valid Cool programs (test cases). There are 20 separate held-out seeded type-checker bugs waiting on the grading server. For each bug, if one of your tests causes the reference and the buggy version to produce difference output (that is, either a different .cl-type file or a different error report), you win: that test has revealed that bug. For full credit your tests must reveal at least 15 of the 20 unknown defects.
The secret defects that we have injected into the reference compiler correspond to common defects made by students in PA4. Thus, if you make a rich test suite for PA4t that reveals many defects, you can use it on your own PA4 submission to reveal and fix your own bugs!
For PA4t you should turn in (electronically):
For PA4c you should turn in (electronically) an early version of PA4 that does the following:
You must turn in a zip file containing these files:
Students on a team are expected to participate equally in the effort and to be thoroughly familiar with all aspects of the joint work. Both members bear full responsibility for the completion of assignments. Partners turn in one solution for each programming assignment; each member receives the same grade for the assignment. If a partnership is not going well, the teaching assistants will help to negotiate new partnerships. Teams may not be dissolved in the middle of an assignment.
If you are working in a team, exactly one team member should submit a PA4 zipfile. That submission should include the file team.txt, a one-line flat ASCII text file that contains exactly and only the email address of your teammate. Don't include the @virgnia.edu bit. Example: If ph4u and wrw6y are working together, ph4u would submit ph4u-pa4.zip with a team.txt file that contains the word wrw6y. Then ph4u and wrw6y will both receive the same grade for that submission.
In each case we will then compare your output to the correct answer:
If your answer is not the same as the reference answer you get 0
points for that testcase. Otherwise you get 1 point for that testcase.
For error messages and negative testcases we will compare your output but not the particular error message. Basically, your semantic analyzer need only correctly identify that there is an error on line X. You do not have to faithfully duplicate our English error messages. Many people choose to (because it makes testing easier) -- but it's not required.
We will perform the autograding on some unspecified test system. It is likely to be Solaris/UltraSPARC, Cygwin/x86 or Linux/x86. However, your submissions must officialy be platform-independent (not that hard with a scripting language). You cannot depend on running on any particular platform.
There is more to your grade than autograder results. See the Programming Assignment page for a point breakdown.
Your submission may not create any temporary files. Your submission may not read or write any files beyond its input and output. We may test your submission in a special "jail" or "sandbox".