runtime.scm 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. ;;; Guile Emacs Lisp
  2. ;;; Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software; you can redistribute it and/or
  5. ;;; modify it under the terms of the GNU Lesser General Public
  6. ;;; License as published by the Free Software Foundation; either
  7. ;;; version 3 of the License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this library; if not, write to the Free Software
  16. ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;; Code:
  18. (define-module (language elisp runtime)
  19. #:use-module (ice-9 format)
  20. #:use-module ((system base compile)
  21. #:select (compile))
  22. #:export (nil-value
  23. t-value
  24. value-slot-module
  25. function-slot-module
  26. elisp-bool
  27. ensure-dynamic!
  28. symbol-name
  29. symbol-value
  30. set-symbol-value!
  31. symbol-function
  32. set-symbol-function!
  33. symbol-plist
  34. set-symbol-plist!
  35. symbol-bound?
  36. symbol-fbound?
  37. symbol-default-bound?
  38. symbol-default-value
  39. set-symbol-default-value!
  40. bind-symbol
  41. makunbound!
  42. fmakunbound!
  43. symbol-desc
  44. proclaim-special!
  45. special?
  46. emacs!
  47. unbound
  48. lexical-binding?
  49. set-lexical-binding-mode
  50. log!
  51. eval-elisp
  52. compile-elisp
  53. local-eval-elisp
  54. make-lisp-string
  55. lisp-string?)
  56. #:export-syntax (defspecial prim))
  57. ;;; This module provides runtime support for the Elisp front-end.
  58. ;;; Values for t and nil. (FIXME remove this abstraction)
  59. (define nil-value #nil)
  60. (define t-value #t)
  61. (define make-lisp-string identity)
  62. (define lisp-string? string?)
  63. ;;; Modules for the binding slots.
  64. ;;; Note: Naming those value-slot and/or function-slot clashes with the
  65. ;;; submodules of these names!
  66. (define value-slot-module (define-module* '(elisp-symbols) #:pure #t))
  67. (define function-slot-module (define-module* '(elisp-functions) #:pure #t))
  68. (define plist-slot-module (define-module* '(elisp-plists) #:pure #t))
  69. (define nil_ 'nil)
  70. (define t_ 't)
  71. ;;; Routines for access to elisp dynamically bound symbols. This is
  72. ;;; used for runtime access using functions like symbol-value or set,
  73. ;;; where the symbol accessed might not be known at compile-time. These
  74. ;;; always access the dynamic binding and can not be used for the
  75. ;;; lexical!
  76. (define lexical-binding #t)
  77. (define (lexical-binding?)
  78. lexical-binding)
  79. (define (set-lexical-binding-mode x)
  80. (set! lexical-binding x))
  81. (define unbound (make-symbol "unbound"))
  82. (define dynamic? vector?)
  83. (define (make-dynamic)
  84. (vector #f 4 0 0 unbound))
  85. (define (dynamic-ref x)
  86. (vector-ref x 4))
  87. (define (dynamic-set! x v)
  88. (vector-set! x 4 v))
  89. (define (dynamic-unset! x)
  90. (vector-set! x 4 unbound))
  91. (define (dynamic-bound? x)
  92. (not (eq? (vector-ref x 4) unbound)))
  93. (define (dynamic-bind x v thunk)
  94. (let ((old (vector-ref x 4)))
  95. (dynamic-wind
  96. (lambda () (vector-set! x 4 v))
  97. thunk
  98. (lambda () (vector-set! x 4 old)))))
  99. (define-inlinable (ensure-present! module sym thunk)
  100. (or (module-local-variable module sym)
  101. (let ((variable (make-variable (thunk))))
  102. (module-add! module sym variable)
  103. variable)))
  104. (define-inlinable (ensure-desc! module sym)
  105. (ensure-present! module
  106. sym
  107. (lambda ()
  108. (let ((x (make-dynamic)))
  109. (vector-set! x 0 sym)
  110. x))))
  111. (define-inlinable (schemify symbol)
  112. (case symbol
  113. ((#nil) nil_)
  114. ((#t) t_)
  115. (else symbol)))
  116. (define (symbol-name symbol)
  117. (symbol->string (schemify symbol)))
  118. (define (symbol-desc symbol)
  119. (let ((symbol (schemify symbol)))
  120. (let ((module value-slot-module))
  121. (variable-ref (ensure-desc! module symbol)))))
  122. (define (ensure-dynamic! sym)
  123. (vector-set! (symbol-desc sym) 3 1))
  124. (define (symbol-dynamic symbol)
  125. (ensure-dynamic! symbol)
  126. (symbol-desc symbol))
  127. (define (symbol-value symbol)
  128. (dynamic-ref (symbol-desc symbol)))
  129. (define (set-symbol-value! symbol value)
  130. (dynamic-set! (symbol-desc symbol) value)
  131. value)
  132. (define (symbol-function symbol)
  133. (cond
  134. ((module-variable function-slot-module (schemify symbol))
  135. => variable-ref)
  136. (else #nil)))
  137. (define (set-symbol-function! symbol value)
  138. (set! symbol (schemify symbol))
  139. (ensure-present! function-slot-module symbol (lambda () #nil))
  140. (let ((module function-slot-module))
  141. (module-define! module symbol value)
  142. (module-export! module (list symbol)))
  143. value)
  144. (define (symbol-plist symbol)
  145. (set! symbol (schemify symbol))
  146. (ensure-present! plist-slot-module symbol (lambda () #nil))
  147. (let ((module plist-slot-module))
  148. (module-ref module symbol)))
  149. (define (set-symbol-plist! symbol value)
  150. (set! symbol (schemify symbol))
  151. (ensure-present! plist-slot-module symbol (lambda () #nil))
  152. (let ((module plist-slot-module))
  153. (module-define! module symbol value)
  154. (module-export! module (list symbol)))
  155. value)
  156. (define (symbol-bound? symbol)
  157. (set! symbol (schemify symbol))
  158. (and
  159. (module-bound? value-slot-module symbol)
  160. (let ((var (module-variable value-slot-module
  161. symbol)))
  162. (and (variable-bound? var)
  163. (if (dynamic? (variable-ref var))
  164. (dynamic-bound? (variable-ref var))
  165. #t)))))
  166. (define symbol-default-bound? symbol-bound?)
  167. (define symbol-default-value symbol-value)
  168. (define set-symbol-default-value! set-symbol-value!)
  169. (define (symbol-fbound? symbol)
  170. (set! symbol (schemify symbol))
  171. (and
  172. (module-bound? function-slot-module symbol)
  173. (variable-bound?
  174. (module-variable function-slot-module symbol))
  175. (variable-ref (module-variable function-slot-module symbol))))
  176. (define (bind-symbol symbol value thunk)
  177. (dynamic-bind (symbol-desc symbol) value thunk))
  178. (define (makunbound! symbol)
  179. (if (module-bound? value-slot-module symbol)
  180. (let ((var (module-variable value-slot-module
  181. symbol)))
  182. (if (and (variable-bound? var) (dynamic? (variable-ref var)))
  183. (dynamic-unset! (variable-ref var))
  184. (variable-unset! var))))
  185. symbol)
  186. (define (fmakunbound! symbol)
  187. (if (module-bound? function-slot-module symbol)
  188. (variable-unset! (module-variable function-slot-module symbol)))
  189. symbol)
  190. (define (special? sym)
  191. (eqv? (vector-ref (symbol-desc sym) 3) 1))
  192. (define (proclaim-special! sym)
  193. (vector-set! (symbol-desc sym) 3 1)
  194. #nil)
  195. (define (emacs! ref set boundp dref dset dboundp bind)
  196. (set! symbol-value ref)
  197. (set! set-symbol-value! set)
  198. (set! symbol-bound? boundp)
  199. (set! symbol-default-value dref)
  200. (set! set-symbol-default-value! dset)
  201. (set! symbol-default-bound? dboundp)
  202. (set! bind-symbol bind)
  203. (set! lexical-binding? (lambda () (symbol-value 'lexical-binding)))
  204. (set! set-lexical-binding-mode (lambda (x) (set-symbol-value! 'lexical-binding x))))
  205. (define (eval-elisp form)
  206. (eval (compile form #:from 'elisp #:to 'tree-il) (current-module)))
  207. (define (compile-elisp form)
  208. (compile (compile form #:from 'elisp #:to 'bytecode)
  209. #:from 'bytecode #:to 'value))
  210. (set-symbol-value! nil_ #nil)
  211. (set-symbol-value! t_ #t)
  212. (define (make-string s) s)
  213. ;;; Define a predefined macro for use in the function-slot module.
  214. (define (make-id template-id . data)
  215. (let ((append-symbols
  216. (lambda (symbols)
  217. (string->symbol
  218. (apply string-append (map symbol->string symbols))))))
  219. (datum->syntax template-id
  220. (append-symbols
  221. (map (lambda (datum)
  222. ((if (identifier? datum)
  223. syntax->datum
  224. identity)
  225. datum))
  226. data)))))
  227. (define-syntax defspecial
  228. (lambda (x)
  229. (syntax-case x ()
  230. ((_ name args body ...)
  231. (with-syntax ((scheme-name (make-id #'name 'compile- #'name)))
  232. #'(begin
  233. (define scheme-name
  234. (cons 'special-operator (lambda args body ...)))
  235. (set-symbol-function! 'name scheme-name)))))))