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,65 @@ 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 CondClause] 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 CondClause = (Clause Expr Expr)
82+
83+ ;; type Op =
84+ ;; ...
85+ ;; | 'abs | '- | 'not
86+
87+ (struct Cond (cs e) #:prefab )
88+ (struct Clause (p b) #:prefab )
89+ )
90+
91+ There is one new kind of expression constructor: @racket[Cond]. A
92+ @racket[Cond] AST node contains a list of cond-clauses and expression,
93+ which the expression of the @racket[else ] clause. Each cond-clause is
94+ represented by a @racket[Clause] structure containing two expressions:
95+ the left-hand-side of the clause which is used to determine whether
96+ the right-hand-side is evaluated, and the right-hand-side expression.
97+
98+ Here are some examples of how concrete expressions are parsed into
99+ ASTs using this representation:
100+
101+ @itemlist[
102+
103+ @item{@racket[(abs 1 )] parses as @racket[(Prim1 'abs (Lit 1 ))],}
104+
105+ @item{@racket[(not #t )] parses as @racket[(Prim1 'not (Lit #t ))],}
106+
107+ @item{@racket[(cond [else 5 ])] parses as @racket[(Cond '() (Lit 5 ))],}
108+
109+ @item{@racket[(cond [(not #t ) 3 ] [else 5 ])] parses as @racket[(Cond
110+ (list (Clause (Prim1 'not (Lit #t )) (Lit 3 ))) (Lit 5 ))],}
111+
112+ @item{@racket[(cond [(not #t ) 3 ] [7 4 ] [else 5 ])] parses as
113+ @racket[(Cond (list (Clause (Prim1 'not (Lit #t )) (Lit 3 )) (Clause
114+ (Lit 7 ) (Lit 4 ))) (Lit 5 ))],}
115+ ]
96116
97117@subsection[#:tag-prefix "a3- " #:style 'unnumbered ]{Implementing primitives}
98118
@@ -103,8 +123,7 @@ these using the limited a86 instruction set.
103123
104124To do this , you should:
105125@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.}
126+ @item{Study @tt{ast.rkt} to understand how these new forms of expression are represented.}
108127
109128@item{Study @tt{parse.rkt} and add support for parsing these
110129expressions. (See @secref[#:tag-prefixes '("a3- " )]{parse} for guidance.)}
@@ -126,7 +145,6 @@ To do this, you should:
126145
127146@itemlist[
128147@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.)}
130148@item{Update @tt{interp-prim.rkt} and @tt{interp.rkt} to correctly interpret @racket[cond ] expressions.}
131149
132150@item{Make examples of @racket[cond ]-expressions and potential translations of them
@@ -138,108 +156,6 @@ expressions based on your examples.}
138156@item{Check your implementation by running the tests in @tt{test/all.rkt}.}
139157]
140158
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-
243159@section[#:tag-prefix "a3- " #:style 'unnumbered ]{Testing}
244160
245161You can test your code in several ways:
0 commit comments