123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- (define-module (lang elisp transform)
- #:use-module (lang elisp internals trace)
- #:use-module (lang elisp internals fset)
- #:use-module (lang elisp internals evaluation)
- #:use-module (ice-9 session)
- #:export (transformer transform))
- ;;; A note on the difference between `(transform-* (cdr x))' and `(map
- ;;; transform-* (cdr x))'.
- ;;;
- ;;; In most cases, none, as most of the transform-* functions are
- ;;; recursive.
- ;;;
- ;;; However, if (cdr x) is not a proper list, the `map' version will
- ;;; signal an error immediately, whereas the non-`map' version will
- ;;; produce a similarly improper list as its transformed output. In
- ;;; some cases, improper lists are allowed, so at least these cases
- ;;; require non-`map'.
- ;;;
- ;;; Therefore we use the non-`map' approach in most cases below, but
- ;;; `map' in transform-application, since in the application case we
- ;;; know that `(func arg . args)' is an error. It would probably be
- ;;; better for the transform-application case to check for an improper
- ;;; list explicitly and signal a more explicit error.
- (define (syntax-error x)
- (error "Syntax error in expression" x))
- (define-macro (scheme exp . module)
- (let ((m (if (null? module)
- the-root-module
- (save-module-excursion
- (lambda ()
- ;; In order for `resolve-module' to work as
- ;; expected, the current module must contain the
- ;; `app' variable. This is not true for #:pure
- ;; modules, specifically (lang elisp base). So,
- ;; switch to the root module (guile) before calling
- ;; resolve-module.
- (set-current-module the-root-module)
- (resolve-module (car module)))))))
- (let ((x `(,eval (,quote ,exp) ,m)))
- ;;(write x)
- ;;(newline)
- x)))
- (define (transformer x)
- (cond ((pair? x)
- (cond ((symbol? (car x))
- (case (car x)
- ;; Allow module-related forms through intact.
- ((define-module use-modules use-syntax)
- x)
- ;; Escape to Scheme.
- ((scheme)
- (cons-source x scheme (cdr x)))
- ;; Quoting.
- ((quote function)
- (cons-source x quote (transform-quote (cdr x))))
- ((quasiquote)
- (cons-source x quasiquote (transform-quasiquote (cdr x))))
- ;; Anything else is a function or macro application.
- (else (transform-application x))))
- ((and (pair? (car x))
- (eq? (caar x) 'quasiquote))
- (transformer (car x)))
- (else (syntax-error x))))
- (else
- (transform-datum x))))
- (define (transform-datum x)
- (cond ((eq? x 'nil) %nil)
- ((eq? x 't) #t)
- ;; Could add other translations here, notably `?A' -> 65 etc.
- (else x)))
- (define (transform-quote x)
- (trc 'transform-quote x)
- (cond ((not (pair? x))
- (transform-datum x))
- (else
- (cons-source x
- (transform-quote (car x))
- (transform-quote (cdr x))))))
- (define (transform-quasiquote x)
- (trc 'transform-quasiquote x)
- (cond ((not (pair? x))
- (transform-datum x))
- ((symbol? (car x))
- (case (car x)
- ((unquote) (list 'unquote (transformer (cadr x))))
- ((unquote-splicing) (list 'unquote-splicing (transformer (cadr x))))
- (else (cons-source x
- (transform-datum (car x))
- (transform-quasiquote (cdr x))))))
- (else
- (cons-source x
- (transform-quasiquote (car x))
- (transform-quasiquote (cdr x))))))
- (define (transform-application x)
- (cons-source x @fop `(,(car x) (,transformer-macro ,@(map transform-quote (cdr x))))))
- (define transformer-macro
- (procedure->memoizing-macro
- (let ((cdr cdr))
- (lambda (exp env)
- (cons-source exp list (map transformer (cdr exp)))))))
- (define transform transformer)
|