dynamic-states.scm 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. ;;; Dynamic states
  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. ;;; Dynamic states.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot dynamic-states)
  21. (export current-dynamic-state
  22. dynamic-state?
  23. with-dynamic-state)
  24. (import (hoot primitives)
  25. (hoot debug)
  26. (hoot errors)
  27. (hoot lists)
  28. (hoot match)
  29. (hoot values)
  30. (hoot vectors)
  31. (hoot numbers))
  32. (define (copy-alist alist)
  33. (match alist
  34. (() (values '() 0))
  35. (((k . v) . alist)
  36. (call-with-values (lambda () (copy-alist alist))
  37. (lambda (alist len)
  38. (values (acons k v alist) (1+ len)))))))
  39. (define (copy-hash-table table)
  40. (define buckets
  41. (%inline-wasm
  42. '(func (param $table (ref $hash-table)) (result (ref eq))
  43. (struct.new $vector (i32.const 0)
  44. (struct.get $hash-table $buckets
  45. (local.get $table))))
  46. table))
  47. (define nbuckets (vector-length buckets))
  48. (define buckets* (make-vector nbuckets '()))
  49. (let lp ((i 0) (size 0))
  50. (cond
  51. ((< i nbuckets)
  52. (call-with-values (lambda () (copy-alist (vector-ref buckets i)))
  53. (lambda (bucket len)
  54. (vector-set! buckets* i bucket)
  55. (lp (1+ i) (+ size len)))))
  56. (else
  57. (%inline-wasm
  58. '(func (param $buckets (ref $vector))
  59. (param $size i32)
  60. (result (ref eq))
  61. (struct.new
  62. $hash-table
  63. (i32.const 0)
  64. (local.get $size)
  65. (struct.get $vector $vals (local.get $buckets))))
  66. buckets* size)))))
  67. (define (current-dynamic-state)
  68. (define current-fluids
  69. (%inline-wasm
  70. '(func (result (ref eq)) (global.get $current-fluids))))
  71. (%inline-wasm
  72. '(func (param $fluids (ref $hash-table))
  73. (result (ref eq))
  74. (struct.new $dynamic-state (i32.const 0) (local.get $fluids)))
  75. (copy-hash-table current-fluids)))
  76. (define (dynamic-state? x)
  77. (%inline-wasm
  78. '(func (param $x (ref eq)) (result (ref eq))
  79. (if (ref eq)
  80. (ref.test $dynamic-state (local.get $x))
  81. (then (ref.i31 (i32.const 17)))
  82. (else (ref.i31 (i32.const 1)))))
  83. x))
  84. (define (with-dynamic-state state thunk)
  85. (check-type state dynamic-state? 'with-dynamic-state)
  86. (%with-dynamic-state state thunk)))