scan-package.scm 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Scanning structures and processing package clauses.
  4. ; Utility for compile-structures (link/link.scm) and
  5. ; ensure-loaded (env/load-package.scm).
  6. ;
  7. ; Returns a list of all packages reachable from STRUCTS that answer true to
  8. ; INCLUDE-THIS-PACKAGE?.
  9. (define (collect-packages structs include-this-package?)
  10. (let ((package-seen '())
  11. (structure-seen '())
  12. (packages '()))
  13. (letrec ((recur
  14. (lambda (structure visited)
  15. (if (memq (structure-package structure) visited)
  16. (warning 'collect-packages "cycle in structures dependencies"
  17. structure visited))
  18. (if (not (memq structure structure-seen))
  19. (begin
  20. (set! structure-seen (cons structure structure-seen))
  21. (let ((package (structure-package structure)))
  22. (if (not (memq package package-seen))
  23. (begin
  24. (set! package-seen (cons package package-seen))
  25. (if (include-this-package? package)
  26. (let ((visited (cons package visited)))
  27. (for-each (lambda (struct)
  28. (recur struct visited))
  29. (package-opens package))
  30. (for-each (lambda (name+struct)
  31. (recur (cdr name+struct) visited))
  32. (package-accesses package))
  33. (set! packages (cons package packages))))))))))))
  34. (for-each (lambda (struct)
  35. (recur struct '()))
  36. structs)
  37. (reverse packages))))
  38. ; Walk through PACKAGE's clauses to find the source code. The relevant
  39. ; clauses are:
  40. ; (files name ...)
  41. ; (begin form ...)
  42. ; (define-all-operators)
  43. ; (usual-transforms name ...)
  44. ;
  45. ; Returns a list of pairs (file . (node1 node2 ...)), a list of names
  46. ; of standard transforms, and a boolean value which is true if the package
  47. ; is to include definitions of all primitives.
  48. (define (package-source package)
  49. (let* ((config-file (package-file-name package))
  50. (dir (if config-file
  51. (file-name-directory config-file)
  52. #f)))
  53. (call-with-values
  54. (lambda ()
  55. (fold->3 (lambda (clause stuff transforms primitives?)
  56. (case (car clause)
  57. ((files)
  58. (values (read-files (cdr clause) stuff dir package)
  59. transforms
  60. primitives?))
  61. ((begin)
  62. (values (cons (cons config-file (cdr clause))
  63. stuff)
  64. transforms
  65. primitives?))
  66. ((integrate)
  67. (set-package-integrate?! package
  68. (or (null? (cdr clause))
  69. (cadr clause)))
  70. (values stuff transforms primitives?))
  71. ((optimize)
  72. (values stuff transforms primitives?))
  73. ((define-all-operators)
  74. (values stuff transforms #t))
  75. ((usual-transforms)
  76. (values stuff
  77. (append (reverse (cdr clause)) transforms)
  78. primitives?))
  79. ((reader)
  80. (let ((r (force (comp-env-macro-eval (package->environment package)))))
  81. (set-package-reader! package ((car r) (cadr clause) (cdr r))))
  82. (values stuff transforms primitives?))
  83. (else
  84. (assertion-violation 'package-source
  85. "unrecognized define-structure keyword"
  86. clause))))
  87. (package-clauses package)
  88. '() '() #f))
  89. (lambda (stuff transforms primitives?)
  90. (values (reverse stuff)
  91. (reverse transforms)
  92. primitives?)))))
  93. ; Also prints out the filenames (courtesy of READ-FORMS).
  94. (define (read-files all-files stuff dir package)
  95. (force-output (current-output-port)) ; just to be nice
  96. (fold (lambda (filespec stuff)
  97. (let ((file (namestring filespec
  98. dir
  99. *scheme-file-type*)))
  100. (display #\space (current-noise-port))
  101. (cons (cons file (read-forms file package #f))
  102. stuff)))
  103. all-files
  104. stuff))
  105. (define (package-optimizer-names package)
  106. (if (package-integrate? package)
  107. (let ((opts (apply append
  108. (map cdr (filter (lambda (clause)
  109. (eq? (car clause) 'optimize))
  110. (package-clauses package))))))
  111. (reduce (lambda (name opts)
  112. (if (memq name opts)
  113. opts
  114. (cons name opts)))
  115. opts
  116. '()))
  117. '()))
  118. (define (check-structure structure)
  119. (let ((undefined '()))
  120. (for-each-export
  121. (lambda (name want-type binding)
  122. (if (binding? binding)
  123. (let ((have-type (binding-type binding)))
  124. (if (not (compatible-types? have-type want-type))
  125. (warning 'check-structure
  126. "Type in interface doesn't match binding"
  127. name
  128. `(binding: ,(type->sexp have-type #t))
  129. `(interface: ,(type->sexp want-type #t))
  130. structure)))
  131. (set! undefined (cons name undefined))))
  132. structure)
  133. (if (not (null? undefined))
  134. (warning 'check-structure
  135. "Structure has undefined exports"
  136. structure
  137. undefined))))