66
77@(require "../notes/ev.rkt " )
88
9- @bold{Due: Friday, Oct 30 , 11:59PM EDT}
9+ @bold{Due: Thursday, April 7th , 11:59PM EDT}
1010
11- @(define repo "https://classroom. github.com/a/fqM9KeO1 " )
11+ @(define repo "https://github.com/cmsc430/assign05 " )
1212
1313The goal of this assignment is to extend a compiler with data types
14- that require memory allocation and dereferencing.
14+ that require memory allocation and dereferencing. A secondary goal is to hone your test-writing skills.
1515
1616Assignment repository:
1717@centered{@link[repo repo]}
@@ -22,44 +22,21 @@ with:
2222
2323@itemlist[
2424
25- @item{incorporating the Con+ features you added in
26- @seclink["Assignment 3 " ]{Assignment 3 },}
27-
28- @item{incorporating the Fraud+ features you added in
29- @seclink["Assignment 4 " ]{Assignment 4 },}
30-
3125@item{extending the language to include a string data type,}
3226
33- @item{implementing a number of primitives, }
27+ @item{extend the (very few) tests provided to be as comprehensive as possible. }
3428
3529]
3630
37- As usual, the code in @tt{ast.rkt} will need to be studied in order to
38- understand the structure of the AST and how to traverse/operate on
39- Hustle+ programs.
40-
41- @section[#:tag-prefix "a5- " #:style 'unnumbered ]{From Fraud+ to Hustle+}
42-
43- Implement all the features of Con+ and Fraud+, extended to Hustle+.
44-
45- In order to get all the points for this section of the assignment you will
46- need to modify the following files:
47-
48- @itemlist[
49-
50- @item{@tt{compile.rkt}}
51-
52- @item{@tt{syntax.rkt}}
53-
54- ]
5531
5632@section[#:tag-prefix "a5- " #:style 'unnumbered ]{Strung out}
5733
58- In the last assignment, you implemented a character data type for
34+ In Dodger, we implemented a character data type for
5935representing single letters. In this assignment, you will implement a
6036String data type for representing arbitrarily long sequences of
6137characters.
6238
39+
6340Strings are disjoint from all other data types and are essentially a
6441fixed-size array of characters. Literal strings are written by
6542enclosing the characters within the string in double quotes (@tt{"}).
@@ -72,18 +49,22 @@ You must add the following operations to Hustle+:
7249@item{@code[#:lang " racket"]{string? ; Any -> Boolean}, which determines if its argument is a string.}
7350@item{@code[#:lang " racket"]{string-ref ; String Natural -> Char}, which
7451extracts the character at the given index (using 0-based counting). An error is signalled if
75- the index is out of bounds for the given string.}
76- @item{@code[#:lang " racket"]{string-length ; String -> Natural}, which computes the length of the string.}
77- @item{@code[#:lang " racket"]{make-string ; Natural Char -> Natural }, which constructs a string of the given
78- length, filled with the given character.}
52+ the index is out of bounds for the given string or if the first argument is not a string .}
53+ @item{@code[#:lang " racket"]{string-length ; String -> Natural}, which computes the length of the string, or yields an error if its argument is not a string .}
54+ @item{@code[#:lang " racket"]{make-string ; Natural Char -> String }, which constructs a string of the given
55+ length, filled with the given character If the first argument is not a non-negative integer, of if the second argument is not a character, an error should be returned .}
7956]
8057
81- The run-time system has been updated to account for a string type. It
82- assumes a representation where the length of the string is stored in
83- memory, followed by the characters of the string, in order. You are
84- free to change the representation if you'd like, but you will have to
85- update the run-time system to properly print strings. Otherwise, no
86- changes to the run-time system should be necessary.
58+ We have already added a @tt{String} struct in @tt{ast.rkt} and
59+ provided the parsing code in @tt{parse.rkt}.
60+
61+ More importantly, the run-time system has been updated to account for
62+ a string type. It assumes a representation where the length of the
63+ string is stored in memory, followed by the characters of the string,
64+ in order. You can change the representation if you'd like,
65+ but you will have to update the run-time system to properly print
66+ strings and discuss it with the instructors beforehand. Not recommended!
67+ Otherwise, no changes to the run-time system should be necessary.
8768
8869If you want to understand the details of how strings are implemented in
8970the run-time system. See the function @tt{print_string()}
@@ -94,207 +75,61 @@ need to modify the following files:
9475
9576@itemlist[
9677
78+ @item{@tt{interp.rkt}}
79+ @item{@tt{interp-prim.rkt}}
9780@item{@tt{compile.rkt}}
9881
99- @item{@tt{syntax.rkt}}
100-
10182]
10283
103- @section[#:tag-prefix " a5-" #:style 'unnumbered]{More operations}
104-
105- Add the following operations to the Hustle+ language:
106-
107- @itemize[
108-
109- @item{@code[#:lang " racket"]{box? ; Any -> Boolean}, which determines
110- if a value is a box.}
111-
112- @item{@code[#:lang " racket"]{empty? ; Any -> Boolean}, which
113- determines if a value is the empty list.}
114-
115- @item{@code[#:lang " racket"]{cons? ; Any -> Boolean}, which determines
116- if a value is a pair.}
117-
118- @item{@code[#:lang " racket"]{= ; Number Number -> Boolean}, which determines if
119- two numbers are equal.}
120-
121- @item{@code[#:lang " racket"]{< ; Number Number -> Boolean}, which determines if
122- the first number is less than the second.}
123-
124- @item{@code[#:lang " racket"]{<= ; Number Number -> Boolean}, which determines if
125- the first number is less than or equal to the second.}
84+ @section[#:tag-prefix " a5-" #:style 'unnumbered]{Add tests!}
85+
86+ One thing that has been not stressed enough this semester is the need
87+ to add tests. There are 6 files under the @tt{test/} directory in the
88+ repo. Three of them contain regression tests to ensure that you don't
89+ break functionality when you add the new constructs. These are
90+ @tt{test-runner.rkt}, @tt{interp.rkt} and @tt{compile.rkt}. The
91+ @tt{test-runner.rkt} file provides two functions @tt{test-runner} and
92+ @tt{test-runner-io} which execute a sequence of calls to an input
93+ @tt{run} function, and check that they yield the expected result. This
94+ @tt{run} function is instantiated in @tt{interp.rkt} with a call to
95+ the interpreter, and in @tt{compile.rkt} with a call to the compiler.
96+
97+ With this setup, when you do @tt{raco test test/interp.rkt} or
98+ @tt{raco test test/compile.rkt} you should be seeing "76 tests passed".
99+
100+ There are also three similar files with the " -string" suffix in the
101+ test directory in the repo (@tt{interp-string.rkt},
102+ @tt{compile-string.rkt}, and @tt{test-runner-string.rkt}. You'll
103+ notice that there are exactly two public tests there - one using io
104+ and one not. The second part of the assingment is to extend these tests
105+ to thoroughly test the behavior of the four primitives you added.
106+
107+ You should ONLY add tests to @tt{test-runner-string.rkt} and they should
108+ all be of the same form as the ones provided: either @tt{(check-equal? (run XXX) Y)}
109+ for the @tt{test-runner} function, or @tt{(check-equal? (run XXX SSS) (cons YYY ZZZ))}
110+ if your tests use IO.
111+
112+ Your test suite will be autograded based on its ability to reveal bugs
113+ in a series of implementations we have provided, each with 1 or more
114+ bugs injected. That is, we will run @tt{raco test} using YOUR
115+ @tt{test-runner-string} file against OUR (intentionally faulty)
116+ implementations. Of course, your test suite should not be failing
117+ any tests for a correct implementation.
126118
127- @item{@code[#:lang " racket"]{char=? ; Number Number -> Boolean}, which determines if
128- two characters are equal.}
129-
130- @item{@code[#:lang " racket"]{boolean=? ; Boolean Boolean -> Boolean}, which determines if
131- two booleans are equal.}
132-
133- ]
134-
135- Tests for these primitives have not been provided in @tt{test/compile.rkt},
136- therefore you will need to write appropriate tests for these primitives.
119+ @section[#:tag-prefix " a5-" #:style 'unnumbered]{Submitting}
137120
138- In order to get all the points for this section of the assignment you will
139- need to modify the following files:
121+ You should submit on Gradescope. You should submit a zip file that has
122+ exactly the same structure that the stub contains. We will only use
123+ the @tt{compile.rkt}, @tt{interp.rkt}, @tt{interp-prim.rkt}, and
124+ @tt{test/test-runner-string.rkt} files for grading, so make sure all
125+ your work is contained there!
140126
141127@itemlist[
142128
143- @item{@tt{compile.rkt}}
144-
145- @item{@tt{syntax.rkt}}
146-
147- @item{@tt{test/compile.rkt}}
148-
129+ @item{Not breaking past behavior is worth 20 points.}
130+ @item{The 4 string primitives are worth 60 points (30 interpreter, 30 compiler).}
131+ @item{Finding bugs with your tests is worth 20 points.}
149132]
150133
151- @section[#:tag-prefix " a5-" #:style 'unnumbered]{Extending the Parser}
152-
153- You should not need to make any changes to @tt{lex.rkt} or to @tt{parse.rkt},
154- but you do need to understand the structure of the resulting AST, which is why
155- the information below is provided. The grammar, along with the definitions and
156- utility functions in @tt{ast.rkt} provide all the information necessary to
157- work with the AST in implementing the new features of Hustle+.
158-
159- The parser has been extended @emph{for you} from the Fraud+ parser for the
160- Hustle+ language based on the following grammar:
161-
162- @verbatim{
163- <expr> ::= integer
164- | character
165- | boolean
166- | variable
167- | string
168- | empty
169- | ( <compound> )
170- | [ <compound> ]
171-
172- <compound> ::= <prim1> <expr>
173- | <prim2> <expr> <expr>
174- | - <expr> <maybe-expr>
175- | if <expr> <expr> <expr>
176- | cond <clause>* <else>
177- | let <bindings> <expr>
178-
179- <prim1> ::= add1 | sub1 | abs | zero? | integer->char | char->integer
180- | char? | integer? | boolean? | string? | box? | empty? | cons?
181- | box | unbox | car | cdr | string-length
182-
183- <prim2> ::= make-string | string-ref | = | < | <=
184- | char=? | boolean=? | + | cons
185-
186- <maybe-expr> ::=
187- | <expr>
188-
189- <clause> ::= ( <expr> <expr> )
190- | [ <expr> <expr> ]
191-
192- <else> ::= ( else <expr> )
193- | [ else <expr> ]
194-
195- <bindings> ::= ( <binding>* )
196- | [ <binding>* ]
197-
198- <binding> ::= ( variable <expr> )
199- | [ variable <expr> ]
200- }
201-
202- There is a lexer given to you in @tt{lex.rkt}, which provides two
203- functions: @racket[lex-string] and @racket[lex-port], which consume a
204- string or an input port, respectively, and produce a list of tokens,
205- which are defined as follows (only the new parts are shown):
206-
207- @#reader scribble/comment-reader
208- (racketblock
209- ; type Token =
210- ; ...
211- ; | '()
212- ; | String
213-
214- ; type Prim = Prim1 | Prim2 | '-
215-
216- ; type Prim1 =
217- ; | 'add1
218- ; | 'sub1
219- ; | 'zero?
220- ; | 'abs
221- ; | 'integer->char
222- ; | 'char->integer
223- ; | 'char?
224- ; | 'boolean?
225- ; | 'integer?
226- ; | 'string?
227- ; | 'box?
228- ; | 'empty?
229- ; | 'cons?
230- ; | 'box
231- ; | 'unbox
232- ; | 'car
233- ; | 'cdr
234- ; | 'string-length
235-
236- ; type Prim2 =
237- ; | 'make-string
238- ; | 'string-ref
239- ; | '=
240- ; | '<
241- ; | '<=
242- ; | 'char=?
243- ; | 'boolean=?
244- ; | '+
245- ; | 'cons
246- )
247-
248- The lexer will take care of reading the @tt{#lang racket} header and
249- remove any whitespace.
250-
251- The code in @tt{parse.rkt} implements the parser which constructs an
252- AST representing a valid Hustle+ expression, if possible, from a list
253- of tokens.
254-
255- As an example, @racket[parse] should produce
256- @racket[(prim-e `add1 (list (prim-e `sub1 (list (int-e 7)))))]
257- if given
258-
259- @racketblock['(lparen (prim add1) lparen (prim sub1) 7 rparen rparen eof)]
260-
261- @section[#:tag-prefix " a5-" #:style 'unnumbered]{Testing}
262-
263- You can test your code in several ways:
264-
265- @itemlist[
266-
267- @item{Using the command line @tt{raco test .} from
268- the directory containing the repository to test everything.}
269-
270- @item{Using the command line @tt{raco test <file>} to
271- test only @tt{<file>}.}
272-
273- @item{Pushing to github. You can
274- see test reports at:
275- @centered{@link[ " https://travis-ci.com/cmsc430/"]{
276- https://travis-ci.com/cmsc430/}}
277-
278- (You will need to be signed in in order see results for your private repo.)}]
279-
280- Note that only a small number of tests are given to you, so you should
281- write additional test cases.
282-
283- @bold{There is separate a repository for tests!} The testing set-up
284- is slightly different for this assignment. There is a whole other
285- repository that contains tests. When you push your code, Travis will
286- automatically run your code against the tests. If you would like to
287- run the tests locally, clone the following repository into the
288- directory that contains your compiler and run @tt{raco test .} to test
289- everything:
290-
291- @centered{@tt{https://github.com/cmsc430/assign05-test.git}}
292-
293- This repository will evolve as the week goes on, but any time there's
294- a significant update it will be announced on ELMS.
295-
296- @section[#:tag-prefix " a5-" #:style 'unnumbered]{Submitting}
297-
298- Pushing your local repository to github ``submits'' your work. We
299- will grade the latest submission that occurs before the deadline.
300-
134+ Just zipping the empty template we provide is worth ~30 points!
135+ Upload often to make sure you don't run into autograder issues!
0 commit comments