-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #177 from cmsc430/pdarragh
Rewrite assignment 4 instructions
- Loading branch information
Showing
2 changed files
with
126 additions
and
134 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,194 +1,187 @@ | ||
#lang scribble/manual | ||
@title[#:tag "Assignment 4" #:style 'unnumbered]{Assignment 4: Let there be (Many) Variables} | ||
|
||
@(require (for-label (except-in racket ...))) | ||
@(require "../../langs/fraud-plus/semantics.rkt") | ||
@(require redex/pict) | ||
@title[#:tag "Assignment 4 (New)" #:style 'unnumbered]{Assignment 4: Let There Be (Many) Variables} | ||
|
||
@(require "../notes/ev.rkt") | ||
@bold{Part 1 Due: Wednesday, March 27, 11:59PM EST} | ||
|
||
@bold{Due: Wednesday, November 1, 11:59PM EST} | ||
@bold{Part 2 Due: Wednesday, March 27, 11:59PM EST} | ||
|
||
The goal of this assignment is to extend a compiler with binding | ||
forms and primitives that can take any number of arguments. | ||
|
||
You are given a @tt{fraud-plus.zip} file on ELMS with a starter | ||
compiler similar to the @seclink["Fraud"]{Fraud} language we studied | ||
in class. You are tasked with: | ||
The goal of this assignment is to extend a compiler with binding forms and | ||
primitives that can take any number of arguments. | ||
|
||
@itemlist[ | ||
|
||
@item{incorporating the language features you added in | ||
@seclink["Assignment 3"]{Assignment 3}, scaled up to Fraud,} | ||
This assignment consists of two parts. In Part 1 you must submit test programs | ||
written in the new Fraud+ language. In Part 2 you must implement Fraud+. | ||
|
||
@item{extending the addition primitive to handle an arbitrary number of arguments,} | ||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Part 1} | ||
|
||
@item{extending the @racket[let]-binding form of the language to bind any number of variables, and} | ||
For the first part of the assignment, you must write test programs in the | ||
Fraud+ language. These programs should be syntactically well-formed and | ||
@bold{must produce an answer} when evaluated, i.e., these should be programs | ||
that either produce values or are expected to return @tt{'err} according to the | ||
Fraud semantics, but should not cause other errors. (The concept of an | ||
@emph{answer} was introduced in @seclink["errors"]{Extort}.) | ||
|
||
@item{adding a @racket[let*]-binding form to the language to allow back-references.} | ||
] | ||
You may write as many test programs as you like, but @bold{each program must be | ||
written in a separate file}. You can put all of your files in one directory and | ||
compress ("zip") that directory to submit it. Each program should be formatted | ||
as usual for a standalone program, i.e., it should have the line @tt{#lang | ||
racket} at the top and your program expression on a line below that. | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{From Dupe+ to Fraud+} | ||
Your submission will be graded by running each program on a set of Fraud+ | ||
compilers implemented by students in previous semesters, and your goal is to | ||
craft test programs that discover bugs in these implementations. Your programs | ||
will be run on many more compilers than you need to eliminate for a full score; | ||
this is so students do not all need to find the same bugs. Additionally, we do | ||
not know for certain that every compiler has a bug, so it may not be possible | ||
to eliminate all of them. (We randomly select some compilers that pass all of | ||
our tests so that students have the opportunity to write better tests than us. | ||
This has helped us find deficiencies in our compilers before.) | ||
|
||
Implement the @racket[abs], unary @racket[-], and @racket[not] | ||
operations and the @racket[cond] and @racket[case] forms from | ||
@seclink["Assignment 3"]{Assignment 3}. | ||
|
||
Unlike Assignment 3, the AST struct definitions and parsing code are | ||
provided. Study the relevant parts in @tt{ast.rkt} and @tt{parse.rkt}, | ||
understand what is different (if anything) from your own | ||
implementation and implement the relevant functionality in | ||
@tt{interp.rkt}, @tt{interp-prim.rkt}, and @tt{compile.rkt}. You can | ||
start from your previous code, but you will need to update it to work | ||
for the structures provided. What's essentially left for you to do is | ||
to make sure to correctly signal an error (@racket['err]) when these | ||
constructs are applied to the wrong type of argument. | ||
|
||
While you're at it, implement the predicates @racket[integer?] and | ||
@racket[boolean?] for checking the type of an argument, modeled by | ||
@racket[char?] which was covered in the lectures. | ||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Part 2} | ||
|
||
For the second part of the assignment, you are given a @tt{fraud-plus.zip} file | ||
on ELMS with a starter compiler similar to the @seclink["Fraud"]{Fraud} | ||
language we studied in class. | ||
|
||
The following files have already been updated for you: | ||
Unlike @seclink["Assignment 3"]{Assignment 3}, the following files have already | ||
been updated for you @bold{and should not be changed by you}: | ||
@itemlist[ | ||
@item{@tt{ast.rkt}} | ||
@item{@tt{parse.rkt}} | ||
@item{@tt{parse.rkt}} | ||
] | ||
|
||
You will need to modify: | ||
So you will only need to modify: | ||
@itemlist[ | ||
@item{@tt{compile.rkt}} | ||
@item{@tt{interp.rkt}} | ||
@item{@tt{interp-prim.rkt}} | ||
@item{@tt{compile.rkt}} | ||
@item{@tt{compile-ops.rkt}} | ||
] | ||
to correctly implement these features. | ||
to correctly implement the new features. These features are described below. | ||
|
||
|
||
You do not necessarily need to change all of these files depending on | ||
your design choices, but you shouldn't alter any other files for | ||
Gradescope to work. | ||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Submitting} | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{From Binary to Variadic Addition} | ||
Submit a zip file containing your work to Gradescope. Use @tt{make submit.zip} | ||
from within the @tt{fraud-plus} directory to create a zip file with the proper | ||
structure. | ||
|
||
In Fraud, we implemented a binary operation for addition. However, | ||
Racket supports an arbitrary number of arguments for @racket[+]. Your | ||
job is to extend the interpreter and compiler to behave similarly. | ||
We will not use your @tt{ast.rkt} or @tt{parse.rkt} files. Part of Assignment 3 | ||
was learning to design your own structures, but part of Assignment 4 is | ||
learning to work within the constraints of an existing design! | ||
|
||
The following file have already been updated for you: | ||
|
||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Testing} | ||
|
||
You can test your code in several ways: | ||
|
||
@itemlist[ | ||
@item{@tt{ast.rkt}} | ||
@item{@tt{parse.rkt}} | ||
] | ||
|
||
You will need to modify | ||
@item{Using the command line @tt{raco test test/} from the @tt{fraud-plus} | ||
directory to test everything.} | ||
|
||
@item{Using the command line @tt{raco test <file>} to only test @tt{<file>}.} | ||
] | ||
|
||
Note that only a small number of tests are given to you, so you should | ||
write additional test cases. We recommend using your tests from Part 1! | ||
|
||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Fraud+} | ||
|
||
The Fraud+ language extends the Fraud language we studied in class with some | ||
new features: | ||
|
||
@itemlist[ | ||
@item{@tt{compile.rkt}} | ||
@item{@tt{interp.rkt}} | ||
@item{@tt{interp-prim.rkt}} | ||
] | ||
to correctly implement these features. | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Generalizing Let} | ||
@item{The features added in @seclink["Assignment 3"]{Assignment 3}, namely: | ||
|
||
The Fraud language has a let form that binds a single variable in the | ||
scope of some expression. This is a restriction of the more general | ||
form of @racket[let] that binds any number of expressions. So for | ||
example, | ||
@itemlist[ | ||
|
||
@racketblock[ | ||
(let ((x 1) (y 2) (z 3)) | ||
_e) | ||
] | ||
@item{@racket[abs], @racket[-], and @racket[not]} | ||
@item{@racket[cond]} | ||
@item{@racket[case]} | ||
|
||
simultaneously binds @racket[x], @racket[y], and @racket[z] in the | ||
scope of @racket[_e]. | ||
]} | ||
|
||
The syntax of a @racket[let] expression allows any number of binders | ||
to occur, so @racket[(let () _e)] is valid syntax and is equivalent to | ||
@racket[_e]. | ||
@item{New primitives @racket[integer?] and @racket[boolean?].} | ||
|
||
The binding of each variable is only in scope in the body, @bold{not} | ||
in the right-hand-sides of any of the @racket[let]. | ||
@item{An extended @racket[+] that accepts any number of arguments.} | ||
|
||
For example, @racketblock[(let ((x 1) (y x)) 0)] is a syntax error | ||
because the occurrence of @racket[x] is not bound. | ||
@item{An extended @racket[let] that can bind multiple variables at once.} | ||
|
||
The following file have already been updated for you: | ||
@item{Back-referencing @racket[let*] that can bind multiple variables at once.} | ||
|
||
@itemlist[ | ||
@item{@tt{ast.rkt}} | ||
@item{@tt{parse.rkt}} | ||
] | ||
|
||
You will need to modify | ||
@itemlist[ | ||
@item{@tt{compile.rkt}} | ||
@item{@tt{interp.rkt}} | ||
] | ||
to correctly implement the generalized form of @racket[let]. | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Back-Referencing Let} | ||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{From Dupe+ to Fraud+} | ||
|
||
Similar to @racket[let] there is also @racket[let*] that also binds any number | ||
of expressions. The difference is that previous bindings are available to | ||
subsequent bindings. For example, | ||
Implement the @racket[abs], unary @racket[-], and @racket[not] operations and | ||
the @racket[cond] and @racket[case] forms from | ||
@seclink["Assignment 3"]{Assignment 3} by modifying @tt{interp.rkt}, | ||
@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-ops.rkt}. You can | ||
start from your previous code, but you will need to update it to work for the | ||
structures provided. What's essentially left for you to do is to make sure to | ||
correctly signal an error (@racket['err]) when these constructs are | ||
applied to the wrong type of argument. | ||
|
||
@racketblock[ | ||
(let* ((x 1) (y 2) (z (add1 y))) | ||
_e) | ||
] | ||
While you're at it, implement the predicates @racket[integer?] and | ||
@racket[boolean?] for checking the type of an argument, modeled by the | ||
@racket[char?] predicate that was covered in the lectures. | ||
|
||
binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in | ||
the scope of @racket[_e]. | ||
|
||
The syntax of a @racket[let*] expression allows any number of binders | ||
to occur, so @racket[(let* () _e)] is valid syntax and is equivalent to | ||
@racket[_e]. | ||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{From Binary to Variadic Addition} | ||
|
||
Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a syntax | ||
error. | ||
In Fraud, we implemented a binary operation for addition. However, Racket | ||
supports an arbitrary number of arguments for @racket[+]. Your job is to extend | ||
the interpreter and compiler to behave similarly. | ||
|
||
The following file have already been updated for you: | ||
|
||
@itemlist[ | ||
@item{@tt{ast.rkt}} | ||
@item{@tt{parse.rkt}} | ||
] | ||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Generalizing Let} | ||
|
||
You will need to modify | ||
@itemlist[ | ||
@item{@tt{compile.rkt}} | ||
@item{@tt{interp.rkt}} | ||
The Fraud language has a @tt{let} form that binds a single variable in the | ||
scope of some expression. This is a restriction of the more general form of | ||
@racket[let] that binds any number of expressions. So, for example, | ||
|
||
@racketblock[ | ||
(let ((x 1) (y 2) (z 3)) | ||
_e) | ||
] | ||
to correctly implement the generalized form of @racket[let*]. | ||
|
||
HINT: what would a lazy compiler writer do? | ||
simultaneously binds @racket[x], @racket[y], and @racket[z] in the scope of | ||
@racket[_e]. | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Testing} | ||
The syntax of a @racket[let] expression allows any number of binders to occur, | ||
so @racket[(let () _e)] is valid syntax and is equivalent to @racket[_e]. | ||
|
||
You can test your code in several ways: | ||
The binding of each variable is only in-scope within the body, @bold{not} in | ||
the right-hand sides of any of the @racket[let]. So, for example, | ||
@racketblock[(let ((x 1) (y x)) 0)] is a syntax error because the occurrence of | ||
@racket[x] is not bound. | ||
|
||
@itemlist[ | ||
|
||
@item{Using the command line @tt{raco test .} from | ||
the directory containing the repository to test everything.} | ||
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Back-Referencing Let} | ||
|
||
Similar to @racket[let], there is also @racket[let*] that can also bind any | ||
number of expressions. The difference is that previous bindings are available | ||
in the right-hand sides of subsequent bindings. For example, | ||
|
||
@item{Using the command line @tt{raco test <file>} to | ||
test only @tt{<file>}.} | ||
@racketblock[ | ||
(let* ((x 1) (y 2) (z (add1 y))) | ||
_e) | ||
] | ||
|
||
Note that only a small number of tests are given to you, so you should | ||
write additional test cases. | ||
binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in | ||
the scope of @racket[_e]. | ||
|
||
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Submitting} | ||
The syntax of a @racket[let*] expression allows any number of binders to occur, | ||
so @racket[(let* () _e)] is valid syntax and is equivalent to @racket[_e]. | ||
|
||
Submit a zip file containing your work to Gradescope. Use @tt{make | ||
submit.zip} from within the @tt{fraud-plus} directory to create a zip | ||
file with the proper structure. | ||
Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a | ||
syntax error. However, bindings are only available forward, so | ||
@racketblock[(let* ((x y) (y 1)) 0)] @emph{is} a syntax error. | ||
|
||
We will only use the @tt{compile.rkt}, @tt{interp.rkt}, and | ||
@tt{interp-prim.rkt} files for grading, so make sure all your work is | ||
contained there! Note the lack of @tt{ast.rkt}, @tt{parse.rkt}, etc. - | ||
part of assignment 3 was learning to design your own structures, part | ||
of assignment 4 is learning to work within the constraints of an | ||
existing design! | ||
HINT: Think about what a lazy compiler writer would do. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters