11#lang scribble/manual
2- @(require "../defns.rkt " )
2+ @(require "../defns.rkt "
3+ "../notes/ev.rkt " )
4+
35@title[#:tag "Assignment 5 " #:style 'unnumbered ]{Assignment 5: Let There Be (Many) Variables}
46
57@(require (for-label a86/ast (except-in racket ... )))
68
9+ @(ev '(require fraud-plus))
10+
711@bold{Due: @assign-deadline[5 ]}
812
913The goal of this assignment is to extend a compiler with binding forms
@@ -77,10 +81,49 @@ the right-hand sides of any of the @racket[let]. So, for example,
7781@racketblock[(let ((x 1 ) (y x)) 0 )] is a syntax error because the occurrence of
7882@racket[x] is not bound.
7983
84+ The given code uses the following abstract representation of
85+ @racket[let ] expressions:
86+
87+ @#reader scribble/comment-reader
88+ (racketblock
89+ ;; type Expr = ...
90+ ;; | (Let [Listof Id] [Listof Expr] Expr)
91+ (struct Let (xs es e) #:prefab )
92+ )
93+
94+ Notice that all of the variable bindings and their RHS expressions
95+ have been split into two (equal-length) lists. The third component
96+ is the body expression.
97+
98+ The provided parser has been revised to parse these @racket[let ]
99+ expressions (as well as the new operation forms):
100+
101+ @ex[
102+ (parse '(let ((x 1 )) x))
103+ (parse '(let () 1 ))
104+ (parse '(let ((x 1 ) (y 2 )) (+ x y)))
105+ ]
106+
107+ Recall that there are two parsers: @racket[parse] parses any
108+ expression form, while @racket[parse-closed] only parses closed
109+ expressions. The interpreter and compiler may assume that the program
110+ is closed (i.e. it is parsed with @racket[parse-closed]).
111+
112+ @ex[
113+ (parse 'x )
114+ (eval:error (parse-closed 'x ))
115+ (eval:error (parse-closed '(let ((x 1 ) (y x)) x)))]
116+
117+
80118The provided interpreter and compiler work when the @racket[let ]
81119expression happens to bind a single variable, but you must revise the
82120code to work for any number of bindings.
83121
122+ @ex[
123+ (interp (parse '(let ((x 1 )) (add1 x))))
124+ (eval:error (interp (parse '(let ((x 1 ) (y 2 )) (+ x y)))))
125+ (exec (parse '(let ((x 1 )) (add1 x))))
126+ (eval:error (exec (parse '(let ((x 1 ) (y 2 )) (+ x y)))))]
84127
85128@subsection[#:tag-prefix "a5- " #:style 'unnumbered ]{Back-Referencing Let}
86129
@@ -103,9 +146,53 @@ Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a
103146syntax error. However, bindings are only available forward, so
104147@racketblock[(let* ((x y) (y 1 )) 0 )] @emph{is} a syntax error.
105148
149+ The given code uses the following abstract representation of
150+ @racket[let* ] expressions:
151+
152+ @#reader scribble/comment-reader
153+ (racketblock
154+ ;; type Expr = ...
155+ ;; | (Let* [Listof Id] [Listof Expr] Expr)
156+ (struct Let* (xs es e) #:prefab )
157+ )
158+
159+ The provided parser works for @racket[let* ]
160+ expressions:
161+
162+ @ex[
163+ (parse '(let* ((x 1 )) x))
164+ (parse '(let* () 1 ))
165+ (parse '(let* ((x 1 ) (y 2 )) (+ x y)))
166+ ]
167+
168+ And the @racket[parse-closed] parser works appropriately, too:
169+
170+ @ex[
171+ (parse-closed '(let* ((x 1 ) (y 2 ) (z (add1 y))) z))]
172+
173+
106174The provided interpreter and compiler work when the @racket[let* ]
107175expression happens to bind a single variable, but you must revise the
108- code to work for any number of bindings.
176+ code to work for any number of bindings:
177+
178+ @ex[
179+ (interp (parse '(let* ((x 1 )) (add1 x))))
180+ (eval:error (interp (parse '(let* ((x 1 ) (y 2 )) (+ x y)))))
181+ (exec (parse '(let* ((x 1 )) (add1 x))))
182+ (eval:error (exec (parse '(let* ((x 1 ) (y 2 )) (+ x y)))))]
183+
184+ Note that when there is only a single binding, @racket[let ] and
185+ @racket[let* ] are equivalent.
186+
187+ @subsection[#:tag-prefix "a5- " #:style 'unnumbered ]{Testing}
188+
189+ A small number of test cases have been provided in
190+ @tt{test/test-runner.rkt}. There is function called @racket[test]
191+ that contains I/O-free test cases and another called @racket[test/io]
192+ that contains I/O tests. To run these tests, @tt{raco test
193+ test/interp.rkt} will test the interpreter and @tt{raco test
194+ test/compile.rkt} will test the compiler. You are encouraged to add
195+ your own tests.
109196
110197@section[#:tag-prefix "a5- " #:style 'unnumbered ]{Submitting}
111198
0 commit comments