r7rs-libraries.scm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. ;; R7RS library support
  2. ;; Copyright (C) 2020, 2021, 2023 Free Software Foundation, Inc.
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public
  15. ;; License along with this library; if not, write to the Free Software
  16. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;; This file is included from boot-9.scm and assumes the existence of (and
  18. ;; expands into) procedures and syntactic forms defined therein.
  19. (define-syntax include-library-declarations
  20. (lambda (x)
  21. (syntax-violation
  22. 'include-library-declarations
  23. "use of 'include-library-declarations' outside define-library" x x)))
  24. ;; FIXME: Implement properly!
  25. (define-syntax-rule (include-ci filename)
  26. (include filename))
  27. (include-from-path "scheme/features.scm")
  28. (define-syntax define-library
  29. (lambda (stx)
  30. (define (r7rs-module-name->r6rs-module-name name)
  31. ;; This is a hack to support (srfi N x ...) modules in R7RS. The
  32. ;; longer term solution would be to add support at the level of
  33. ;; resolve-interface (bug #40371).
  34. (define (n? stx)
  35. (let ((n (syntax->datum stx)))
  36. (and (exact-integer? n)
  37. (not (negative? n)))))
  38. (define (srfi-name? stx)
  39. (syntax-case stx (srfi)
  40. ((srfi n rest ...)
  41. (n? #'n))
  42. (_ #f)))
  43. (define (make-srfi-n context n)
  44. (datum->syntax
  45. context
  46. (string->symbol
  47. (string-append
  48. "srfi-"
  49. (let ((n (syntax->datum n)))
  50. (number->string n))))))
  51. (syntax-case name (srfi)
  52. ;; (srfi n ...) -> (srfi srfi-n ...)
  53. ((srfi n rest ...) (srfi-name? #'(srfi n rest ...))
  54. #`(srfi #,(make-srfi-n #'srfi #'n) rest ...))
  55. (_ name)))
  56. (define (handle-includes filenames)
  57. (syntax-case filenames ()
  58. (() #'())
  59. ((filename . filenames)
  60. (append (call-with-include-port
  61. #'filename
  62. (lambda (p)
  63. (let lp ()
  64. (let ((x (read p)))
  65. (if (eof-object? x)
  66. #'()
  67. (cons (datum->syntax #'filename x) (lp)))))))
  68. (handle-includes #'filenames)))))
  69. (define (handle-cond-expand clauses)
  70. (define (has-req? req)
  71. (syntax-case req (and or not library)
  72. ((and req ...)
  73. (and-map has-req? #'(req ...)))
  74. ((or req ...)
  75. (or-map has-req? #'(req ...)))
  76. ((not req)
  77. (not (has-req? #'req)))
  78. ((library lib-name)
  79. (->bool
  80. (false-if-exception
  81. (resolve-r6rs-interface
  82. (syntax->datum #'lib-name)))))
  83. (id
  84. (identifier? #'id)
  85. (memq (syntax->datum #'id) (features)))))
  86. (syntax-case clauses (else)
  87. (() #'()) ; R7RS says this is not specified :-/
  88. (((else decl ...))
  89. #'(decl ...))
  90. (((test decl ...) . clauses)
  91. (if (has-req? #'test)
  92. #'(decl ...)
  93. (handle-cond-expand #'clauses)))))
  94. (define (partition-decls decls exports imports code)
  95. (syntax-case decls (export import begin include include-ci
  96. include-library-declarations cond-expand)
  97. (() (values exports imports (reverse code)))
  98. (((export clause ...) . decls)
  99. (partition-decls #'decls (append exports #'(clause ...)) imports code))
  100. (((import clause ...) . decls)
  101. (partition-decls #'decls exports (append imports #'(clause ...)) code))
  102. (((begin expr ...) . decls)
  103. (partition-decls #'decls exports imports
  104. (cons #'(begin expr ...) code)))
  105. (((include filename ...) . decls)
  106. (partition-decls #'decls exports imports
  107. (cons #'(begin (include filename) ...) code)))
  108. (((include-ci filename ...) . decls)
  109. (partition-decls #'decls exports imports
  110. (cons #'(begin (include-ci filename) ...) code)))
  111. (((include-library-declarations filename ...) . decls)
  112. (syntax-case (handle-includes #'(filename ...)) ()
  113. ((decl ...)
  114. (partition-decls #'(decl ... . decls) exports imports code))))
  115. (((cond-expand clause ...) . decls)
  116. (syntax-case (handle-cond-expand #'(clause ...)) ()
  117. ((decl ...)
  118. (partition-decls #'(decl ... . decls) exports imports code))))))
  119. (define (r7rs-export->r6rs-export export-spec)
  120. (syntax-case export-spec (rename)
  121. ((rename from-identifier to-identifier)
  122. #'(rename (from-identifier to-identifier)))
  123. (identifier #'identifier)))
  124. (define (r7rs-import->r6rs-import import-set)
  125. ;; Normalize SRFI names.
  126. (syntax-case import-set (only except prefix rename)
  127. ((only import-set identifier ...)
  128. #`(only #,(r7rs-import->r6rs-import #'import-set) identifier ...))
  129. ((except import-set identifier ...)
  130. #`(except #,(r7rs-import->r6rs-import #'import-set) identifier ...))
  131. ((prefix import-set identifier ...)
  132. #`(prefix #,(r7rs-import->r6rs-import #'import-set) identifier ...))
  133. ((rename import-set (from-identifier to-identifier) ...)
  134. #`(rename #,(r7rs-import->r6rs-import #'import-set)
  135. (from-identifier to-identifier) ...))
  136. (_ (r7rs-module-name->r6rs-module-name import-set))))
  137. (syntax-case stx ()
  138. ((_ name decl ...)
  139. (call-with-values (lambda ()
  140. (partition-decls #'(decl ...) '() '() '()))
  141. (lambda (exports imports code)
  142. #`(library #,(r7rs-module-name->r6rs-module-name #'name)
  143. (export . #,(map r7rs-export->r6rs-export exports))
  144. (import . #,(map r7rs-import->r6rs-import imports))
  145. . #,code)))))))