From 22def6f4ba17101ce36641127a3d380d0882169e Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Thu, 25 Sep 2025 21:58:32 -0400 Subject: [PATCH 1/6] Clean up requires in notes. --- www/notes/abscond.scrbl | 4 +--- www/notes/evildoer.scrbl | 7 ++----- www/notes/extort.scrbl | 6 +----- www/notes/fraud.scrbl | 7 +------ 4 files changed, 5 insertions(+), 19 deletions(-) diff --git a/www/notes/abscond.scrbl b/www/notes/abscond.scrbl index ce9a20b2..b8ab85b6 100644 --- a/www/notes/abscond.scrbl +++ b/www/notes/abscond.scrbl @@ -13,9 +13,7 @@ @(define codeblock-include (make-codeblock-include #'here)) -@(ev '(require rackunit a86)) -@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "abscond" f)))))) - '("main.rkt" "correct.rkt")) +@(ev '(require rackunit a86 abscond abscond/correct)) @(define (shellbox . s) (parameterize ([current-directory (build-path langs "abscond")]) diff --git a/www/notes/evildoer.scrbl b/www/notes/evildoer.scrbl index b02ff0bd..794bc823 100644 --- a/www/notes/evildoer.scrbl +++ b/www/notes/evildoer.scrbl @@ -18,12 +18,9 @@ @(define codeblock-include (make-codeblock-include #'h)) -@(ev '(require rackunit a86)) -@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "evildoer" f)))))) - '("main.rkt" "compile-ops.rkt" "correct.rkt")) - +@(ev '(require rackunit a86 evildoer evildoer/correct evildoer/compile-ops)) +@;{This is needed for the example that uses current-objs} @(ev `(current-directory ,(path->string (build-path langs "evildoer")))) -@(void (ev '(with-output-to-string (thunk (system "make runtime.o"))))) @(require (for-syntax racket/base)) @(begin-for-syntax diff --git a/www/notes/extort.scrbl b/www/notes/extort.scrbl index d95279eb..dc548060 100644 --- a/www/notes/extort.scrbl +++ b/www/notes/extort.scrbl @@ -15,12 +15,8 @@ @(define codeblock-include (make-codeblock-include #'h)) -@(ev '(require rackunit a86)) -@(for-each (λ (f) (ev `(require (file ,(path->string (build-path langs "extort" f)))))) - '("main.rkt" "correct.rkt" "compile-ops.rkt")) +@(ev '(require rackunit a86 extort extort/compile-ops extort/correct)) -@(ev `(current-directory ,(path->string (build-path langs "extort")))) -@(void (ev '(with-output-to-string (thunk (system "make runtime.o"))))) @;{Hack to get un-provided functions from compile-ops} @(ev '(require (only-in rackunit require/expose))) @(ev '(require/expose extort/compile-ops [assert-integer assert-char assert-byte assert-codepoint])) diff --git a/www/notes/fraud.scrbl b/www/notes/fraud.scrbl index 71afcb38..c47d9ec7 100644 --- a/www/notes/fraud.scrbl +++ b/www/notes/fraud.scrbl @@ -12,12 +12,7 @@ @(define codeblock-include (make-codeblock-include #'h)) -@(ev '(require rackunit a86)) -@(ev `(current-directory ,(path->string (build-path langs "fraud")))) -@(void (ev '(with-output-to-string (thunk (system "make runtime.o"))))) -@(for-each (λ (f) (ev `(require (file ,f)))) - '("main.rkt" "translate.rkt")) - +@(ev '(require rackunit a86 fraud fraud/translate)) @(define this-lang "Fraud") @(define prefix (string-append this-lang "-")) From fe6d2162e98dede1f8777a99e2907720314b7962 Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Fri, 26 Sep 2025 07:28:33 -0400 Subject: [PATCH 2/6] Fix concrete grammar, remove dependence on semantic files in Fraud lang. --- www/notes/fraud.scrbl | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/www/notes/fraud.scrbl b/www/notes/fraud.scrbl index c47d9ec7..9fa8382f 100644 --- a/www/notes/fraud.scrbl +++ b/www/notes/fraud.scrbl @@ -2,14 +2,23 @@ @(require (for-label (except-in racket ... compile) a86/ast)) @(require redex/pict + redex/reduction-semantics racket/runtime-path scribble/examples - (except-in fraud/semantics ext lookup) - (prefix-in sem: (only-in fraud/semantics ext lookup)) "utils.rkt" "ev.rkt" "../utils.rkt") + +@(define-language L (e ::= ignored)) +@(define-extended-language F-let L + (e ::= .... x (let ((x e)) e)) + (x ::= variable)) + +@(define-extended-language F-prim2 L + (e ::= .... (p2 e_1 e_2)) + (p2 ::= + - = <)) + @(define codeblock-include (make-codeblock-include #'h)) @(ev '(require rackunit a86 fraud fraud/translate)) @@ -63,7 +72,7 @@ variables to the syntax of expressions. Together this leads to the following grammar for @|this-lang|: -@centered{@render-language[F-pre]} +@centered{@render-language[F-let]} Which can be modeled with the following data type definition: @@ -112,9 +121,9 @@ What's new are the following @emph{binary} operations: (= _e0 _e1) ] -This leads to the following revised grammar for @|this-lang|: +This leads to the following additions to the grammar for @|this-lang|: -@centered[(render-language G)] +@centered[(render-language F-prim2)] We can model it as a datatype as usual: From 4deb630acba65194e072d026897a3505d040b563 Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Tue, 7 Oct 2025 11:26:03 -0400 Subject: [PATCH 3/6] Tweak. --- www/notes/fraud.scrbl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/www/notes/fraud.scrbl b/www/notes/fraud.scrbl index 9fa8382f..1120f3fb 100644 --- a/www/notes/fraud.scrbl +++ b/www/notes/fraud.scrbl @@ -17,7 +17,7 @@ @(define-extended-language F-prim2 L (e ::= .... (p2 e_1 e_2)) - (p2 ::= + - = <)) + (p2 ::= + - < =)) @(define codeblock-include (make-codeblock-include #'h)) @@ -70,7 +70,8 @@ what it should produce. Adding a notion of variable binding also means we need to add variables to the syntax of expressions. -Together this leads to the following grammar for @|this-lang|: +Together this leads to the following grammar for concrete +@|this-lang|: @centered{@render-language[F-let]} @@ -121,7 +122,8 @@ What's new are the following @emph{binary} operations: (= _e0 _e1) ] -This leads to the following additions to the grammar for @|this-lang|: +This leads to the following additions to the grammar for concrete +@|this-lang|: @centered[(render-language F-prim2)] From 43f0692b55c2fa8ed8fb31665090b4e921601b67 Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Tue, 7 Oct 2025 17:09:14 -0400 Subject: [PATCH 4/6] Fix up runtime path issue with Extort notes. --- www/notes/extort.scrbl | 61 +++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/www/notes/extort.scrbl b/www/notes/extort.scrbl index dc548060..5957ba96 100644 --- a/www/notes/extort.scrbl +++ b/www/notes/extort.scrbl @@ -266,20 +266,19 @@ check: (ex ;; Produces (add1 v) if v is an integer value, #f otherwise (define (plus1 v) ;; Value -> Integer | Boolean - (bits->value - (asm-interp - (prog (Global 'entry) - (Label 'entry) - (Mov 'rax (value->bits v)) - (Mov 'r9 'rax) - (And 'r9 mask-int) - (Cmp 'r9 type-int) - (Jne 'err) - (Add 'rax (value->bits 1)) - (Ret) - (Label 'err) - (Mov 'rax (value->bits #f)) - (Ret))))) + (run + (prog (Global 'entry) + (Label 'entry) + (Mov 'rax (value->bits v)) + (Mov 'r9 'rax) + (And 'r9 mask-int) + (Cmp 'r9 type-int) + (Jne 'err) + (Add 'rax (value->bits 1)) + (Ret) + (Label 'err) + (Mov 'rax (value->bits #f)) + (Ret)))) (plus1 0) (plus1 1) @@ -297,8 +296,7 @@ error. The @racket[asm-interp] intercepts these calls are returns the @racket['err] symbol to match what the interpreter does: @ex[ -(current-objs '("runtime.o")) -(asm-interp +(run (prog (Global 'entry) (Label 'entry) (Extern 'raise_error) @@ -311,22 +309,19 @@ error: (ex ;; Produces (add1 v) if v is an integer, 'err otherwise (define (plus1 v) ;; Value -> Integer | 'err - (match - (asm-interp - (prog (Global 'entry) - (Label 'entry) - (Mov 'rax (value->bits v)) - (Mov 'r9 'rax) - (And 'r9 mask-int) - (Cmp 'r9 type-int) - (Jne 'err) - (Add 'rax (value->bits 1)) - (Ret) - (Label 'err) - (Extern 'raise_error) - (Call 'raise_error))) - ['err 'err] - [b (bits->value b)])) + (run + (prog (Global 'entry) + (Label 'entry) + (Mov 'rax (value->bits v)) + (Mov 'r9 'rax) + (And 'r9 mask-int) + (Cmp 'r9 type-int) + (Jne 'err) + (Add 'rax (value->bits 1)) + (Ret) + (Label 'err) + (Extern 'raise_error) + (Call 'raise_error)))) (plus1 0) (plus1 1) @@ -423,6 +418,6 @@ totality of the semantics: And again, we can randomly test the compiler by generating programs and inputs: @ex[ -(require "random.rkt") +(require extort/random) (for ((i 100)) (check-compiler (random-expr) (random-input)))] From 5febfae1100e2477f7f1f3dd0e3c38a24363f628 Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Tue, 7 Oct 2025 17:11:20 -0400 Subject: [PATCH 5/6] Revised assignment schedule, publish assign 5. --- www/assignments.scrbl | 2 +- www/assignments/5.scrbl | 100 ++++++++++++++++++++++++++++++++++++++-- www/assignments/6.scrbl | 2 +- www/assignments/8.scrbl | 2 +- www/assignments/9.scrbl | 2 +- www/defns.rkt | 1 - 6 files changed, 101 insertions(+), 8 deletions(-) diff --git a/www/assignments.scrbl b/www/assignments.scrbl index 1a3d71e8..8f6f5246 100644 --- a/www/assignments.scrbl +++ b/www/assignments.scrbl @@ -12,7 +12,7 @@ @include-section{assignments/7.scrbl} @include-section{assignments/8.scrbl} @include-section{assignments/9.scrbl} -@include-section{assignments/10.scrbl} +@;include-section{assignments/10.scrbl} @;{assignment 8: quote in general, and quasiquote} diff --git a/www/assignments/5.scrbl b/www/assignments/5.scrbl index 12192892..86efa8b2 100644 --- a/www/assignments/5.scrbl +++ b/www/assignments/5.scrbl @@ -1,12 +1,106 @@ #lang scribble/manual @(require "../defns.rkt") -@title[#:tag "Assignment 5" #:style 'unnumbered]{Assignment 5: When and unless} +@title[#:tag "Assignment 5" #:style 'unnumbered]{Assignment 5: Let There Be (Many) Variables} @(require (for-label a86/ast (except-in racket ...))) @bold{Due: @assign-deadline[5]} -Details of this assignment will be released later in the semester. +The goal of this assignment is to extend a compiler with binding forms +that can take any number of arguments. + +@section[#:tag-prefix "a5-" #:style 'unnumbered]{Overview} + +For this assignment, you are given a @tt{fraud-plus.zip} file on ELMS +with a starter compiler similar to the @seclink["Fraud"]{Fraud} +language we studied in class. + +@section[#:tag-prefix "a5-" #:style 'unnumbered]{Fraud+} + +The Fraud+ language extends the Fraud language we studied in class with some +new features: + +@itemlist[ + +@item{The features added in @seclink["Assignment 4"]{Assignment 4}, namely: + + @itemlist[ + + @item{@racket[abs], @racket[-], and @racket[not]} + @item{@racket[cond]} + @item{@racket[case]} + + ]} + +@item{New primitives @racket[integer?] and @racket[boolean?].} + +@item{An extended @racket[let] form that can bind multiple variables at once.} + +@item{Back-referencing @racket[let*] form that can bind multiple variables at once.} + +] + +@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{From Dupe++ to Fraud+} + +Implement the @racket[abs], unary @racket[-], and @racket[not] operations and +the @racket[cond] and @racket[case] forms from +@seclink["Assignment 4"]{Assignment 4} by modifying @tt{interp.rkt}, +@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-op.rkt}. You can +start from your previous code, but you will need to update it to work for the +code you are given. What's essentially left for you to do is to make sure to +correctly signal an error (@racket['err]) when these constructs are +applied to the wrong type of argument. + +While you're at it, implement the predicates @racket[integer?] and +@racket[boolean?] for checking the type of an argument, modeled by the +@racket[char?] predicate that was covered in the lectures. + +@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{Generalizing Let} + +The Fraud language has a @tt{let} form that binds a single variable in the +scope of some expression. This is a restriction of the more general form of +@racket[let] that binds any number of expressions. So, for example, + +@racketblock[ +(let ((x 1) (y 2) (z 3)) + _e) +] + +simultaneously binds @racket[x], @racket[y], and @racket[z] in the scope of +@racket[_e]. + +The syntax of a @racket[let] expression allows any number of binders to occur, +so @racket[(let () _e)] is valid syntax and is equivalent to @racket[_e]. + +The binding of each variable is only in-scope within the body, @bold{not} in +the right-hand sides of any of the @racket[let]. So, for example, +@racketblock[(let ((x 1) (y x)) 0)] is a syntax error because the occurrence of +@racket[x] is not bound. + + +@subsection[#:tag-prefix "a5-" #:style 'unnumbered]{Back-Referencing Let} + +Similar to @racket[let], there is also @racket[let*] that can also bind any +number of expressions. The difference is that previous bindings are available +in the right-hand sides of subsequent bindings. For example, + +@racketblock[ +(let* ((x 1) (y 2) (z (add1 y))) + _e) +] + +binds @racket[x] to 1, @racket[y] to 2, and @racket[z] to 3 in +the scope of @racket[_e]. + +The syntax of a @racket[let*] expression allows any number of binders to occur, +so @racket[(let* () _e)] is valid syntax and is equivalent to @racket[_e]. + +Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a +syntax error. However, bindings are only available forward, so +@racketblock[(let* ((x y) (y 1)) 0)] @emph{is} a syntax error. + + + @;{ The goal of this assignment is to extend the language developed in @@ -20,7 +114,7 @@ The Extort+ language extends Extort in the follow ways: @itemlist[ @item{adding @racket[when],} @item{adding @racket[unless], and} -@item{bringing forward all the features of Dupe+.} +@item{bringing forward all the features of Dupe++.} ] diff --git a/www/assignments/6.scrbl b/www/assignments/6.scrbl index 6fa300c9..aace6dc9 100644 --- a/www/assignments/6.scrbl +++ b/www/assignments/6.scrbl @@ -1,6 +1,6 @@ #lang scribble/manual @(require "../defns.rkt") -@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: Binding many variables} +@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: List primitives and n-ary primitives} @(require (for-label a86 (except-in racket ...))) diff --git a/www/assignments/8.scrbl b/www/assignments/8.scrbl index 7cb3f28e..5755b31f 100644 --- a/www/assignments/8.scrbl +++ b/www/assignments/8.scrbl @@ -1,6 +1,6 @@ #lang scribble/manual @(require "../defns.rkt") -@title[#:tag "Assignment 8" #:style 'unnumbered]{Assignment 8: List primitives} +@title[#:tag "Assignment 8" #:style 'unnumbered]{Assignment 8: Functions with default arguments} @(require (for-label a86 (except-in racket ...))) diff --git a/www/assignments/9.scrbl b/www/assignments/9.scrbl index d9b501b0..6f5d77f2 100644 --- a/www/assignments/9.scrbl +++ b/www/assignments/9.scrbl @@ -1,6 +1,6 @@ #lang scribble/manual @(require "../defns.rkt") -@title[#:tag "Assignment 9" #:style 'unnumbered]{Assignment 9: Functions with default arguments} +@title[#:tag "Assignment 9" #:style 'unnumbered]{Assignment 9: Patterns} @(require (for-label a86 (except-in racket ...))) diff --git a/www/defns.rkt b/www/defns.rkt index 6c813a86..2d675351 100644 --- a/www/defns.rkt +++ b/www/defns.rkt @@ -58,7 +58,6 @@ "Thursday, September 18, 11:59PM" "Thursday, September 25, 11:59PM" "Thursday, October 2, 11:59PM" - "Thursday, October 9, 11:59PM" "Thursday, October 23, 11:59PM" "Thursday, October 30, 11:59PM" "Thursday, November 6, 11:59PM" From 4f070276ec1ecb0f9c51b83ec7ca648e2db113f8 Mon Sep 17 00:00:00 2001 From: David Van Horn Date: Tue, 7 Oct 2025 17:22:54 -0400 Subject: [PATCH 6/6] Slight revision to assign 5. --- www/assignments/5.scrbl | 48 +++++++++-------------------------------- 1 file changed, 10 insertions(+), 38 deletions(-) diff --git a/www/assignments/5.scrbl b/www/assignments/5.scrbl index 86efa8b2..095265fe 100644 --- a/www/assignments/5.scrbl +++ b/www/assignments/5.scrbl @@ -45,7 +45,7 @@ new features: Implement the @racket[abs], unary @racket[-], and @racket[not] operations and the @racket[cond] and @racket[case] forms from @seclink["Assignment 4"]{Assignment 4} by modifying @tt{interp.rkt}, -@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-op.rkt}. You can +@tt{interp-prim.rkt}, @tt{compile.rkt}, and @tt{compile-ops.rkt}. You can start from your previous code, but you will need to update it to work for the code you are given. What's essentially left for you to do is to make sure to correctly signal an error (@racket['err]) when these constructs are @@ -77,6 +77,10 @@ the right-hand sides of any of the @racket[let]. So, for example, @racketblock[(let ((x 1) (y x)) 0)] is a syntax error because the occurrence of @racket[x] is not bound. +The provided interpreter and compiler work when the @racket[let] +expression happens to bind a single variable, but you must revise the +code to work for any number of bindings. + @subsection[#:tag-prefix "a5-" #:style 'unnumbered]{Back-Referencing Let} @@ -99,43 +103,11 @@ Unlike @racket[let], @racketblock[(let* ((x 1) (y x)) 0)] is @emph{not} a syntax error. However, bindings are only available forward, so @racketblock[(let* ((x y) (y 1)) 0)] @emph{is} a syntax error. - - - -@;{ -The goal of this assignment is to extend the language developed in -@secref{Extort} with new forms of control flow expressions: -@racket[when]- and @racket[unless]-expressions. - -@section[#:tag-prefix "a5-" #:style 'unnumbered]{Extort+} - -The Extort+ language extends Extort in the follow ways: - -@itemlist[ -@item{adding @racket[when],} -@item{adding @racket[unless], and} -@item{bringing forward all the features of Dupe++.} -] - - -@section[#:tag-prefix "a5-" #:style 'unnumbered]{Testing} - -You can test your code in several ways: - -@itemlist[ - - @item{Using the command line @tt{raco test .} from - the directory containing the repository to test everything.} - - @item{Using the command line @tt{raco test } to - test only @tt{}.} -] - -Note that only a small number of tests are given to you, so you should -write additional test cases. +The provided interpreter and compiler work when the @racket[let*] +expression happens to bind a single variable, but you must revise the +code to work for any number of bindings. @section[#:tag-prefix "a5-" #:style 'unnumbered]{Submitting} -To submit, use @tt{make} from within the code directory to create a -zip file containing your work and submit it to Gradescope. -} \ No newline at end of file +To submit, use @tt{make} from within the @tt{fraud-plus} directory to +create a zip file containing your work and submit it to Gradescope.