pedit.scm 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Package / structure / interface mutation operations.
  4. ; None of these is essential for the static semantics of packages.
  5. ; They only come into play in order to implement dynamic package
  6. ; mutation, which is solely a debugging operation.
  7. ; This is work in progress. There are surely numerous bugs.
  8. ; (define (package-system-sentinel) #f)
  9. (define (package-open! p struct-thunk)
  10. (if (not (memq (struct-thunk) (package-opens p)))
  11. (let ((thunk (package-opens-thunk p)))
  12. (set-package-opens-thunk! p (lambda ()
  13. (cons (struct-thunk) (thunk))))
  14. (reinitialize-package! p)
  15. (verify-package p)
  16. )))
  17. (define (reinitialize-package! p)
  18. (if *debug?*
  19. (begin (write `(reinitialize ,p)) (newline)))
  20. ;; (set-package-opens! p #f)
  21. (if (package-opens-really p)
  22. (initialize-package! p)))
  23. (define (reinitialize-structure! s)
  24. (if *debug?*
  25. (begin (write `(reinitialize ,s)) (newline)))
  26. ;; (set-structure-interface! s #f)
  27. (if (structure-interface-really s)
  28. (initialize-structure! s)))
  29. ; GET-NEW-LOCATION-CAREFULLY is called to obtain a location when
  30. ; a variable becomes newly defined.
  31. ; If the variable has already been referenced in any code that ought
  32. ; to see the new binding, we need to alter all such references to
  33. ; access the new location instead of whatever location they saw
  34. ; before.
  35. (define (get-new-location-carefully p name)
  36. (let* ((prev (package-lookup p name))
  37. (new (if (binding? prev)
  38. (let ((new (make-new-location p name))
  39. (cached (table-ref (package-cached p) name)))
  40. (copy-shadowed-contents! (binding-place prev) new)
  41. (cond (cached
  42. (if (eq? (binding-place prev) cached)
  43. (cope-with-mutation p name new cached)
  44. (assertion-violation
  45. 'get-new-location-carefully
  46. "binding cache inconsistency"
  47. p name new cached))))
  48. new)
  49. (get-new-location-non-shadowing p name)))
  50. (aloc (table-ref (package-undefined-but-assigneds p)
  51. name)))
  52. (if aloc ; Assigned?
  53. (begin (if *debug?*
  54. (note "assigned -> defined" name))
  55. (table-set! (package-undefined-but-assigneds p) name #f)
  56. (set-location-forward! aloc new name p)))
  57. new))
  58. (define (get-new-location-non-shadowing p name)
  59. (let* ((uloc (table-ref (package-undefineds p) name))
  60. (loc
  61. (if uloc
  62. (begin (if *debug?* (note "undefined -> defined" name uloc))
  63. (table-set! (package-undefineds p) name #f)
  64. uloc)
  65. (make-new-location p name))))
  66. (if (and (not uloc)
  67. (symbol? name)) ; interfaces can't handle generated names
  68. (let recur ((q p))
  69. (let loop ((opens (package-opens q)))
  70. (if (not (null? opens))
  71. (call-with-values
  72. (lambda ()
  73. (interface-ref (structure-interface (car opens))
  74. name))
  75. (lambda (base-name type)
  76. (if base-name
  77. ;; Shadowing
  78. (let* ((q (structure-package (car opens)))
  79. (probe (table-ref (package-undefineds q)
  80. base-name)))
  81. (if probe
  82. (begin (if *debug?*
  83. (note "undefined -> shadowed"
  84. name loc probe))
  85. (cope-with-mutation p name loc probe))
  86. (recur q)))
  87. (loop (cdr opens)))))))))
  88. loc))
  89. ; COPE-WITH-MUTATION:
  90. ; A package system mutation has newly caused NAME to be bound in
  91. ; package P to NEW, but prior references assumed that its binding was
  92. ; PREV (perhaps inherited from another package). If PREV is a
  93. ; location, then each occurrence of it stowed away in templates and
  94. ; packages must eventually be replaced by either location NEW, if P's
  95. ; binding is the one that's visible at that occurrence, or to a fresh
  96. ; location to replace PREV, if not.
  97. (define (cope-with-mutation p name new prev)
  98. (if (eq? new prev)
  99. (assertion-violation 'cope-with-mutation
  100. "lossage in cope-with-mutation" p name new prev))
  101. (let ((replacement (make-new-location p name)))
  102. (copy-location-info! prev replacement)
  103. (table-set! (package-cached p) name new)
  104. (if *debug?*
  105. (begin (write `(mutation ,prev ,new ,replacement)) (newline)))
  106. (shadow-location! prev
  107. (map package-uid
  108. (packages-seeing-location p name prev))
  109. new
  110. replacement)))
  111. ;(define (set-binding-place! b foo) (vector-set! b 1 foo))
  112. ; Hmm. It ought to be possible to turn this into an RPC.
  113. (define (copy-shadowed-contents! import loc)
  114. (if (location-defined? import)
  115. (set-contents! loc (contents import))))
  116. ; Return a list of all packages that might have cached a particular
  117. ; inherited binding.
  118. (define (packages-seeing-location package name loc)
  119. (if (not (symbol? name)) ; interfaces cannot handle generated names
  120. (list package)
  121. (let ((losers '())) ; was (list package) but that disables the
  122. ; entire procedure
  123. (let recur ((package-or-structure package))
  124. (let ((package (if (package? package-or-structure)
  125. package-or-structure
  126. (structure-package package-or-structure))))
  127. (if (and (not (memq package losers))
  128. (not (table-ref (package-definitions package) name)))
  129. (begin (set! losers (cons package losers))
  130. (walk-population
  131. (lambda (struct)
  132. (if (interface-member? (structure-interface struct)
  133. name)
  134. (walk-population recur
  135. (structure-clients struct))))
  136. (package-clients package))))))
  137. losers)))
  138. (define (set-location-forward! loser new name p)
  139. (if *debug?*
  140. (begin (write `(forward ,loser ,new)) (newline)))
  141. (for-each (lambda (q)
  142. (package-note-caching! q name new))
  143. (packages-seeing-location p name loser))
  144. (shadow-location! loser '() #f new))
  145. (fluid-cell-set! $get-location get-new-location-carefully) ;foo
  146. (define (copy-location-info! from to)
  147. (let ((probe (location-info from)))
  148. (if probe
  149. (table-set! location-info-table (location-id to) probe))))
  150. ;; Deal with editing operations
  151. (define (really-verify-later! thunk) ;cf. define-structure macro
  152. (let ((premature (ignore-errors thunk))) ; old value if we're redefining
  153. (let ((cell (fluid $losers))
  154. (loser (if (or (structure? premature)
  155. (interface? premature))
  156. (cons premature thunk)
  157. (cons #f thunk))))
  158. (cell-set! cell
  159. (cons loser
  160. (cell-ref cell))))))
  161. ; each element is a a pair (thing, thunk)
  162. (define $losers (make-fluid (make-cell '())))
  163. (define $package-losers (make-fluid (make-cell '())))
  164. (define (package-system-sentinel)
  165. (drain $losers verify-loser)
  166. (drain $package-losers verify-package))
  167. (define (verify-loser loser)
  168. (really-verify-loser (car loser)
  169. (ignore-errors (cdr loser))))
  170. (define (really-verify-loser premature thing)
  171. (if *debug?*
  172. (begin (write `(verify-loser ,premature ,thing)) (newline)))
  173. (cond
  174. ((structure? thing) (verify-structure premature thing))
  175. ((interface? thing) (verify-interface premature thing))))
  176. (define (verify-structure premature struct)
  177. (reinitialize-structure! struct)
  178. (if *debug?*
  179. (begin
  180. (write `(verify-structure ,struct ,(population->list (structure-clients struct))))
  181. (newline)))
  182. (walk-population (lambda (thing)
  183. (cond
  184. ((package? thing) (note-verify-package thing))
  185. ((structure? thing) (verify-structure #f thing))))
  186. (structure-clients struct)))
  187. (define (verify-interface premature int)
  188. ;; add clients of old interface to new one
  189. (if (interface? premature)
  190. (walk-population
  191. (lambda (client)
  192. (note-reference-to-interface! int client))
  193. (interface-clients premature)))
  194. (if *debug?*
  195. (begin
  196. (write `(verify-interface ,(population->list (interface-clients int))))
  197. (newline)))
  198. (walk-population (lambda (thing) (really-verify-loser #f thing))
  199. (interface-clients int)))
  200. (define (note-verify-package pack)
  201. (reinitialize-package! pack)
  202. (let* ((cell (fluid $package-losers))
  203. (losers (cell-ref cell)))
  204. (if (not (memq pack losers))
  205. (cell-set! cell
  206. (cons pack losers)))))
  207. (define (drain flu check)
  208. (let ((cell (fluid flu)))
  209. (let loop ()
  210. (let ((losers (cell-ref cell)))
  211. (if (not (null? losers))
  212. (let ((loser (car losers)))
  213. (cell-set! cell (cdr losers))
  214. (check loser)
  215. (loop)))))))
  216. (define *debug?* #f)
  217. ; --------------------
  218. ; If any looked-up location is now invalid, do something about it. We
  219. ; might have a previously unbound variable that is now exported by
  220. ; some structure; or, we might have a variable that was bound in some
  221. ; structure before, but now either that structure doesn't export it at
  222. ; all, or we're now getting that binding from some new structure.
  223. (define (verify-package p)
  224. (verify-package-cached p)
  225. (verify-package-undefineds p))
  226. ; unbound -> bound
  227. (define (verify-package-undefineds p)
  228. (if *debug?*
  229. (begin (write `(verify undefineds ,p)) (newline)))
  230. (let ((newly-defined '())
  231. (defs (package-definitions p))
  232. (undefs (package-undefineds p)))
  233. (table-walk (lambda (name prev)
  234. (if (table-ref defs name)
  235. (assertion-violation 'verify-package-undefineds
  236. "lossage" p name))
  237. (let ((binding (package-lookup p name)))
  238. (if (binding? binding)
  239. (let ((place (binding-place binding)))
  240. (if (eq? place prev)
  241. (assertion-violation 'verify-package-undefineds
  242. "lossage"
  243. p name binding))
  244. (set-location-forward! prev place name p)
  245. (set! newly-defined
  246. (cons name newly-defined)))
  247. (let ((loc (location-for-reference p name)))
  248. (if (not (eq? loc prev))
  249. ;; Newly imported
  250. (begin (set-location-forward! prev loc name p)
  251. (set! newly-defined
  252. (cons name newly-defined))))))))
  253. undefs)
  254. (if (not (null? newly-defined))
  255. (begin (display "Newly accessible in ")
  256. (write (package-name p))
  257. (display ": ")
  258. (write newly-defined)
  259. (newline)))
  260. (for-each (lambda (winner)
  261. (table-set! undefs winner #f))
  262. newly-defined)))
  263. (define (verify-package-cached p)
  264. ;; (write `(verify ,p cached)) (newline)
  265. (let ((newly-moved '())
  266. (newly-undefined '())
  267. (cached (package-cached p)))
  268. (table-walk (lambda (name prev)
  269. (let ((binding (package-lookup p name)))
  270. (if (binding? binding)
  271. (if (not (eq? (binding-place binding) prev))
  272. (set! newly-moved
  273. (cons name newly-moved)))
  274. ;; Otherwise either (a) it was previously
  275. ;; defined but has become newly undefined, or
  276. ;; (b) it was undefined before and is still, but
  277. ;; is inherited (or not) from a different place.
  278. (let ((u (location-for-reference p name)))
  279. (if (not (eq? u prev))
  280. (set! newly-undefined
  281. (cons name newly-undefined)))))))
  282. cached)
  283. (if (not (null? newly-moved))
  284. (begin (display "Definitions visible in ")
  285. (write (package-name p))
  286. (display " have moved: ")
  287. (write newly-moved)
  288. (newline)))
  289. (for-each (lambda (name)
  290. (let ((new (binding-place (package-lookup p name))))
  291. (cope-with-mutation p name new
  292. (table-ref cached name))
  293. (table-set! cached name new)))
  294. newly-moved)
  295. (if (and *debug?* (not (null? newly-undefined)))
  296. (begin (display "Newly undefined in ")
  297. (write (package-name p))
  298. (display ": ")
  299. (write newly-undefined)
  300. (newline)))
  301. (for-each (lambda (name)
  302. (let ((new (location-for-reference p name)))
  303. (cope-with-mutation p name new
  304. (table-ref cached name))
  305. (table-set! cached name new)))
  306. newly-undefined)))
  307. (set-verify-later! really-verify-later!)
  308. ;(define (maybe-note-redefinition p name seen new)
  309. ; (if (and seen (not (compatible? new seen)))
  310. ; (let ((old-description (binding-description-string seen))
  311. ; (new-description (binding-description-string new))
  312. ; (doing (if (package-definition p name)
  313. ; "redefining"
  314. ; "shadowing")))
  315. ; (warning 'maybe-note-redefinition
  316. ; (if (equal? old-description new-description)
  317. ; doing
  318. ; (string-append doing
  319. ; " as "
  320. ; new-description
  321. ; " (prior references assumed "
  322. ; old-description
  323. ; ")"))
  324. ; name))))
  325. ;
  326. ;; Foo. This should really set SEEN for all the packages up the
  327. ;; inheritance chain.
  328. ;
  329. ;(define (assume-denotation p name info)
  330. ; (if (package-unstable? p) ;***** save space? and time?
  331. ; (table-set! (package-seen p) name info))
  332. ; info)
  333. ;
  334. ;; Little utility for warning messages.
  335. ;
  336. ;(define (binding-description-string d)
  337. ; (cond ((transform? d)
  338. ; (if (syntax? d) "macro" "integrated procedure"))
  339. ; ((operator? d)
  340. ; (if (syntax? d) "special operator" "primitive procedure"))
  341. ; (else "variable")))
  342. (define (package-undefine! p name)
  343. (let ((probe (table-ref (package-definitions p) name)))
  344. (if probe
  345. (begin (table-set! (package-definitions p) name #f)
  346. (set-location-defined?! (binding-place probe) #f)
  347. (set-location-forward!
  348. (binding-place probe)
  349. (let ((new (package-lookup p name)))
  350. (if (binding? new)
  351. (binding-place new)
  352. (location-for-reference p name)))
  353. name p))
  354. (warning 'package-undefine!
  355. "can't undefine - binding is inherited"
  356. p name))))