diff options
Diffstat (limited to 'Macroexpand.scm')
-rw-r--r-- | Macroexpand.scm | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/Macroexpand.scm b/Macroexpand.scm deleted file mode 100644 index 3b658f8..0000000 --- a/Macroexpand.scm +++ /dev/null @@ -1,370 +0,0 @@ -;; Copyright (C) 1999 Free Software Foundation, Inc. -;; -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this software; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111, USA. -;; -;; As a special exception, the Free Software Foundation gives permission -;; for additional uses of the text contained in its release of GUILE. -;; -;; The exception is that, if you link the GUILE library with other files -;; to produce an executable, this does not by itself cause the -;; resulting executable to be covered by the GNU General Public License. -;; Your use of that executable is in no way restricted on account of -;; linking the GUILE library code into it. -;; -;; This exception does not however invalidate any other reasons why -;; the executable file might be covered by the GNU General Public License. -;; -;; This exception applies only to the code released by the -;; Free Software Foundation under the name GUILE. If you copy -;; code from other Free Software Foundation releases into a copy of -;; GUILE, as the General Public License permits, the exception does -;; not apply to the code that you add in this way. To avoid misleading -;; anyone as to the status of such modified files, you must delete -;; this exception notice from them. -;; -;; If you write modifications of your own for GUILE, it is your choice -;; whether to permit this exception to apply to your modifications. -;; If you do not wish that, delete this exception notice. - -;;;; "Macroexpand.scm", macro expansion, respecting hygiene. -;;; Author: Radey Shouman - -;; It is possible to break MACRO:EXPAND by redefining primitive -;; syntax, eg LAMBDA, LET, QUOTE to different primitive syntax, -;; or by defining any of @LAMBDA, @LET, @LET*, @LETREC, @DO, -;; or @EXPAND as primitive syntax. - -;; We still need LET-SYNTAX and LETREC-SYNTAX. - -(define macro:expand - (let (($lambda (renamed-identifier 'lambda '())) - ($let (renamed-identifier 'let '())) - ($let* (renamed-identifier 'let* '())) - ($letrec (renamed-identifier 'letrec '())) - ($do (renamed-identifier 'do '())) - ($define (renamed-identifier 'define '())) - ($quote (renamed-identifier 'quote '())) - ($quasiquote (renamed-identifier 'quasiquote '())) - ($unquote (renamed-identifier 'unquote '())) - ($unquote-splicing (renamed-identifier 'unquote-splicing '())) - ($case (renamed-identifier 'case '())) - ($cond (renamed-identifier 'cond '())) - ($begin (renamed-identifier 'begin '())) - ($if (renamed-identifier 'if '())) - ($and (renamed-identifier 'and '())) - ($or (renamed-identifier 'or '())) - ($set! (renamed-identifier 'set! '())) - ($delay (renamed-identifier 'delay '())) - ($syntax-quote (renamed-identifier 'syntax-quote '())) - ($@apply (renamed-identifier '@apply '())) - ($else (renamed-identifier 'else '())) - (@lambda (renamed-identifier '@lambda '())) - (@let (renamed-identifier '@let '())) - (@let* (renamed-identifier '@let* '())) - (@letrec (renamed-identifier '@letrec '())) - (@do (renamed-identifier '@do '())) - (@expand (renamed-identifier '@expand '()))) - - (define expander - (macro:compile-syntax-rules - '(syntax-rules (lambda let letrec let* do @let*) - ((_ (lambda ?formals ?body ...)) - (@lambda ?formals ?body ...)) - - ((_ (let ((?name ?val) ...) ?body ...)) - (@let ((?name ...) ?val ...) ?body ...)) - ((_ (let ?proc ((?name ?val) ...) ?body ...)) - (@expand - (letrec ((?proc (lambda (?name ...) ?body ...))) - (?proc ?val ...)))) - - ((_ (letrec ((?name ?val) ...) ?body ...)) - (@letrec ((?name ...) ?val ...) ?body ...)) - - ((_ (let* () ?body ...)) - (@let (()) ?body ...)) - ((_ (let* ((?name1 ?val1) (?name ?val) ...) ?body ...)) - (@expand - (@let* (?name1 ?val1) (let* ((?name ?val) ...) ?body ...)))) - ((_ (@let* (?name ?val ...) (let* () ?body ...))) - (@let* (?name ?val ...) ?body ...)) - ((_ (@let* (?name ?val ...) - (let* ((?name2 ?val2) (?name3 ?val3) ...) ?body ...))) - (@expand - (@let* (?name ?val ... ?name2 ?val2) - (let* ((?name3 ?val3) ...) ?body ...)))) - ((_ (@let* (?name ?val ...) ?body ...)) - (@let* (?name ?val ...) ?body ...)) - - ((_ (do ((?var ?init ?step) ...) - (?test ?clause ...) - ?body ...)) - (@do (?var ...) (?init ...) - (?test ?clause ...) - (?body ...) - (?step ...))) - - ((_ ?form) - ?form)) - '())) - - (define (simplify-identifiers expr env) - (let simplify ((expr expr)) - (cond ((identifier? expr) - (let ((sym (identifier->symbol expr))) - (if (identifier-equal? sym expr env) sym expr))) - ((pair? expr) - (cons (simplify (car expr)) - (simplify (cdr expr)))) - (else expr)))) - - (define (unpaint expr) - (cond ((identifier? expr) - (identifier->symbol expr)) - ((pair? expr) - (cons (unpaint (car expr)) (unpaint (cdr expr)))) - ((vector? expr) - (list->vector (map unpaint (vector->list expr)))) - (else expr))) - - (define (defines->bindings defs) - (reverse ;purely cosmetic - (map (lambda (b) - (if (pair? (cadr b)) - (list (caadr b) - (cons $lambda (cons (cdadr b) (cddr b)))) - (cdr b))) - defs))) - - (define (expand-define expr env) - (let ((binding (car (defines->bindings (list expr))))) - (cons (simplify-identifiers $define env) - (list (simplify-identifiers (car binding) env) - (macro:expand (cadr binding) env))))) - - (define (expand-body expr-list env) - (let loop ((defines '()) - (exprs expr-list)) - (if (null? exprs) #f ; should check higher up. - (let ((exp1 (macro:expand (car exprs) env))) - (if (and (pair? exp1) - (identifier? (car exp1)) - (identifier-equal? (car exp1) $define env)) - (loop (cons exp1 defines) (cdr exprs)) - (if (null? defines) - (cons exp1 (expand* (cdr exprs) env)) - (let ((bindings (defines->bindings defines))) - (list - (macro:expand - (cons $letrec (cons bindings exprs)) - env))))))))) - - (define (expand* exprs env) - (map (lambda (x) - (macro:expand x env)) - exprs)) - - ;;(@lambda formals body ...) - (define (expand-lambda expr env) - (let* ((formals (cadr expr)) - (body (cddr expr)) - (bound - (let recur ((f formals)) - (cond ((null? f) '()) - ((pair? f) (cons 'required (recur (cdr f)))) - ((identifier? f) (list 'rest-list)) - (else (error 'lambda 'bad-formals expr))))) - (env1 (extended-environment formals bound env))) - (cons (simplify-identifiers $lambda env) - (cons (simplify-identifiers formals env1) - (expand-body body env1))))) - - ;;(@let ((formals) bindings) body ...) - (define (expand-let expr env) - (let* ((formals (caadr expr)) - (bindings (expand* (cdadr expr) env)) - (env1 (extended-environment formals - (map (lambda (x) 'let) formals) - env))) - (cons (simplify-identifiers $let env) - (cons (map list formals bindings) - (expand-body (cddr expr) env1))))) - - (define (expand-let* expr env) - (let loop ((inp (cadr expr)) - (formals '()) - (bindings '()) - (env1 env)) - (if (null? inp) - (cons (simplify-identifiers $let* env) - (map list (reverse formals) (reverse bindings)) - (expand-body (cddr expr) env1)) - (loop (cddr inp) - (cons (car inp) formals) - (cons (macro:expand (cadr inp) env1) bindings) - (extended-environment (car inp) 'let* env1))))) - - ;;(@letrec ((formals) bindings) body ...) - (define (expand-letrec expr env) - (let* ((formals (caadr expr)) - (env1 (extended-environment - formals - (map (lambda (x) 'letrec) formals) - env)) - (bindings (expand* (cdadr expr) env1))) - (cons (simplify-identifiers $letrec env) - (cons (map list formals bindings) - (expand-body (cddr expr) env1))))) - - ;;(@do vars inits (test clause ...) (body ...) steps) - (define (expand-do expr env) - (let* ((vars (cadr expr)) - (inits (expand* (caddr expr) env)) - (env1 (extended-environment - vars (map (lambda (x) 'do) inits) env)) - (steps (expand* (list-ref expr 5) env1))) - (cons (simplify-identifiers $do env) - (cons - (map list vars inits steps) - (cons (expand* (cadddr expr) env1) - (expand* (list-ref expr 4) env1)))))) - - (define (expand-quote expr env) - (let ((obj (cadr expr))) - (if (or (boolean? obj) - (number? obj) - (string? obj)) - obj - (list (simplify-identifiers $quote env) - (unpaint obj))))) - - (define (expand-quasiquote expr env) - (list (simplify-identifiers $quasiquote env) - (let qq ((expr (cadr expr)) - (level 0)) - (cond ((vector? expr) - (list->vector (qq (vector->list expr) level))) - ((not (pair? expr)) - (unpaint expr)) - ((not (identifier? (car expr))) - (cons (qq (car expr) level) (qq (cdr expr) level))) - ((identifier-equal? (car expr) $quasiquote env) - (list (simplify-identifiers $quasiquote env) - (qq (cadr expr) (+ level 1)))) - ((or (identifier-equal? (car expr) $unquote env) - (identifier-equal? (car expr) $unquote-splicing env)) - (list (simplify-identifiers (car expr) env) - (if (zero? level) - (macro:expand (cadr expr) env) - (qq (cadr expr) (- level 1))))) - (else - (cons (qq (car expr) level) - (qq (cdr expr) level))))))) - - (define (expand-case expr env) - (cons (simplify-identifiers $case env) - (cons (macro:expand (cadr expr) env) - (map (lambda (clause) - (cond ((pair? (car clause)) - (cons (unpaint (car clause)) - (expand* (cdr clause) env))) - ((and (identifier? (car clause)) - (identifier-equal? $else - (car clause) env)) - (cons (simplify-identifiers - (car clause) env) - (expand* (cdr clause) env))) - (else (error 'macro:expand 'case - "bad clause" expr)))) - (cddr expr))))) - - (define (expand-cond expr env) - (cons (simplify-identifiers $cond env) - (map (lambda (clause) (expand* clause env)) - (cdr expr)))) - - ;; for IF, BEGIN, SET! - (define (expand-simple expr env) - (cons (simplify-identifiers (car expr) env) - (expand* (cdr expr) env))) - - (define (expand-primitives expr env) - (let loop ((expr (list '@expand expr))) - (let* ((expanded (expander expr env)) - (head (car expanded))) - (cond ((identifier-equal? @LAMBDA head env) - (expand-lambda expanded env)) - ((identifier-equal? @LET head env) - (expand-let expanded env)) - ((identifier-equal? @LET* head env) - (expand-let* expanded env)) - ((identifier-equal? @LETREC head env) - (expand-letrec expanded env)) - ((identifier-equal? @DO head env) - (expand-do expanded env)) - ((identifier-equal? $QUOTE head env) - (expand-quote expanded env)) - ((identifier-equal? $QUASIQUOTE head env) - (expand-quasiquote expanded env)) - ((identifier-equal? $BEGIN head env) - (expand-simple expanded env)) - ((identifier-equal? $IF head env) - (expand-simple expanded env)) - ((identifier-equal? $AND head env) - (expand-simple expanded env)) - ((identifier-equal? $OR head env) - (expand-simple expanded env)) - ((identifier-equal? $SET! head env) - (expand-simple expanded env)) - ((identifier-equal? $DELAY head env) - (expand-simple expanded env)) - ((identifier-equal? $@APPLY head env) - (expand-simple expanded env)) - ((identifier-equal? $CASE head env) - (expand-case expanded env)) - ((identifier-equal? $COND head env) - (expand-cond expanded env)) - ((and (identifier-equal? $DEFINE head env) - (null? (environment->tree env))) - (expand-define expanded env)) - ((identifier-equal? $SYNTAX-QUOTE head env) - (cons (simplify-identifiers head env) - (cdr expanded))) - ((identifier-equal? @EXPAND head env) - (loop expanded)) - (else - (print 'macro:expand - "Warning: unknown primitive syntax" (car expanded)) - expanded))))) - - (lambda (expr env) - (let loop ((expr expr)) - (let ((expanded (@macroexpand1 expr env))) - (cond ((not expanded) - (cond ((pair? expr) - (if (list? expr) - (expand* expr env) - (print 'macro:expand "expansion not a list" expr))) - ((identifier? expr) - (simplify-identifiers expr env)) - (else expr))) - ((eq? expanded expr) - (expand-primitives expr env)) - (else - (loop expanded)))))))) - -;;; Local Variables: -;;; eval: (put 'identifier-case 'scheme-indent-function 1) -;;; End: |