fluids.scm 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. ;;; Fluids
  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. ;;; Fluids and dynamic states.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot fluids)
  21. (export make-fluid
  22. fluid?
  23. fluid-ref
  24. fluid-set!
  25. with-fluid*
  26. with-fluids)
  27. (import (only (hoot primitives)
  28. %fluid-ref %fluid-set! %with-fluid*
  29. guile:make-fluid guile:fluid?)
  30. (hoot cond-expand)
  31. (hoot inline-wasm)
  32. (hoot syntax))
  33. (cond-expand
  34. (guile-vm
  35. (define make-fluid guile:make-fluid)
  36. (define fluid? guile:fluid?))
  37. (else
  38. (define* (make-fluid #:optional default-value)
  39. (%inline-wasm '(func (param $default (ref eq)) (result (ref eq))
  40. (struct.new $fluid (i32.const 0)
  41. (local.get $default)))
  42. default-value))
  43. ;; FIXME: We should just add support for the fluid? CPS primitive
  44. ;; to the backend and emit this code directly.
  45. (define (fluid? x)
  46. (%inline-wasm
  47. '(func (param $x (ref eq)) (result (ref eq))
  48. (if (ref eq)
  49. (ref.test $fluid (local.get $x))
  50. (then (ref.i31 (i32.const 17)))
  51. (else (ref.i31 (i32.const 1)))))
  52. x))))
  53. (define (fluid-ref x) (%fluid-ref x))
  54. (define (fluid-set! x y) (%fluid-set! x y))
  55. (define (with-fluid* fluid val thunk) (%with-fluid* fluid val thunk))
  56. (define-syntax with-fluids
  57. (lambda (stx)
  58. (define (emit-with-fluids bindings body)
  59. (syntax-case bindings ()
  60. (()
  61. body)
  62. (((f v) . bindings)
  63. #`(with-fluid* f v
  64. (lambda ()
  65. #,(emit-with-fluids #'bindings body))))))
  66. (syntax-case stx ()
  67. ((_ ((fluid val) ...) exp exp* ...)
  68. (with-syntax (((fluid-tmp ...) (generate-temporaries #'(fluid ...)))
  69. ((val-tmp ...) (generate-temporaries #'(val ...))))
  70. #`(let ((fluid-tmp fluid) ...)
  71. (let ((val-tmp val) ...)
  72. #,(emit-with-fluids #'((fluid-tmp val-tmp) ...)
  73. #'(let () exp exp* ...))))))))))