11#lang scribble/manual
22@(require "../defns.rkt " )
3- @title[#:tag "Assignment 5 " #:style 'unnumbered ]{Assignment 5: When and unless }
3+ @title[#:tag "Assignment 5 " #:style 'unnumbered ]{Assignment 5: Let There Be (Many) Variables }
44
55@(require (for-label a86/ast (except-in racket ... )))
66
77@bold{Due: @assign-deadline[5 ]}
88
9- Details of this assignment will be released later in the semester.
9+ The goal of this assignment is to extend a compiler with binding forms
10+ that can take any number of arguments.
1011
11- @;{
12- The goal of this assignment is to extend the language developed in
13- @secref{Extort} with new forms of control flow expressions:
14- @racket[when ]- and @racket[unless ]-expressions.
12+ @section[#:tag-prefix "a5- " #:style 'unnumbered ]{Overview}
1513
16- @section[#:tag-prefix "a5- " #:style 'unnumbered ]{Extort+}
14+ For this assignment, you are given a @tt{fraud-plus.zip} file on ELMS
15+ with a starter compiler similar to the @seclink["Fraud " ]{Fraud}
16+ language we studied in class.
1717
18- The Extort+ language extends Extort in the follow ways:
18+ @section[#:tag-prefix "a5- " #:style 'unnumbered ]{Fraud+}
19+
20+ The Fraud+ language extends the Fraud language we studied in class with some
21+ new features:
1922
2023@itemlist[
21- @item{adding @racket[when ],}
22- @item{adding @racket[unless ], and }
23- @item{bringing forward all the features of Dupe+.}
24+
25+ @item{The features added in @seclink["Assignment 4 " ]{Assignment 4 }, namely:
26+
27+ @itemlist[
28+
29+ @item{@racket[abs], @racket[-], and @racket[not]}
30+ @item{@racket[cond ]}
31+ @item{@racket[case ]}
32+
33+ ]}
34+
35+ @item{New primitives @racket[integer?] and @racket[boolean?].}
36+
37+ @item{An extended @racket[let ] form that can bind multiple variables at once.}
38+
39+ @item{Back-referencing @racket[let* ] form that can bind multiple variables at once.}
40+
2441]
2542
43+ @subsection[#:tag-prefix "a5- " #:style 'unnumbered ]{From Dupe++ to Fraud+}
2644
27- @section[#:tag-prefix "a5- " #:style 'unnumbered ]{Testing}
45+ Implement the @racket[abs], unary @racket[-], and @racket[not] operations and
46+ the @racket[cond ] and @racket[case ] forms from
47+ @seclink["Assignment 4 " ]{Assignment 4 } by modifying @tt{interp.rkt},
48+ @tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-ops.rkt}. You can
49+ start from your previous code, but you will need to update it to work for the
50+ code you are given. What's essentially left for you to do is to make sure to
51+ correctly signal an error (@racket['err ]) when these constructs are
52+ applied to the wrong type of argument.
2853
29- You can test your code in several ways:
54+ While you're at it, implement the predicates @racket[integer?] and
55+ @racket[boolean?] for checking the type of an argument, modeled by the
56+ @racket[char?] predicate that was covered in the lectures.
3057
31- @itemlist[
58+ @subsection[#:tag-prefix "a5- " #:style 'unnumbered ]{Generalizing Let}
59+
60+ The Fraud language has a @tt{let } form that binds a single variable in the
61+ scope of some expression. This is a restriction of the more general form of
62+ @racket[let ] that binds any number of expressions. So, for example,
63+
64+ @racketblock[
65+ (let ((x 1 ) (y 2 ) (z 3 ))
66+ _e)
67+ ]
68+
69+ simultaneously binds @racket[x], @racket[y], and @racket[z] in the scope of
70+ @racket[_e].
71+
72+ The syntax of a @racket[let ] expression allows any number of binders to occur,
73+ so @racket[(let () _e)] is valid syntax and is equivalent to @racket[_e].
74+
75+ The binding of each variable is only in-scope within the body, @bold{not} in
76+ the right-hand sides of any of the @racket[let ]. So, for example,
77+ @racketblock[(let ((x 1 ) (y x)) 0 )] is a syntax error because the occurrence of
78+ @racket[x] is not bound.
79+
80+ The provided interpreter and compiler work when the @racket[let ]
81+ expression happens to bind a single variable, but you must revise the
82+ code to work for any number of bindings.
3283
33- @item{Using the command line @tt{raco test .} from
34- the directory containing the repository to test everything.}
3584
36- @item{Using the command line @tt{raco test <file>} to
37- test only @tt{<file>}.}
85+ @subsection[#:tag-prefix "a5- " #:style 'unnumbered ]{Back-Referencing Let}
86+
87+ Similar to @racket[let ], there is also @racket[let* ] that can also bind any
88+ number of expressions. The difference is that previous bindings are available
89+ in the right-hand sides of subsequent bindings. For example,
90+
91+ @racketblock[
92+ (let* ((x 1 ) (y 2 ) (z (add1 y)))
93+ _e)
3894]
3995
40- Note that only a small number of tests are given to you, so you should
41- write additional test cases.
96+ binds @racket[x] to 1 , @racket[y] to 2 , and @racket[z] to 3 in
97+ the scope of @racket[_e].
98+
99+ The syntax of a @racket[let* ] expression allows any number of binders to occur,
100+ so @racket[(let* () _e)] is valid syntax and is equivalent to @racket[_e].
101+
102+ Unlike @racket[let ], @racketblock[(let* ((x 1 ) (y x)) 0 )] is @emph{not} a
103+ syntax error. However, bindings are only available forward, so
104+ @racketblock[(let* ((x y) (y 1 )) 0 )] @emph{is} a syntax error.
105+
106+ The provided interpreter and compiler work when the @racket[let* ]
107+ expression happens to bind a single variable, but you must revise the
108+ code to work for any number of bindings.
42109
43110@section[#:tag-prefix "a5- " #:style 'unnumbered ]{Submitting}
44111
45- To submit, use @tt{make} from within the code directory to create a
46- zip file containing your work and submit it to Gradescope.
47- }
112+ To submit, use @tt{make} from within the @tt{fraud-plus} directory to
113+ create a zip file containing your work and submit it to Gradescope.
0 commit comments