r7rs-libraries.scm 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. ;; R7RS library support
  2. ;; Copyright (C) 2020 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. (define-syntax define-library
  28. (lambda (stx)
  29. (define (handle-includes filenames)
  30. (syntax-case filenames ()
  31. (() #'())
  32. ((filename . filenames)
  33. (append (call-with-include-port
  34. #'filename
  35. (lambda (p)
  36. (let lp ()
  37. (let ((x (read p)))
  38. (if (eof-object? x)
  39. #'()
  40. (cons (datum->syntax #'filename x) (lp)))))))
  41. (handle-includes #'filenames)))))
  42. (define (handle-cond-expand clauses)
  43. (define (has-req? req)
  44. (syntax-case req (and or not library)
  45. ((and req ...)
  46. (and-map has-req? #'(req ...)))
  47. ((or req ...)
  48. (or-map has-req? #'(req ...)))
  49. ((not req)
  50. (not (has-req? #'req)))
  51. ((library lib-name)
  52. (->bool (resolve-interface (syntax->datum #'lib-name))))
  53. (id
  54. (identifier? #'id)
  55. ;; FIXME: R7RS (features) isn't quite the same as
  56. ;; %cond-expand-features; see scheme/base.scm.
  57. (memq (syntax->datum #'id) %cond-expand-features))))
  58. (syntax-case clauses ()
  59. (() #'()) ; R7RS says this is not specified :-/
  60. (((test decl ...) . clauses)
  61. (if (has-req? #'test)
  62. #'(decl ...)
  63. (handle-cond-expand #'clauses)))))
  64. (define (partition-decls decls exports imports code)
  65. (syntax-case decls (export import begin include include-ci
  66. include-library-declarations cond-expand)
  67. (() (values exports imports (reverse code)))
  68. (((export clause ...) . decls)
  69. (partition-decls #'decls (append exports #'(clause ...)) imports code))
  70. (((import clause ...) . decls)
  71. (partition-decls #'decls exports (append imports #'(clause ...)) code))
  72. (((begin expr ...) . decls)
  73. (partition-decls #'decls exports imports
  74. (cons #'(begin expr ...) code)))
  75. (((include filename ...) . decls)
  76. (partition-decls #'decls exports imports
  77. (cons #'(begin (include filename) ...) code)))
  78. (((include-ci filename ...) . decls)
  79. (partition-decls #'decls exports imports
  80. (cons #'(begin (include-ci filename) ...) code)))
  81. (((include-library-declarations filename ...) . decls)
  82. (syntax-case (handle-includes #'(filename ...)) ()
  83. ((decl ...)
  84. (partition-decls #'(decl ... decls) exports imports code))))
  85. (((cond-expand clause ...) . decls)
  86. (syntax-case (handle-cond-expand #'(clause ...)) ()
  87. ((decl ...)
  88. (partition-decls #'(decl ... decls) exports imports code))))))
  89. (syntax-case stx ()
  90. ((_ name decl ...)
  91. (call-with-values (lambda ()
  92. (partition-decls #'(decl ...) '() '() '()))
  93. (lambda (exports imports code)
  94. #`(library name
  95. (export . #,exports)
  96. (import . #,imports)
  97. . #,code)))))))