safe-r5rs.scm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. ;;;; Copyright (C) 2000-2001,2004,2006,2008-2010,2019
  2. ;;;; 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. ;;;;
  18. ;;;; Safe subset of R5RS bindings
  19. (define-module (ice-9 safe-r5rs)
  20. #:pure
  21. #:use-module ((guile) #:hide (case cond syntax-rules _ => else ...))
  22. #:use-module (ice-9 ports)
  23. #:use-module ((guile) #:select ((_ . ^_)
  24. (... . ^...)))
  25. #:re-export (quote
  26. quasiquote
  27. unquote unquote-splicing
  28. define-syntax let-syntax letrec-syntax
  29. define lambda let let* letrec begin do
  30. if set! delay and or
  31. eqv? eq? equal?
  32. number? complex? real? rational? integer?
  33. exact? inexact?
  34. = < > <= >=
  35. zero? positive? negative? odd? even?
  36. max min
  37. + * - /
  38. abs
  39. quotient remainder modulo
  40. gcd lcm
  41. numerator denominator
  42. rationalize
  43. floor ceiling truncate round
  44. exp log sin cos tan asin acos atan
  45. sqrt
  46. expt
  47. make-rectangular make-polar real-part imag-part magnitude angle
  48. exact->inexact inexact->exact
  49. number->string string->number
  50. boolean?
  51. not
  52. pair?
  53. cons car cdr
  54. set-car! set-cdr!
  55. caar cadr cdar cddr
  56. caaar caadr cadar caddr cdaar cdadr cddar cdddr
  57. caaaar caaadr caadar caaddr cadaar cadadr caddar cadddr
  58. cdaaar cdaadr cdadar cdaddr cddaar cddadr cdddar cddddr
  59. null?
  60. list?
  61. list
  62. length
  63. append
  64. reverse
  65. list-tail list-ref
  66. memq memv member
  67. assq assv assoc
  68. symbol?
  69. symbol->string string->symbol
  70. char?
  71. char=? char<? char>? char<=? char>=?
  72. char-ci=? char-ci<? char-ci>? char-ci<=? char-ci>=?
  73. char-alphabetic? char-numeric? char-whitespace?
  74. char-upper-case? char-lower-case?
  75. char->integer integer->char
  76. char-upcase
  77. char-downcase
  78. string?
  79. make-string
  80. string
  81. string-length
  82. string-ref string-set!
  83. string=? string-ci=?
  84. string<? string>? string<=? string>=?
  85. string-ci<? string-ci>? string-ci<=? string-ci>=?
  86. substring
  87. string-length
  88. string-append
  89. string->list list->string
  90. string-copy string-fill!
  91. vector?
  92. make-vector
  93. vector
  94. vector-length
  95. vector-ref vector-set!
  96. vector->list list->vector
  97. vector-fill!
  98. procedure?
  99. apply
  100. map
  101. for-each
  102. force
  103. call-with-current-continuation
  104. values
  105. call-with-values
  106. dynamic-wind
  107. eval
  108. input-port? output-port?
  109. current-input-port current-output-port
  110. read
  111. read-char
  112. peek-char
  113. eof-object?
  114. char-ready?
  115. write
  116. display
  117. newline
  118. write-char
  119. ;;transcript-on
  120. ;;transcript-off
  121. )
  122. #:export (null-environment
  123. syntax-rules cond case))
  124. ;;; These definitions of `cond', `case', and `syntax-rules' differ from
  125. ;;; the ones in Guile in that they expect their auxiliary syntax (`_',
  126. ;;; `...', `else', and `=>') to be unbound. They also don't support
  127. ;;; some extensions from Guile (e.g. `=>' in `case'.).
  128. (define-syntax syntax-rules
  129. (lambda (x)
  130. (define (replace-underscores pattern)
  131. (syntax-case pattern (_)
  132. (_ #'^_)
  133. ((x . y)
  134. (with-syntax ((x (replace-underscores #'x))
  135. (y (replace-underscores #'y)))
  136. #'(x . y)))
  137. ((x . y)
  138. (with-syntax ((x (replace-underscores #'x))
  139. (y (replace-underscores #'y)))
  140. #'(x . y)))
  141. (#(x ^...)
  142. (with-syntax (((x ^...) (map replace-underscores #'(x ^...))))
  143. #'#(x ^...)))
  144. (x #'x)))
  145. (syntax-case x ()
  146. ((^_ dots (k ^...) . clauses)
  147. (identifier? #'dots)
  148. #'(with-ellipsis dots (syntax-rules (k ^...) . clauses)))
  149. ((^_ (k ^...) ((keyword . pattern) template) ^...)
  150. (with-syntax (((pattern ^...) (replace-underscores #'(pattern ^...))))
  151. #`(lambda (x)
  152. (syntax-case x (k ^...)
  153. ((dummy . pattern) #'template)
  154. ^...)))))))
  155. (define-syntax case
  156. (lambda (stx)
  157. (let lp ((stx stx))
  158. (syntax-case stx (else)
  159. (("case" x)
  160. #'(if #f #f))
  161. (("case" x ((y ^...) expr ^...) clause ^...)
  162. #`(if (memv x '(y ^...))
  163. (begin expr ^...)
  164. #,(lp #'("case" x clause ^...))))
  165. (("case" x (else expr ^...))
  166. #'(begin expr ^...))
  167. (("case" x clause . ^_)
  168. (syntax-violation 'case "bad 'case' clause" #'clause))
  169. ((^_ x clause clause* ^...)
  170. #`(let ((t x))
  171. #,(lp #'("case" t clause clause* ^...))))))))
  172. (define-syntax cond
  173. (lambda (stx)
  174. (let lp ((stx stx))
  175. (syntax-case stx (else =>)
  176. (("cond")
  177. #'(if #f #f))
  178. (("cond" (else expr ^...))
  179. #'(begin expr ^...))
  180. (("cond" (test => expr) clause ^...)
  181. #`(let ((t test))
  182. (if t
  183. (expr t)
  184. #,(lp #'("cond" clause ^...)))))
  185. (("cond" (test) clause ^...)
  186. #`(or test #,(lp #'("cond" clause ^...))))
  187. (("cond" (test expr ^...) clause ^...)
  188. #`(if test
  189. (begin expr ^...)
  190. #,(lp #'("cond" clause ^...))))
  191. (("cond" clause . ^_)
  192. (syntax-violation 'cond "bad 'cond' clause" #'clause))
  193. ((^_ clause clause* ^...)
  194. (lp #'("cond" clause clause* ^...)))))))
  195. (define (null-environment n)
  196. (unless (eqv? n 5)
  197. (scm-error 'misc-error 'null-environment
  198. "~A is not a valid version" (list n) '()))
  199. ;; Note that we need to create a *fresh* interface
  200. (let ((interface (make-module)))
  201. (set-module-kind! interface 'interface)
  202. (define bindings
  203. '(define quote lambda if set! cond case and or let let* letrec
  204. begin do delay quasiquote unquote
  205. define-syntax let-syntax letrec-syntax syntax-rules))
  206. (module-use! interface
  207. (resolve-interface '(ice-9 safe-r5rs) #:select bindings))
  208. interface))