fset.scm 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. (define-module (lang elisp internals fset)
  2. #:use-module (lang elisp internals evaluation)
  3. #:use-module (lang elisp internals lambda)
  4. #:use-module (lang elisp internals signal)
  5. #:export (fset
  6. fref
  7. fref/error-if-void
  8. elisp-apply
  9. interactive-specification
  10. not-subr?
  11. elisp-export-module))
  12. (define the-variables-module (resolve-module '(lang elisp variables)))
  13. ;; By default, Guile GC's unreachable symbols. So we need to make
  14. ;; sure they stay reachable!
  15. (define syms '())
  16. ;; elisp-export-module, if non-#f, holds a module to which definitions
  17. ;; should be exported under their normal symbol names. This is used
  18. ;; when importing Elisp definitions into Scheme.
  19. (define elisp-export-module (make-fluid))
  20. ;; Store the procedure, macro or alias symbol PROC in SYM's function
  21. ;; slot.
  22. (define (fset sym proc)
  23. (or (memq sym syms)
  24. (set! syms (cons sym syms)))
  25. (let ((vcell (symbol-fref sym))
  26. (vsym #f)
  27. (export-module (fluid-ref elisp-export-module)))
  28. ;; Playing around with variables and name properties... For the
  29. ;; reasoning behind this, see the commentary in (lang elisp
  30. ;; variables).
  31. (cond ((procedure? proc)
  32. ;; A procedure created from Elisp will already have a name
  33. ;; property attached, with value of the form
  34. ;; <elisp-defun:NAME> or <elisp-lambda>. Any other
  35. ;; procedure coming through here must be an Elisp primitive
  36. ;; definition, so we give it a name of the form
  37. ;; <elisp-subr:NAME>.
  38. (or (procedure-name proc)
  39. (set-procedure-property! proc
  40. 'name
  41. (symbol-append '<elisp-subr: sym '>)))
  42. (set! vsym (procedure-name proc)))
  43. ((macro? proc)
  44. ;; Macros coming through here must be defmacros, as all
  45. ;; primitive special forms are handled directly by the
  46. ;; transformer.
  47. (set-procedure-property! (macro-transformer proc)
  48. 'name
  49. (symbol-append '<elisp-defmacro: sym '>))
  50. (set! vsym (procedure-name (macro-transformer proc))))
  51. (else
  52. ;; An alias symbol.
  53. (set! vsym (symbol-append '<elisp-defalias: sym '>))))
  54. ;; This is the important bit!
  55. (if (variable? vcell)
  56. (variable-set! vcell proc)
  57. (begin
  58. (set! vcell (make-variable proc))
  59. (symbol-fset! sym vcell)
  60. ;; Playing with names and variables again - see above.
  61. (module-add! the-variables-module vsym vcell)
  62. (module-export! the-variables-module (list vsym))))
  63. ;; Export variable to the export module, if non-#f.
  64. (if (and export-module
  65. (or (procedure? proc)
  66. (macro? proc)))
  67. (begin
  68. (module-add! export-module sym vcell)
  69. (module-export! export-module (list sym))))))
  70. ;; Retrieve the procedure or macro stored in SYM's function slot.
  71. ;; Note the asymmetry w.r.t. fset: if fref finds an alias symbol, it
  72. ;; recursively calls fref on that symbol. Returns #f if SYM's
  73. ;; function slot doesn't contain a valid definition.
  74. (define (fref sym)
  75. (let ((var (symbol-fref sym)))
  76. (if (and var (variable? var))
  77. (let ((proc (variable-ref var)))
  78. (cond ((symbol? proc)
  79. (fref proc))
  80. (else
  81. proc)))
  82. #f)))
  83. ;; Same as fref, but signals an Elisp error if SYM's function
  84. ;; definition is void.
  85. (define (fref/error-if-void sym)
  86. (or (fref sym)
  87. (signal 'void-function (list sym))))
  88. ;; Maps a procedure to its (interactive ...) spec.
  89. (define interactive-specification (make-object-property))
  90. ;; Maps a procedure to #t if it is NOT a built-in.
  91. (define not-subr? (make-object-property))
  92. (define (elisp-apply function . args)
  93. (apply apply
  94. (cond ((symbol? function)
  95. (fref/error-if-void function))
  96. ((procedure? function)
  97. function)
  98. ((and (pair? function)
  99. (eq? (car function) 'lambda))
  100. (eval (transform-lambda/interactive function '<elisp-lambda>)
  101. the-root-module))
  102. (else
  103. (signal 'invalid-function (list function))))
  104. args))