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
95 changes: 92 additions & 3 deletions www/assignments/6.scrbl
Original file line number Diff line number Diff line change
@@ -1,9 +1,98 @@
#lang scribble/manual
@(require "../defns.rkt")
@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: List primitives and n-ary primitives}
@(require "../defns.rkt"
"../notes/ev.rkt")
@title[#:tag "Assignment 6" #:style 'unnumbered]{Assignment 6: List and vector primitives}

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

@(require racket/port)

@bold{Due: @assign-deadline[6]}

Details of this assignment will be released later in the semester.
@;{ All this to silence some Makefile output on Linux -- should probably be taken care of at the Makefile level }
@(ev '(begin (define p (current-output-port))
(current-output-port (open-output-string))
(require hoax-plus)
(current-output-port p)))

The goal of this assignment is to gain proficiency with our
representation of memory-allocated values by implementing a number of
list and vector primitives.

@section[#:tag-prefix "a6-" #:style 'unnumbered]{Overview}

For this assignment, you are given a @tt{hoax-plus.zip} file on ELMS
with a starter compiler similar to the @seclink["Hoax"]{Hoax}
language we studied in class.


@section[#:tag-prefix "a6-" #:style 'unnumbered]{Hoax+}

The Hoax+ language extends the Hoax language we studied in class with four
new unary primitives:

@itemlist[
@item{@racket[length]: given a list, computes its length.}
@item{@racket[reverse]: given a list, computes a list with elements in the reverse order of the given list.}
@item{@racket[list->vector]: given a list, computes a vector with elements in the order of the given list.}
@item{@racket[vector->list]: given a vector, computes a list with elements in the order of the given vector.}
]

Unlike past assignments, you do not need to bring forward in any
features from earlier assignments.

@section[#:tag-prefix "a6-" #:style 'unnumbered]{List and vector primitves}


The new primitives have been added to the parser and the interpreter.
The behavior of compiled primitives should be consistent with the
interpreter:

@ex[
(interp (parse '(length '())))
(interp (parse '(length (cons 1 (cons 2 '())))))
(interp (parse '(length #f)))
(interp (parse '(reverse '())))
(interp (parse '(reverse (cons 1 (cons 2 '())))))
(interp (parse '(reverse #f)))
(interp (parse '(list->vector '())))
(interp (parse '(list->vector (cons 1 (cons 2 '())))))
(interp (parse '(list->vector #f)))
(interp (parse '(vector->list (make-vector 0 #t))))
(interp (parse '(vector->list (make-vector 2 #t))))
(interp (parse '(vector->list #f)))
]

The interpreter is consistent with Racket's own behavior, so if you're
unsure about what your compiler should do, you can look to Racket (or
the interpreter) for guidance:

@ex[
(length '())
(length (cons 1 (cons 2 '())))
(eval:error (length #f))
(reverse '())
(reverse (cons 1 (cons 2 '())))
(eval:error (reverse #f))
(list->vector '())
(list->vector (cons 1 (cons 2 '())))
(eval:error (list->vector #f))
(vector->list (make-vector 0 #t))
(vector->list (make-vector 2 #t))
(eval:error (vector->list #f))
]

@subsection[#:tag-prefix "a6-" #:style 'unnumbered]{Testing}

A small number of test cases have been provided in
@tt{test/test-runner.rkt}. There is function called @racket[test]
that contains I/O-free test cases and another called @racket[test/io]
that contains I/O tests. To run these tests, @tt{raco test
test/interp.rkt} will test the interpreter and @tt{raco test
test/compile.rkt} will test the compiler. You are encouraged to add
your own tests.

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

To submit, use @tt{make} from within the @tt{hoax-plus} directory to
create a zip file containing your work and submit it to Gradescope.
4 changes: 2 additions & 2 deletions www/defns.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@
"Thursday, September 25, 11:59PM"
"Thursday, October 2, 11:59PM"
"Thursday, October 23, 11:59PM"
"Thursday, October 30, 11:59PM"
"Thursday, November 6, 11:59PM"
"Tuesday, November 4, 11:59PM"
"Tuesday, November 11, 11:59PM"
"Thursday, November 20, 11:59PM"
"Thursday, December 4, 11:59PM")
(sub1 i)))
Expand Down
78 changes: 70 additions & 8 deletions www/notes/diagrams.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@

(define n 40)

(define (make-str-cells s)
(hc-append
(foldl (λ (c p)
(hc-append p
(cc-superimpose (rectangle (/ n 2) n) ((current-code-tt) (string c)))))
(cc-superimpose (rectangle n n) (code #,(string-length s)))
(string->list s))
(if (even? (string-length s))
(rectangle 0 n)
(cc-superimpose (rectangle (/ n 2) n) (code 0)))))

(define (make-imm-cell i)
(cc-superimpose
(code #,i)
Expand All @@ -17,6 +28,9 @@
(cb-superimpose (rectangle n n)
(code cons)))

(define (make-str-cell)
(cb-superimpose (rectangle n n)
(code str)))

(define (make-box-cell)
(cb-superimpose (rectangle n n)
Expand Down Expand Up @@ -72,13 +86,16 @@
[`(cons ,_) (make-cons-cell)]
[`(box ,_) (make-box-cell)]
[`(vect ,_) (make-vect-cell)]
[`(str ,_) (make-str-cell)]
[(? string?) (make-str-cells v)]
[_ (make-imm-cell v)]))

(define (add-arrows spec cells p)
;(printf "~a~n" spec)
(match spec
['() p]
[(cons `(_ ,i) s)
[(cons `(,_ ,(? integer? i)) s)

(add-arrows s
cells
(fwd-pts-to (list-ref cells (sub1 (- (length cells) (length s))))
Expand All @@ -99,17 +116,62 @@
heap)))

(define heap/arrows/label
(vc-append
0
heap/arrows
(text "heap")))
(vc-append 10
(vc-append
0
heap/arrows
(text "heap"))
(text "← lower addresses, higher addresses →")))

(define rax/label
(vc-append 0 rax (text "rax")))
(vc-append 10 (vc-append 0 rax (text "rax"))
(text " ")))

(inset
(fwd-pts-to rax (list-ref heap i) (hc-append n rax/label heap/arrows/label))
(* n 2))]))
(fwd-pts-to rax (list-ref heap i)
(hc-append n rax/label heap/arrows/label))
0 (* n 2) 0 0)]))

#;
(define cons-quiz
(list (make-heap-diagram
'((cons 4)
3
'()
2
(cons 0)
1
(cons 2)))
(make-heap-diagram
'((cons 0)
1
(cons 2)
2
(cons 4)
3
'()))
(make-heap-diagram
'((cons 4)
'()
3
(cons 0)
2
(cons 2)
1))
(make-heap-diagram
'((cons 0)
(cons 2)
1
(cons 4)
2
'()
3))
))



;(text "← lower addresses, higher addresses →")

#;
(make-heap-diagram
'((cons 0)
Expand Down
24 changes: 24 additions & 0 deletions www/notes/hoax.scrbl
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,18 @@ So, suppose we want to create the string @racket["abc"]:
(Pop rbx)
(Ret))))

This creates a string in memory like this:

@make-heap-diagram['((str 0) "abc")]


In this diagram, we use half-sized boxes to indicate that only 4 bytes
are used per codepoint. Also the contents of the array are not
values, but codepoints (shown as the letters the codepoint encodes).
In odd length strings, we write @racket[0] for the padded element, but
in reality there are arbitrary bits at that memory location, which is
fine because they will never be read.

At first glance, this looks remarkably similar to creating a vector,
however there are some imporant things to notice:

Expand Down Expand Up @@ -926,6 +938,18 @@ you are seeing here.}

]

Notice that a string like @racket["fred"] is not represented the same
as a vector of characters @racket[#(#\f #\r #\e #\d)], which uses more
space. Compare:

@make-heap-diagram['((str 0) "fred")]

versus:

@make-heap-diagram['((vect 0) 4 #\f #\r #\e #\d)]



Now let's set things up like we did before to be able to interactively
write examples in order to arrive at the code for
@racket[string-length], @racket[string-ref], and @racket[make-string]:
Expand Down