88
99The goal of this assignment is to extend the language developed in
1010@secref{Dupe} with some simple unary numeric and boolean operations
11- and two forms of control flow expressions: @racket[cond ]-expressions
12- and @racket[case ]-expressions.
11+ and a new form of control flow expressions: @racket[cond ]-expressions.
1312
14- @section[#:tag-prefix "a3- " #:style 'unnumbered ]{Dupe+}
13+ @section[#:tag "a3-dupe-plus " #:style 'unnumbered ]{Dupe+}
1514
1615The Dupe+ language extends Dupe in the follow ways:
1716
1817@itemlist[
1918@item{adding new primitive operations,}
20- @item{adding @racket[cond ], and }
21- @item{adding @racket[case ].}
19+ @item{adding @racket[cond ].}
2220]
2321
2422@subsection[#:tag-prefix "a3- " #:style 'unnumbered ]{Primitives}
@@ -27,7 +25,7 @@ The following new primitves are included in Dupe+:
2725
2826@itemlist[
2927@item{@racket[(abs _e)]: compute the absolute value of @racket[_e],}
30- @item{@racket[(- _e)]: flips the sign of @racket[_e], i.e. compute @math{0-@racket[_e]}, and }
28+ @item{@racket[(- _e)]: flip the sign of @racket[_e], i.e. compute @math{0-@racket[_e]}, and }
3129@item{@racket[(not _e)]: compute the logical negation of @racket[_e]; note that the negation of @emph{any} value other than @racket[#f] is @racket[#f] and the negation of @racket[#f] is @racket[#t].}
3230]
3331
@@ -42,10 +40,10 @@ The following new conditional form is included in Dupe+:
4240]
4341
4442A @racket[cond ] expression has any number of clauses @racket[[_e-pi
45- _e-ai] ... ], followed by an ``else '' clause @racket[[else _en ]]. For
46- the purposes of this assignment, we will assume every @racket[ cond ]
47- expression ends in an @racket[else ] clause, even though this is not
48- true in general for Racket. The parser should reject any
43+ _e-ai] ... ], followed by an ``else '' clause @racket[[else _e-an ]].
44+ For the purposes of this assignment, we will assume every
45+ @racket[ cond ] expression ends in an @racket[else ] clause, even though
46+ this is not true in general for Racket. The parser will reject any
4947@racket[cond ]-expression that does not end in @racket[else ].
5048
5149
@@ -56,43 +54,61 @@ does not evaluate to @racket[#f] is found, in which case, the corresponding expr
5654@racket[cond ] expression. If no such @racket[_e-pi] exists, the
5755expression @racket[_e-an]'s value is the value of the @racket[cond ].
5856
59- @subsection[#:tag-prefix "a3- " #:style 'unnumbered ]{Case expressions}
6057
61- The following new case form is included in Dupe+:
58+ @section[ #:tag-prefix " a3- " #:style 'unnumbered ]{Implementing Dupe+}
6259
63- @racketblock[
64- (case _ev
65- [(_d1 ... ) _e1]
66- ...
67- [else _en])
68- ]
60+ You must extend the interpreter and compiler to implement Dupe+. (The
61+ parser for Dupe+ is given to you.) You are given a file
62+ @tt{dupe-plus.zip} on ELMS with a starter compiler based on the
63+ @secref{Dupe} language we studied in class.
6964
70- The @racket[ case ] expression form is a mechanism for dispatching
71- between a number of possible expressions based on a value, much like
72- C 's notion of a @tt{switch}-statement .
65+ You may use any a86 instructions you 'd like, however it is possible to
66+ complete the assignment using @racket[Cmp], @racket[Je], @racket[Jg],
67+ @racket[Jmp], @racket[Label], @racket[Mov], and @racket[Sub] .
7368
74- The meaning of a @racket[case ] expression is computed by evaluating
75- the expression @racket[_ev] and then proceeding in order through each
76- clause until one is found that has a datum @racket[_di] equal to
77- @racket[_ev]'s value. Once such a clause is found, the corresponding
78- expression @racket[_ei] is evaluated and its value is the value of the
79- @racket[case ] expression. If no such clause exists, expression
80- @racket[_en] is evaluated and its value is the value of the
81- @racket[case ] expression.
69+ @section[#:tag-prefix "a3- " #:style 'unnumbered #:tag "parse " ]{Parsing Dupe+}
8270
83- Note that each clause consists of a parenthesized list of
84- @emph{datums}, which in the setting of Dupe means either integer or
85- boolean literals.
71+ The AST type and parser for Dupe+ are given to you.
8672
87- @section[ #:tag-prefix " a3- " #:style 'unnumbered ]{Implementing Dupe+}
73+ Here 's the AST definition for the added primitives and @racket[ cond ]:
8874
89- You must extend the parser, interpreter, and compiler to implement
90- Dupe+. You are given a file @tt{dupe-plus.zip} on ELMS with a starter
91- compiler based on the @secref{Dupe} language we studied in class.
75+ @#reader scribble/comment-reader
76+ (racketblock
77+ ;; type Expr =
78+ ;; ...
79+ ;; | (Cond [Listof Expr] [Listof Expr] Expr)
9280
93- You may use any a86 instructions you'd like, however it is possible to
94- complete the assignment using @racket[Cmp], @racket[Je], @racket[Jg],
95- @racket[Jmp], @racket[Label], @racket[Mov], and @racket[Sub].
81+ ;; type Op =
82+ ;; ...
83+ ;; | 'abs | '- | 'not
84+
85+ (struct Cond (cs e) #:prefab )
86+ )
87+
88+ There is one new kind of expression constructor: @racket[Cond]. A
89+ @racket[Cond] AST node contains three parts: two equal length lists of
90+ expression and an expression. The two lists represent the clauses,
91+ where the first list contains all of the left-hand-side parts of the
92+ clauses and the other contains all of the right-hand-side parts.
93+
94+ Here are some examples of how concrete expressions are parsed into
95+ ASTs using this representation:
96+
97+ @itemlist[
98+
99+ @item{@racket[(abs 1 )] parses as @racket[(Prim1 'abs (Lit 1 ))],}
100+
101+ @item{@racket[(not #t )] parses as @racket[(Prim1 'not (Lit #t ))],}
102+
103+ @item{@racket[(cond [else 5 ])] parses as @racket[(Cond '() '() (Lit 5 ))],}
104+
105+ @item{@racket[(cond [(not #t ) 3 ] [else 5 ])] parses as @racket[(Cond
106+ (list (Prim1 'not (Lit #t ))) (list (Lit 3 )) (Lit 5 ))],}
107+
108+ @item{@racket[(cond [(not #t ) 3 ] [7 4 ] [else 5 ])] parses as
109+ @racket[(Cond (list (Prim1 'not (Lit #t )) (Lit 7 )) (list (Lit 3 )
110+ (Lit 4 )) (Lit 5 ))],}
111+ ]
96112
97113@subsection[#:tag-prefix "a3- " #:style 'unnumbered ]{Implementing primitives}
98114
@@ -103,8 +119,7 @@ these using the limited a86 instruction set.
103119
104120To do this , you should:
105121@itemlist[
106- @item{Study @tt{ast.rkt} and the new forms of expression (i.e. new AST nodes)
107- then update the comment at the top describing what the grammmar should look like.}
122+ @item{Study @tt{ast.rkt} to understand how these new forms of expression are represented.}
108123
109124@item{Study @tt{parse.rkt} and add support for parsing these
110125expressions. (See @secref[#:tag-prefixes '("a3- " )]{parse} for guidance.)}
@@ -126,7 +141,6 @@ To do this, you should:
126141
127142@itemlist[
128143@item{Study @tt{ast.rkt} to add appropriate AST nodes.}
129- @item{Extend @tt{parse.rkt} to parse such expressions. (See @secref[#:tag-prefixes '("a3- " )]{parse} for guidance.)}
130144@item{Update @tt{interp-prim.rkt} and @tt{interp.rkt} to correctly interpret @racket[cond ] expressions.}
131145
132146@item{Make examples of @racket[cond ]-expressions and potential translations of them
@@ -138,108 +152,6 @@ expressions based on your examples.}
138152@item{Check your implementation by running the tests in @tt{test/all.rkt}.}
139153]
140154
141- @section[#:tag-prefix "a3- " #:style 'unnumbered ]{Implementing case }
142-
143- Implement the @racket[case ] expression form as described earlier.
144- To do this , you should:
145-
146- @itemlist[
147- @item{Study @tt{ast.rkt} to add appropriate AST nodes.}
148- @item{Extend @tt{parse.rkt} to parse such expressions. (See @secref[#:tag-prefixes '("a3- " )]{parse} for guidance.)}
149- @item{Update @tt{interp-prim.rkt} and @tt{interp.rkt} to correctly interpret @racket[case ] expressions.}
150-
151- @item{Make examples of @racket[case ]-expressions and potential translations of them
152- to assembly.}
153-
154- @item{Update @tt{compile.rkt} to correctly compile @racket[case ] expressions based on your examples.}
155-
156- @item{Check your implementation by running the tests in @tt{test/all.rkt}.}
157- ]
158-
159- @section[#:tag-prefix "a3- " #:style 'unnumbered #:tag "parse " ]{A Leg Up on Parsing}
160-
161- In the past, designing the AST type and structure definitions has
162- given students some grief. Getting stuck at this point means you
163- can't make any progress on the assignment and making a mistake at this
164- level can cause real trouble down the line for your compiler.
165-
166- For that reason, let us give you a strong hint for a potential design
167- of the ASTs and examples of how parsing could work. You are not
168- required to follow this design, but you certainly may.
169-
170- Here's a potential AST definition for the added primitives,
171- @racket[cond ], and @racket[case ]:
172-
173- @#reader scribble/comment-reader
174- (racketblock
175- ;; type Expr =
176- ;; ...
177- ;; | (Cond [Listof CondClause] Expr)
178- ;; | (Case Expr [Listof CaseClause] Expr)
179-
180- ;; type CondClause = (Clause Expr Expr)
181- ;; type CaseClause = (Clause [Listof Datum] Expr)
182-
183- ;; type Datum = Integer | Boolean
184-
185- ;; type Op =
186- ;; ...
187- ;; | 'abs | '- | 'not
188-
189- (struct Cond (cs e) #:prefab )
190- (struct Case (e cs el) #:prefab )
191- (struct Clause (p b) #:prefab )
192- )
193-
194- There are two new kinds of expression constructors: @racket[Cond] and
195- @racket[Case]. A @racket[Cond] AST node contains a list of
196- cond-clauses and expression, which the expression of the @racket[else ]
197- clause. Each cond-clause is represented by a @racket[Clause]
198- structure containing two expressions: the left-hand-side of the
199- clause which is used to determine whether the right-hand-side is
200- evaluated, and the right-hand-side expression.
201-
202- The @racket[Case] AST node contains three things: an expression that
203- is the subject of the dispatch (i.e. the expression that is evaluated
204- to determine which clause should be taken), a list of case-clauses
205- (not to be confused with cond-clauses), and an @racket[else ]-clause
206- expression. Each case-clause, like a cond-clause, consists of two
207- things. Hence we re-use the @racket[Clause] structure, but with
208- different types of elements. The first element is a list of
209- @emph{datums}, each being either an integer or a boolean.
210-
211- Now, we won't go so far as to @emph{give} you the code for
212- @racket[parse], but we can give you some examples:
213-
214- @itemlist[
215-
216- @item{@racket[(abs 1 )] parses as @racket[(Prim1 'abs (Lit 1 ))],}
217-
218- @item{@racket[(not #t )] parses as @racket[(Prim1 'not (Lit #t ))],}
219-
220- @item{@racket[(cond [else 5 ])] parses as @racket[(Cond '() (Lit 5 ))],}
221-
222- @item{@racket[(cond [(not #t ) 3 ] [else 5 ])] parses as @racket[(Cond
223- (list (Clause (Prim1 'not (Lit #t )) (Lit 3 ))) (Lit 5 ))],}
224-
225- @item{@racket[(cond [(not #t ) 3 ] [7 4 ] [else 5 ])] parses as
226- @racket[(Cond (list (Clause (Prim1 'not (Lit #t )) (Lit 3 )) (Clause
227- (Lit 7 ) (Lit 4 ))) (Lit 5 ))],}
228-
229- @item{@racket[(case (add1 3 ) [else 2 ])] parses as @racket[(Case (Prim1
230- 'add1 (Lit 3 )) '() (Lit 2 ))].}
231-
232- @item{@racket[(case 4 [(4 ) 1 ] [else 2 ])] parses as @racket[(Case (Lit
233- 4 ) (list (Clause (list 4 ) (Lit 1 ))) (Lit 2 ))],}
234-
235- @item{@racket[(case 4 [(4 5 6 ) 1 ] [else 2 ])] parses as @racket[(Case (Lit
236- 4 ) (list (Clause (list 4 5 6 ) (Lit 1 ))) (Lit 2 ))], and }
237-
238- @item{@racket[(case 4 [(4 5 6 ) 1 ] [(#t #f ) 7 ] [else 2 ])] parses as @racket[(Case (Lit
239- 4 ) (list (Clause (list 4 5 6 ) (Lit 1 )) (Clause (list #t #f ) (Lit 7 ))) (Lit 2 ))].}
240- ]
241-
242-
243155@section[#:tag-prefix "a3- " #:style 'unnumbered ]{Testing}
244156
245157You can test your code in several ways:
0 commit comments