bindings.scm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. #:use-module (srfi srfi-1)
  20. #:use-module (srfi srfi-8)
  21. #:use-module (srfi srfi-9)
  22. #:use-module (srfi srfi-26)
  23. #:export (make-bindings
  24. with-lexical-bindings
  25. with-dynamic-bindings
  26. with-function-bindings
  27. get-lexical-binding
  28. get-function-binding))
  29. ;;; This module defines routines to handle analysis of symbol bindings
  30. ;;; used during elisp compilation. This data allows to collect the
  31. ;;; symbols, for which globals need to be created, or mark certain
  32. ;;; symbols as lexically bound.
  33. ;;;
  34. ;;; The lexical bindings of symbols are stored in a hash-table that
  35. ;;; associates symbols to fluids; those fluids are used in the
  36. ;;; with-lexical-binding and with-dynamic-binding routines to associate
  37. ;;; symbols to different bindings over a dynamic extent.
  38. ;;; Record type used to hold the data necessary.
  39. (define-record-type bindings
  40. (%make-bindings lexical-bindings function-bindings)
  41. bindings?
  42. (lexical-bindings lexical-bindings)
  43. (function-bindings function-bindings))
  44. ;;; Construct an 'empty' instance of the bindings data structure to be
  45. ;;; used at the start of a fresh compilation.
  46. (define (make-bindings)
  47. (%make-bindings (make-hash-table) (make-hash-table)))
  48. ;;; Get the current lexical binding (gensym it should refer to in the
  49. ;;; current scope) for a symbol or #f if it is dynamically bound.
  50. (define (get-lexical-binding bindings sym)
  51. (let* ((lex (lexical-bindings bindings))
  52. (slot (hash-ref lex sym #f)))
  53. (if slot
  54. (fluid-ref slot)
  55. #f)))
  56. (define (get-function-binding bindings symbol)
  57. (and=> (hash-ref (function-bindings bindings) symbol)
  58. fluid-ref))
  59. ;;; Establish a binding or mark a symbol as dynamically bound for the
  60. ;;; extent of calling proc.
  61. (define (with-symbol-bindings bindings syms targets proc)
  62. (if (or (not (list? syms))
  63. (not (and-map symbol? syms)))
  64. (error "can't bind non-symbols" syms))
  65. (let ((lex (lexical-bindings bindings)))
  66. (for-each (lambda (sym)
  67. (if (not (hash-ref lex sym))
  68. (hash-set! lex sym (make-fluid))))
  69. syms)
  70. (with-fluids* (map (lambda (sym) (hash-ref lex sym)) syms)
  71. targets
  72. proc)))
  73. (define (with-lexical-bindings bindings syms targets proc)
  74. (if (or (not (list? targets))
  75. (not (and-map symbol? targets)))
  76. (error "invalid targets for lexical binding" targets)
  77. (with-symbol-bindings bindings syms targets proc)))
  78. (define (with-dynamic-bindings bindings syms proc)
  79. (with-symbol-bindings bindings
  80. syms
  81. (map (lambda (el) #f) syms)
  82. proc))
  83. (define (with-function-bindings bindings symbols gensyms thunk)
  84. (let ((fb (function-bindings bindings)))
  85. (for-each (lambda (symbol)
  86. (if (not (hash-ref fb symbol))
  87. (hash-set! fb symbol (make-fluid))))
  88. symbols)
  89. (with-fluids* (map (cut hash-ref fb <>) symbols)
  90. gensyms
  91. thunk)))