(define *bq-clobberable* (gensym)) (define *bq-quote-nil* (list 'quote ()))
(define-macro (quasiquote x) (bq-completely-process x))
(define (bq-completely-process x) (bq-simplify (bq-process x)))
(define (bq-process x) (cond ((not (pair? x)) (list 'quote x)) ((eq? (car x) 'quasiquote) (bq-process (bq-completely-process (cadr x)))) ((eq? (car x) 'unquote) (cadr x)) ((eq? (car x) 'unquote-splicing) (error ",@~S after `" (cadr x))) ((eq? (car x) 'unquote-dot) (error ",.~S after `" (cadr x))) (else (let loop ((p x) (q '())) (if (not (pair? p)) (cons 'append (nreconc q (list (list 'quote p)))) (if (eq? (car p) 'unquote) (begin (unless (null? (cddr p)) (error "Malformed ,~S" p)) (cons 'append (nreconc q (list (cadr p))))) (begin (when (eq? (car p) 'unquote-splicing) (error "Dotted ,@~S" p)) (when (eq? (car p) 'unquote-dot) (error "Dotted ,.~S" p)) (loop (cdr p) (cons (bracket (car p)) q)))))))))
(define (bracket x) (cond ((not (pair? x)) (list 'list (bq-process x))) ((eq? (car x) 'unquote) (list 'list (cadr x))) ((eq? (car x) 'unquote-splicing) (cadr x)) ((eq? (car x) 'unquote-dot) (list *bq-clobberable* (cadr x))) (else (list 'list (bq-process x)))))
(define (maptree fn x) (if (not (pair? x)) (fn x) (let ((a (fn (car x))) (d (maptree fn (cdr x)))) (if (and (equal? a (car x)) (equal? d (cdr x))) x (cons a d)))))
(define (bq-splicing-frob x) (and (pair? x) (or (eq? (car x) 'unquote-splicing) (eq? (car x) 'unquote-dot))))
(define (bq-frob x) (and (pair? x) (or (eq? (car x) 'unquote) (eq? (car x) 'unquote-splicing) (eq? (car x) 'unquote-dot))))
(define (bq-simplify x) (if (pair? x) (let ((x (if (eq? (car x) 'quote) x (maptree bq-simplify x)))) (if (not (eq? (car x) 'append)) x (bq-simplify-args x))) x))
(define (bq-simplify-args x) (let loop ((args (reverse (cdr x))) (result '())) (if (not (null? args)) (loop (cdr args) (cond ((not (pair? (car args))) (bq-attach-append 'append (car args) result)) ((and (eq? (caar args) 'list) (not (any bq-splicing-frob (cdar args)))) (bq-attach-conses (cdar args) result)) ((and (eq? (caar args) 'list*) (not (any bq-splicing-frob (cdar args)))) (bq-attach-conses (reverse (cdr (reverse (cdar args)))) (bq-attach-append 'append (car (last (car args))) result))) ((and (eq? (caar args) 'quote) (pair? (cadar args)) (not (bq-frob (cadar args))) (not (cddar args))) (bq-attach-conses (list (list 'quote (caadar args))) result)) ((eq? (caar args) *bq-clobberable*) (bq-attach-append 'append! (cadar args) result)) (else (bq-attach-append 'append (car args) result)))) result)))
(define (null-or-quoted x) (or (null? x) (and (pair? x) (eq? (car x) 'quote))))
(define (bq-attach-append op item result) (cond ((and (null-or-quoted item) (null-or-quoted result)) (list 'quote (append (safe-cadr item) (safe-cadr result)))) ((or (null? result) (equal? result *bq-quote-nil*)) (if (bq-splicing-frob item) (list op item) item)) ((and (pair? result) (eq? (car result) op)) (list* (car result) item (cdr result))) (else (list op item result))))
(define (bq-attach-conses items result) (cond ((and (every null-or-quoted items) (null-or-quoted result)) (list 'quote (append (map cadr items) (cadr result)))) ((or (null? result) (equal? result *bq-quote-nil*)) (cons 'list items)) ((and (pair? result) (or (eq? (car result) 'list) (eq? (car result) 'list*))) (cons (car result) (append items (cdr result)))) (else (cons 'list* (append items (list result))))))
|