package-undef.scm 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; The entry point for all this.
  3. (define (link! template package noise?)
  4. (if noise?
  5. (noting-undefined-variables package
  6. (lambda ()
  7. (really-link! template package)))
  8. (really-link! template package)))
  9. (define (really-link! template package)
  10. (do ((i 0 (+ i 1)))
  11. ((= i (template-length template)))
  12. (let ((x (template-ref template i)))
  13. (cond ((thingie? x)
  14. (template-set! template
  15. i
  16. (get-location (thingie-binding x)
  17. package
  18. (thingie-name x)
  19. (thingie-want-type x))))
  20. ((template? x)
  21. (really-link! x package))))))
  22. ; GET-LOCATION returns a location to be stored away in a template. If the
  23. ; wanted meta-type, which is either `value-type' or `usual-variable-type'
  24. ; (for SET!), matches that in the binding, then we just return the binding's
  25. ; location after noting that we are doing so.
  26. ;
  27. ; If the type doesn't match then we make a location and remember that we
  28. ; have done so. If correct location becomes available later we will replace
  29. ; the bogus one (see env/pedit.scm).
  30. (define (get-location binding cenv name want-type)
  31. (if (binding? binding)
  32. (let ((place (binding-place binding)))
  33. (cond ((compatible-types? (binding-type binding) want-type)
  34. (note-caching! cenv name place)
  35. place)
  36. ((variable-type? want-type)
  37. (get-location-for-unassignable cenv name))
  38. (else
  39. (warn "invalid variable reference" name cenv)
  40. (note-caching! cenv name place)
  41. place)))
  42. (get-location-for-undefined cenv name)))
  43. ; Packages have three tables used by env/pedit.scm:
  44. ; undefineds
  45. ; locations introduced for missing values
  46. ; undefined-but-assigneds
  47. ; locations introduced for missing cells
  48. ; cached
  49. ; locations used here that were supposed to have been provided by
  50. ; someone else
  51. ; Get a location from PACKAGE's table at ACCESSOR.
  52. (define (location-on-demand accessor)
  53. (lambda (package name)
  54. (let ((table (accessor package)))
  55. (or (table-ref table name)
  56. (let ((new (make-new-location package name)))
  57. (table-set! table name new)
  58. new)))))
  59. (define get-undefined
  60. (location-on-demand package-undefineds))
  61. (define location-for-assignment
  62. (location-on-demand package-undefined-but-assigneds))
  63. ; If this package is mutable and it gets NAME from some other structure
  64. ; then add NAME and PLACE to its table of cached locations.
  65. (define (package-note-caching! package name place)
  66. (if (package-unstable? package)
  67. (if (not (table-ref (package-definitions package) name))
  68. (let loop ((opens (package-opens package)))
  69. (if (not (null? opens))
  70. (call-with-values
  71. (lambda ()
  72. (interface-ref (structure-interface (car opens))
  73. name))
  74. (lambda (internal-name type)
  75. (if internal-name
  76. (begin
  77. (table-set! (package-cached package) name place)
  78. (package-note-caching!
  79. (structure-package (car opens))
  80. internal-name place))
  81. (loop (cdr opens))))))))))
  82. ; Find the actual package providing PLACE and remember that it is being used.
  83. (define (note-caching! cenv name place)
  84. (if (generated? name)
  85. (note-caching! (generated-env name)
  86. (generated-name name)
  87. place)
  88. (let ((package (cenv->package cenv)))
  89. (if (package? package)
  90. (package-note-caching! package name place)))))
  91. ; Get a location for NAME which is SET! but isn't supposed to be.
  92. (define (get-location-for-unassignable cenv name)
  93. (if (generated? name)
  94. (get-location-for-unassignable (generated-env name)
  95. (generated-name name))
  96. (let ((package (cenv->package cenv)))
  97. (warn "invalid assignment" name)
  98. (if (package? package)
  99. (lambda () (location-for-assignment package name))
  100. (lambda () (make-undefined-location name))))))
  101. ; Get a location for NAME, which is undefined.
  102. (define (get-location-for-undefined cenv name)
  103. (if (generated? name)
  104. (get-location-for-undefined (generated-env name)
  105. (generated-name name))
  106. (let ((package (cenv->package cenv)))
  107. ((or (fluid $note-undefined)
  108. (lambda (cenv name) (values)))
  109. cenv
  110. name)
  111. (if (package? package)
  112. (let ((place (location-for-reference package name)))
  113. (package-note-caching! package name place)
  114. place)
  115. (make-undefined-location name)))))
  116. (define $note-undefined (make-fluid (lambda (cenv name) (values))))
  117. ; Because of generated names CENV may not be an actual compile-env
  118. ; (i.e. a procedure).
  119. (define (cenv->package cenv)
  120. (cond ((procedure? cenv)
  121. ;; This returns #f if package is stable (static linking).
  122. (extract-package-from-environment cenv))
  123. ((package? cenv)
  124. cenv)
  125. ((structure? cenv)
  126. (structure-package cenv))))
  127. ; Exported for env/pedit.scm.
  128. (define (location-for-reference package name)
  129. (let loop ((opens (package-opens package)))
  130. (if (null? opens)
  131. (get-undefined package name)
  132. (call-with-values
  133. (lambda ()
  134. (interface-ref (structure-interface (car opens))
  135. name))
  136. (lambda (internal-name type)
  137. (if internal-name
  138. (location-for-reference (structure-package (car opens))
  139. internal-name)
  140. (loop (cdr opens))))))))
  141. ;----------------
  142. ; Maintain and display a list of undefined names.
  143. ; We bind $NOTE-UNDEFINED to a procedure that adds names to LOSERS, an a-list of
  144. ; (<package> . <undefined-names>). Once THUNK has finished we print out any
  145. ; names that are still undefined. CURRENT-PACKAGE is used only to avoid printing
  146. ; out the name of the current package unnecessarily. CURRENT-PACKAGE may be #f.
  147. (define (noting-undefined-variables current-package thunk)
  148. (let* ((losers '())
  149. (add-name (lambda (env name)
  150. (let ((probe (assq env losers)))
  151. (if probe
  152. (if (not (member name (cdr probe)))
  153. (set-cdr! probe (cons name (cdr probe))))
  154. (set! losers (cons (list env name) losers)))))))
  155. (let-fluid $note-undefined
  156. (lambda (env name)
  157. (if (generated? name)
  158. (add-name (generated-env name)
  159. (generated-name name))
  160. (add-name env name)))
  161. (lambda ()
  162. (dynamic-wind
  163. (lambda () #f)
  164. thunk
  165. (lambda ()
  166. (for-each (lambda (env+names)
  167. (print-undefined-names (car env+names)
  168. (cdr env+names)
  169. current-package))
  170. losers)))))))
  171. (define (print-undefined-names env names current-package)
  172. (let ((names (filter (lambda (name)
  173. ;; Keep the ones that are still unbound.
  174. (not (generic-lookup env name)))
  175. names)))
  176. (if (not (null? names))
  177. (let ((names (map (lambda (name)
  178. (if (generated? name)
  179. (generated-name name)
  180. name))
  181. (reverse names))))
  182. (apply warn
  183. "undefined variables"
  184. env
  185. names)))))
  186. ; (let ((out (current-noise-port)))
  187. ; (newline out)
  188. ; (display "Undefined" out)
  189. ; (if (and current-package
  190. ; (not (eq? env current-package)))
  191. ; (begin (display " in " out)
  192. ; (write env out)))
  193. ; (display ": " out)
  194. ; (write (map (lambda (name)
  195. ; (if (generated? name)
  196. ; (generated-name name)
  197. ; name))
  198. ; (reverse names))
  199. ; out)
  200. ; (newline out)))))