srfi-71.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. ;; Copyright (c) 2005 Sebastian Egner.
  2. ;;
  3. ;; Permission is hereby granted, free of charge, to any person obtaining a
  4. ;; copy of this software and associated documentation files (the
  5. ;; ``Software''), to deal in the Software without restriction, including
  6. ;; without limitation the rights to use, copy, modify, merge, publish,
  7. ;; distribute, sublicense, and/or sell copies of the Software, and to
  8. ;; permit persons to whom the Software is furnished to do so, subject to
  9. ;; the following conditions:
  10. ;;
  11. ;; The above copyright notice and this permission notice shall be included
  12. ;; in all copies or substantial portions of the Software.
  13. ;;
  14. ;; THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
  15. ;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  16. ;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. ;; NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  18. ;; LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  19. ;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  20. ;; WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. ;; Reference implementation of SRFI-71 using PLT 208's modules
  22. ;; Sebastian.Egner@philips.com, 2005-04-29
  23. ;;
  24. ;; Adjusted for Guile module system by
  25. ;; Christopher Allan Webber <cwebber@dustycloud.org>, 2017-06-29
  26. (define-module (srfi srfi-71)
  27. #:export (uncons unlist unvector values->list
  28. values->vector)
  29. #:replace ((srfi-let . let)
  30. (srfi-let* . let*)
  31. (srfi-letrec . letrec)))
  32. (cond-expand-provide (current-module) '(srfi-71))
  33. (define-syntax r5rs-let
  34. (syntax-rules ()
  35. ((r5rs-let ((v x) ...) body1 body ...)
  36. (let ((v x) ...) body1 body ...))
  37. ((r5rs-let tag ((v x) ...) body1 body ...)
  38. (let tag ((v x) ...) body1 body ...))))
  39. (define-syntax r5rs-let*
  40. (syntax-rules ()
  41. ((r5rs-let* ((v x) ...) body1 body ...)
  42. (let* ((v x) ...) body1 body ...))))
  43. (define-syntax r5rs-letrec
  44. (syntax-rules ()
  45. ((r5rs-letrec ((v x) ...) body1 body ...)
  46. (letrec ((v x) ...) body1 body ...))))
  47. ; --- textual copy of 'letvalues.scm' starts here ---
  48. ; Reference implementation of SRFI-71 (generic part)
  49. ; Sebastian.Egner@philips.com, 20-May-2005, PLT 208
  50. ;
  51. ; In order to avoid conflicts with the existing let etc.
  52. ; the macros defined here are called srfi-let etc.,
  53. ; and they are defined in terms of r5rs-let etc.
  54. ; It is up to the actual implementation to save let/*/rec
  55. ; in r5rs-let/*/rec first and redefine let/*/rec
  56. ; by srfi-let/*/rec then.
  57. ;
  58. ; There is also a srfi-letrec* being defined (in view of R6RS.)
  59. ;
  60. ; Macros used internally are named i:<something>.
  61. ;
  62. ; Abbreviations for macro arguments:
  63. ; bs - <binding spec>
  64. ; b - component of a binding spec (values, <variable>, or <expression>)
  65. ; v - <variable>
  66. ; vr - <variable> for rest list
  67. ; x - <expression>
  68. ; t - newly introduced temporary variable
  69. ; vx - (<variable> <expression>)
  70. ; rec - flag if letrec is produced (and not let)
  71. ; cwv - call-with-value skeleton of the form (x formals)
  72. ; (call-with-values (lambda () x) (lambda formals /payload/))
  73. ; where /payload/ is of the form (let (vx ...) body1 body ...).
  74. ;
  75. ; Remark (*):
  76. ; We bind the variables of a letrec to i:undefined since there is
  77. ; no portable (R5RS) way of binding a variable to a values that
  78. ; raises an error when read uninitialized.
  79. (define i:undefined 'undefined)
  80. (define-syntax srfi-letrec* ; -> srfi-letrec
  81. (syntax-rules ()
  82. ((srfi-letrec* () body1 body ...)
  83. (srfi-letrec () body1 body ...))
  84. ((srfi-letrec* (bs) body1 body ...)
  85. (srfi-letrec (bs) body1 body ...))
  86. ((srfi-letrec* (bs1 bs2 bs ...) body1 body ...)
  87. (srfi-letrec (bs1) (srfi-letrec* (bs2 bs ...) body1 body ...)))))
  88. (define-syntax srfi-letrec ; -> i:let
  89. (syntax-rules ()
  90. ((srfi-letrec ((b1 b2 b ...) ...) body1 body ...)
  91. (i:let "bs" #t () () (body1 body ...) ((b1 b2 b ...) ...)))))
  92. (define-syntax srfi-let* ; -> srfi-let
  93. (syntax-rules ()
  94. ((srfi-let* () body1 body ...)
  95. (srfi-let () body1 body ...))
  96. ((srfi-let* (bs) body1 body ...)
  97. (srfi-let (bs) body1 body ...))
  98. ((srfi-let* (bs1 bs2 bs ...) body1 body ...)
  99. (srfi-let (bs1) (srfi-let* (bs2 bs ...) body1 body ...)))))
  100. (define-syntax srfi-let ; -> i:let or i:named-let
  101. (syntax-rules ()
  102. ((srfi-let ((b1 b2 b ...) ...) body1 body ...)
  103. (i:let "bs" #f () () (body1 body ...) ((b1 b2 b ...) ...)))
  104. ((srfi-let tag ((b1 b2 b ...) ...) body1 body ...)
  105. (i:named-let tag () (body1 body ...) ((b1 b2 b ...) ...)))))
  106. (define-syntax i:let
  107. (syntax-rules (values)
  108. ; (i:let "bs" rec (cwv ...) (vx ...) body (bs ...))
  109. ; processes the binding specs bs ... by adding call-with-values
  110. ; skeletons to cwv ... and bindings to vx ..., and afterwards
  111. ; wrapping the skeletons around the payload (let (vx ...) . body).
  112. ; no more bs to process -> wrap call-with-values skeletons
  113. ((i:let "bs" rec (cwv ...) vxs body ())
  114. (i:let "wrap" rec vxs body cwv ...))
  115. ; recognize form1 without variable -> dummy binding for side-effects
  116. ((i:let "bs" rec cwvs (vx ...) body (((values) x) bs ...))
  117. (i:let "bs" rec cwvs (vx ... (dummy (begin x #f))) body (bs ...)))
  118. ; recognize form1 with single variable -> just extend vx ...
  119. ((i:let "bs" rec cwvs (vx ...) body (((values v) x) bs ...))
  120. (i:let "bs" rec cwvs (vx ... (v x)) body (bs ...)))
  121. ; recognize form1 without rest arg -> generate cwv
  122. ((i:let "bs" rec cwvs vxs body (((values v ...) x) bs ...))
  123. (i:let "form1" rec cwvs vxs body (bs ...) (x ()) (values v ...)))
  124. ; recognize form1 with rest arg -> generate cwv
  125. ((i:let "bs" rec cwvs vxs body (((values . vs) x) bs ...))
  126. (i:let "form1+" rec cwvs vxs body (bs ...) (x ()) (values . vs)))
  127. ; recognize form2 with single variable -> just extend vx ...
  128. ((i:let "bs" rec cwvs (vx ...) body ((v x) bs ...))
  129. (i:let "bs" rec cwvs (vx ... (v x)) body (bs ...)))
  130. ; recognize form2 with >=2 variables -> transform to form1
  131. ((i:let "bs" rec cwvs vxs body ((b1 b2 b3 b ...) bs ...))
  132. (i:let "form2" rec cwvs vxs body (bs ...) (b1 b2) (b3 b ...)))
  133. ; (i:let "form1" rec cwvs vxs body bss (x (t ...)) (values v1 v2 v ...))
  134. ; processes the variables in v1 v2 v ... adding them to (t ...)
  135. ; and producing a cwv when finished. There is not rest argument.
  136. ((i:let "form1" rec (cwv ...) vxs body bss (x ts) (values))
  137. (i:let "bs" rec (cwv ... (x ts)) vxs body bss))
  138. ((i:let "form1" rec cwvs (vx ...) body bss (x (t ...)) (values v1 v ...))
  139. (i:let "form1" rec cwvs (vx ... (v1 t1)) body bss (x (t ... t1)) (values v ...)))
  140. ; (i:let "form1+" rec cwvs vxs body bss (x (t ...)) (values v ... . vr))
  141. ; processes the variables in v ... . vr adding them to (t ...)
  142. ; and producing a cwv when finished. The rest arg is vr.
  143. ((i:let "form1+" rec cwvs (vx ...) body bss (x (t ...)) (values v1 v2 . vs))
  144. (i:let "form1+" rec cwvs (vx ... (v1 t1)) body bss (x (t ... t1)) (values v2 . vs)))
  145. ((i:let "form1+" rec (cwv ...) (vx ...) body bss (x (t ...)) (values v1 . vr))
  146. (i:let "bs" rec (cwv ... (x (t ... t1 . tr))) (vx ... (v1 t1) (vr tr)) body bss))
  147. ((i:let "form1+" rec (cwv ...) (vx ...) body bss (x ()) (values . vr))
  148. (i:let "bs" rec (cwv ... (x tr)) (vx ... (vr tr)) body bss))
  149. ; (i:let "form2" rec cwvs vxs body bss (v ...) (b ... x))
  150. ; processes the binding items (b ... x) from form2 as in
  151. ; (v ... b ... x) into ((values v ... b ...) x), i.e. form1.
  152. ; Then call "bs" recursively.
  153. ((i:let "form2" rec cwvs vxs body (bs ...) (v ...) (x))
  154. (i:let "bs" rec cwvs vxs body (((values v ...) x) bs ...)))
  155. ((i:let "form2" rec cwvs vxs body bss (v ...) (b1 b2 b ...))
  156. (i:let "form2" rec cwvs vxs body bss (v ... b1) (b2 b ...)))
  157. ; (i:let "wrap" rec ((v x) ...) (body ...) cwv ...)
  158. ; wraps cwv ... around the payload generating the actual code.
  159. ; For letrec this is of course different than for let.
  160. ((i:let "wrap" #f vxs body)
  161. (r5rs-let vxs . body))
  162. ((i:let "wrap" #f vxs body (x formals) cwv ...)
  163. (call-with-values
  164. (lambda () x)
  165. (lambda formals (i:let "wrap" #f vxs body cwv ...))))
  166. ((i:let "wrap" #t vxs body)
  167. (r5rs-letrec vxs . body))
  168. ((i:let "wrap" #t ((v t) ...) body cwv ...)
  169. (r5rs-let ((v i:undefined) ...) ; (*)
  170. (i:let "wraprec" ((v t) ...) body cwv ...)))
  171. ; (i:let "wraprec" ((v t) ...) body cwv ...)
  172. ; generate the inner code for a letrec. The variables v ...
  173. ; are the user-visible variables (bound outside), and t ...
  174. ; are the temporary variables bound by the cwv consumers.
  175. ((i:let "wraprec" ((v t) ...) (body ...))
  176. (begin (set! v t) ... (r5rs-let () body ...)))
  177. ((i:let "wraprec" vxs body (x formals) cwv ...)
  178. (call-with-values
  179. (lambda () x)
  180. (lambda formals (i:let "wraprec" vxs body cwv ...))))
  181. ))
  182. (define-syntax i:named-let
  183. (syntax-rules (values)
  184. ; (i:named-let tag (vx ...) body (bs ...))
  185. ; processes the binding specs bs ... by extracting the variable
  186. ; and expression, adding them to vx and turning the result into
  187. ; an ordinary named let.
  188. ((i:named-let tag vxs body ())
  189. (r5rs-let tag vxs . body))
  190. ((i:named-let tag (vx ...) body (((values v) x) bs ...))
  191. (i:named-let tag (vx ... (v x)) body (bs ...)))
  192. ((i:named-let tag (vx ...) body ((v x) bs ...))
  193. (i:named-let tag (vx ... (v x)) body (bs ...)))))
  194. ; --- standard procedures ---
  195. (define (uncons pair)
  196. (values (car pair) (cdr pair)))
  197. (define (uncons-2 list)
  198. (values (car list) (cadr list) (cddr list)))
  199. (define (uncons-3 list)
  200. (values (car list) (cadr list) (caddr list) (cdddr list)))
  201. (define (uncons-4 list)
  202. (values (car list) (cadr list) (caddr list) (cadddr list) (cddddr list)))
  203. (define (uncons-cons alist)
  204. (values (caar alist) (cdar alist) (cdr alist)))
  205. (define (unlist list)
  206. (apply values list))
  207. (define (unvector vector)
  208. (apply values (vector->list vector)))
  209. ; --- standard macros ---
  210. (define-syntax values->list
  211. (syntax-rules ()
  212. ((values->list x)
  213. (call-with-values (lambda () x) list))))
  214. (define-syntax values->vector
  215. (syntax-rules ()
  216. ((values->vector x)
  217. (call-with-values (lambda () x) vector))))
  218. ; --- textual copy of 'letvalues.scm' ends here ---