transform.scm 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. (define-module (lang elisp transform)
  2. #:use-module (lang elisp internals trace)
  3. #:use-module (lang elisp internals fset)
  4. #:use-module (lang elisp internals evaluation)
  5. #:use-module (ice-9 session)
  6. #:export (transformer transform))
  7. ;;; A note on the difference between `(transform-* (cdr x))' and `(map
  8. ;;; transform-* (cdr x))'.
  9. ;;;
  10. ;;; In most cases, none, as most of the transform-* functions are
  11. ;;; recursive.
  12. ;;;
  13. ;;; However, if (cdr x) is not a proper list, the `map' version will
  14. ;;; signal an error immediately, whereas the non-`map' version will
  15. ;;; produce a similarly improper list as its transformed output. In
  16. ;;; some cases, improper lists are allowed, so at least these cases
  17. ;;; require non-`map'.
  18. ;;;
  19. ;;; Therefore we use the non-`map' approach in most cases below, but
  20. ;;; `map' in transform-application, since in the application case we
  21. ;;; know that `(func arg . args)' is an error. It would probably be
  22. ;;; better for the transform-application case to check for an improper
  23. ;;; list explicitly and signal a more explicit error.
  24. (define (syntax-error x)
  25. (error "Syntax error in expression" x))
  26. (define-macro (scheme exp . module)
  27. (let ((m (if (null? module)
  28. the-root-module
  29. (save-module-excursion
  30. (lambda ()
  31. ;; In order for `resolve-module' to work as
  32. ;; expected, the current module must contain the
  33. ;; `app' variable. This is not true for #:pure
  34. ;; modules, specifically (lang elisp base). So,
  35. ;; switch to the root module (guile) before calling
  36. ;; resolve-module.
  37. (set-current-module the-root-module)
  38. (resolve-module (car module)))))))
  39. (let ((x `(,eval (,quote ,exp) ,m)))
  40. ;;(write x)
  41. ;;(newline)
  42. x)))
  43. (define (transformer x)
  44. (cond ((pair? x)
  45. (cond ((symbol? (car x))
  46. (case (car x)
  47. ;; Allow module-related forms through intact.
  48. ((define-module use-modules use-syntax)
  49. x)
  50. ;; Escape to Scheme.
  51. ((scheme)
  52. (cons-source x scheme (cdr x)))
  53. ;; Quoting.
  54. ((quote function)
  55. (cons-source x quote (transform-quote (cdr x))))
  56. ((quasiquote)
  57. (cons-source x quasiquote (transform-quasiquote (cdr x))))
  58. ;; Anything else is a function or macro application.
  59. (else (transform-application x))))
  60. ((and (pair? (car x))
  61. (eq? (caar x) 'quasiquote))
  62. (transformer (car x)))
  63. (else (syntax-error x))))
  64. (else
  65. (transform-datum x))))
  66. (define (transform-datum x)
  67. (cond ((eq? x 'nil) %nil)
  68. ((eq? x 't) #t)
  69. ;; Could add other translations here, notably `?A' -> 65 etc.
  70. (else x)))
  71. (define (transform-quote x)
  72. (trc 'transform-quote x)
  73. (cond ((not (pair? x))
  74. (transform-datum x))
  75. (else
  76. (cons-source x
  77. (transform-quote (car x))
  78. (transform-quote (cdr x))))))
  79. (define (transform-quasiquote x)
  80. (trc 'transform-quasiquote x)
  81. (cond ((not (pair? x))
  82. (transform-datum x))
  83. ((symbol? (car x))
  84. (case (car x)
  85. ((unquote) (list 'unquote (transformer (cadr x))))
  86. ((unquote-splicing) (list 'unquote-splicing (transformer (cadr x))))
  87. (else (cons-source x
  88. (transform-datum (car x))
  89. (transform-quasiquote (cdr x))))))
  90. (else
  91. (cons-source x
  92. (transform-quasiquote (car x))
  93. (transform-quasiquote (cdr x))))))
  94. (define (transform-application x)
  95. (cons-source x @fop `(,(car x) (,transformer-macro ,@(map transform-quote (cdr x))))))
  96. (define transformer-macro
  97. (procedure->memoizing-macro
  98. (let ((cdr cdr))
  99. (lambda (exp env)
  100. (cons-source exp list (map transformer (cdr exp)))))))
  101. (define transform transformer)