dynamic-states.scm 3.1 KB

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