link.scm 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; The static linker.
  3. ; link-simple-system:
  4. ; resumer-exp should evaluate to a procedure
  5. ; (lambda (arg i-port i-port-encoding o-port o-port-encoding ...) ...)
  6. (define (link-simple-system filename resumer-exp . structs)
  7. (link-system structs (lambda () resumer-exp) filename))
  8. ; resumer-exp should evaluate to a procedure
  9. ; (lambda (structs-thunk) ... (lambda (arg i-port i-port-encoding o-port o-port-encoding ...) ...))
  10. (define (link-reified-system some filename make-resumer-exp . structs)
  11. (link-system (append structs (map cdr some))
  12. (lambda ()
  13. `(,make-resumer-exp
  14. (lambda ()
  15. ,(call-with-values
  16. (lambda () (reify-structures some))
  17. (lambda (exp locs least-uid)
  18. `(,exp (lambda (i)
  19. (vector-ref ,(strange-quotation locs)
  20. (- i ,least-uid)))))))))
  21. filename))
  22. ; The compiler doesn't like to see unusual objects quoted, but this will
  23. ; fake it out.
  24. (define strange-quotation
  25. (let ((operator/quote (get-operator 'quote)))
  26. (lambda (thing)
  27. (make-node operator/quote `',thing))))
  28. ; `(,make-resumer-exp ',vector) should evaluate to a procedure
  29. ; (lambda (locs) ... (lambda (arg i-port i-port-encoding o-port o-port-encoding ...) ...))
  30. (define (link-semireified-system some filename
  31. make-resumer-exp . structs)
  32. (let ((loser #f))
  33. (link-system (append structs (map cdr some))
  34. (lambda ()
  35. (call-with-values (lambda ()
  36. (reify-structures some))
  37. (lambda (exp locs least)
  38. (set! loser exp)
  39. `(,make-resumer-exp ,(strange-quotation locs)
  40. ,least))))
  41. filename)
  42. (let ((f (namestring filename #f 'env)))
  43. (call-with-output-file f
  44. (lambda (port)
  45. (display "Writing environment structure to ")
  46. (display f)
  47. (newline)
  48. ;; loser evaluates to a procedure
  49. ;; (lambda (uid->location) struct-alist)
  50. (write `(define make-the-structures
  51. (,loser location-from-id))
  52. port))))))
  53. ; (link-system structs make-resumer filename)
  54. ; structs is a list of structures to be compiled,
  55. ; make-resumer is a thunk which should return an expression, to be
  56. ; evaluated in a package that opens the given structures, that
  57. ; evaluates to the procedure to be called after all
  58. ; initializations are run, and
  59. ; filename is the name of the file to which the image should be written.
  60. (define (link-system structs make-resumer filename)
  61. (with-fresh-compiler-state
  62. (if *debug-linker?* 100000 0) ;Location uid
  63. (lambda ()
  64. (set! *loser* #f)
  65. (let* ((location-info (make-table))
  66. (generator (make-location-generator location-info
  67. (if *debug-linker?* 10000 0)))
  68. (templates (compile-structures structs
  69. generator
  70. package->environment))
  71. (package (make-simple-package structs #f #f))
  72. (startup-template (begin
  73. (set-package-get-location! package generator)
  74. (expand&compile-form (make-resumer) package))))
  75. (let ((startup (make-closure
  76. (make-startup-procedure templates startup-template)
  77. 0)))
  78. (if *debug-linker?* (set! *loser* startup))
  79. (write-image-file startup
  80. (namestring filename #f 'image)))
  81. (write-debug-info location-info
  82. (namestring filename #f 'debug))))))
  83. (define (expand&compile-form form package)
  84. (let* ((env (package->environment package))
  85. (template (compile-forms (map (lambda (form)
  86. (expand-scanned-form form env))
  87. (scan-forms (list form) env))
  88. #f ;filename
  89. (package-uid package))))
  90. (link! template package #t)
  91. template))
  92. (define *loser* #f)
  93. (define *debug-linker?* #f)
  94. (define (compile-structures structs generator package->env)
  95. (let ((packages (collect-packages structs (lambda (package) #t)))
  96. (out (current-noise-port)))
  97. (for-each (lambda (package)
  98. (set-package-get-location! package generator))
  99. packages)
  100. (map (lambda (package)
  101. (display #\[ out)
  102. (display (package-name package) out)
  103. (let ((template (compile-package package)))
  104. (display #\] out)
  105. (newline out)
  106. template))
  107. packages)))
  108. ; Locations in new image will have their own sequence of unique id's.
  109. (define (make-location-generator location-info start)
  110. (let ((*location-uid* start))
  111. (define (make-new-location p name)
  112. (let ((uid *location-uid*))
  113. (set! *location-uid* (+ *location-uid* 1))
  114. (table-set! location-info uid
  115. (cons (name->symbol name) (package-uid p))) ;?
  116. (make-undefined-location uid)))
  117. make-new-location))
  118. (define (write-image-file start filename)
  119. (write-image filename
  120. start
  121. "This heap image was made by the Scheme 48 linker."))
  122. ; Handy utility for making arguments to link-reified-system
  123. (define-syntax struct-list
  124. (syntax-rules ()
  125. ((struct-list name ...) (list (cons 'name name) ...))))