values.scm 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. ;;; Multiple values
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Multiple values.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot values)
  21. (export call-with-values (rename %values values)
  22. define-values let-values let*-values)
  23. (import (only (hoot primitives)
  24. %values %call-with-values
  25. %cons %car %cdr)
  26. (hoot apply)
  27. (hoot syntax))
  28. (define-syntax call-with-values
  29. (lambda (stx)
  30. (syntax-case stx (lambda)
  31. ((_ producer (lambda args body0 body ...))
  32. #'(%call-with-values producer (lambda args body0 body ...)))
  33. ((_ producer consumer)
  34. #'(%call-with-values producer (lambda args (apply consumer args))))
  35. (id (identifier? #'id)
  36. #'(lambda (producer consumer)
  37. (let ((p producer) (c consumer))
  38. (%call-with-values p (lambda args (apply c args)))))))))
  39. (define-syntax list
  40. (syntax-rules ()
  41. ((_) '())
  42. ((_ head . tail) (%cons head (list . tail)))))
  43. (define-syntax define-values
  44. (syntax-rules ()
  45. ((_ () expr)
  46. (%call-with-values (lambda () expr)
  47. (lambda () (%values))))
  48. ((_ (val) expr)
  49. (define val
  50. (%call-with-values (lambda () expr)
  51. (lambda (x) x))))
  52. ((_ (val ...) expr)
  53. (begin
  54. (define vals
  55. (%call-with-values (lambda () expr)
  56. (lambda (val ...) (list val ...))))
  57. (define val
  58. (let ((x (%car vals)))
  59. (set! vals (%cdr vals))
  60. x))
  61. ...))))
  62. (define-syntax let*-values
  63. (syntax-rules ()
  64. ((_ () . body)
  65. (let () . body))
  66. ((_ ((vars expr) . clauses) . body)
  67. (%call-with-values (lambda () expr)
  68. (lambda vars
  69. (let*-values clauses . body))))))
  70. (define-syntax let-values
  71. (lambda (stx)
  72. (syntax-case stx ()
  73. ((_ ((vars expr) ...) . body)
  74. (with-syntax (((thunk ...) (generate-temporaries #'(expr ...))))
  75. #'(let ((thunk (lambda () expr))
  76. ...)
  77. (let*-values ((vars (thunk)) ...)
  78. . body))))))))