linking.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. ;;; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey, Mike Sperber
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/prescheme/linking.scm
  8. ;;;
  9. ;;; This file has the Pre-Scheme compiler's code for dealing with the
  10. ;;; Scheme 48's module system.
  11. (define-module (ps-compiler prescheme linking)
  12. #:use-module (prescheme scheme48)
  13. #:use-module (prescheme bcomp binding)
  14. #:use-module ((prescheme bcomp mtype) #:select (syntax-type usual-variable-type))
  15. #:use-module ((prescheme bcomp node) #:select (get-operator))
  16. #:use-module (prescheme bcomp interface)
  17. #:use-module (prescheme bcomp package)
  18. #:use-module (prescheme bcomp read-form)
  19. #:use-module (prescheme bcomp scan-package)
  20. #:use-module (prescheme bcomp transform)
  21. #:use-module (prescheme bcomp usual)
  22. #:use-module (prescheme environment)
  23. #:use-module (prescheme env stubs)
  24. #:use-module (prescheme locations)
  25. #:use-module ((ps-compiler node variable) #:select (make-global-variable))
  26. #:use-module ((ps-compiler prescheme type) #:select (type/unknown))
  27. #:use-module (ps-compiler util util)
  28. #:export (package-specs->packages+exports
  29. package-source
  30. define-prescheme!
  31. prescheme-compiler-env))
  32. ;; FILES is a list of files that contain structure definitions, including
  33. ;; a definition for NAME. The files are loaded into a config package
  34. ;; containing:
  35. ;; - the procedures and macros for defining structures and interfaces
  36. ;; - a Pre-Scheme structure (called PRESCHEME)
  37. ;; - a ps-memory structure
  38. ;; - a ps-receive structure
  39. ;; - the STRUCTURE-REFS structure
  40. ;; We then return:
  41. ;; 1. a list of the packages required to implement the named structures
  42. ;; 2. a list of the names exported by the named structures
  43. ;; 3. a procedure that for looking up names defined in packages in the
  44. ;; config package (this is used to map user directives to their targets)
  45. (define (package-specs->packages+exports struct-names files)
  46. (let ((config (make-very-simple-package 'config (list defpackage)))
  47. (old-config (config-package)))
  48. (environment-define! config 'prescheme prescheme)
  49. (environment-define! config 'ps-memory ps-memory)
  50. (environment-define! config 'ps-receive ps-receive)
  51. (environment-define! config 'ps-flonums ps-flonums)
  52. (environment-define! config 'ps-unsigned-integers ps-unsigned-integers)
  53. (environment-define! config 'ps-record-types ps-record-types)
  54. (environment-define! config 'structure-refs structure-refs)
  55. (environment-define! config ':syntax syntax-type)
  56. (set-reflective-tower-maker! config (get-reflective-tower-maker old-config))
  57. (with-fluids (($get-location
  58. (make-cell get-variable))
  59. ($note-file-package
  60. (make-cell (lambda (filename package) (values)))))
  61. (lambda ()
  62. (for-each (lambda (file)
  63. (load file config))
  64. files)))
  65. (values (collect-packages (map (lambda (name)
  66. (environment-ref config name))
  67. struct-names)
  68. (lambda (package)
  69. #t))
  70. (let ((names '()))
  71. (for-each (lambda (struct-name)
  72. (let ((my-names '()))
  73. (for-each-declaration
  74. (lambda (name package-name type)
  75. (set! my-names (cons name my-names)))
  76. (structure-interface
  77. (environment-ref config struct-name)))
  78. (set! names
  79. (cons (cons struct-name my-names)
  80. names))))
  81. struct-names)
  82. names)
  83. (make-lookup config))))
  84. ;; This creates new variables as needed for packages.
  85. (define (get-variable package name)
  86. ;;(format #t "Making variable ~S for ~S~%" name package)
  87. (make-global-variable
  88. name
  89. type/unknown))
  90. ;; Return something that will find the binding of ID in the package belonging
  91. ;; to the structure PACKAGE-ID in the CONFIG package.
  92. (define (make-lookup config)
  93. (lambda (package-id id)
  94. (let ((binding (package-lookup config package-id)))
  95. (if (and (binding? binding)
  96. (location? (binding-place binding))
  97. (structure? (contents (binding-place binding))))
  98. (let* ((package (structure-package
  99. (contents (binding-place binding))))
  100. (binding (package-lookup package id)))
  101. (if (binding? binding)
  102. (binding-place binding)
  103. #f))
  104. #f))))
  105. ;;----------------------------------------------------------------
  106. ;; Handy packages and package making stuff.
  107. (define defpackage #f) ;; (structure-ref built-in-structures defpackage))
  108. (define structure-refs #f) ;; (structure-ref built-in-structures structure-refs))
  109. (define scheme #f) ;; (structure-ref built-in-structures scheme))
  110. (define (make-env-for-syntax-promise . structures)
  111. (make-reflective-tower eval structures 'prescheme-linking))
  112. (define (make-very-simple-package name opens)
  113. (make-simple-package opens
  114. eval
  115. (make-env-for-syntax-promise scheme)
  116. name))
  117. (define (get-reflective-tower-maker p)
  118. (environment-ref p (string->symbol ".make-reflective-tower.")))
  119. ;;----------------------------------------------------------------
  120. ;; The following stuff is used to define the DEFINE-RECORD-TYPE macro.
  121. ;; We produce a structure that exports EXPAND-DEFINE-RECORD-TYPE. The
  122. ;; base package then includes that structure in its FOR-SYNTAX package.
  123. (define defrecord-for-syntax-package
  124. (make-very-simple-package 'defrecord-for-syntax-package '()))
  125. (define defrecord-for-syntax-structure
  126. (make-structure defrecord-for-syntax-package
  127. (lambda () (export expand-define-record-type))
  128. 'defrecord-for-syntax-structure))
  129. (define (define-for-syntax-value id value)
  130. (let ((loc (make-new-location defrecord-for-syntax-package id)))
  131. (set-contents! loc value)
  132. (package-define! defrecord-for-syntax-package
  133. id
  134. usual-variable-type
  135. loc
  136. #f)))
  137. ;; (define-for-syntax-value 'expand-define-record-type expand-define-record-type)
  138. ;;----------------------------------------------------------------
  139. ;; BASE-PACKAGE contains all of the primitives, syntax, etc. for Pre-Scheme
  140. (define (prescheme-unbound package name)
  141. (bug "~S has no binding in package ~S" name package))
  142. (define base-package
  143. ;; (let-fluid (structure-ref packages-internal $get-location) prescheme-unbound
  144. ;; (lambda () ))
  145. (make-simple-package '()
  146. eval
  147. (make-env-for-syntax-promise
  148. scheme
  149. defrecord-for-syntax-structure)
  150. 'base-package))
  151. ;; Add the operators.
  152. (for-each (lambda (id)
  153. (package-define! base-package
  154. id
  155. syntax-type
  156. #f
  157. (get-operator id syntax-type)))
  158. '(if begin lambda letrec quote set!
  159. define define-syntax let-syntax letrec-syntax
  160. ;; the rest are special for Prescheme
  161. goto type-case real-external))
  162. ;; Add the usual macros.
  163. (for-each (lambda (name)
  164. (package-define! base-package
  165. name
  166. syntax-type
  167. #f
  168. (make-transform
  169. (usual-transform name)
  170. base-package
  171. syntax-type
  172. `(usual-transform ',name)
  173. name)))
  174. '(and cond do let let* or quasiquote)) ;; delay
  175. ;; Plus whatever primitives are wanted.
  176. (define (define-prescheme! name location static)
  177. (package-define! base-package
  178. name
  179. usual-variable-type
  180. location
  181. static))
  182. ;; Copy over the enumeration macros and the ERRORS enumeration.
  183. (define (import-syntax! package-id name)
  184. (let ((config (config-package)))
  185. (let ((binding (structure-lookup (environment-ref config package-id)
  186. name
  187. #t)))
  188. (package-define! base-package
  189. name
  190. syntax-type
  191. (binding-place binding)
  192. (binding-static binding)))))
  193. (import-syntax! 'enumerated 'define-enumeration)
  194. (import-syntax! 'enumerated 'enum)
  195. (import-syntax! 'enumerated 'name->enumerand)
  196. (import-syntax! 'enumerated 'enumerand->name)
  197. (import-syntax! 'prescheme 'errors)
  198. (import-syntax! 'prescheme 'define-external-enumeration)
  199. (import-syntax! 'scheme 'syntax-rules)
  200. ;; define still more syntax
  201. (load "prescheme/ps-syntax.scm" base-package)
  202. (eval '(define-syntax define-record-type expand-define-record-type)
  203. base-package)
  204. ;;(eval '(define-syntax define-union-type expand-define-union-type)
  205. ;; base-package)
  206. ;;----------------------------------------------------------------
  207. ;; Make the Pre-Scheme structure and related structures
  208. (define (get-interface name)
  209. (environment-ref (config-package)
  210. name))
  211. (define prescheme
  212. (make-structure base-package
  213. (lambda () (get-interface 'prescheme-interface))
  214. 'prescheme))
  215. (define ps-memory
  216. (make-structure base-package
  217. (lambda () (get-interface 'ps-memory-interface))
  218. 'ps-memory))
  219. (define ps-flonums
  220. (make-structure base-package
  221. (lambda () (get-interface 'ps-flonums-interface))
  222. 'ps-flonums))
  223. (define ps-unsigned-integers
  224. (make-structure base-package
  225. (lambda () (get-interface 'ps-unsigned-integers-interface))
  226. 'ps-unsigned-integers))
  227. (define ps-receive
  228. (make-structure base-package
  229. (lambda () (get-interface 'ps-receive-interface))
  230. 'ps-receive))
  231. (define ps-record-types
  232. (make-structure base-package
  233. (lambda () (export (define-record-type :syntax)))
  234. 'ps-record-types))
  235. ;; and a handy environment
  236. (define prescheme-compiler-env
  237. (package->environment base-package))