Skip to content

Commit 01d9a93

Browse files
authored
Merge pull request #202 from cmsc430/fall-2025
Fall 2025
2 parents 1e6f1ae + 4f07027 commit 01d9a93

File tree

10 files changed

+143
-86
lines changed

10 files changed

+143
-86
lines changed

www/assignments.scrbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
@include-section{assignments/7.scrbl}
1313
@include-section{assignments/8.scrbl}
1414
@include-section{assignments/9.scrbl}
15-
@include-section{assignments/10.scrbl}
15+
@;include-section{assignments/10.scrbl}
1616

1717

1818
@;{assignment 8: quote in general, and quasiquote}

www/assignments/5.scrbl

Lines changed: 89 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,113 @@
11
#lang scribble/manual
22
@(require "../defns.rkt")
3-
@title[#:tag "Assignment 5" #:style 'unnumbered]{Assignment 5: When and unless}
3+
@title[#:tag "Assignment 5" #:style 'unnumbered]{Assignment 5: Let There Be (Many) Variables}
44

55
@(require (for-label a86/ast (except-in racket ...)))
66

77
@bold{Due: @assign-deadline[5]}
88

9-
Details of this assignment will be released later in the semester.
9+
The goal of this assignment is to extend a compiler with binding forms
10+
that can take any number of arguments.
1011

11-
@;{
12-
The goal of this assignment is to extend the language developed in
13-
@secref{Extort} with new forms of control flow expressions:
14-
@racket[when]- and @racket[unless]-expressions.
12+
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Overview}
1513

16-
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Extort+}
14+
For this assignment, you are given a @tt{fraud-plus.zip} file on ELMS
15+
with a starter compiler similar to the @seclink["Fraud"]{Fraud}
16+
language we studied in class.
1717

18-
The Extort+ language extends Extort in the follow ways:
18+
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Fraud+}
19+
20+
The Fraud+ language extends the Fraud language we studied in class with some
21+
new features:
1922

2023
@itemlist[
21-
@item{adding @racket[when],}
22-
@item{adding @racket[unless], and}
23-
@item{bringing forward all the features of Dupe+.}
24+
25+
@item{The features added in @seclink["Assignment 4"]{Assignment 4}, namely:
26+
27+
@itemlist[
28+
29+
@item{@racket[abs], @racket[-], and @racket[not]}
30+
@item{@racket[cond]}
31+
@item{@racket[case]}
32+
33+
]}
34+
35+
@item{New primitives @racket[integer?] and @racket[boolean?].}
36+
37+
@item{An extended @racket[let] form that can bind multiple variables at once.}
38+
39+
@item{Back-referencing @racket[let*] form that can bind multiple variables at once.}
40+
2441
]
2542

43+
@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{From Dupe++ to Fraud+}
2644

27-
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Testing}
45+
Implement the @racket[abs], unary @racket[-], and @racket[not] operations and
46+
the @racket[cond] and @racket[case] forms from
47+
@seclink["Assignment 4"]{Assignment 4} by modifying @tt{interp.rkt},
48+
@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-ops.rkt}. You can
49+
start from your previous code, but you will need to update it to work for the
50+
code you are given. What's essentially left for you to do is to make sure to
51+
correctly signal an error (@racket['err]) when these constructs are
52+
applied to the wrong type of argument.
2853

29-
You can test your code in several ways:
54+
While you're at it, implement the predicates @racket[integer?] and
55+
@racket[boolean?] for checking the type of an argument, modeled by the
56+
@racket[char?] predicate that was covered in the lectures.
3057

31-
@itemlist[
58+
@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{Generalizing Let}
59+
60+
The Fraud language has a @tt{let} form that binds a single variable in the
61+
scope of some expression. This is a restriction of the more general form of
62+
@racket[let] that binds any number of expressions. So, for example,
63+
64+
@racketblock[
65+
(let ((x 1) (y 2) (z 3))
66+
_e)
67+
]
68+
69+
simultaneously binds @racket[x], @racket[y], and @racket[z] in the scope of
70+
@racket[_e].
71+
72+
The syntax of a @racket[let] expression allows any number of binders to occur,
73+
so @racket[(let () _e)] is valid syntax and is equivalent to @racket[_e].
74+
75+
The binding of each variable is only in-scope within the body, @bold{not} in
76+
the right-hand sides of any of the @racket[let]. So, for example,
77+
@racketblock[(let ((x 1) (y x)) 0)] is a syntax error because the occurrence of
78+
@racket[x] is not bound.
79+
80+
The provided interpreter and compiler work when the @racket[let]
81+
expression happens to bind a single variable, but you must revise the
82+
code to work for any number of bindings.
3283

33-
@item{Using the command line @tt{raco test .} from
34-
the directory containing the repository to test everything.}
3584

36-
@item{Using the command line @tt{raco test <file>} to
37-
test only @tt{<file>}.}
85+
@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{Back-Referencing Let}
86+
87+
Similar to @racket[let], there is also @racket[let*] that can also bind any
88+
number of expressions. The difference is that previous bindings are available
89+
in the right-hand sides of subsequent bindings. For example,
90+
91+
@racketblock[
92+
(let* ((x 1) (y 2) (z (add1 y)))
93+
_e)
3894
]
3995

40-
Note that only a small number of tests are given to you, so you should
41-
write additional test cases.
96+
binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in
97+
the scope of @racket[_e].
98+
99+
The syntax of a @racket[let*] expression allows any number of binders to occur,
100+
so @racket[(let* () _e)] is valid syntax and is equivalent to @racket[_e].
101+
102+
Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a
103+
syntax error. However, bindings are only available forward, so
104+
@racketblock[(let* ((x y) (y 1)) 0)] @emph{is} a syntax error.
105+
106+
The provided interpreter and compiler work when the @racket[let*]
107+
expression happens to bind a single variable, but you must revise the
108+
code to work for any number of bindings.
42109

43110
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Submitting}
44111

45-
To submit, use @tt{make} from within the code directory to create a
46-
zip file containing your work and submit it to Gradescope.
47-
}
112+
To submit, use @tt{make} from within the @tt{fraud-plus} directory to
113+
create a zip file containing your work and submit it to Gradescope.

www/assignments/6.scrbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#lang scribble/manual
22
@(require "../defns.rkt")
3-
@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: Binding many variables}
3+
@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: List primitives and n-ary primitives}
44

55
@(require (for-label a86 (except-in racket ...)))
66

www/assignments/8.scrbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#lang scribble/manual
22
@(require "../defns.rkt")
3-
@title[#:tag "Assignment 8" #:style 'unnumbered]{Assignment 8: List primitives}
3+
@title[#:tag "Assignment 8" #:style 'unnumbered]{Assignment 8: Functions with default arguments}
44

55
@(require (for-label a86 (except-in racket ...)))
66

www/assignments/9.scrbl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#lang scribble/manual
22
@(require "../defns.rkt")
3-
@title[#:tag "Assignment 9" #:style 'unnumbered]{Assignment 9: Functions with default arguments}
3+
@title[#:tag "Assignment 9" #:style 'unnumbered]{Assignment 9: Patterns}
44

55
@(require (for-label a86 (except-in racket ...)))
66

www/defns.rkt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
"Thursday, September 18, 11:59PM"
5959
"Thursday, September 25, 11:59PM"
6060
"Thursday, October 2, 11:59PM"
61-
"Thursday, October 9, 11:59PM"
6261
"Thursday, October 23, 11:59PM"
6362
"Thursday, October 30, 11:59PM"
6463
"Thursday, November 6, 11:59PM"

www/notes/abscond.scrbl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313

1414
@(define codeblock-include (make-codeblock-include #'here))
1515

16-
@(ev '(require rackunit a86))
17-
@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "abscond" f))))))
18-
'("main.rkt" "correct.rkt"))
16+
@(ev '(require rackunit a86 abscond abscond/correct))
1917

2018
@(define (shellbox . s)
2119
(parameterize ([current-directory (build-path langs "abscond")])

www/notes/evildoer.scrbl

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@
1818

1919
@(define codeblock-include (make-codeblock-include #'h))
2020

21-
@(ev '(require rackunit a86))
22-
@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "evildoer" f))))))
23-
'("main.rkt" "compile-ops.rkt" "correct.rkt"))
24-
21+
@(ev '(require rackunit a86 evildoer evildoer/correct evildoer/compile-ops))
22+
@;{This is needed for the example that uses current-objs}
2523
@(ev `(current-directory ,(path->string (build-path langs "evildoer"))))
26-
@(void (ev '(with-output-to-string (thunk (system "make runtime.o")))))
2724

2825
@(require (for-syntax racket/base))
2926
@(begin-for-syntax

www/notes/extort.scrbl

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@
1515

1616
@(define codeblock-include (make-codeblock-include #'h))
1717

18-
@(ev '(require rackunit a86))
19-
@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "extort" f))))))
20-
'("main.rkt" "correct.rkt" "compile-ops.rkt"))
18+
@(ev '(require rackunit a86 extort extort/compile-ops extort/correct))
2119

22-
@(ev `(current-directory ,(path->string (build-path langs "extort"))))
23-
@(void (ev '(with-output-to-string (thunk (system "make runtime.o")))))
2420
@;{Hack to get un-provided functions from compile-ops}
2521
@(ev '(require (only-in rackunit require/expose)))
2622
@(ev '(require/expose extort/compile-ops [assert-integer assert-char assert-byte assert-codepoint]))
@@ -270,20 +266,19 @@ check:
270266
(ex
271267
;; Produces (add1 v) if v is an integer value, #f otherwise
272268
(define (plus1 v) ;; Value -> Integer | Boolean
273-
(bits->value
274-
(asm-interp
275-
(prog (Global 'entry)
276-
(Label 'entry)
277-
(Mov 'rax (value->bits v))
278-
(Mov 'r9 'rax)
279-
(And 'r9 mask-int)
280-
(Cmp 'r9 type-int)
281-
(Jne 'err)
282-
(Add 'rax (value->bits 1))
283-
(Ret)
284-
(Label 'err)
285-
(Mov 'rax (value->bits #f))
286-
(Ret)))))
269+
(run
270+
(prog (Global 'entry)
271+
(Label 'entry)
272+
(Mov 'rax (value->bits v))
273+
(Mov 'r9 'rax)
274+
(And 'r9 mask-int)
275+
(Cmp 'r9 type-int)
276+
(Jne 'err)
277+
(Add 'rax (value->bits 1))
278+
(Ret)
279+
(Label 'err)
280+
(Mov 'rax (value->bits #f))
281+
(Ret))))
287282

288283
(plus1 0)
289284
(plus1 1)
@@ -301,8 +296,7 @@ error. The @racket[asm-interp] intercepts these calls are returns the
301296
@racket['err] symbol to match what the interpreter does:
302297

303298
@ex[
304-
(current-objs '("runtime.o"))
305-
(asm-interp
299+
(run
306300
(prog (Global 'entry)
307301
(Label 'entry)
308302
(Extern 'raise_error)
@@ -315,22 +309,19 @@ error:
315309
(ex
316310
;; Produces (add1 v) if v is an integer, 'err otherwise
317311
(define (plus1 v) ;; Value -> Integer | 'err
318-
(match
319-
(asm-interp
320-
(prog (Global 'entry)
321-
(Label 'entry)
322-
(Mov 'rax (value->bits v))
323-
(Mov 'r9 'rax)
324-
(And 'r9 mask-int)
325-
(Cmp 'r9 type-int)
326-
(Jne 'err)
327-
(Add 'rax (value->bits 1))
328-
(Ret)
329-
(Label 'err)
330-
(Extern 'raise_error)
331-
(Call 'raise_error)))
332-
['err 'err]
333-
[b (bits->value b)]))
312+
(run
313+
(prog (Global 'entry)
314+
(Label 'entry)
315+
(Mov 'rax (value->bits v))
316+
(Mov 'r9 'rax)
317+
(And 'r9 mask-int)
318+
(Cmp 'r9 type-int)
319+
(Jne 'err)
320+
(Add 'rax (value->bits 1))
321+
(Ret)
322+
(Label 'err)
323+
(Extern 'raise_error)
324+
(Call 'raise_error))))
334325

335326
(plus1 0)
336327
(plus1 1)
@@ -427,6 +418,6 @@ totality of the semantics:
427418
And again, we can randomly test the compiler by generating programs and inputs:
428419

429420
@ex[
430-
(require "random.rkt")
421+
(require extort/random)
431422
(for ((i 100))
432423
(check-compiler (random-expr) (random-input)))]

www/notes/fraud.scrbl

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,26 @@
22

33
@(require (for-label (except-in racket ... compile) a86/ast))
44
@(require redex/pict
5+
redex/reduction-semantics
56
racket/runtime-path
67
scribble/examples
7-
(except-in fraud/semantics ext lookup)
8-
(prefix-in sem: (only-in fraud/semantics ext lookup))
98
"utils.rkt"
109
"ev.rkt"
1110
"../utils.rkt")
1211

13-
@(define codeblock-include (make-codeblock-include #'h))
1412

15-
@(ev '(require rackunit a86))
16-
@(ev `(current-directory ,(path->string (build-path langs "fraud"))))
17-
@(void (ev '(with-output-to-string (thunk (system "make runtime.o")))))
18-
@(for-each (λ (f) (ev `(require (file ,f))))
19-
'("main.rkt" "translate.rkt"))
13+
@(define-language L (e ::= ignored))
14+
@(define-extended-language F-let L
15+
(e ::= .... x (let ((x e)) e))
16+
(x ::= variable))
17+
18+
@(define-extended-language F-prim2 L
19+
(e ::= .... (p2 e_1 e_2))
20+
(p2 ::= + - < =))
21+
22+
@(define codeblock-include (make-codeblock-include #'h))
2023

24+
@(ev '(require rackunit a86 fraud fraud/translate))
2125

2226
@(define this-lang "Fraud")
2327
@(define prefix (string-append this-lang "-"))
@@ -66,9 +70,10 @@ what it should produce.
6670
Adding a notion of variable binding also means we need to add
6771
variables to the syntax of expressions.
6872

69-
Together this leads to the following grammar for @|this-lang|:
73+
Together this leads to the following grammar for concrete
74+
@|this-lang|:
7075

71-
@centered{@render-language[F-pre]}
76+
@centered{@render-language[F-let]}
7277

7378
Which can be modeled with the following data type definition:
7479

@@ -117,9 +122,10 @@ What's new are the following @emph{binary} operations:
117122
(= _e0 _e1)
118123
]
119124

120-
This leads to the following revised grammar for @|this-lang|:
125+
This leads to the following additions to the grammar for concrete
126+
@|this-lang|:
121127

122-
@centered[(render-language G)]
128+
@centered[(render-language F-prim2)]
123129

124130
We can model it as a datatype as usual:
125131

0 commit comments

Comments
 (0)