|
| 1 | +#lang scribble/manual |
| 2 | + |
| 3 | +@(require (for-label racket)) |
| 4 | + |
| 5 | +@title{Midterm 1} |
| 6 | + |
| 7 | +@bold{Due: Tues, Oct 8, 11:59PM} |
| 8 | + |
| 9 | +@(define repo "https://classroom.github.com/a/-N-q7mJ7") |
| 10 | + |
| 11 | +Midterm repository: |
| 12 | +@centered{@link[repo repo]} |
| 13 | + |
| 14 | +The repository contains a single plaintext file @tt{m1.txt}, which you |
| 15 | +can edit to submit your answers to the following questions. Your |
| 16 | +submision must be pushed by midnight on Tuesday. |
| 17 | + |
| 18 | +During the 48 hours of the exam period, you may only ask private |
| 19 | +questions on Piazza if you need assistance for the course staff. You |
| 20 | +may not comminicate or collaborate with any one else about the content |
| 21 | +of this exam. |
| 22 | + |
| 23 | +@section{Short answer} |
| 24 | + |
| 25 | +@bold{Question 1} |
| 26 | + |
| 27 | +[10 points] |
| 28 | + |
| 29 | +Briefly describe the difference, if any, between these two Asm instructions: |
| 30 | + |
| 31 | +@verbatim{ |
| 32 | +(mov rax rbx) |
| 33 | +} |
| 34 | + |
| 35 | +@verbatim{ |
| 36 | +(mov rax (offset rbx 0)) |
| 37 | +} |
| 38 | + |
| 39 | +@bold{Question 2} |
| 40 | + |
| 41 | +[10 points] |
| 42 | + |
| 43 | +Briefly describe the difference, if any, between these two Asm instructions: |
| 44 | + |
| 45 | +@verbatim{ |
| 46 | +(mov rax (offset rbx 0)) |
| 47 | +} |
| 48 | + |
| 49 | +@verbatim{ |
| 50 | +(mov (offset rbx 0) rax) |
| 51 | +} |
| 52 | + |
| 53 | +@section{Representation} |
| 54 | + |
| 55 | +@bold{Question 3} |
| 56 | + |
| 57 | +[20 points] |
| 58 | + |
| 59 | +When studying the @secref{Dupe} language, we used the least |
| 60 | +significant bit of a 64-bit integer to indicate whether the value |
| 61 | +being represented was an integer (tagged with @code[#:lang |
| 62 | +"racket"]{#b0}) or a boolean (tagged with @code[#:lang |
| 63 | +"racket"]{#b1}). |
| 64 | + |
| 65 | +Cosider the following alternative design: @racket[#t] is represented |
| 66 | +by the number 0, @racket[#f] is represented by the number 1. All other |
| 67 | +numbers beside 0 and 1 are used to represent integers. |
| 68 | + |
| 69 | +@itemlist[ |
| 70 | + |
| 71 | +@item{Describe one way in which this design is worse that the tagging |
| 72 | +approach.} |
| 73 | + |
| 74 | +@item{Describe on way in which this design is better.} |
| 75 | + |
| 76 | +@item{Describe, at a high-level in English, how you could implement |
| 77 | +@racket[add1] using this design.} |
| 78 | + |
| 79 | +] |
| 80 | + |
| 81 | +@section{Interpreting Boolean connectives} |
| 82 | + |
| 83 | +@bold{Question 4} |
| 84 | + |
| 85 | +[25 points] |
| 86 | + |
| 87 | +Consider the following interpreter from @secref{Extort}. |
| 88 | + |
| 89 | +@#reader scribble/comment-reader |
| 90 | +(racketblock |
| 91 | +;; type Answer = Value | 'err |
| 92 | + |
| 93 | +;; Expr -> Answer |
| 94 | +(define (interp e) |
| 95 | + (match e |
| 96 | + [(? integer? i) i] |
| 97 | + [(? boolean? b) b] |
| 98 | + [`(add1 ,e0) |
| 99 | + (match (interp e0) |
| 100 | + [(? integer? i) (add1 i)] |
| 101 | + [_ 'err])] |
| 102 | + [`(sub1 ,e0) |
| 103 | + (match (interp e0) |
| 104 | + [(? integer? i) (sub1 i)] |
| 105 | + [_ 'err])] |
| 106 | + [`(zero? ,e0) |
| 107 | + (match (interp e0) |
| 108 | + [(? integer? i) (zero? i)] |
| 109 | + [_ 'err])] |
| 110 | + [`(if ,e0 ,e1 ,e2) |
| 111 | + (match (interp e0) |
| 112 | + ['err 'err] |
| 113 | + [v |
| 114 | + (if v |
| 115 | + (interp e1) |
| 116 | + (interp e2))])])) |
| 117 | + |
| 118 | +) |
| 119 | + |
| 120 | +Now extend the interpreter to include @racket[and] and @racket[or] |
| 121 | +connectives similar to those found in Racket. |
| 122 | + |
| 123 | +The @racket[or] form takes any number of subexpressions. The |
| 124 | +subexpressions are evaluated from left to right until a subexpression |
| 125 | +evaluates to a non-@racket[#f] value, which is produces by the |
| 126 | +@racket[or]. If no such subexpression exists, then @racket[#f] is |
| 127 | +produced. |
| 128 | + |
| 129 | +The @racket[and] form is similar. It takes any number of |
| 130 | +subexpressions. The subexpressions are evaluated from left to right |
| 131 | +until a subexpression evaluates to a @racket[#f] value, which is |
| 132 | +produced by @racket[and]. Otherwise, @racket[and] produces the value |
| 133 | +of the last subexpression. If there are no subexpressions, then |
| 134 | +@racket[#f] is produced. |
| 135 | + |
| 136 | +To make things interesting, you should not use Racket's @racket[and] |
| 137 | +and @racket[or] in @racket[interp]. |
| 138 | + |
| 139 | +@section{Compiling a new primitive operation} |
| 140 | + |
| 141 | +@bold{Question 5} |
| 142 | + |
| 143 | +[35 points] |
| 144 | + |
| 145 | +Consider the following excerpt of a compiler that is able to compile |
| 146 | +the @racket[cons] primitive and empty lists @racket['()]. The |
| 147 | +relevant representation information is given as is the function for |
| 148 | +compiling @racket[cons]: |
| 149 | + |
| 150 | +@#reader scribble/comment-reader |
| 151 | +(racketblock |
| 152 | + |
| 153 | +(define result-shift 3) |
| 154 | +(define result-type-mask (sub1 (arithmetic-shift 1 result-shift))) |
| 155 | +(define type-imm #b000) |
| 156 | +(define type-pair #b010) |
| 157 | + |
| 158 | +(define imm-shift (+ 2 result-shift)) |
| 159 | +(define imm-type-empty (arithmetic-shift #b11 result-shift)) |
| 160 | + |
| 161 | +;; Expr Expr CEnv -> Asm |
| 162 | +(define (compile-cons e0 e1 c) |
| 163 | + (let ((c0 (compile-e e0 c)) |
| 164 | + (c1 (compile-e e1 (cons #f c)))) |
| 165 | + `(,@c0 |
| 166 | + (mov (offset rsp ,(- (add1 (length c)))) rax) |
| 167 | + ,@c1 |
| 168 | + (mov (offset rdi 0) rax) |
| 169 | + (mov rax (offset rsp ,(- (add1 (length c))))) |
| 170 | + (mov (offset rdi 1) rax) |
| 171 | + (mov rax rdi) |
| 172 | + (or rax ,type-pair) |
| 173 | + (add rdi 16)))) |
| 174 | +) |
| 175 | + |
| 176 | +Now suppose a @racket[map-add1] operation is added to the language |
| 177 | +which takes a single argument, which must be a list of numbers. The |
| 178 | +operation adds one to each element of the list and produces a list of |
| 179 | +the results. In other words, @racket[(map-add1 _xs)] should produce |
| 180 | +what @racket[(map add1 _xs)] produces in Racket. |
| 181 | + |
| 182 | +Write a @racket[compile-map-add1] function that compiles an expression |
| 183 | +of the form @racket[(map-add1 _e0)]: |
| 184 | + |
| 185 | +@#reader scribble/comment-reader |
| 186 | +(racketblock |
| 187 | + |
| 188 | +;; Expr CEnv -> Asm |
| 189 | +(define (compile-map-add1 e0 c) |
| 190 | + ...) |
| 191 | +) |
| 192 | + |
| 193 | +You may use any of the x86 registers as scratch registers, with the |
| 194 | +exception of @racket['rsp] and @racket['rdi] which need to point to |
| 195 | +the stack and heap, respectively. |
| 196 | + |
0 commit comments