1; Part of Scheme 48 1.9. See file COPYING for notices and license. 2 3; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber, Robert Ransom 4 5; Macro expansion. 6 7;---------------- 8; Scanning for definitions. 9; 10; Returns a list of forms expanded to the point needed to distinguish 11; definitions from other forms. Definitions and syntax definitions are 12; added to ENV. 13 14(define (scan-forms forms env) 15 (let loop ((forms forms) (expanded '())) 16 (if (null? forms) 17 (reverse expanded) 18 (let ((form (expand-head (car forms) env)) 19 (more-forms (cdr forms))) 20 (cond ((define? form) 21 (loop more-forms 22 (cons (scan-define form env) expanded))) 23 ((define-syntax? form) 24 (loop more-forms 25 (append (scan-define-syntax form env) 26 expanded))) 27 ((begin? form) 28 (loop (append (cdr form) more-forms) 29 expanded)) 30 (else 31 (loop more-forms (cons form expanded)))))))) 32 33(define (expand-scanned-form form env) 34 (if (define? form) 35 (expand-define form env) 36 (expand form env))) 37 38(define (scan-define form env) 39 (let ((new-form (destructure-define form))) 40 (if new-form 41 (begin 42 (comp-env-define! env (cadr new-form) usual-variable-type) 43 new-form) 44 (syntax-violation 'syntax-rules "ill-formed definition" form)))) 45 46(define (expand-define form env) 47 (make-node operator/define 48 (list (car form) 49 (expand (cadr form) env) 50 (expand (caddr form) env)))) 51 52(define (scan-define-syntax form env) 53 (if (and (or (this-long? form 3) 54 (this-long? form 4)) ; may have name list for reifier 55 (name? (cadr form))) 56 (let ((name (cadr form)) 57 (source (caddr form)) 58 (package (extract-package-from-comp-env env))) 59 (comp-env-define! env 60 name 61 syntax-type 62 (process-syntax (if (null? (cdddr form)) 63 source 64 `(cons ,source ',(cadddr form))) 65 env 66 name 67 package)) 68 '()) 69 (syntax-violation 'define-syntax "ill-formed syntax definition" form))) 70 71; This is used by the ,expand command. 72 73(define (expand-form form env) 74 (let loop ((forms (list form)) (expanded '())) 75 (if (null? forms) 76 (if (= (length expanded) 1) 77 (car expanded) 78 (make-node operator/begin (cons 'begin (reverse expanded)))) 79 (let ((form (expand-head (car forms) env)) 80 (more-forms (cdr forms))) 81 (cond ((define? form) 82 (let* ((new-form (destructure-define form)) 83 (temp (if new-form 84 (expand-define new-form env) 85 (syntax-violation 'expand "ill-formed definition" 86 form)))) 87 (loop more-forms (cons temp expanded)))) 88 ((define-syntax? form) 89 (loop more-forms 90 (cons (make-node operator/define-syntax 91 (list (car form) 92 (expand (cadr form) env) 93 (make-node operator/quote 94 `',(caddr form)))) 95 expanded))) 96 ((begin? form) 97 (loop (append (cdr form) more-forms) 98 expanded)) 99 (else 100 (loop more-forms 101 (cons (expand form env) expanded)))))))) 102 103;---------------- 104; Looking for definitions. 105; This expands the form until it reaches a name, a form whose car is an 106; operator, a form whose car is unknown, or a literal. 107 108(define (expand-head form env) 109 (cond ((node? form) 110 (if (and (name-node? form) 111 (not (node-ref form 'binding))) 112 (expand-name (node-form form) env) 113 form)) 114 ((name? form) 115 (expand-name form env)) 116 ((pair? form) 117 (let ((op (expand-head (car form) env))) 118 (if (and (node? op) 119 (name-node? op)) 120 (let ((probe (node-ref op 'binding))) 121 (if (binding? probe) 122 (let ((s (binding-static probe))) 123 (cond ((and (transform? s) 124 (eq? (binding-type probe) syntax-type)) 125 (expand-macro-application 126 s (cons op (cdr form)) env expand-head)) 127 ((and (operator? s) 128 (eq? s operator/structure-ref)) 129 (expand-structure-ref form env expand-head)) 130 (else 131 (cons op (cdr form))))) 132 (cons op (cdr form)))) 133 (cons op (cdr form))))) 134 (else 135 form))) 136 137; Returns a DEFINE of the form (define <id> <value>). This handles the following 138; kinds of defines: 139; (define <id> <value>) 140; (define <id>) ; value is unassigned 141; (define (<id> . <formals>) <value>) ; value is a lambda 142; The return value is #f if any syntax error is found. 143 144(define (destructure-define form) 145 (if (at-least-this-long? form 2) 146 (let ((pat (cadr form)) 147 (operator (car form))) 148 (cond ((pair? pat) 149 (if (and (name? (car pat)) 150 (names? (cdr pat)) 151 (not (null? (cddr form)))) 152 `(,operator ,(car pat) 153 (,operator/lambda ,(cdr pat) 154 . ,(cddr form))) 155 #f)) 156 ((null? (cddr form)) 157 `(,operator ,pat (,operator/unassigned))) 158 ((null? (cdddr form)) 159 `(,operator ,pat ,(caddr form))) 160 (else 161 #f))) 162 #f)) 163 164(define (make-operator-predicate operator-id) 165 (let ((operator (get-operator operator-id syntax-type))) 166 (lambda (form) 167 (and (pair? form) 168 (eq? operator 169 (static-value (car form))))))) 170 171(define define? (make-operator-predicate 'define)) 172(define begin? (make-operator-predicate 'begin)) 173(define define-syntax? (make-operator-predicate 'define-syntax)) 174 175(define (static-value form) 176 (if (and (node? form) 177 (name-node? form)) 178 (let ((probe (node-ref form 'binding))) 179 (if (binding? probe) 180 (binding-static probe) 181 #f)) 182 #f)) 183 184; -------------------- 185; The horror of internal defines 186 187; This returns a single node, either a LETREC, if there are internal definitions, 188; or a BEGIN if there aren't any. If there are no expressions we turn the last 189; definition back into an expression, thus causing the correct warning to be 190; printed by the compiler. 191 192(define (expand-body body env) 193 (if (null? (cdr body)) ;++ 194 (expand (car body) env) 195 (call-with-values 196 (lambda () 197 (scan-body-forms body env '())) 198 (lambda (defs exps env) 199 (if (null? defs) 200 (make-node operator/begin (cons 'begin (expand-list exps env))) 201 (call-with-values 202 (lambda () 203 (if (null? exps) 204 (values (reverse (cdr defs)) 205 `((,operator/define ,(caar defs) ,(cdar defs)))) 206 (values (reverse defs) 207 exps))) 208 (lambda (defs exps) 209 (expand-letrec operator/letrec 210 (map car defs) 211 (map cdr defs) 212 exps 213 env)))))))) 214 215; Walk through FORMS looking for definitions. ENV is the current environment, 216; DEFS a list of definitions found so far. 217; 218; Returns three values: a list of (define <name> <value>) lists, a list of 219; remaining forms, and the environment to use for expanding all of the above. 220 221(define (scan-body-forms forms env defs) 222 (if (null? forms) 223 (values defs '() env) 224 (let ((form (expand-head (car forms) env)) 225 (more-forms (cdr forms))) 226 (cond ((define? form) 227 (let ((new-form (destructure-define form))) 228 (if new-form 229 (let* ((name (cadr new-form)) 230 (node (make-node operator/name name))) 231 (scan-body-forms more-forms 232 (bind1 name node env) 233 (cons (cons node 234 (caddr new-form)) 235 defs))) 236 (syntax-violation 'scan-body-forms 237 "ill-formed definition" form)))) 238 ((begin? form) 239 (call-with-values 240 (lambda () 241 (scan-body-forms (cdr form) 242 env 243 defs)) 244 (lambda (new-defs exps env) 245 (cond ((null? exps) 246 (scan-body-forms more-forms env new-defs)) 247 ((eq? new-defs defs) 248 (values defs (append exps more-forms) env)) 249 (else 250 (body-lossage forms env)))))) 251 (else 252 (values defs (cons form more-forms) env)))))) 253 254(define (body-lossage node env) 255 (syntax-violation 'body 256 "definitions and expressions intermixed" 257 (schemify node env))) 258 259;-------------------- 260; Expands all macros in FORM and returns a node. 261 262(define (expand form env) 263 (cond ((node? form) 264 (if (and (name-node? form) 265 (not (node-ref form 'binding))) 266 (expand-name (node-form form) env) 267 form)) 268 ((name? form) 269 (expand-name form env)) 270 ((pair? form) 271 (if (operator? (car form)) 272 (expand-operator-form (car form) (car form) form env) 273 (let ((op-node (expand (car form) env))) 274 (if (name-node? op-node) 275 (let ((probe (node-ref op-node 'binding))) 276 (if (binding? probe) 277 (let ((s (binding-static probe))) 278 (cond ((operator? s) 279 (expand-operator-form s op-node form env)) 280 ((and (transform? s) 281 (eq? (binding-type probe) syntax-type)) 282 ;; Non-syntax transforms get done later 283 (expand-macro-application 284 s (cons op-node (cdr form)) env expand)) 285 (else 286 (expand-call op-node form env)))) 287 (expand-call op-node form env))) 288 (expand-call op-node form env))))) 289 ((literal? form) 290 (expand-literal form)) 291 ;; ((qualified? form) ...) 292 (else 293 (syntax-violation 'expand "invalid expression" form)))) 294 295(define (expand-list exps env) 296 (map (lambda (exp) 297 (expand exp env)) 298 exps)) 299 300(define (expand-literal exp) 301 (make-node operator/literal (make-immutable! exp))) 302 303(define (expand-call proc-node exp env) 304 (if (list? exp) 305 (make-node operator/call 306 (cons proc-node (expand-list (cdr exp) env))) 307 (syntax-violation 'expand-call "invalid expression" exp))) 308 309; An environment is a procedure that takes a name and returns one of 310; the following: 311; 312; 1. A binding record. 313; 2. A pair (<binding-record> . <path>) 314; 3. A node, which is taken to be a substitution for the name. 315; Or, for lexically bound variables, this is just a name node. 316; 4. #f, for unbound variables 317; 318; In case 1, EXPAND caches the binding as the node's BINDING property. 319; In case 2, it simply returns the node. 320 321(define (expand-name name env) 322 (let ((binding (lookup env name))) 323 (if (node? binding) 324 binding 325 (let ((node (make-node operator/name name))) 326 (node-set! node 'binding (or binding 'unbound)) 327 node)))) 328 329; Expand a macro. EXPAND may either be expand or expand-head. 330 331(define (expand-macro-application transform form env-of-use expand) 332 (call-with-values 333 (lambda () 334 (maybe-apply-macro-transform transform 335 form 336 (node-form (car form)) 337 env-of-use)) 338 (lambda (new-form new-env) 339 (if (eq? new-form form) 340 (syntax-violation (schemify (car form) env-of-use) 341 "use of macro doesn't match definition" 342 (cons (schemify (car form) env-of-use) 343 (desyntaxify (cdr form)))) 344 (expand new-form new-env))))) 345 346;-------------------- 347; Specialist classifiers for particular operators 348 349(define (expand-operator-form op op-node form env) 350 ((operator-table-ref expanders (operator-uid op)) 351 op op-node form env)) 352 353(define expanders 354 (make-operator-table (lambda (op op-node form env) 355 (if (let ((nargs (operator-nargs op))) 356 (or (not nargs) 357 (and (list? (cdr form)) 358 (= nargs (length (cdr form)))))) 359 (make-node op 360 (cons op-node 361 (expand-list (cdr form) env))) 362 (expand-call op-node form env))))) 363 364(define (define-expander name proc) 365 (operator-define! expanders name syntax-type proc)) 366 367; Definitions are not expressions. 368 369(define-expander 'define 370 (lambda (op op-node exp env) 371 (syntax-violation 'define 372 (if (destructure-define exp) 373 "definition in expression context" 374 "ill-formed definition") 375 exp))) 376 377; Remove generated names from quotations. 378 379(define-expander 'quote 380 (lambda (op op-node exp env) 381 (if (this-long? exp 2) 382 (make-node op (list op (desyntaxify (cadr exp)))) 383 (syntax-violation 'quote "invalid expression" exp)))) 384 385; Don't evaluate, but don't remove generated names either. This is 386; used when writing macro-defining macros. Once we have avoided the 387; use of DESYNTAXIFY it is safe to replace this with regular QUOTE. 388 389(define-expander 'code-quote 390 (lambda (op op-node exp env) 391 (if (this-long? exp 2) 392 (make-node operator/quote (list op (cadr exp))) 393 (syntax-violation 'code-quote "invalid expression" exp)))) 394 395; Convert one-armed IF to two-armed IF. 396 397(define-expander 'if 398 (lambda (op op-node exp env) 399 (cond ((this-long? exp 3) 400 (make-node op 401 (cons op 402 (expand-list (append (cdr exp) 403 (list (unspecific-node))) 404 env)))) 405 ((this-long? exp 4) 406 (make-node op 407 (cons op (expand-list (cdr exp) env)))) 408 (else 409 (syntax-violation 'if "invalid expression" exp))))) 410 411(define (unspecific-node) 412 (make-node operator/unspecific '(unspecific))) 413 414; For the module system: 415 416(define-expander 'structure-ref 417 (lambda (op op-node form env) 418 (expand-structure-ref form env expand))) 419 420; This is also called by EXPAND-HEAD, which passes in a different expander. 421 422(define (expand-structure-ref form env expander) 423 (let ((struct-node (expand (cadr form) env)) 424 (lose (lambda () 425 (syntax-violation 'structure-ref "invalid structure reference" form)))) 426 (if (and (this-long? form 3) 427 (name? (caddr form)) 428 (name-node? struct-node)) 429 (let ((b (node-ref struct-node 'binding))) 430 (if (and (binding? b) 431 (binding-static b)) ; (structure? ...) 432 (expander (generate-name (desyntaxify (caddr form)) 433 (binding-static b) 434 (node-form struct-node)) 435 env) 436 (lose))) 437 (lose)))) 438 439; Scheme 48 internal special form principally for use by the 440; DEFINE-STRUCTURES macro. 441 442(define-expander '%file-name% 443 (lambda (op op-node form env) 444 (make-node operator/quote `',(source-file-name env)))) 445 446; Checking the syntax of others special forms 447 448(define-expander 'lambda 449 (lambda (op op-node exp env) 450 (if (and (at-least-this-long? exp 3) 451 (names? (cadr exp))) 452 (expand-lambda (cadr exp) (cddr exp) env) 453 (syntax-violation 'lambda "invalid expression" exp)))) 454 455(define (expand-lambda names body env) 456 (call-with-values 457 (lambda () 458 (bind-names names env)) 459 (lambda (names env) 460 (make-node operator/lambda 461 (list 'lambda names (expand-body body env)))))) 462 463(define (bind-names names env) 464 (let loop ((names names) (nodes '()) (out-names '())) 465 (cond ((null? names) 466 (values (reverse nodes) 467 (bind out-names nodes env))) 468 ((name? names) 469 (let ((last (make-node operator/name names))) 470 (values (append (reverse nodes) last) 471 (bind (cons names out-names) (cons last nodes) env)))) 472 (else 473 (let ((node (make-node operator/name (car names)))) 474 (loop (cdr names) (cons node nodes) (cons (car names) out-names))))))) 475 476(define (names? l) 477 (or (null? l) 478 (name? l) 479 (and (pair? l) 480 (name? (car l)) 481 (names? (cdr l))))) 482 483(define-expander 'set! 484 (lambda (op op-node exp env) 485 (if (and (this-long? exp 3) 486 (name? (cadr exp))) 487 (make-node op (cons op (expand-list (cdr exp) env))) 488 (syntax-violation 'set! "invalid expression" exp)))) 489 490(define (letrec-expander op/letrec) 491 (lambda (op op-node exp env) 492 (if (and (at-least-this-long? exp 3) 493 (let-specs? (cadr exp))) 494 (let ((specs (cadr exp)) 495 (body (cddr exp))) 496 (let* ((names (map (lambda (spec) 497 (make-node operator/name (car spec))) 498 specs)) 499 (env (bind (map car specs) names env))) 500 (expand-letrec op/letrec names (map cadr specs) body env))) 501 (syntax-violation 'letrec "invalid expression" exp)))) 502 503(define-expander 'letrec 504 (letrec-expander operator/letrec)) 505 506(define-expander 'letrec* 507 (letrec-expander operator/letrec*)) 508 509(define (expand-letrec op/letrec names values body env) 510 (let* ((new-specs (map (lambda (name value) 511 (list name 512 (expand value env))) 513 names 514 values))) 515 (make-node op/letrec 516 (list 'letrec new-specs (expand-body body env))))) 517 518(define-expander 'loophole 519 (lambda (op op-node exp env) 520 (if (this-long? exp 3) 521 (make-node op (list op 522 (sexp->type (desyntaxify (cadr exp)) #t) 523 (expand (caddr exp) env))) 524 (syntax-violation 'loophole "invalid expression" exp)))) 525 526(define-expander 'let-syntax 527 (lambda (op op-node exp env) 528 (if (and (at-least-this-long? exp 3) 529 (let-specs? (cadr exp))) 530 (let ((specs (cadr exp))) 531 (expand-body (cddr exp) 532 (bind (map car specs) 533 (map (lambda (spec) 534 (make-binding syntax-type 535 (list 'let-syntax) 536 (process-syntax (cadr spec) 537 env 538 (car spec) 539 env))) 540 specs) 541 env))) 542 (syntax-violation 'let-syntax "invalid expression" exp)))) 543 544(define-expander 'letrec-syntax 545 (lambda (op op-node exp env) 546 (if (and (at-least-this-long? exp 3) 547 (let-specs? (cadr exp))) 548 (let* ((specs (cadr exp)) 549 (bindings (map (lambda (spec) 550 (make-binding syntax-type 551 (list 'letrec-syntax) 552 'unassigned)) 553 specs)) 554 (new-env (bind (map car specs) bindings env))) 555 (for-each (lambda (spec binding) 556 (set-binding-static! binding 557 (process-syntax (cadr spec) 558 new-env 559 (car spec) 560 new-env))) 561 specs bindings) 562 (expand-body (cddr exp) new-env)) 563 (syntax-violation 'letrec-syntax "invalid expression" exp)))) 564 565(define (process-syntax form env name env-or-package) 566 (let ((eval+env (force (comp-env-macro-eval env)))) 567 (make-transform/macro ((car eval+env) form (cdr eval+env)) 568 env-or-package 569 syntax-type 570 form 571 name))) 572 573; This just looks up the names that the LAP code will want and replaces them 574; with the appropriate node. 575; 576; (lap <id> (<free name> ...) <instruction> ...) 577 578(define-expander 'lap 579 (lambda (op op-node exp env) 580 (if (and (at-least-this-long? exp 4) 581 (name? (cdr exp)) 582 (every name? (caddr exp))) 583 (make-node op `(,op 584 ,(desyntaxify (cadr exp)) 585 ,(map (lambda (name) 586 (expand-name (cadr exp) env)) 587 (caddr exp)) 588 . ,(cdddr exp))) 589 (syntax-violation 'lap "invalid expression" exp)))) 590 591; -------------------- 592; Syntax checking utilities 593 594(define (this-long? l n) 595 (cond ((null? l) 596 (= n 0)) 597 ((pair? l) 598 (this-long? (cdr l) (- n 1))) 599 (else 600 #f))) 601 602(define (at-least-this-long? l n) 603 (cond ((null? l) 604 (<= n 0)) 605 ((pair? l) 606 (at-least-this-long? (cdr l) (- n 1))) 607 (else 608 #f))) 609 610(define (let-specs? x) 611 (or (null? x) 612 (and (pair? x) 613 (let ((s (car x))) 614 (and (pair? s) 615 (name? (car s)) 616 (pair? (cdr s)) 617 (null? (cddr s)))) 618 (let-specs? (cdr x))))) 619 620; -------------------- 621; Utilities 622 623(define (literal? exp) 624 (or (number? exp) (char? exp) (string? exp) (boolean? exp) 625 (code-vector? exp))) 626 627(define (syntax? d) 628 (cond ((operator? d) 629 (eq? (operator-type d) syntax-type)) 630 ((transform? d) 631 (eq? (transform-type d) syntax-type)) 632 (else #f))) 633