1#lang eopl 2 3(require "cps-in-lang.rkt") 4(require "cps-out-lang.rkt") 5 6(provide cps-of-program) 7 8;; cps-of-program : InpExp -> TfExp 9;; Page: 224 10(define cps-of-program 11 (lambda (pgm) 12 (cases program pgm 13 (a-program (exp1) 14 (cps-a-program 15 (cps-of-exps (list exp1) 16 (lambda (new-args) 17 (simple-exp->exp (car new-args))))))))) 18 19;; cps-of-exp : Exp * SimpleExp -> TfExp 20;; Page: 222, 228, 231 21(define cps-of-exp 22 (lambda (exp k-exp) 23 (cases expression exp 24 (const-exp (num) (make-send-to-cont k-exp (cps-const-exp num))) 25 (var-exp (var) (make-send-to-cont k-exp (cps-var-exp var))) 26 (proc-exp (vars body) 27 (make-send-to-cont k-exp 28 (cps-proc-exp (append vars (list 'k%00)) 29 (cps-of-exp body (cps-var-exp 'k%00))))) 30 (zero?-exp (exp1) 31 (cps-of-zero?-exp exp1 k-exp)) 32 (diff-exp (exp1 exp2) 33 (cps-of-diff-exp exp1 exp2 k-exp)) 34 (sum-exp (exps) 35 (cps-of-sum-exp exps k-exp)) 36 (if-exp (exp1 exp2 exp3) 37 (cps-of-if-exp exp1 exp2 exp3 k-exp)) 38 (let-exp (var exp1 body) 39 (cps-of-let-exp var exp1 body k-exp)) 40 (letrec-exp (ids bidss proc-bodies body) 41 (cps-of-letrec-exp ids bidss proc-bodies body k-exp)) 42 (call-exp (rator rands) 43 (cps-of-call-exp rator rands k-exp)) 44 45 ;; new for cps-side-effects-lang 46 ;; Page: 228 47 (print-exp (rator) 48 (cps-of-exps (list rator) 49 (lambda (simples) 50 (cps-printk-exp 51 (car simples) 52 (make-send-to-cont k-exp (cps-const-exp 38)))))) 53 54 ;; Page 231 55 (newref-exp (exp1) 56 (cps-of-exps (list exp1) 57 (lambda (simples) 58 (cps-newrefk-exp (car simples) k-exp)))) 59 60 (deref-exp (exp1) 61 (cps-of-exps (list exp1) 62 (lambda (simples) 63 (cps-derefk-exp (car simples) k-exp)))) 64 65 (setref-exp (exp1 exp2) 66 (cps-of-exps (list exp1 exp2) 67 (lambda (simples) 68 (cps-setrefk-exp 69 (car simples) 70 (cadr simples) 71 ;; the third argument will be evaluated tail-recursively. 72 ;; returns 23, just like in explicit-refs 73 (make-send-to-cont k-exp (cps-const-exp 23)))))) 74 75 ))) 76 77;; cps-of-exps : (list-of expression) * 78;; ((list-of cps-simple-expression) -> cps-expression) 79;; -> cps-expression 80;; Page: 219 81;; usage: 82;; -- assume e_i's are non-simple, b_i's are simple 83;; -- then 84;; (cps-of-exps '(b1 b2 e1 b3 e2 e3) F) == 85;; [e1](\v1.[e2](\v2.[e3](\v3.(F `(,<b1> ,<b2> ,v1 ,<b3> ,v2 ,v3))))) 86;; where <b> is cps-of-simple-exp of b. 87(define cps-of-exps 88 (lambda (exps builder) 89 (let cps-of-rest ((exps exps)) 90 ;; cps-of-rest : Listof(InpExp) -> TfExp 91 (let ((pos (list-index 92 (lambda (exp) 93 (not (inp-exp-simple? exp))) 94 exps))) 95 (if (not pos) 96 (builder (map cps-of-simple-exp exps)) 97 (let ((var (fresh-identifier 'var))) 98 (cps-of-exp 99 (list-ref exps pos) 100 (cps-proc-exp (list var) 101 (cps-of-rest 102 (list-set exps pos (var-exp var))))))))))) 103 104;; inp-exp-simple? : InpExp -> Bool 105;; returns #t or #f, depending on whether exp would be a 106;; simple-exp if reparsed using the CPS-OUT language. 107(define inp-exp-simple? 108 (lambda (exp) 109 (cases expression exp 110 (const-exp (num) #t) 111 (var-exp (var) #t) 112 (diff-exp (exp1 exp2) 113 (and 114 (inp-exp-simple? exp1) 115 (inp-exp-simple? exp2))) 116 (zero?-exp (exp1) 117 (inp-exp-simple? exp1)) 118 (proc-exp (ids exp) #t) 119 (sum-exp (exps) 120 (all-simple? exps)) 121 (else #f)))) 122 123(define all-simple? 124 (lambda (exps) 125 (if (null? exps) 126 #t 127 (and (inp-exp-simple? (car exps)) 128 (all-simple? (cdr exps)))))) 129 130 131;; takes a list of expressions and finds the position of the first 132;; one that is not a simple-exp, else returns #f 133(define index-of-first-non-simple 134 (lambda (exps) 135 (cond 136 ((null? exps) #f) 137 ((inp-exp-simple? (car exps)) 138 (let ((pos (index-of-first-non-simple (cdr exps)))) 139 (if pos 140 (+ pos 1) #f))) 141 (else 0)))) 142 143;; cps-of-simple-exp : InpExp -> SimpleExp 144;; Page: 220 145;; assumes (inp-exp-simple? exp). 146(define cps-of-simple-exp 147 (lambda (exp) 148 (cases expression exp 149 (const-exp (num) (cps-const-exp num)) 150 (var-exp (var) (cps-var-exp var)) 151 (diff-exp (exp1 exp2) 152 (cps-diff-exp 153 (cps-of-simple-exp exp1) 154 (cps-of-simple-exp exp2))) 155 (zero?-exp (exp1) 156 (cps-zero?-exp 157 (cps-of-simple-exp exp1))) 158 (proc-exp (ids exp) 159 (cps-proc-exp (append ids (list 'k%00)) 160 (cps-of-exp exp (cps-var-exp 'k%00)))) 161 (sum-exp (exps) 162 (cps-sum-exp 163 (map cps-of-simple-exp exps))) 164 (else 165 (report-invalid-exp-to-cps-of-simple-exp exp))))) 166 167(define report-invalid-exp-to-cps-of-simple-exp 168 (lambda (exp) 169 (eopl:error 'cps-simple-of-exp 170 "non-simple expression to cps-of-simple-exp: ~s" 171 exp))) 172 173;; make-send-to-cont : SimpleExp * SimpleExp -> TfExp 174;; Page: 214 175(define make-send-to-cont 176 (lambda (cont bexp) 177 (cps-call-exp cont (list bexp)))) 178 179 180;; cps-of-zero?-exp : InpExp * SimpleExp -> TfExp 181;; Page: 222 182(define cps-of-zero?-exp 183 (lambda (exp1 k-exp) 184 (cps-of-exps (list exp1) 185 (lambda (new-rands) 186 (make-send-to-cont 187 k-exp 188 (cps-zero?-exp 189 (car new-rands))))))) 190 191;; cps-of-sum-exp : Listof (InpExp) * SimpleExp -> TfExp 192;; Page: 219 193(define cps-of-sum-exp 194 (lambda (exps k-exp) 195 (cps-of-exps exps 196 (lambda (new-rands) 197 (make-send-to-cont 198 k-exp 199 (cps-sum-exp new-rands)))))) 200 201;; cps-of-diff-exp : InpExp * InpExp * SimpleExp -> TfExp 202;; Page: 223 203(define cps-of-diff-exp 204 (lambda (exp1 exp2 k-exp) 205 (cps-of-exps 206 (list exp1 exp2) 207 (lambda (new-rands) 208 (make-send-to-cont 209 k-exp 210 (cps-diff-exp 211 (car new-rands) 212 (cadr new-rands))))))) 213 214 215;; cps-of-if-exp : InpExp * InpExp * InpExp * SimpleExp -> TfExp 216;; Page: 223 217(define cps-of-if-exp 218 (lambda (exp1 exp2 exp3 k-exp) 219 (cps-of-exps (list exp1) 220 (lambda (new-rands) 221 (cps-if-exp (car new-rands) 222 (cps-of-exp exp2 k-exp) 223 (cps-of-exp exp3 k-exp)))))) 224 225;; cps-of-let-exp : Var * InpExp * InpExp * SimpleExp -> TfExp 226;; Page: 222 227(define cps-of-let-exp 228 (lambda (id rhs body k-exp) 229 (cps-of-exps (list rhs) 230 (lambda (new-rands) 231 (cps-let-exp id 232 (car new-rands) 233 (cps-of-exp body k-exp)))))) 234 235;; cps-of-letrec-exp : 236;; Listof(Listof(Var)) * Listof(InpExp) * InpExp * SimpleExp -> TfExp 237;; Page: 223 238(define cps-of-letrec-exp 239 (lambda (proc-names idss proc-bodies body k-exp) 240 (cps-letrec-exp 241 proc-names 242 (map 243 (lambda (ids) (append ids (list 'k%00))) 244 idss) 245 (map 246 (lambda (exp) (cps-of-exp exp (cps-var-exp 'k%00))) 247 proc-bodies) 248 (cps-of-exp body k-exp)))) 249 250;; cps-of-call-exp : InpExp * Listof(InpExp) * SimpleExp -> TfExp 251;; Page: 220 252(define cps-of-call-exp 253 (lambda (rator rands k-exp) 254 (cps-of-exps (cons rator rands) 255 (lambda (new-rands) 256 (cps-call-exp 257 (car new-rands) 258 (append (cdr new-rands) (list k-exp))))))) 259 260;;;;;;;;;;;;;;;; utilities ;;;;;;;;;;;;;;;; 261 262(define fresh-identifier 263 (let ((sn 0)) 264 (lambda (identifier) 265 (set! sn (+ sn 1)) 266 (string->symbol 267 (string-append 268 (symbol->string identifier) 269 "%" ; this can't appear in an input identifier 270 (number->string sn)))))) 271 272;; list-set : SchemeList * Int * SchemeVal -> SchemeList 273;; returns a list lst1 that is just like lst, except that 274;; (listref lst1 n) = val. 275(define list-set 276 (lambda (lst n val) 277 (cond 278 ((null? lst) (eopl:error 'list-set "ran off end")) 279 ((zero? n) (cons val (cdr lst))) 280 (else (cons (car lst) (list-set (cdr lst) (- n 1) val)))))) 281 282;; list-index : (SchemeVal -> Bool) * SchemeList -> Maybe(Int) 283;; returns the smallest number n such that (pred (listref lst n)) 284;; is true. If pred is false on every element of lst, then returns 285;; #f. 286(define list-index 287 (lambda (pred lst) 288 (cond 289 ((null? lst) #f) 290 ((pred (car lst)) 0) 291 ((list-index pred (cdr lst)) => (lambda (n) (+ n 1))) 292 (else #f)))) 293 294