Skip to content

Commit 4af1fb2

Browse files
authored
Merge pull request #177 from cmsc430/pdarragh
Rewrite assignment 4 instructions
2 parents 3a94b34 + 3e6d163 commit 4af1fb2

File tree

2 files changed

+126
-134
lines changed

2 files changed

+126
-134
lines changed

www/assignments/4.scrbl

Lines changed: 124 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -1,194 +1,187 @@
11
#lang scribble/manual
2-
@title[#:tag "Assignment 4" #:style 'unnumbered]{Assignment 4: Let there be (Many) Variables}
32

4-
@(require (for-label (except-in racket ...)))
5-
@(require "../../langs/fraud-plus/semantics.rkt")
6-
@(require redex/pict)
3+
@title[#:tag "Assignment 4 (New)" #:style 'unnumbered]{Assignment 4: Let There Be (Many) Variables}
74

8-
@(require "../notes/ev.rkt")
5+
@bold{Part 1 Due: Wednesday, March 27, 11:59PM EST}
96

10-
@bold{Due: Wednesday, November 1, 11:59PM EST}
7+
@bold{Part 2 Due: Wednesday, March 27, 11:59PM EST}
118

12-
The goal of this assignment is to extend a compiler with binding
13-
forms and primitives that can take any number of arguments.
149

15-
You are given a @tt{fraud-plus.zip} file on ELMS with a starter
16-
compiler similar to the @seclink["Fraud"]{Fraud} language we studied
17-
in class. You are tasked with:
10+
The goal of this assignment is to extend a compiler with binding forms and
11+
primitives that can take any number of arguments.
1812

19-
@itemlist[
20-
21-
@item{incorporating the language features you added in
22-
@seclink["Assignment 3"]{Assignment 3}, scaled up to Fraud,}
13+
This assignment consists of two parts. In Part 1 you must submit test programs
14+
written in the new Fraud+ language. In Part 2 you must implement Fraud+.
2315

24-
@item{extending the addition primitive to handle an arbitrary number of arguments,}
16+
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Part 1}
2517

26-
@item{extending the @racket[let]-binding form of the language to bind any number of variables, and}
18+
For the first part of the assignment, you must write test programs in the
19+
Fraud+ language. These programs should be syntactically well-formed and
20+
@bold{must produce an answer} when evaluated, i.e., these should be programs
21+
that either produce values or are expected to return @tt{'err} according to the
22+
Fraud semantics, but should not cause other errors. (The concept of an
23+
@emph{answer} was introduced in @seclink["errors"]{Extort}.)
2724

28-
@item{adding a @racket[let*]-binding form to the language to allow back-references.}
29-
]
25+
You may write as many test programs as you like, but @bold{each program must be
26+
written in a separate file}. You can put all of your files in one directory and
27+
compress ("zip") that directory to submit it. Each program should be formatted
28+
as usual for a standalone program, i.e., it should have the line @tt{#lang
29+
racket} at the top and your program expression on a line below that.
3030

31-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{From Dupe+ to Fraud+}
31+
Your submission will be graded by running each program on a set of Fraud+
32+
compilers implemented by students in previous semesters, and your goal is to
33+
craft test programs that discover bugs in these implementations. Your programs
34+
will be run on many more compilers than you need to eliminate for a full score;
35+
this is so students do not all need to find the same bugs. Additionally, we do
36+
not know for certain that every compiler has a bug, so it may not be possible
37+
to eliminate all of them. (We randomly select some compilers that pass all of
38+
our tests so that students have the opportunity to write better tests than us.
39+
This has helped us find deficiencies in our compilers before.)
3240

33-
Implement the @racket[abs], unary @racket[-], and @racket[not]
34-
operations and the @racket[cond] and @racket[case] forms from
35-
@seclink["Assignment 3"]{Assignment 3}.
3641

37-
Unlike Assignment 3, the AST struct definitions and parsing code are
38-
provided. Study the relevant parts in @tt{ast.rkt} and @tt{parse.rkt},
39-
understand what is different (if anything) from your own
40-
implementation and implement the relevant functionality in
41-
@tt{interp.rkt}, @tt{interp-prim.rkt}, and @tt{compile.rkt}. You can
42-
start from your previous code, but you will need to update it to work
43-
for the structures provided. What's essentially left for you to do is
44-
to make sure to correctly signal an error (@racket['err]) when these
45-
constructs are applied to the wrong type of argument.
46-
47-
While you're at it, implement the predicates @racket[integer?] and
48-
@racket[boolean?] for checking the type of an argument, modeled by
49-
@racket[char?] which was covered in the lectures.
42+
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Part 2}
5043

44+
For the second part of the assignment, you are given a @tt{fraud-plus.zip} file
45+
on ELMS with a starter compiler similar to the @seclink["Fraud"]{Fraud}
46+
language we studied in class.
5147

52-
The following files have already been updated for you:
48+
Unlike @seclink["Assignment 3"]{Assignment 3}, the following files have already
49+
been updated for you @bold{and should not be changed by you}:
5350
@itemlist[
5451
@item{@tt{ast.rkt}}
55-
@item{@tt{parse.rkt}}
52+
@item{@tt{parse.rkt}}
5653
]
5754

58-
You will need to modify:
55+
So you will only need to modify:
5956
@itemlist[
60-
@item{@tt{compile.rkt}}
6157
@item{@tt{interp.rkt}}
6258
@item{@tt{interp-prim.rkt}}
59+
@item{@tt{compile.rkt}}
60+
@item{@tt{compile-ops.rkt}}
6361
]
64-
to correctly implement these features.
62+
to correctly implement the new features. These features are described below.
63+
6564

66-
You do not necessarily need to change all of these files depending on
67-
your design choices, but you shouldn't alter any other files for
68-
Gradescope to work.
65+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Submitting}
6966

70-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{From Binary to Variadic Addition}
67+
Submit a zip file containing your work to Gradescope. Use @tt{make submit.zip}
68+
from within the @tt{fraud-plus} directory to create a zip file with the proper
69+
structure.
7170

72-
In Fraud, we implemented a binary operation for addition. However,
73-
Racket supports an arbitrary number of arguments for @racket[+]. Your
74-
job is to extend the interpreter and compiler to behave similarly.
71+
We will not use your @tt{ast.rkt} or @tt{parse.rkt} files. Part of Assignment 3
72+
was learning to design your own structures, but part of Assignment 4 is
73+
learning to work within the constraints of an existing design!
7574

76-
The following file have already been updated for you:
75+
76+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Testing}
77+
78+
You can test your code in several ways:
7779

7880
@itemlist[
79-
@item{@tt{ast.rkt}}
80-
@item{@tt{parse.rkt}}
81-
]
8281

83-
You will need to modify
82+
@item{Using the command line @tt{raco test test/} from the @tt{fraud-plus}
83+
directory to test everything.}
84+
85+
@item{Using the command line @tt{raco test <file>} to only test @tt{<file>}.}
86+
]
87+
88+
Note that only a small number of tests are given to you, so you should
89+
write additional test cases. We recommend using your tests from Part 1!
90+
91+
92+
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Fraud+}
93+
94+
The Fraud+ language extends the Fraud language we studied in class with some
95+
new features:
96+
8497
@itemlist[
85-
@item{@tt{compile.rkt}}
86-
@item{@tt{interp.rkt}}
87-
@item{@tt{interp-prim.rkt}}
88-
]
89-
to correctly implement these features.
9098

91-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Generalizing Let}
99+
@item{The features added in @seclink["Assignment 3"]{Assignment 3}, namely:
92100

93-
The Fraud language has a let form that binds a single variable in the
94-
scope of some expression. This is a restriction of the more general
95-
form of @racket[let] that binds any number of expressions. So for
96-
example,
101+
@itemlist[
97102

98-
@racketblock[
99-
(let ((x 1) (y 2) (z 3))
100-
_e)
101-
]
103+
@item{@racket[abs], @racket[-], and @racket[not]}
104+
@item{@racket[cond]}
105+
@item{@racket[case]}
102106

103-
simultaneously binds @racket[x], @racket[y], and @racket[z] in the
104-
scope of @racket[_e].
107+
]}
105108

106-
The syntax of a @racket[let] expression allows any number of binders
107-
to occur, so @racket[(let () _e)] is valid syntax and is equivalent to
108-
@racket[_e].
109+
@item{New primitives @racket[integer?] and @racket[boolean?].}
109110

110-
The binding of each variable is only in scope in the body, @bold{not}
111-
in the right-hand-sides of any of the @racket[let].
111+
@item{An extended @racket[+] that accepts any number of arguments.}
112112

113-
For example, @racketblock[(let ((x 1) (y x)) 0)] is a syntax error
114-
because the occurrence of @racket[x] is not bound.
113+
@item{An extended @racket[let] that can bind multiple variables at once.}
115114

116-
The following file have already been updated for you:
115+
@item{Back-referencing @racket[let*] that can bind multiple variables at once.}
117116

118-
@itemlist[
119-
@item{@tt{ast.rkt}}
120-
@item{@tt{parse.rkt}}
121117
]
122118

123-
You will need to modify
124-
@itemlist[
125-
@item{@tt{compile.rkt}}
126-
@item{@tt{interp.rkt}}
127-
]
128-
to correctly implement the generalized form of @racket[let].
129119

130-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Back-Referencing Let}
120+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{From Dupe+ to Fraud+}
131121

132-
Similar to @racket[let] there is also @racket[let*] that also binds any number
133-
of expressions. The difference is that previous bindings are available to
134-
subsequent bindings. For example,
122+
Implement the @racket[abs], unary @racket[-], and @racket[not] operations and
123+
the @racket[cond] and @racket[case] forms from
124+
@seclink["Assignment 3"]{Assignment 3} by modifying @tt{interp.rkt},
125+
@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-ops.rkt}. You can
126+
start from your previous code, but you will need to update it to work for the
127+
structures provided. What's essentially left for you to do is to make sure to
128+
correctly signal an error (@racket['err]) when these constructs are
129+
applied to the wrong type of argument.
135130

136-
@racketblock[
137-
(let* ((x 1) (y 2) (z (add1 y)))
138-
_e)
139-
]
131+
While you're at it, implement the predicates @racket[integer?] and
132+
@racket[boolean?] for checking the type of an argument, modeled by the
133+
@racket[char?] predicate that was covered in the lectures.
140134

141-
binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in
142-
the scope of @racket[_e].
143135

144-
The syntax of a @racket[let*] expression allows any number of binders
145-
to occur, so @racket[(let* () _e)] is valid syntax and is equivalent to
146-
@racket[_e].
136+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{From Binary to Variadic Addition}
147137

148-
Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a syntax
149-
error.
138+
In Fraud, we implemented a binary operation for addition. However, Racket
139+
supports an arbitrary number of arguments for @racket[+]. Your job is to extend
140+
the interpreter and compiler to behave similarly.
150141

151-
The following file have already been updated for you:
152142

153-
@itemlist[
154-
@item{@tt{ast.rkt}}
155-
@item{@tt{parse.rkt}}
156-
]
143+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Generalizing Let}
157144

158-
You will need to modify
159-
@itemlist[
160-
@item{@tt{compile.rkt}}
161-
@item{@tt{interp.rkt}}
145+
The Fraud language has a @tt{let} form that binds a single variable in the
146+
scope of some expression. This is a restriction of the more general form of
147+
@racket[let] that binds any number of expressions. So, for example,
148+
149+
@racketblock[
150+
(let ((x 1) (y 2) (z 3))
151+
_e)
162152
]
163-
to correctly implement the generalized form of @racket[let*].
164153

165-
HINT: what would a lazy compiler writer do?
154+
simultaneously binds @racket[x], @racket[y], and @racket[z] in the scope of
155+
@racket[_e].
166156

167-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Testing}
157+
The syntax of a @racket[let] expression allows any number of binders to occur,
158+
so @racket[(let () _e)] is valid syntax and is equivalent to @racket[_e].
168159

169-
You can test your code in several ways:
160+
The binding of each variable is only in-scope within the body, @bold{not} in
161+
the right-hand sides of any of the @racket[let]. So, for example,
162+
@racketblock[(let ((x 1) (y x)) 0)] is a syntax error because the occurrence of
163+
@racket[x] is not bound.
170164

171-
@itemlist[
172165

173-
@item{Using the command line @tt{raco test .} from
174-
the directory containing the repository to test everything.}
166+
@subsection[#:tag-prefix "a4-" #:style 'unnumbered]{Back-Referencing Let}
167+
168+
Similar to @racket[let], there is also @racket[let*] that can also bind any
169+
number of expressions. The difference is that previous bindings are available
170+
in the right-hand sides of subsequent bindings. For example,
175171

176-
@item{Using the command line @tt{raco test <file>} to
177-
test only @tt{<file>}.}
172+
@racketblock[
173+
(let* ((x 1) (y 2) (z (add1 y)))
174+
_e)
178175
]
179176

180-
Note that only a small number of tests are given to you, so you should
181-
write additional test cases.
177+
binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in
178+
the scope of @racket[_e].
182179

183-
@section[#:tag-prefix "a4-" #:style 'unnumbered]{Submitting}
180+
The syntax of a @racket[let*] expression allows any number of binders to occur,
181+
so @racket[(let* () _e)] is valid syntax and is equivalent to @racket[_e].
184182

185-
Submit a zip file containing your work to Gradescope. Use @tt{make
186-
submit.zip} from within the @tt{fraud-plus} directory to create a zip
187-
file with the proper structure.
183+
Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a
184+
syntax error. However, bindings are only available forward, so
185+
@racketblock[(let* ((x y) (y 1)) 0)] @emph{is} a syntax error.
188186

189-
We will only use the @tt{compile.rkt}, @tt{interp.rkt}, and
190-
@tt{interp-prim.rkt} files for grading, so make sure all your work is
191-
contained there! Note the lack of @tt{ast.rkt}, @tt{parse.rkt}, etc. -
192-
part of assignment 3 was learning to design your own structures, part
193-
of assignment 4 is learning to work within the constraints of an
194-
existing design!
187+
HINT: Think about what a lazy compiler writer would do.

www/notes/extort.scrbl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
@table-of-contents[]
3333

34-
@section{Errors}
34+
@section[#:tag "errors"]{Errors}
3535

3636
We have added multiple, disjoint types, but mostly swept issues of
3737
errors under the rug by considering type mismatches as meaningless.
@@ -94,7 +94,7 @@ defined as @racket['err]:
9494
['= (rewrite '=)]
9595
['!= (rewrite '≠)])
9696
(apply centered
97-
(add-between
97+
(add-between
9898
(build-list (- j i)
9999
(λ (n) (begin (judgment-form-cases (list (+ n i)))
100100
(render-judgment-form name))))
@@ -206,4 +206,3 @@ usual way again:
206206
(check-correctness (Prim1 'add1 (Lit 7)))
207207
(check-correctness (Prim1 'add1 (Lit #f)))
208208
]
209-

0 commit comments

Comments
 (0)