Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion www/assignments.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down
112 changes: 89 additions & 23 deletions www/assignments/5.scrbl
Original file line number Diff line number Diff line change
@@ -1,47 +1,113 @@
#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.

@;{
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]{Overview}

@section[#:tag-prefix "a5-" #:style 'unnumbered]{Extort+}
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.

The Extort+ language extends Extort in the follow ways:
@section[#:tag-prefix "a5-" #:style 'unnumbered]{Fraud+}

The Fraud+ language extends the Fraud language we studied in class with some
new features:

@itemlist[
@item{adding @racket[when],}
@item{adding @racket[unless], and}
@item{bringing forward all the features of Dupe+.}

@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+}

@section[#:tag-prefix "a5-" #:style 'unnumbered]{Testing}
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-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
applied to the wrong type of argument.

You can test your code in several ways:
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.

@itemlist[
@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.

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.

@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 <file>} to
test only @tt{<file>}.}
@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)
]

Note that only a small number of tests are given to you, so you should
write additional test cases.
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 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.
}
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.
2 changes: 1 addition & 1 deletion www/assignments/6.scrbl
Original file line number Diff line number Diff line change
@@ -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 ...)))

Expand Down
2 changes: 1 addition & 1 deletion www/assignments/8.scrbl
Original file line number Diff line number Diff line change
@@ -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 ...)))

Expand Down
2 changes: 1 addition & 1 deletion www/assignments/9.scrbl
Original file line number Diff line number Diff line change
@@ -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 ...)))

Expand Down
1 change: 0 additions & 1 deletion www/defns.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 1 addition & 3 deletions www/notes/abscond.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -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")])
Expand Down
7 changes: 2 additions & 5 deletions www/notes/evildoer.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
67 changes: 29 additions & 38 deletions www/notes/extort.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -270,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)
Expand All @@ -301,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)
Expand All @@ -315,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)
Expand Down Expand Up @@ -427,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)))]
30 changes: 18 additions & 12 deletions www/notes/fraud.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@

@(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 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"))
@(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))

@(define this-lang "Fraud")
@(define prefix (string-append this-lang "-"))
Expand Down Expand Up @@ -66,9 +70,10 @@ 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-pre]}
@centered{@render-language[F-let]}

Which can be modeled with the following data type definition:

Expand Down Expand Up @@ -117,9 +122,10 @@ 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 concrete
@|this-lang|:

@centered[(render-language G)]
@centered[(render-language F-prim2)]

We can model it as a datatype as usual:

Expand Down