home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-386-Vol-2of3.iso / c / cr-macro.zip / CLASSIFY.SCM < prev    next >
Text File  |  1990-02-20  |  16KB  |  583 lines

  1. ; Expression classification
  2.  
  3. ; Entry points (not a complete list):
  4. ;  classify
  5. ;  scan-body
  6. ;  process-syntax-binding   [for use by define-syntax]
  7. ;  classify-let-syntax, classify-letrec-syntax
  8. ;  bind
  9. ;  bindrec
  10. ;  bind-aliases
  11. ;  lookup
  12. ;  lookup-variable
  13.  
  14. ;  classify : form * env * (class * form * env -> answer) -> answer
  15. ;  env = name -> binding
  16. ;  binding = special + macro + variable
  17. ;  special = {let-syntax, letrec-syntax, define, begin, ...}
  18. ;  variable = [defined elsewhere]
  19. ;  macro = transformer * env
  20. ;  transformer = form * (name -> name) * (name * name -> bool) -> form
  21.  
  22. (define (classify form env cont)
  23.   (cond ((literal? form)
  24.      (cont class/literal form env))
  25.     ((name? form)
  26.      (cont class/variable form env))
  27.     ((compound? form)
  28.      (classify-compound form env cont))
  29.     ((classified? form)
  30.      (cont (classified-class form)
  31.            (classified-form form)
  32.            (classified-env form)))
  33.     (else (syntax-error "unknown expression type" form))))
  34.  
  35. (define (classify-compound form env cont)
  36.   (let ((op-form (operator form)))
  37.     (if (name? op-form)
  38.     (let ((binding (lookup op-form env)))
  39.       (cond ((special-operator? binding)
  40.          (classify-special-form binding form env cont))
  41.         ((macro? binding)
  42.          (classify-macro-application binding form env cont))
  43.         (else
  44.          (cont class/application form env))))
  45.     (cont class/application form env))))
  46.  
  47. (define (classify-special-form op form env cont)
  48.   (let ((class (special-operator-class op)))
  49.     (if (check-special-form-syntax class form)
  50.     (cont class form env)
  51.     (syntax-error "invalid special form syntax" form))))
  52.  
  53. ; Macro application
  54.  
  55. (define (classify-macro-application op form env cont)
  56.   (let ((macro-env (macro-environment op)))
  57.     (with-new-color macro-env env
  58.       (lambda (rename output-env)
  59.     (let* ((compare (lambda (client-name macro-name)
  60.               (same-binding? (lookup client-name env)
  61.                      (lookup macro-name macro-env))))
  62.            (new-form
  63.         ((macro-transformer op) form rename compare)))
  64.       (classify new-form output-env cont))))))
  65.  
  66. ; let-syntax and letrec-syntax
  67.  
  68. (define (classify-let-syntax form env cont)
  69.   (let ((bspecs (let-syntax-bspecs form)))
  70.     (classify (let-syntax-body form)
  71.     (bind (map bspec-name bspecs)
  72.           (map (lambda (bspec)
  73.              (process-syntax-binding (bspec-rhs bspec)
  74.                          env))
  75.            bspecs)
  76.           env)
  77.       cont)))
  78.  
  79. (define (classify-letrec-syntax form outer-env cont)
  80.   (let ((bspecs (letrec-syntax-bspecs form)))
  81.     (classify (letrec-syntax-body form)
  82.     (bindrec (map bspec-name bspecs)
  83.          (lambda (env)
  84.            (map (lambda (bspec)
  85.               (process-syntax-binding (bspec-rhs bspec)
  86.                           env))
  87.             bspecs))
  88.          outer-env)
  89.       cont)))
  90.  
  91. (define (process-syntax-binding transformer env)
  92.   (make-macro (if (procedure? transformer)
  93.           transformer
  94.           (eval-transformer transformer
  95.                     (get-transformer-environment env)))
  96.           env))
  97.  
  98. (define (make-classified class form env)
  99.   (vector 'classified class form env))
  100. (define classified?
  101.   (vector-predicate 'classified))
  102. (define classified-class
  103.   (vector-accessor 'classified 1))
  104. (define classified-form
  105.   (vector-accessor 'classified 2))
  106. (define classified-env
  107.   (vector-accessor 'classified 3))
  108.  
  109. ; Process internal definitions
  110.  
  111. ; This code goes to considerable contortions in order to avoid using
  112. ; side effects.  I think that it could be considerably simplified if
  113. ; it were less scrupulous about that.
  114.  
  115. ; It could also be simplified if it were willing to expand the forms
  116. ; in the body more than once.
  117.  
  118. ; There is still one bug: if a body contains more than one expression
  119. ; (following some number of definitions), and classifying the first of
  120. ; those expressions uses a name bound outside the body to a syntactic
  121. ; operator, and that name is shadowed by one of the definitions, then
  122. ; the wrong (outer) binding of that name will be used in classifying
  123. ; the body.  (Example: (lambda () (define cond list) (cond 1 2) 3).)
  124. ; This can be fixed, but I've already wasted too much time on this
  125. ; problem.
  126.  
  127. (define (scan-body forms env cont)
  128.   (tracking-lookups env        ; Only for error checking
  129.     (lambda (env seen-thunk)
  130.       (let ((done
  131.          (lambda (names def-forms body-forms)
  132.            (let ((seen (seen-thunk)))
  133.          (for-each (lambda (name)
  134.                  (if (name-member name seen)
  135.                  (syntax-error "defined name was used in expanding definition"
  136.                            name)))
  137.                names))
  138.            (cont names def-forms body-forms))))
  139.     (let loop ((names '())
  140.            (def-forms '())
  141.            (forms forms))
  142.       (if (null? (cdr forms))  ;Optimization.
  143.           ;; Last form must be an expression.
  144.           (done names def-forms forms)
  145.           (scan-body-form (car forms)
  146.                   (re-extension-barrier env)
  147.                   (lambda (more-names more-def-forms)
  148.                 (loop (append more-names names)
  149.                       (append more-def-forms def-forms)
  150.                       (cdr forms)))
  151.                   (lambda (form)
  152.                 (done names
  153.                       def-forms
  154.                       (cons form (cdr forms)))))))))))
  155.  
  156. (define (scan-body-form form env d-cont e-cont)
  157.   (classify form env
  158.     (lambda (class form env)
  159.       (cond ((= class class/define)
  160.          (let ((extender (re-extender env)))
  161.            (d-cont (list (define-name form))
  162.                (list (lambda (env cont)
  163.                    (classify (define-rhs form)
  164.                    (extender env)
  165.                  cont))))))
  166.         ((= class class/begin)
  167.          (scan-body-begin form env d-cont e-cont))
  168.         (else
  169.          (e-cont (make-classified class form env)))))))
  170.  
  171. (define (scan-body-begin form env d-cont e-cont)
  172.   (let ((forms (begin-statements form)))
  173.     (cond ((null? forms) (d-cont '() '()))
  174.       ((null? (cdr forms))
  175.        (scan-body-form (car forms) env d-cont e-cont))
  176.       (else
  177.        (scan-body-form
  178.           (car forms)
  179.           env
  180.           (lambda (names def-forms)
  181.         (let loop ((names names)
  182.                (def-forms def-forms)
  183.                (forms (cdr forms)))
  184.           (if (null? forms)
  185.               (d-cont names def-forms)
  186.               (scan-body-form
  187.                  (car forms)
  188.              env
  189.              (lambda (more-names more-def-forms)
  190.                (loop (append more-names names)
  191.                  (append more-def-forms def-forms)
  192.                  (cdr forms)))
  193.              (lambda (form)
  194.                (syntax-error "intermixed expressions and definitions"
  195.                      form))))))
  196.           (lambda (form)
  197.         (e-cont (make-classified class/begin
  198.                      `(begin ,form ,@(cdr forms))
  199.                      env))))))))
  200.  
  201. ; Environment operations
  202.  
  203. (define (lookup name env)
  204.   ((env 'lookup) name))
  205.  
  206. (define (lookup-variable name env)
  207.   (let ((binding (lookup name env)))
  208.     (if (or (special-operator? binding)
  209.         (macro? binding))
  210.     (syntax-error "syntactic keyword encountered in invalid context" name)
  211.     binding)))
  212.  
  213. (define (simple-environment lookup outer-env)
  214.   (lambda (op)
  215.     (case op
  216.       ((lookup) lookup)
  217.       (else (outer-env op)))))
  218.  
  219. (define (bind names bindings outer-env)
  220.   (simple-environment
  221.     (lambda (name)
  222.       (lookup-internal name names bindings outer-env))
  223.     outer-env))
  224.  
  225. (define (bindrec names bindings-proc outer-env)
  226.   (letrec ((env (simple-environment
  227.           (lambda (name)
  228.             (lookup-internal name names (force bindings)
  229.                      outer-env))
  230.           outer-env))
  231.        (bindings (delay (bindings-proc env))))
  232.     env))
  233.  
  234. (define (lookup-internal name names bindings outer-env)
  235.   (let loop ((names names) (bindings bindings))
  236.     (if (null? names)
  237.     (lookup name outer-env)
  238.     (if (same-name? name (car names))
  239.         (car bindings)
  240.         (loop (cdr names) (cdr bindings))))))
  241.  
  242. ; Keep track of keyword lookups for lambda body error checking.
  243.  
  244. (define (tracking-lookups env cont)
  245.   (let ((seen '()))
  246.     (cont (simple-environment
  247.          (lambda (name)
  248.            (let ((binding (lookup name env)))
  249.          (if (or (macro? binding)
  250.              (special-operator? binding))
  251.              (set! seen (cons name seen)))
  252.          binding))
  253.          env)
  254.       (lambda () seen))))
  255.  
  256. ; Make a mutable environment, for program top level and/or REP loop.
  257.  
  258. (define (make-mutable-environment transformer-env)
  259.   (let ((defined (make-table)))
  260.     (let ((lookup
  261.        (lambda (name)
  262.          (or (table-ref defined name)
  263.          (make-unbound name))))
  264.       (define!
  265.        (lambda (name binding)
  266.          (table-set! defined name binding))))
  267.       (lambda (op)
  268.     (case op
  269.       ((lookup) lookup)
  270.       ((define!) define!)
  271.       ((transformer-environment) transformer-env)
  272.       (else (error "unknown environment operation" op)))))))
  273.  
  274. (define (environment-define! env name binding)
  275.   ((env 'define!) name binding))
  276.  
  277. ; Get the environment in which to evaluate transformer procedure expressions.
  278.  
  279. (define (get-transformer-environment env)
  280.   (env 'transformer-environment))
  281.  
  282. ; Environment for macro output
  283.  
  284. (define (diversion-environment color macro-env client-env)
  285.   (simple-environment
  286.     (lambda (name)
  287.       (if (and (painted? name)
  288.            (same-color? (painted-color name) color))
  289.       (lookup (painted-name name) macro-env)
  290.       (lookup name client-env)))
  291.     client-env))
  292.  
  293. ; Kludgiferous stuff for internal define
  294.  
  295. (define (re-extension-barrier env)
  296.   (lambda (op)
  297.     (case op
  298.       ((re-extender) (lambda (env) env))
  299.       (else (env op)))))
  300.  
  301. (define (re-extendable-environment extend outer-env)
  302.   (let ((env (extend outer-env)))
  303.     (lambda (op)
  304.       (case op
  305.     ((re-extender)
  306.      ;; Kludge for processing internal defines
  307.      (let ((outer-extend (re-extender outer-env)))
  308.        (lambda (env-again)
  309.          (outer-extend (extend env-again)))))
  310.     (else (env op))))))
  311.  
  312. (define (re-extender env)
  313.   (env 're-extender))
  314.  
  315. ; Define special operator names to be special operators.
  316.  
  317. (define (define-special-operators! env)
  318.   (for-each (lambda (name class)
  319.           (environment-define! env name (make-special-operator class)))
  320.         (list 'let-syntax 'letrec-syntax
  321.           'define-syntax '%define
  322.           'lambda 'letrec 'if
  323.           'quote 'begin 'set!)
  324.         (list class/let-syntax class/letrec-syntax
  325.           class/define-syntax class/define
  326.           class/lambda class/letrec class/if
  327.           class/quote class/begin class/set!)))
  328.  
  329. ; Binding = special operator + macro + unbound + variable
  330. ; All of these can be compared using EQ?, except unbound.
  331.  
  332. (define same-binding? equal?)
  333.  
  334. ; Special operators
  335.  
  336. (define (make-special-operator class)
  337.   (vector 'special class))
  338. (define special-operator?
  339.   (vector-predicate 'special))
  340. (define special-operator-class
  341.   (vector-accessor 'special 1))
  342.  
  343. ; Macros
  344.  
  345. (define (make-macro transformer env)
  346.   (vector 'macro transformer env))
  347. (define macro?
  348.   (vector-predicate 'macro))
  349. (define macro-transformer
  350.   (vector-accessor 'macro 1))
  351. (define macro-environment
  352.   (vector-accessor 'macro 2))
  353.  
  354. ; Unbound
  355.  
  356. (define (make-unbound name) (vector 'unbound name))
  357. (define unbound? (vector-predicate 'unbound))
  358. (define unbound-name (vector-accessor 'unbound 1))
  359.  
  360. ; Names, colors, painting
  361.  
  362. (define (make-painted name color)
  363.   (vector 'painted name color))
  364. (define painted? (vector-predicate 'painted))
  365. (define painted-name (vector-accessor 'painted 1))
  366. (define painted-color (vector-accessor 'painted 2))
  367.  
  368. (define (name? thing)
  369.   (or (symbol? thing) (painted? thing)))
  370.  
  371. (define (unpaint thing)
  372.   (cond ((painted? thing) (unpaint (painted-name thing)))
  373.     ((pair? thing)
  374.      (let ((x (unpaint (car thing)))
  375.            (y (unpaint (cdr thing))))
  376.        (if (and (eq? x (car thing))
  377.             (eq? y (cdr thing)))
  378.            thing
  379.            (cons x y))))
  380.     ((vector? thing)
  381.      (let ((new (make-vector (vector-length thing))))
  382.        (let loop ((i 0) (same? #t))
  383.          (if (>= i (vector-length thing))
  384.          (if same? thing new)
  385.          (let ((x (unpaint (vector-ref thing i))))
  386.            (vector-set! new i x)
  387.            (loop (+ i 1)
  388.              (and same? (eq? x (vector-ref thing i)))))))))
  389.     (else thing)))
  390.  
  391. (define (name->symbol name)
  392.   (cond ((symbol? name) name)
  393.     ((painted? name)
  394.      (string->symbol
  395.       (string-append "."
  396.              (symbol->string (name->symbol (painted-name name)))
  397.              "."
  398.              (number->string (painted-color name) '(heur)))))
  399.     (else (error "not a name" name))))
  400.  
  401. (define *color* 0)
  402.  
  403. (define (new-color)
  404.   (set! *color* (+ *color* 1))
  405.   *color*)
  406.  
  407. (define same-color? =)
  408.  
  409. (define (with-new-color macro-env client-env cont)
  410.   (let ((alist '())            ;list of name * painted
  411.     (color (new-color)))
  412.     (cont (lambda (name)
  413.         (let ((probe (assq name alist)))
  414.           (if probe
  415.           (cdr probe)
  416.           (let ((new-name (make-painted name color)))
  417.             (set! alist (cons (cons name new-name)
  418.                       alist))
  419.             new-name))))
  420.       (re-extendable-environment
  421.         (lambda (client-env)
  422.           (diversion-environment color macro-env client-env))
  423.         client-env))))
  424.  
  425. (define same-name? eq?)
  426. (define name-member memq)
  427. (define name-assoc assq)
  428.  
  429. ; Expressions
  430.  
  431. (define (literal? x)
  432.   (or (number? x) (string? x) (boolean? x) (char? x)))
  433.  
  434. (define (literal-value lit) lit)
  435.  
  436. (define compound? pair?)
  437. (define operator car)
  438. (define operands cdr)
  439.  
  440. ; (let-syntax ((<name> <exp>)) <body>)
  441.  
  442. (define let-syntax-bspecs cadr)
  443. (define let-syntax-body caddr)
  444.  
  445. (define (check-let-syntax exp)
  446.   (and (= (careful-length exp) 3)
  447.        (careful-every check-bspec (let-syntax-bspecs exp))))
  448.  
  449. ; (letrec-syntax ((<name> <exp>)) <body>)
  450.  
  451. (define letrec-syntax-bspecs let-syntax-bspecs)
  452. (define letrec-syntax-body   let-syntax-body)
  453.  
  454. (define check-letrec-syntax check-let-syntax)
  455.  
  456. ; Binding specs (<name> <exp>)
  457.  
  458. (define bspec-name car)
  459. (define bspec-rhs cadr)
  460.  
  461. (define (check-bspec bspec)
  462.   (and (= (careful-length bspec) 2)
  463.        (name? (bspec-name bspec))))
  464.  
  465. ; (define <name> <rhs>)     [rhs = right-hand side]
  466.  
  467. (define define-name cadr)
  468. (define define-rhs caddr)
  469.  
  470. (define (check-define form)
  471.   (and (= (careful-length form) 3)
  472.        (name? (define-name form))))
  473.  
  474. ; (define-syntax <name> <rhs>)
  475.  
  476. (define define-syntax-name cadr)
  477. (define define-syntax-rhs caddr)
  478.  
  479. (define (check-define-syntax form)
  480.   (and (= (careful-length form) 3)
  481.        (name? (define-syntax-name form))))
  482.  
  483. ; (begin <statement>*)
  484.  
  485. (define begin-statements cdr)
  486.  
  487. (define (check-begin form)
  488.   (>= (careful-length form) 1))  ;must be a proper list
  489.  
  490. ; variable reference
  491.  
  492. (define (variable-name var) var)
  493.  
  494. ; application
  495.  
  496. (define application-procedure operator)
  497. (define application-arguments operands)
  498.  
  499. ; (lambda (<name>*) <body>)
  500.  
  501. (define lambda-formals cadr)
  502. (define lambda-body cddr)
  503.  
  504. (define (check-lambda exp)
  505.   (and (>= (careful-length exp) 3)
  506.        (let recur ((formals (lambda-formals exp)))
  507.      (or (null? formals)
  508.          (name? formals)
  509.          (and (name? (car formals)) (recur (cdr formals)))))))
  510.  
  511. ; (letrec ((<name> <exp>)) <body>)
  512.  
  513. (define letrec-bspecs cadr)
  514. (define letrec-body cddr)
  515.  
  516. (define (check-letrec exp)
  517.   (and (>= (careful-length exp) 3)
  518.        (careful-every check-bspec (letrec-bspecs exp))))
  519.  
  520. ; (quote <text>)
  521.  
  522. (define quotation-text cadr)
  523.  
  524. (define (check-quote exp)
  525.   (= (careful-length exp) 2))
  526.  
  527. ; (if <test> <con> <alt>)
  528.  
  529. (define if-test cadr)
  530. (define if-consequent caddr)
  531. (define (if-alternate exp)
  532.   (let ((z (cdddr exp)))
  533.     (if (null? z) unspecified-expression (car z))))
  534. (define unspecified-expression (list 'unspecified-value))
  535.  
  536. (define (check-if exp)
  537.   (let ((len (careful-length exp)))
  538.     (or (= len 3) (= len 4))))
  539.  
  540. ; (set! <lhs> <rhs>)
  541.  
  542. (define set!-lhs cadr)
  543. (define set!-rhs caddr)
  544.  
  545. (define (check-set! exp)
  546.   (and (= (careful-length exp) 3)
  547.        (name? (set!-lhs exp))))
  548.  
  549. ;
  550.  
  551. (define (careful-length l)
  552.   (if (null? l)
  553.       0
  554.       (if (pair? l)
  555.       (+ 1 (careful-length (cdr l)))
  556.       -1)))
  557.  
  558. (define (careful-every pred l)
  559.   (if (null? l)
  560.       #t
  561.       (and (pair? l)
  562.        (pred (car l))
  563.        (careful-every pred (cdr l)))))
  564.  
  565. (define (check-special-form-syntax class form)
  566.   ((vector-ref syntax-checkers class) form))
  567.  
  568. (define syntax-checkers
  569.   (let ((v (make-vector number-of-classes (lambda (form) #t))))
  570.     (vector-set! v class/lambda        check-lambda)
  571.     (vector-set! v class/letrec        check-letrec)
  572.     (vector-set! v class/if            check-if)
  573.     (vector-set! v class/quote         check-quote)
  574.     (vector-set! v class/begin         check-begin)
  575.     (vector-set! v class/set!          check-set!)
  576.     (vector-set! v class/let-syntax    check-let-syntax)
  577.     (vector-set! v class/letrec-syntax check-letrec-syntax)
  578.     (vector-set! v class/define        check-define)
  579.     (vector-set! v class/define-syntax check-define-syntax)
  580.     v))
  581.  
  582. ; (put 'bind 'scheme-indent-hook nil)
  583.