link.scm 4.8 KB

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