bindings.scm 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. ;;; Guile Emacs Lisp
  2. ;;; Copyright (C) 2009, 2010 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 bindings)
  19. #:export (make-bindings
  20. mark-global-needed!
  21. map-globals-needed
  22. with-lexical-bindings
  23. with-dynamic-bindings
  24. get-lexical-binding))
  25. ;;; This module defines routines to handle analysis of symbol bindings
  26. ;;; used during elisp compilation. This data allows to collect the
  27. ;;; symbols, for which globals need to be created, or mark certain
  28. ;;; symbols as lexically bound.
  29. ;;;
  30. ;;; Needed globals are stored in an association-list that stores a list
  31. ;;; of symbols for each module they are needed in.
  32. ;;;
  33. ;;; The lexical bindings of symbols are stored in a hash-table that
  34. ;;; associates symbols to fluids; those fluids are used in the
  35. ;;; with-lexical-binding and with-dynamic-binding routines to associate
  36. ;;; symbols to different bindings over a dynamic extent.
  37. ;;; Record type used to hold the data necessary.
  38. (define bindings-type
  39. (make-record-type 'bindings '(needed-globals lexical-bindings)))
  40. ;;; Construct an 'empty' instance of the bindings data structure to be
  41. ;;; used at the start of a fresh compilation.
  42. (define (make-bindings)
  43. ((record-constructor bindings-type) '() (make-hash-table)))
  44. ;;; Mark that a given symbol is needed as global in the specified
  45. ;;; slot-module.
  46. (define (mark-global-needed! bindings sym module)
  47. (let* ((old-needed ((record-accessor bindings-type 'needed-globals)
  48. bindings))
  49. (old-in-module (or (assoc-ref old-needed module) '()))
  50. (new-in-module (if (memq sym old-in-module)
  51. old-in-module
  52. (cons sym old-in-module)))
  53. (new-needed (assoc-set! old-needed module new-in-module)))
  54. ((record-modifier bindings-type 'needed-globals)
  55. bindings
  56. new-needed)))
  57. ;;; Cycle through all globals needed in order to generate the code for
  58. ;;; their creation or some other analysis.
  59. (define (map-globals-needed bindings proc)
  60. (let ((needed ((record-accessor bindings-type 'needed-globals)
  61. bindings)))
  62. (let iterate-modules ((mod-tail needed)
  63. (mod-result '()))
  64. (if (null? mod-tail)
  65. mod-result
  66. (iterate-modules
  67. (cdr mod-tail)
  68. (let* ((aentry (car mod-tail))
  69. (module (car aentry))
  70. (symbols (cdr aentry)))
  71. (let iterate-symbols ((sym-tail symbols)
  72. (sym-result mod-result))
  73. (if (null? sym-tail)
  74. sym-result
  75. (iterate-symbols (cdr sym-tail)
  76. (cons (proc module (car sym-tail))
  77. sym-result))))))))))
  78. ;;; Get the current lexical binding (gensym it should refer to in the
  79. ;;; current scope) for a symbol or #f if it is dynamically bound.
  80. (define (get-lexical-binding bindings sym)
  81. (let* ((lex ((record-accessor bindings-type 'lexical-bindings)
  82. bindings))
  83. (slot (hash-ref lex sym #f)))
  84. (if slot
  85. (fluid-ref slot)
  86. #f)))
  87. ;;; Establish a binding or mark a symbol as dynamically bound for the
  88. ;;; extent of calling proc.
  89. (define (with-symbol-bindings bindings syms targets proc)
  90. (if (or (not (list? syms))
  91. (not (and-map symbol? syms)))
  92. (error "can't bind non-symbols" syms))
  93. (let ((lex ((record-accessor bindings-type 'lexical-bindings)
  94. bindings)))
  95. (for-each (lambda (sym)
  96. (if (not (hash-ref lex sym))
  97. (hash-set! lex sym (make-fluid))))
  98. syms)
  99. (with-fluids* (map (lambda (sym) (hash-ref lex sym)) syms)
  100. targets
  101. proc)))
  102. (define (with-lexical-bindings bindings syms targets proc)
  103. (if (or (not (list? targets))
  104. (not (and-map symbol? targets)))
  105. (error "invalid targets for lexical binding" targets)
  106. (with-symbol-bindings bindings syms targets proc)))
  107. (define (with-dynamic-bindings bindings syms proc)
  108. (with-symbol-bindings bindings
  109. syms
  110. (map (lambda (el) #f) syms)
  111. proc))