1 2;;---------------------------------------------------------------------- 3;; more-scheme : case, do, etc. - remaining syntax 4 5(module more-scheme '#%kernel 6 (#%require "define-et-al.rkt" "qq-and-or.rkt" "cond.rkt" "define.rkt" '#%paramz "case.rkt" "logger.rkt" 7 "member.rkt" 8 (for-syntax '#%kernel "stx.rkt" "define-et-al.rkt" "qq-and-or.rkt" "cond.rkt" "stxcase-scheme.rkt" "qqstx.rkt")) 9 10 ;; For `old-case`: 11 (define-syntax case-test 12 (lambda (x) 13 (syntax-case x () 14 ;; For up to 3 elements, inline `eqv?' tests: 15 [(_ x (k)) 16 (syntax (eqv? x 'k))] 17 [(_ x (k1 k2)) 18 (syntax (let ([tmp x]) (if (eqv? tmp 'k1) #t (eqv? tmp 'k2))))] 19 [(_ x (k1 k2 k3)) 20 (syntax (let ([tmp x]) (if (eqv? tmp 'k1) #t (if (eqv? tmp 'k2) #t (eqv? tmp 'k3)))))] 21 [(_ x (k ...)) 22 (syntax (memv x '(k ...)))]))) 23 24 ;; Mostly from Dybvig: 25 (define-syntax (old-case x) 26 (syntax-case* x (else) (let ([else-stx (datum->syntax #f 'else)]) 27 (lambda (a b) (free-identifier=? a else-stx))) 28 ((_ v) 29 (syntax (#%expression (begin v (void))))) 30 ((_ v (else e1 e2 ...)) 31 (syntax/loc x (#%expression (begin v (let-values () e1 e2 ...))))) 32 ((_ v ((k ...) e1 e2 ...)) 33 (syntax/loc x (if (case-test v (k ...)) (let-values () e1 e2 ...) (void)))) 34 ((self v ((k ...) e1 e2 ...) c1 c2 ...) 35 (syntax/loc x (let ((x v)) 36 (if (case-test x (k ...)) 37 (let-values () e1 e2 ...) 38 (self x c1 c2 ...))))) 39 ((_ v (bad e1 e2 ...) . rest) 40 (raise-syntax-error 41 #f 42 "bad syntax (not a datum sequence)" 43 x 44 (syntax bad))) 45 ((_ v clause . rest) 46 (raise-syntax-error 47 #f 48 "bad syntax (missing expression after datum sequence)" 49 x 50 (syntax clause))) 51 ((_ . v) 52 (not (null? (syntax-e (syntax v)))) 53 (raise-syntax-error 54 #f 55 "bad syntax (illegal use of `.')" 56 x)))) 57 58 ;; From Dybvig: 59 (define-syntax do 60 (lambda (orig-x) 61 (syntax-case orig-x () 62 ((_ ((var init . step) ...) (e0 e1 ...) c ...) 63 (with-syntax (((step ...) 64 (map (lambda (v s) 65 (syntax-case s () 66 (() v) 67 ((e) (syntax e)) 68 (_ (raise-syntax-error 69 #f 70 "bad variable syntax" 71 orig-x)))) 72 (syntax->list (syntax (var ...))) 73 (syntax->list (syntax (step ...)))))) 74 (syntax/loc orig-x 75 (let doloop ((var init) ...) 76 (if e0 77 (begin (void) e1 ...) 78 (begin c ... (doloop step ...)))))))))) 79 80 (define-syntax parameterize 81 (lambda (stx) 82 (syntax-case stx () 83 [(_ () expr1 expr ...) 84 (syntax (let () expr1 expr ...))] 85 [(_ ([param val] ...) expr1 expr ...) 86 (with-syntax ([(p/v ...) 87 (apply append 88 (map list 89 (syntax->list #'(param ...)) 90 (syntax->list #'(val ...))))]) 91 (syntax-protect 92 (syntax/loc stx 93 (with-continuation-mark 94 parameterization-key 95 (extend-parameterization 96 (continuation-mark-set-first #f parameterization-key) 97 p/v ...) 98 (let () 99 expr1 100 expr ...)))))]))) 101 102 (define-syntax parameterize* 103 (syntax-rules () 104 [(_ () body1 body ...) 105 (let () body1 body ...)] 106 [(_ ([lhs1 rhs1] [lhs rhs] ...) body1 body ...) 107 (parameterize ([lhs1 rhs1]) 108 (parameterize* ([lhs rhs] ...) 109 body1 body ...))])) 110 111 (define (current-parameterization) 112 (continuation-mark-set-first #f parameterization-key)) 113 114 (define (call-with-parameterization paramz thunk) 115 (unless (parameterization? paramz) 116 (raise-argument-error 'call-with-parameterization "parameterization?" 0 paramz thunk)) 117 (unless (and (procedure? thunk) 118 (procedure-arity-includes? thunk 0)) 119 (raise-argument-error 'call-with-parameterization "(-> any)" 1 paramz thunk)) 120 (with-continuation-mark 121 parameterization-key 122 paramz 123 (thunk))) 124 125 (define-syntax parameterize-break 126 (lambda (stx) 127 (syntax-case stx () 128 [(_ bool-expr expr1 expr ...) 129 (syntax-protect 130 (syntax/loc stx 131 (with-continuation-mark 132 break-enabled-key 133 (make-thread-cell (and bool-expr #t)) 134 (begin 135 (check-for-break) 136 (let () 137 expr1 138 expr ...)))))]))) 139 140 (define-values (struct:break-paramz make-break-paramz break-paramz? break-paramz-ref break-paramz-set!) 141 (make-struct-type 'break-parameterization #f 1 0 #f)) 142 143 (-define-struct break-parameterization (cell)) 144 145 (define (current-break-parameterization) 146 (make-break-paramz (continuation-mark-set-first #f break-enabled-key))) 147 148 (define (call-with-break-parameterization paramz thunk) 149 (unless (break-paramz? paramz) 150 (raise-argument-error 'call-with-break-parameterization "break-parameterization?" 0 paramz thunk)) 151 (unless (and (procedure? thunk) 152 (procedure-arity-includes? thunk 0)) 153 (raise-argument-error 'call-with-parameterization "(-> any)" 1 paramz thunk)) 154 (begin0 155 (with-continuation-mark 156 break-enabled-key 157 (break-paramz-ref paramz 0) 158 (begin 159 (check-for-break) 160 (thunk))) 161 (check-for-break))) 162 163 (define (select-handler/no-breaks e bpz l) 164 (with-continuation-mark 165 break-enabled-key 166 ;; make a fresh thread cell so that the shared one isn't mutated 167 (make-thread-cell #f) 168 (let loop ([l l]) 169 (cond 170 [(null? l) 171 (raise e)] 172 [((caar l) e) 173 (begin0 174 ((cdar l) e) 175 (with-continuation-mark 176 break-enabled-key 177 bpz 178 (check-for-break)))] 179 [else 180 (loop (cdr l))])))) 181 182 (define (select-handler/breaks-as-is e bpz l) 183 (cond 184 [(null? l) 185 (raise e)] 186 [((caar l) e) 187 (with-continuation-mark 188 break-enabled-key 189 bpz 190 (begin 191 (check-for-break) 192 ((cdar l) e)))] 193 [else 194 (select-handler/breaks-as-is e bpz (cdr l))])) 195 196 (define false-thread-cell (make-thread-cell #f)) 197 198 199 (define (check-with-handlers-in-context handler-prompt-key) 200 (unless (continuation-prompt-available? handler-prompt-key) 201 (error 'with-handlers 202 "exception handler used out of context"))) 203 204 (define handler-prompt-key (make-continuation-prompt-tag 'handler-prompt-tag)) 205 206 (define (call-handled-body bpz handle-proc body-thunk) 207 ;; Disable breaks here, so that when the exception handler jumps 208 ;; to run a handler, breaks are disabled for the handler 209 (with-continuation-mark 210 break-enabled-key 211 false-thread-cell 212 (call-with-continuation-prompt 213 (lambda (bpz body-thunk) 214 ;; Restore the captured break parameterization for 215 ;; evaluating the `with-handlers' body. In this 216 ;; special case, no check for breaks is needed, 217 ;; because bpz is quickly restored past call/ec. 218 ;; Thus, `with-handlers' can evaluate its body in 219 ;; tail position. 220 (with-continuation-mark 221 break-enabled-key 222 bpz 223 (with-continuation-mark 224 exception-handler-key 225 (lambda (e) 226 ;; Deliver the exception to the escape handler: 227 (abort-current-continuation 228 handler-prompt-key 229 e)) 230 (body-thunk)))) 231 handler-prompt-key 232 handle-proc 233 bpz body-thunk))) 234 235 (define-syntaxes (with-handlers with-handlers*) 236 (let ([wh 237 (lambda (disable-break?) 238 (lambda (stx) 239 (syntax-case stx () 240 [(_ () expr1 expr ...) (syntax/loc stx (let () expr1 expr ...))] 241 [(_ ([pred handler] ...) expr1 expr ...) 242 (with-syntax ([(pred-name ...) (generate-temporaries (map (lambda (x) 'with-handlers-predicate) 243 (syntax->list #'(pred ...))))] 244 [(handler-name ...) (generate-temporaries (map (lambda (x) 'with-handlers-handler) 245 (syntax->list #'(handler ...))))]) 246 (syntax-protect 247 (quasisyntax/loc stx 248 (let-values ([(pred-name) pred] ... 249 [(handler-name) handler] ...) 250 ;; Capture current break parameterization, so we can use it to 251 ;; evaluate the body 252 (let ([bpz (continuation-mark-set-first #f break-enabled-key)]) 253 (call-handled-body 254 bpz 255 (lambda (e) 256 (#,(if disable-break? 257 #'select-handler/no-breaks 258 #'select-handler/breaks-as-is) 259 e bpz 260 (list (cons pred-name handler-name) ...))) 261 #,(syntax/loc stx 262 (lambda () 263 expr1 expr ...))))))))])))]) 264 (values (wh #t) (wh #f)))) 265 266 (define (call-with-exception-handler exnh thunk) 267 ;; The `begin0' ensures that we don't overwrite an enclosing 268 ;; exception handler. 269 (begin0 270 (with-continuation-mark 271 exception-handler-key 272 exnh 273 (thunk)) 274 (void))) 275 276 (define-syntax set!-values 277 (lambda (stx) 278 (syntax-case stx () 279 [(_ () expr) (syntax (let-values ([() expr]) (void)))] 280 [(_ (id) expr) (identifier? (syntax id)) (syntax (set! id expr))] 281 [(_ (id ...) expr) 282 (let ([ids (stx->list (syntax (id ...)))]) 283 (for-each 284 (lambda (id) 285 (unless (identifier? id) 286 (raise-syntax-error #f 287 "not an identifier" 288 stx 289 id))) 290 ids) 291 (let ([dup (check-duplicate-identifier ids)]) 292 (when dup 293 (raise-syntax-error #f 294 "duplicate identifier" 295 stx 296 dup)))) 297 (with-syntax ([(temp ...) (generate-temporaries (syntax (id ...)))]) 298 (syntax/loc 299 stx 300 (let-values ([(temp ...) expr]) 301 (set! id temp) ...)))]))) 302 303 (define-values (call/cc) call-with-current-continuation) 304 305 (define-syntax let/cc 306 (lambda (stx) 307 (syntax-case stx () 308 [(_ var body1 body ...) 309 (syntax/loc stx (call/cc (lambda (var) body1 body ...)))]))) 310 311 (define-syntax fluid-let 312 (lambda (stx) 313 (syntax-case stx () 314 [(_ () body1 body ...) (syntax/loc stx (let () body1 body ...))] 315 [(_ ([name val] ...) body1 body ...) 316 (with-syntax ([(tmp ...) (generate-temporaries (syntax (name ...)))]) 317 (syntax/loc 318 stx 319 (let ([tmp val] ...) 320 (let ([swap 321 (lambda () 322 (let ([s tmp]) 323 (set! tmp name) 324 (set! name s)) 325 ...)]) 326 (dynamic-wind 327 swap 328 (lambda () body1 body ...) 329 swap)))))]))) 330 331 (define-syntax time 332 (lambda (stx) 333 (syntax-case stx () 334 [(_ expr1 expr ...) 335 (syntax/loc 336 stx 337 (let-values ([(v cpu user gc) (time-apply (lambda () expr1 expr ...) null)]) 338 (printf "cpu time: ~s real time: ~s gc time: ~s\n" cpu user gc) 339 (apply values v)))]))) 340 341 (define not-there (gensym)) 342 343 (define (do-hash-update who mut? set ht key xform default) 344 (unless (variable-reference-from-unsafe? (#%variable-reference)) 345 (unless (and (hash? ht) 346 (if mut? 347 (not (immutable? ht)) 348 (immutable? ht))) 349 (raise-argument-error who (if mut? "(and/c hash? (not/c immutable?))" "(and/c hash? immutable?)") ht)) 350 (unless (and (procedure? xform) 351 (procedure-arity-includes? xform 1)) 352 (raise-argument-error who "(any/c . -> . any/c)" xform))) 353 (let ([v (hash-ref ht key default)]) 354 (if (eq? v not-there) 355 (raise-mismatch-error who "no value found for key: " key) 356 (set ht key (xform v))))) 357 358 (define hash-update 359 (case-lambda 360 [(ht key xform default) 361 (do-hash-update 'hash-update #f hash-set ht key xform default)] 362 [(ht key xform) 363 (hash-update ht key xform not-there)])) 364 365 (define hash-update! 366 (case-lambda 367 [(ht key xform default) 368 (do-hash-update 'hash-update! #t hash-set! ht key xform default)] 369 [(ht key xform) 370 (hash-update! ht key xform not-there)])) 371 372 (define (hash-has-key? ht key) 373 (unless (hash? ht) 374 (raise-argument-error 'hash-has-key? "hash?" 0 ht key)) 375 (not (eq? not-there (hash-ref ht key not-there)))) 376 377 (define (hash-ref! ht key new) 378 (unless (and (hash? ht) 379 (not (immutable? ht))) 380 (raise-argument-error 'hash-ref! "(and/c hash? (not/c immutable?))" 0 ht key new)) 381 (let ([v (hash-ref ht key not-there)]) 382 (if (eq? not-there v) 383 (let ([n (if (procedure? new) (new) new)]) 384 (hash-set! ht key n) 385 n) 386 v))) 387 388 (#%provide case old-case do 389 parameterize parameterize* current-parameterization call-with-parameterization 390 parameterize-break current-break-parameterization call-with-break-parameterization 391 (rename break-paramz? break-parameterization?) 392 with-handlers with-handlers* call-with-exception-handler 393 set!-values 394 let/cc call/cc fluid-let time 395 log-fatal log-error log-warning log-info log-debug define-logger 396 hash-ref! hash-has-key? hash-update hash-update!)) 397