package.scm 20 KB

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