package.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Structures 'n' packages.
  4. ; --------------------
  5. ; Structures
  6. ;
  7. ; A structure is a map from names to binding records, determined by an
  8. ; interface (a set of names) and a package (a map from names to binding
  9. ; records).
  10. ;
  11. ; The interface is specified as a thunk. This removes dependencies on the
  12. ; order in which structures are defined. Also, if the interface is redefined,
  13. ; re-evaluating the thunk produces the new, correct interface (see
  14. ; env/pedit.scm).
  15. ;
  16. ; Clients are packages that import the structure's bindings.
  17. (define-record-type structure :structure-type ; avoid name conflict with :STRUCTURE type
  18. (really-make-structure package interface-thunk interface clients name)
  19. structure?
  20. (interface-thunk structure-interface-thunk)
  21. (interface structure-interface-really set-structure-interface!)
  22. (package structure-package)
  23. (clients structure-clients)
  24. (name structure-name set-structure-name!))
  25. (define-record-discloser :structure-type
  26. (lambda (structure)
  27. (list 'structure
  28. (package-uid (structure-package structure))
  29. (structure-name structure))))
  30. ; Get the actual interface, calling the thunk if necessary.
  31. (define (structure-interface structure)
  32. (or (structure-interface-really structure)
  33. (begin (initialize-structure! structure)
  34. (structure-interface-really structure))))
  35. (define (initialize-structure! structure)
  36. (let ((int ((structure-interface-thunk structure))))
  37. (if (interface? int)
  38. (begin (set-structure-interface! structure int)
  39. (note-reference-to-interface! int structure))
  40. (assertion-violation 'initialize-structure!
  41. "invalid interface" structure))))
  42. ; Make a structure over PACKAGE and the interface returned by INT-THUNK.
  43. (define (make-structure package int-thunk . name-option)
  44. (if (not (package? package))
  45. (assertion-violation 'make-structure
  46. "invalid package" package int-thunk))
  47. (let ((struct (really-make-structure package
  48. (if (procedure? int-thunk)
  49. int-thunk
  50. (lambda () int-thunk))
  51. #f
  52. (make-population)
  53. #f)))
  54. (if (not (null? name-option))
  55. (note-structure-name! struct (car name-option)))
  56. (add-to-population! struct (package-clients package))
  57. struct))
  58. ; Make a structure by using COMMANDS to modify the STRUCTURE's interface.
  59. ; We parse the commands first so that errors are detected before the new
  60. ; structure is installed anywhere.
  61. (define (make-modified-structure structure commands)
  62. (let* ((interface-maker (make-modified-interface-maker commands))
  63. (new-struct (make-structure (structure-package structure)
  64. (lambda ()
  65. (interface-maker
  66. (structure-interface structure)))
  67. (structure-name structure))))
  68. (if (structure-unstable? structure)
  69. (add-to-population! new-struct (structure-clients structure)))
  70. new-struct))
  71. ; STRUCT has name NAME. NAME can then also be used to refer to STRUCT's
  72. ; package.
  73. (define (note-structure-name! struct name)
  74. (if (and name (not (structure-name struct)))
  75. (begin (set-structure-name! struct name)
  76. (note-package-name! (structure-package struct) name))))
  77. ; A structure is unstable if its package is. An unstable package is one
  78. ; where new code may be added, possibly modifying the exported bindings.
  79. (define (structure-unstable? struct)
  80. (package-unstable? (structure-package struct)))
  81. ; The #F returned for compile-time environments is conservative. You could
  82. ; look up the name of interest and see where it came from. It might come
  83. ; from a lexical binding or a stable package or structure. A procedure to
  84. ; do this could go in cenv.scm.
  85. (define (environment-stable? env)
  86. (cond ((package? env)
  87. (not (package-unstable? env)))
  88. ((structure? env)
  89. (not (structure-unstable? env)))
  90. ((compiler-env? env)
  91. #f) ; conservative
  92. (else
  93. (assertion-violation 'environment-stable? "invalid environment" env))))
  94. ; Map PROC down the the [name type binding] triples provided by STRUCT.
  95. (define (for-each-export proc struct)
  96. (let ((int (structure-interface struct)))
  97. (for-each-declaration
  98. (lambda (name base-name want-type)
  99. (let ((binding (real-structure-lookup struct base-name want-type #t)))
  100. (proc name
  101. (if (and (binding? binding)
  102. (eq? want-type undeclared-type))
  103. (let ((type (binding-type binding)))
  104. (if (variable-type? type)
  105. (variable-value-type type)
  106. type))
  107. want-type)
  108. binding)))
  109. int)))
  110. ; --------------------
  111. ; Packages
  112. (define-record-type package :package
  113. (really-make-package uid
  114. opens-thunk opens accesses-thunk
  115. definitions
  116. undefineds
  117. undefined-but-assigneds
  118. get-location
  119. cached
  120. clients
  121. unstable?
  122. integrate?
  123. file-name reader clauses loaded?)
  124. package?
  125. (uid package-uid)
  126. ;; #f if not initialized, then list of structures
  127. (opens package-opens-really set-package-opens!)
  128. ;; name-table name -> binding
  129. (definitions package-definitions)
  130. (unstable? package-unstable?)
  131. ;; value of integrate clause; use integration in this packages
  132. (integrate? package-integrate? set-package-integrate?!)
  133. ;; For EVAL and LOAD (which can only be done in unstable packages)
  134. ;; package name -> location
  135. (get-location package-get-location set-package-get-location!)
  136. (file-name package-file-name)
  137. (reader package-reader set-package-reader!)
  138. (clauses package-clauses)
  139. (loaded? package-loaded? set-package-loaded?!)
  140. ;; compiler environment
  141. (env package->environment set-package->environment!)
  142. ;; For package mutation
  143. (opens-thunk package-opens-thunk set-package-opens-thunk!)
  144. ;; thunk -> (list (pair name struct))
  145. (accesses-thunk package-accesses-thunk)
  146. ;; locations introduced for missing values
  147. ;; name-table name -> location
  148. (undefineds package-real-undefineds set-package-undefineds!)
  149. ;; locations introduced for missing cells
  150. ;; name-table name -> location
  151. (undefined-but-assigneds
  152. package-real-undefined-but-assigneds
  153. set-package-undefined-but-assigneds!)
  154. (clients package-clients)
  155. ;; locations used here that were supposed to have been provided by someone else
  156. ;; name-table name -> place, see binding.scm
  157. (cached package-cached))
  158. (define-record-discloser :package
  159. (lambda (package)
  160. (let ((name (package-name package)))
  161. (if name
  162. (list 'package (package-uid package) name)
  163. (list 'package (package-uid package))))))
  164. (define (make-package opens-thunk accesses-thunk unstable? tower file clauses
  165. uid name)
  166. (let ((new (really-make-package
  167. (if uid
  168. (begin (if (>= uid *package-uid*)
  169. (set! *package-uid* (+ uid 1)))
  170. uid)
  171. (new-package-uid))
  172. opens-thunk
  173. #f ;opens
  174. accesses-thunk ;thunk returning alist
  175. (make-name-table) ;definitions
  176. #f ;undefineds
  177. #f ;undefined-but-assigned
  178. (fluid-cell-ref $get-location)
  179. ;procedure for making new locations
  180. (make-name-table) ;bindings cached in templates
  181. (make-population) ;structures
  182. unstable? ;unstable (suitable for EVAL)?
  183. #t ;integrate?
  184. file ;file containing DEFINE-STRUCTURE form
  185. read
  186. clauses ;misc. DEFINE-STRUCTURE clauses
  187. #f))) ;loaded?
  188. (note-package-name! new name)
  189. (set-package->environment! new (really-package->environment new tower))
  190. new))
  191. ; TOWER is a promise that is expected to deliver, when forced, a
  192. ; pair (eval . env).
  193. (define (really-package->environment package tower)
  194. (make-compiler-env (lambda (name)
  195. (package-lookup package name))
  196. (lambda (name type . maybe-static)
  197. (cond
  198. ((and (symbol? name) ; generated names are hopefully of no interest here
  199. (opened-structure-for-name package name))
  200. => (lambda (struct)
  201. (warning 'package-define!
  202. "name from opened structure redefined"
  203. package name struct))))
  204. (package-define! package
  205. name
  206. type
  207. #f
  208. (if (null? maybe-static)
  209. #f
  210. (car maybe-static))))
  211. tower
  212. package)) ; interim hack
  213. (define (opened-structure-for-name package name)
  214. (let loop ((opens (package-opens-really package)))
  215. (cond
  216. ((null? opens)
  217. #f)
  218. ((structure-lookup (car opens) name #t)
  219. (car opens))
  220. (else
  221. (loop (cdr opens))))))
  222. ; Two tables that we add lazily.
  223. (define (lazy-table-accessor slot-ref slot-set!)
  224. (lambda (package)
  225. (or (slot-ref package)
  226. (let ((table (make-name-table)))
  227. (slot-set! package table)
  228. table))))
  229. (define package-undefineds
  230. (lazy-table-accessor package-real-undefineds
  231. set-package-undefineds!))
  232. (define package-undefined-but-assigneds
  233. (lazy-table-accessor package-real-undefined-but-assigneds
  234. set-package-undefined-but-assigneds!))
  235. ; Unique id's
  236. (define (new-package-uid)
  237. (let ((uid *package-uid*)) ;unique identifier
  238. (set! *package-uid* (+ *package-uid* 1))
  239. uid))
  240. (define *package-uid* 0)
  241. ; Package names
  242. (define package-name-table (make-table))
  243. (define (package-name package)
  244. (table-ref package-name-table (package-uid package)))
  245. (define (note-package-name! package name)
  246. (if name
  247. (let ((uid (package-uid package)))
  248. (if (not (table-ref package-name-table uid))
  249. (table-set! package-name-table uid name)))))
  250. (define (package-opens package)
  251. (initialize-package-if-necessary! package)
  252. (package-opens-really package))
  253. (define (initialize-package-if-necessary! package)
  254. (if (not (package-opens-really package))
  255. (initialize-package! package)))
  256. (define (package-accesses package) ;=> alist
  257. ((package-accesses-thunk package)))
  258. ; --------------------
  259. ; A simple package has no ACCESSes or other far-out clauses.
  260. (define (make-simple-package opens unstable? tower . name-option)
  261. (if (not (list? opens))
  262. (assertion-violation 'make-simple-package "invalid package opens list" opens))
  263. (let ((package (make-package (lambda () opens)
  264. (lambda () '()) ;accesses-thunk
  265. unstable?
  266. tower
  267. "" ;file containing DEFINE-STRUCTURE form
  268. '() ;clauses
  269. #f ;uid
  270. (if (null? name-option)
  271. #f
  272. (car name-option)))))
  273. (set-package-loaded?! package #t)
  274. package))
  275. ; --------------------
  276. ; The definitions table
  277. ; Each entry in the package-definitions table is a binding.
  278. (define (package-definition package name)
  279. (initialize-package-if-necessary! package)
  280. (let ((probe (table-ref (package-definitions package) name)))
  281. (if probe
  282. (maybe-fix-place! probe)
  283. #f)))
  284. (define (package-define! package name type place static)
  285. (let ((probe (table-ref (package-definitions package) name)))
  286. (if probe
  287. (begin
  288. (clobber-binding! probe type place static)
  289. (binding-place (maybe-fix-place! probe)))
  290. (let ((place (or place (get-new-location package name))))
  291. (table-set! (package-definitions package)
  292. name
  293. (make-binding type place static))
  294. place))))
  295. (define (package-add-static! package name static)
  296. (let ((probe (table-ref (package-definitions package) name)))
  297. (if probe
  298. (clobber-binding! probe
  299. (binding-type probe)
  300. (binding-place probe)
  301. static)
  302. (assertion-violation 'package-add-static!
  303. "internal error: name not bound" package name))))
  304. (define (package-refine-type! package name type)
  305. (let ((probe (table-ref (package-definitions package) name)))
  306. (if probe
  307. (clobber-binding! probe
  308. type
  309. (binding-place probe)
  310. (binding-static probe))
  311. (assertion-violation 'package-refine-type!
  312. "internal error: name not bound" package name))))
  313. ; --------------------
  314. ; Lookup
  315. ; Look up a name in a package. Returns a binding if bound or #F if not.
  316. (define (package-lookup package name)
  317. (really-package-lookup package name (package-integrate? package)))
  318. (define (really-package-lookup package name integrate?)
  319. (let ((probe (package-definition package name)))
  320. (cond (probe
  321. (if integrate?
  322. probe
  323. (forget-integration probe)))
  324. ((generated? name)
  325. ; Access path is (generated-parent-name name)
  326. (generic-lookup (generated-env name)
  327. (generated-name name)))
  328. (else
  329. (search-opens (package-opens-really package) name integrate?)))))
  330. ; Look for NAME in structures OPENS.
  331. (define (search-opens opens name integrate?)
  332. (let loop ((opens opens))
  333. (if (null? opens)
  334. #f
  335. (or (structure-lookup (car opens) name integrate?)
  336. (loop (cdr opens))))))
  337. (define (structure-lookup struct name integrate?)
  338. (call-with-values
  339. (lambda ()
  340. (interface-ref (structure-interface struct) name))
  341. (lambda (base-name type)
  342. (if type
  343. (real-structure-lookup struct base-name type integrate?)
  344. #f))))
  345. (define (real-structure-lookup struct name type integrate?)
  346. (impose-type type
  347. (really-package-lookup (structure-package struct)
  348. name
  349. integrate?)
  350. integrate?))
  351. (define (generic-lookup env name)
  352. (cond ((package? env)
  353. (package-lookup env name))
  354. ((structure? env)
  355. (or (structure-lookup env
  356. name
  357. (package-integrate? (structure-package env)))
  358. (assertion-violation 'generic-lookup "not exported" env name)))
  359. ((compiler-env? env)
  360. (lookup env name))
  361. (else
  362. (assertion-violation 'generic-lookup "invalid environment" env name))))
  363. ; --------------------
  364. ; Package initialization
  365. (define (initialize-package! package)
  366. (let ((opens ((package-opens-thunk package))))
  367. (set-package-opens! package opens)
  368. (check-for-duplicates! package)
  369. (for-each (lambda (struct)
  370. (if (structure-unstable? struct)
  371. (add-to-population! package (structure-clients struct))))
  372. opens))
  373. (for-each (lambda (name+struct)
  374. ;; Cf. CLASSIFY method for STRUCTURE-REF
  375. (package-define! package
  376. (car name+struct)
  377. structure-type
  378. #f
  379. (cdr name+struct)))
  380. (package-accesses package)))
  381. (define (check-for-duplicates! package)
  382. (let ((imported-names (make-symbol-table)) ; maps names to pair of first binding, lists of structures
  383. (duplicates '()))
  384. (for-each (lambda (struct)
  385. (for-each-export
  386. (lambda (name type binding)
  387. (cond
  388. ((table-ref imported-names name)
  389. => (lambda (p)
  390. (if (not (same-denotation? (car p) binding))
  391. (begin
  392. (set! duplicates (cons name duplicates))
  393. (if (not (memq struct (cdr p)))
  394. (set-cdr! p (cons struct (cdr p))))))))
  395. (else
  396. (table-set! imported-names name (cons binding (list struct))))))
  397. struct))
  398. (package-opens package))
  399. (for-each (lambda (duplicate)
  400. (apply warning 'check-for-duplicates!
  401. "duplicate name in opened structure"
  402. duplicate
  403. package
  404. (cdr (table-ref imported-names duplicate))))
  405. duplicates)))
  406. ; (define (package->environment? env)
  407. ; (eq? env (package->environment
  408. ; (extract-package-from-comp-env env))))
  409. ; --------------------
  410. ; For implementation of INTEGRATE-ALL-PRIMITIVES! in scanner, etc.
  411. (define (for-each-definition proc package)
  412. (table-walk (lambda (name binding)
  413. (proc name (maybe-fix-place! binding)))
  414. (package-definitions package)))
  415. ; --------------------
  416. ; Locations
  417. (define (get-new-location package name)
  418. ((package-get-location package) package name))
  419. ; Default new-location method for new packages
  420. (define (make-new-location package name)
  421. (let ((uid *location-uid*))
  422. (set! *location-uid* (+ *location-uid* 1))
  423. (table-set! location-info-table uid
  424. (make-immutable!
  425. (cons (name->symbol name) (package-uid package))))
  426. (make-undefined-location uid)))
  427. (define $get-location (make-fluid (make-cell make-new-location)))
  428. (define *location-uid* 5000) ; 1510 in initial system as of 1/22/94
  429. (define location-info-table (make-table))
  430. (define (flush-location-names)
  431. (set! location-info-table (make-table))
  432. ;; (set! package-name-table (make-table)) ;hmm, not much of a space saver
  433. )
  434. ; (put 'package-define! 'scheme-indent-hook 2)