Skip to content

Commit 21b860f

Browse files
authored
Merge pull request #203 from cmsc430/fall-2025
Update assign 5 with working examples.
2 parents 01d9a93 + 6038163 commit 21b860f

File tree

2 files changed

+93
-4
lines changed

2 files changed

+93
-4
lines changed

.github/workflows/push.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,14 @@ jobs:
2727
distribution: 'full'
2828
variant: 'CS'
2929
version: '8.18'
30-
- name: Install a86 and langs
30+
- name: Install a86, langs, and assignments
3131
run: |
3232
git clone https://github.com/cmsc430/a86.git
33-
git clone https://github.com/cmsc430/langs.git
33+
git clone https://github.com/cmsc430/langs.git
34+
git clone https://github.com/cmsc430/assignments.git
3435
raco pkg install --auto a86/
3536
raco pkg install --auto langs/
37+
raco pkg install --auto assignments/
3638
- name: Build and test
3739
run: |
3840
export LINK_DIR=/usr/lib/x86_64-linux-gnu

www/assignments/5.scrbl

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
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

913
The 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+
80118
The provided interpreter and compiler work when the @racket[let]
81119
expression happens to bind a single variable, but you must revise the
82120
code 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
103146
syntax 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+
106174
The provided interpreter and compiler work when the @racket[let*]
107175
expression 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

Comments
 (0)