gofront 1.8.0 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -5
  3. package/src/backend/js/expressions.js +1157 -408
  4. package/src/backend/js/index.js +327 -153
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +559 -2552
  7. package/src/backend/js/statements.js +670 -158
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +298 -19
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +91 -170
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +884 -256
  16. package/src/backend/wasm/emit-exprs.js +185 -77
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-shared.js +4 -1
  19. package/src/backend/wasm/emit-stmts.js +524 -240
  20. package/src/backend/wasm/emit.js +176 -38
  21. package/src/backend/wasm/globals.js +48 -8
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +44 -530
  24. package/src/backend/wasm/method-expr.js +12 -1
  25. package/src/backend/wasm/module-emitter.js +299 -770
  26. package/src/backend/wasm/monomorph.js +139 -8
  27. package/src/backend/wasm/natives.js +600 -0
  28. package/src/backend/wasm/prescan.js +5 -153
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -32
  31. package/src/backend/wasm/types.js +97 -20
  32. package/src/backend/wasm/variadic.js +9 -4
  33. package/src/cli/cli-core.js +5 -1
  34. package/src/cli/test-runner.js +115 -342
  35. package/src/compiler.js +113 -130
  36. package/src/lexer/lexer.js +106 -11
  37. package/src/lexer/templ-lexer.js +61 -18
  38. package/src/lexer/tokens.js +1 -0
  39. package/src/link/stdlib.js +355 -132
  40. package/src/link/type-names.js +204 -0
  41. package/src/link/wasm.js +30 -6
  42. package/src/lower/bounds.js +153 -0
  43. package/src/lower/captures.js +92 -33
  44. package/src/lower/embedding.js +62 -5
  45. package/src/lower/errors-as.js +196 -0
  46. package/src/lower/fmt-formatters.js +929 -0
  47. package/src/lower/functions.js +225 -7
  48. package/src/lower/gen-types.js +293 -0
  49. package/src/lower/index.js +14 -2
  50. package/src/lower/json-codecs.js +334 -245
  51. package/src/lower/ownership.js +25 -7
  52. package/src/lower/reachability.js +69 -51
  53. package/src/lower/walk.js +12 -0
  54. package/src/parser/declarations.js +30 -5
  55. package/src/parser/expressions.js +111 -57
  56. package/src/parser/statements.js +108 -0
  57. package/src/parser/templ.js +44 -5
  58. package/src/parser/types.js +12 -0
  59. package/src/resolver.js +1 -2
  60. package/src/typechecker/assignability.js +214 -19
  61. package/src/typechecker/const-fold.js +70 -27
  62. package/src/typechecker/constants.js +156 -8
  63. package/src/typechecker/expressions.js +490 -108
  64. package/src/typechecker/index.js +346 -42
  65. package/src/typechecker/init-order.js +136 -40
  66. package/src/typechecker/operand-text.js +41 -0
  67. package/src/typechecker/resolve.js +490 -65
  68. package/src/typechecker/statements.js +288 -27
  69. package/src/typechecker/stdlib/excluded.js +9 -5
  70. package/src/typechecker/stdlib/index.js +25 -9
  71. package/src/typechecker/termination.js +10 -1
  72. package/src/typechecker/types.js +287 -575
  73. package/stdlib/bytes/buffer.go +479 -0
  74. package/stdlib/bytes/bytes.go +1010 -0
  75. package/stdlib/bytes/reader.go +161 -0
  76. package/stdlib/context/context.go +115 -0
  77. package/stdlib/crypto/rand/rand.go +34 -0
  78. package/stdlib/crypto/sha256/sha256.go +249 -0
  79. package/stdlib/encoding/base64/base64.go +331 -0
  80. package/stdlib/encoding/binary/binary.go +332 -0
  81. package/stdlib/encoding/hex/hex.go +140 -0
  82. package/stdlib/encoding/json/json.go +62 -0
  83. package/stdlib/errors/errors.go +174 -0
  84. package/stdlib/fmt/errors.go +110 -0
  85. package/stdlib/fmt/format.go +732 -0
  86. package/stdlib/fmt/print.go +1232 -0
  87. package/stdlib/gom/gom.go +293 -0
  88. package/stdlib/html/html.go +251 -0
  89. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  90. package/stdlib/internal/jsonrt/dec.go +171 -38
  91. package/stdlib/internal/jsonrt/enc.go +186 -36
  92. package/stdlib/internal/jsonrt/scanner.go +17 -8
  93. package/stdlib/io/io.go +157 -1
  94. package/stdlib/maps/maps.go +131 -0
  95. package/stdlib/math/bits/bits.go +507 -0
  96. package/stdlib/math/extra.go +16 -14
  97. package/stdlib/math/math.go +439 -0
  98. package/stdlib/math/rand/rand.go +297 -0
  99. package/stdlib/os/os.go +93 -0
  100. package/stdlib/path/filepath/filepath.go +47 -0
  101. package/stdlib/path/path.go +394 -0
  102. package/stdlib/regexp/regexp.go +231 -0
  103. package/stdlib/slices/slices.go +526 -0
  104. package/stdlib/slices/sort.go +209 -0
  105. package/stdlib/slices/zsort_cmp.go +480 -0
  106. package/stdlib/slices/zsort_ordered.go +482 -0
  107. package/stdlib/sort/sort.go +391 -452
  108. package/stdlib/sort/zsort_func.go +480 -0
  109. package/stdlib/sort/zsort_iface.go +480 -0
  110. package/stdlib/strconv/float.go +1699 -0
  111. package/stdlib/strconv/isprint.go +752 -0
  112. package/stdlib/strconv/quote.go +235 -50
  113. package/stdlib/strconv/strconv.go +616 -0
  114. package/stdlib/strings/builder.go +95 -0
  115. package/stdlib/strings/reader.go +163 -0
  116. package/stdlib/strings/replacer.go +102 -0
  117. package/stdlib/strings/strings.go +807 -0
  118. package/stdlib/sync/sync.go +268 -0
  119. package/stdlib/testing/async_js.go +61 -0
  120. package/stdlib/testing/benchmark.go +297 -0
  121. package/stdlib/testing/testing.go +523 -0
  122. package/stdlib/time/duration.go +233 -0
  123. package/stdlib/time/format.go +745 -0
  124. package/stdlib/time/parse.go +790 -0
  125. package/stdlib/time/sleep_js.go +63 -0
  126. package/stdlib/time/time.go +834 -0
  127. package/stdlib/unicode/unicode.go +141 -3
  128. package/stdlib/unicode/utf8/utf8.go +464 -0
  129. package/src/backend/js/fmt-runtime.js +0 -573
  130. package/src/backend/js/stdlib/base64.js +0 -12
  131. package/src/backend/js/stdlib/binary.js +0 -102
  132. package/src/backend/js/stdlib/bits.js +0 -119
  133. package/src/backend/js/stdlib/builder.js +0 -98
  134. package/src/backend/js/stdlib/bytes.js +0 -368
  135. package/src/backend/js/stdlib/errors.js +0 -45
  136. package/src/backend/js/stdlib/fmt.js +0 -517
  137. package/src/backend/js/stdlib/gom.js +0 -155
  138. package/src/backend/js/stdlib/hex.js +0 -17
  139. package/src/backend/js/stdlib/html.js +0 -20
  140. package/src/backend/js/stdlib/io.js +0 -137
  141. package/src/backend/js/stdlib/json.js +0 -1167
  142. package/src/backend/js/stdlib/maps.js +0 -37
  143. package/src/backend/js/stdlib/math.js +0 -85
  144. package/src/backend/js/stdlib/os.js +0 -13
  145. package/src/backend/js/stdlib/path.js +0 -48
  146. package/src/backend/js/stdlib/rand.js +0 -32
  147. package/src/backend/js/stdlib/regexp.js +0 -54
  148. package/src/backend/js/stdlib/sha256.js +0 -12
  149. package/src/backend/js/stdlib/shared.js +0 -17
  150. package/src/backend/js/stdlib/simd.js +0 -34
  151. package/src/backend/js/stdlib/slices.js +0 -107
  152. package/src/backend/js/stdlib/sort.js +0 -30
  153. package/src/backend/js/stdlib/strconv.js +0 -79
  154. package/src/backend/js/stdlib/strings.js +0 -301
  155. package/src/backend/js/stdlib/sync.js +0 -13
  156. package/src/backend/js/stdlib/testing.js +0 -41
  157. package/src/backend/js/stdlib/time.js +0 -152
  158. package/src/backend/js/stdlib/unicode.js +0 -25
  159. package/src/backend/js/stdlib/utf8.js +0 -26
  160. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  161. package/src/backend/wasm/stdlib/core.js +0 -10278
  162. package/src/backend/wasm/stdlib/io.js +0 -3578
  163. package/src/backend/wasm/stdlib/packages.js +0 -2402
  164. package/src/backend/wasm/stdlib/pure.js +0 -720
  165. package/src/backend/wasm/stdlib/time.js +0 -2229
  166. package/src/typechecker/stdlib/core.js +0 -1079
  167. package/src/typechecker/stdlib/extended.js +0 -1210
  168. package/stdlib/bytes/iter.go +0 -192
  169. package/stdlib/bytes/search.go +0 -240
  170. package/stdlib/bytes/split.go +0 -218
  171. package/stdlib/errors/overlay.go +0 -12
  172. package/stdlib/maps/iter.go +0 -65
  173. package/stdlib/slices/extra.go +0 -73
  174. package/stdlib/slices/iter.go +0 -113
  175. package/stdlib/strings/extra.go +0 -35
  176. package/stdlib/strings/iter.go +0 -122
  177. package/stdlib/sync/extra.go +0 -105
  178. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -1,65 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed maps package: the iterator members are
6
- // written in Go over iter.Seq and iter.Seq2 and merged into the maps
7
- // namespace. Keys and Values return iterators, as in Go 1.23.
8
- package maps
9
-
10
- import "iter"
11
-
12
- // All returns an iterator over key-value pairs from m.
13
- // The iteration order is not specified and is not guaranteed
14
- // to be the same from one call to the next.
15
- func All[K comparable, V any](m map[K]V) iter.Seq2[K, V] {
16
- return func(yield func(K, V) bool) {
17
- for k, v := range m {
18
- if !yield(k, v) {
19
- return
20
- }
21
- }
22
- }
23
- }
24
-
25
- // Keys returns an iterator over keys in m.
26
- // The iteration order is not specified and is not guaranteed
27
- // to be the same from one call to the next.
28
- func Keys[K comparable, V any](m map[K]V) iter.Seq[K] {
29
- return func(yield func(K) bool) {
30
- for k := range m {
31
- if !yield(k) {
32
- return
33
- }
34
- }
35
- }
36
- }
37
-
38
- // Values returns an iterator over values in m.
39
- // The iteration order is not specified and is not guaranteed
40
- // to be the same from one call to the next.
41
- func Values[K comparable, V any](m map[K]V) iter.Seq[V] {
42
- return func(yield func(V) bool) {
43
- for _, v := range m {
44
- if !yield(v) {
45
- return
46
- }
47
- }
48
- }
49
- }
50
-
51
- // Insert adds the key-value pairs from seq to m.
52
- // If a key in seq already exists in m, its value will be overwritten.
53
- func Insert[K comparable, V any](m map[K]V, seq iter.Seq2[K, V]) {
54
- for k, v := range seq {
55
- m[k] = v
56
- }
57
- }
58
-
59
- // Collect collects key-value pairs from seq into a new map
60
- // and returns it.
61
- func Collect[K comparable, V any](seq iter.Seq2[K, V]) map[K]V {
62
- m := make(map[K]V)
63
- Insert(m, seq)
64
- return m
65
- }
@@ -1,73 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed slices package: comparison and repetition
6
- // members written in Go and merged into the slices namespace. The
7
- // checker has no core types for type parameters, so these take []E rather
8
- // than Go's S ~[]E and Repeat returns []E.
9
- package slices
10
-
11
- // EqualFunc reports whether two slices are equal using an equality
12
- // function on each pair of elements. If the lengths are different,
13
- // EqualFunc returns false. Otherwise, the elements are compared in
14
- // increasing index order, and the comparison stops at the first index
15
- // for which eq returns false.
16
- func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool {
17
- if len(s1) != len(s2) {
18
- return false
19
- }
20
- for i, v1 := range s1 {
21
- v2 := s2[i]
22
- if !eq(v1, v2) {
23
- return false
24
- }
25
- }
26
- return true
27
- }
28
-
29
- // CompareFunc is like Compare but uses a custom comparison function on each
30
- // pair of elements.
31
- // The result is the first non-zero result of cmp; if cmp always
32
- // returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
33
- // and +1 if len(s1) > len(s2).
34
- func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int {
35
- for i, v1 := range s1 {
36
- if i >= len(s2) {
37
- return +1
38
- }
39
- v2 := s2[i]
40
- if c := cmp(v1, v2); c != 0 {
41
- return c
42
- }
43
- }
44
- if len(s1) < len(s2) {
45
- return -1
46
- }
47
- return 0
48
- }
49
-
50
- // repeatMaxInt is the largest int, as the overflow bound of Repeat.
51
- const repeatMaxInt = 1<<63 - 1
52
-
53
- // Repeat returns a new slice that repeats the provided slice the given number of times.
54
- // The result has length and capacity (len(x) * count).
55
- // The result is never nil.
56
- // Repeat panics if count is negative or if the result of (len(x) * count)
57
- // overflows.
58
- func Repeat[E any](x []E, count int) []E {
59
- if count < 0 {
60
- panic("cannot be negative")
61
- }
62
-
63
- if len(x) > 0 && count > repeatMaxInt/len(x) {
64
- panic("the result of (len(x) * count) overflows")
65
- }
66
-
67
- newslice := make([]E, len(x)*count)
68
- n := copy(newslice, x)
69
- for n < len(newslice) {
70
- n += copy(newslice[n:], newslice[:n])
71
- }
72
- return newslice
73
- }
@@ -1,113 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed slices package: the iterator members are
6
- // written in Go over iter.Seq and iter.Seq2 and merged into the slices
7
- // namespace. Unqualified references to emitter members (Sort, SortFunc,
8
- // SortStableFunc) resolve to the emitter implementation.
9
- package slices
10
-
11
- import (
12
- "cmp"
13
- "iter"
14
- )
15
-
16
- // All returns an iterator over index-value pairs in the slice
17
- // in the usual order.
18
- func All[E any](s []E) iter.Seq2[int, E] {
19
- return func(yield func(int, E) bool) {
20
- for i, v := range s {
21
- if !yield(i, v) {
22
- return
23
- }
24
- }
25
- }
26
- }
27
-
28
- // Backward returns an iterator over index-value pairs in the slice,
29
- // traversing it backward with descending indices.
30
- func Backward[E any](s []E) iter.Seq2[int, E] {
31
- return func(yield func(int, E) bool) {
32
- for i := len(s) - 1; i >= 0; i-- {
33
- if !yield(i, s[i]) {
34
- return
35
- }
36
- }
37
- }
38
- }
39
-
40
- // Values returns an iterator that yields the slice elements in order.
41
- func Values[E any](s []E) iter.Seq[E] {
42
- return func(yield func(E) bool) {
43
- for _, v := range s {
44
- if !yield(v) {
45
- return
46
- }
47
- }
48
- }
49
- }
50
-
51
- // AppendSeq appends the values from seq to the slice and
52
- // returns the extended slice.
53
- func AppendSeq[E any](s []E, seq iter.Seq[E]) []E {
54
- for v := range seq {
55
- s = append(s, v)
56
- }
57
- return s
58
- }
59
-
60
- // Collect collects values from seq into a new slice and returns it.
61
- func Collect[E any](seq iter.Seq[E]) []E {
62
- var s []E
63
- return AppendSeq(s, seq)
64
- }
65
-
66
- // Sorted collects values from seq into a new slice, sorts the slice,
67
- // and returns it.
68
- func Sorted[E cmp.Ordered](seq iter.Seq[E]) []E {
69
- s := Collect(seq)
70
- Sort(s)
71
- return s
72
- }
73
-
74
- // SortedFunc collects values from seq into a new slice, sorts the slice
75
- // using the comparison function, and returns it.
76
- func SortedFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
77
- s := Collect(seq)
78
- SortFunc(s, cmp)
79
- return s
80
- }
81
-
82
- // SortedStableFunc collects values from seq into a new slice.
83
- // It then sorts the slice while keeping the original order of equal elements,
84
- // using the comparison function to compare elements.
85
- // It returns the new slice.
86
- func SortedStableFunc[E any](seq iter.Seq[E], cmp func(E, E) int) []E {
87
- s := Collect(seq)
88
- SortStableFunc(s, cmp)
89
- return s
90
- }
91
-
92
- // Chunk returns an iterator over consecutive sub-slices of up to n elements
93
- // of s. All but the last sub-slice will have size n. All sub-slices are
94
- // clipped to have no capacity beyond the length. If s is empty, the sequence
95
- // is empty: there is no empty slice in the sequence. Chunk panics if n is
96
- // less than 1.
97
- func Chunk[E any](s []E, n int) iter.Seq[[]E] {
98
- if n < 1 {
99
- panic("cannot be less than 1")
100
- }
101
- return func(yield func([]E) bool) {
102
- for i := 0; i < len(s); i += n {
103
- // Clamp the last chunk to the slice bound as necessary.
104
- end := min(n, len(s[i:]))
105
-
106
- // Set the capacity of each chunk so that appending to a chunk does
107
- // not modify the original slice.
108
- if !yield(s[i : i+end : i+end]) {
109
- return
110
- }
111
- }
112
- }
113
- }
@@ -1,35 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed strings package: small members written in Go
6
- // and merged into the strings namespace.
7
- package strings
8
-
9
- // Clone returns a fresh copy of s. Strings are immutable values here, so
10
- // the copy is s itself.
11
- func Clone(s string) string {
12
- return s
13
- }
14
-
15
- // Compare returns an integer comparing two strings lexicographically.
16
- // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
17
- func Compare(a, b string) int {
18
- if a == b {
19
- return 0
20
- }
21
- if a < b {
22
- return -1
23
- }
24
- return +1
25
- }
26
-
27
- // ContainsFunc reports whether any Unicode code points in s satisfy f(c).
28
- func ContainsFunc(s string, f func(rune) bool) bool {
29
- for _, r := range s {
30
- if f(r) {
31
- return true
32
- }
33
- }
34
- return false
35
- }
@@ -1,122 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed strings package: the sequence members of
6
- // Go 1.24 are written in Go over iter.Seq and merged into the strings
7
- // namespace. Strings are JavaScript strings, so Index and slicing count the
8
- // same units and splitting at a substring is always consistent; the places
9
- // that need code points (an empty separator, Fields) go through []rune.
10
- package strings
11
-
12
- import (
13
- "iter"
14
- "unicode"
15
- )
16
-
17
- // Lines returns an iterator over the newline-terminated lines in the string s.
18
- // The lines yielded by the iterator include their terminating newlines.
19
- // If s is empty, the iterator yields no lines at all.
20
- // If s does not end in a newline, the final yielded line will not end in a newline.
21
- func Lines(s string) iter.Seq[string] {
22
- return func(yield func(string) bool) {
23
- for len(s) > 0 {
24
- var line string
25
- if i := IndexByte(s, '\n'); i >= 0 {
26
- line, s = s[:i+1], s[i+1:]
27
- } else {
28
- line, s = s, ""
29
- }
30
- if !yield(line) {
31
- return
32
- }
33
- }
34
- }
35
- }
36
-
37
- // explodeSeq returns an iterator over the runes in s.
38
- func explodeSeq(s string) iter.Seq[string] {
39
- return func(yield func(string) bool) {
40
- for _, r := range []rune(s) {
41
- if !yield(string(r)) {
42
- return
43
- }
44
- }
45
- }
46
- }
47
-
48
- // splitSeq is SplitSeq or SplitAfterSeq, configured by how many
49
- // bytes of sep to include in the results (none or all).
50
- func splitSeq(s, sep string, sepSave int) iter.Seq[string] {
51
- if len(sep) == 0 {
52
- return explodeSeq(s)
53
- }
54
- return func(yield func(string) bool) {
55
- for {
56
- i := Index(s, sep)
57
- if i < 0 {
58
- break
59
- }
60
- frag := s[:i+sepSave]
61
- if !yield(frag) {
62
- return
63
- }
64
- s = s[i+len(sep):]
65
- }
66
- yield(s)
67
- }
68
- }
69
-
70
- // SplitSeq returns an iterator over substrings of s split by sep.
71
- // The iterator yields the same strings that would be returned by Split(s, sep),
72
- // but without constructing the slice.
73
- func SplitSeq(s, sep string) iter.Seq[string] {
74
- return splitSeq(s, sep, 0)
75
- }
76
-
77
- // SplitAfterSeq returns an iterator over substrings of s split after each instance of sep.
78
- // The iterator yields the same strings that would be returned by SplitAfter(s, sep),
79
- // but without constructing the slice.
80
- func SplitAfterSeq(s, sep string) iter.Seq[string] {
81
- return splitSeq(s, sep, len(sep))
82
- }
83
-
84
- // isSpace is unicode.IsSpace as a func(rune) bool (the checker types the
85
- // unicode predicates over int).
86
- func isSpace(r rune) bool {
87
- return unicode.IsSpace(int(r))
88
- }
89
-
90
- // FieldsSeq returns an iterator over substrings of s split around runs of
91
- // whitespace characters, as defined by unicode.IsSpace.
92
- // The iterator yields the same strings that would be returned by Fields(s),
93
- // but without constructing the slice.
94
- func FieldsSeq(s string) iter.Seq[string] {
95
- return FieldsFuncSeq(s, isSpace)
96
- }
97
-
98
- // FieldsFuncSeq returns an iterator over substrings of s split around runs of
99
- // Unicode code points satisfying f(c).
100
- // The iterator yields the same strings that would be returned by FieldsFunc(s),
101
- // but without constructing the slice.
102
- func FieldsFuncSeq(s string, f func(rune) bool) iter.Seq[string] {
103
- return func(yield func(string) bool) {
104
- runes := []rune(s)
105
- start := -1
106
- for i, r := range runes {
107
- if f(r) {
108
- if start >= 0 {
109
- if !yield(string(runes[start:i])) {
110
- return
111
- }
112
- start = -1
113
- }
114
- } else if start < 0 {
115
- start = i
116
- }
117
- }
118
- if start >= 0 {
119
- yield(string(runes[start:]))
120
- }
121
- }
122
- }
@@ -1,105 +0,0 @@
1
- //go:build gofront
2
-
3
- //gofront:target both
4
-
5
- // Overlay on the emitter-backed sync package: OnceFunc/OnceValue/OnceValues
6
- // and RWMutex.RLocker.
7
- package sync
8
-
9
- // OnceFunc returns a function that invokes f only once. The returned function
10
- // may be called concurrently.
11
- //
12
- // If f panics, the returned function will panic with the same value on every call.
13
- func OnceFunc(f func()) func() {
14
- var (
15
- once Once
16
- valid bool
17
- p any
18
- )
19
- return func() {
20
- once.Do(func() {
21
- defer func() {
22
- p = recover()
23
- if !valid {
24
- panic(p)
25
- }
26
- }()
27
- f()
28
- valid = true
29
- })
30
- if !valid {
31
- panic(p)
32
- }
33
- }
34
- }
35
-
36
- // OnceValue returns a function that invokes f only once and returns the value
37
- // returned by f. The returned function may be called concurrently.
38
- //
39
- // If f panics, the returned function will panic with the same value on every call.
40
- func OnceValue[T any](f func() T) func() T {
41
- var (
42
- once Once
43
- valid bool
44
- p any
45
- result T
46
- )
47
- return func() T {
48
- once.Do(func() {
49
- defer func() {
50
- p = recover()
51
- if !valid {
52
- panic(p)
53
- }
54
- }()
55
- result = f()
56
- valid = true
57
- })
58
- if !valid {
59
- panic(p)
60
- }
61
- return result
62
- }
63
- }
64
-
65
- // OnceValues returns a function that invokes f only once and returns the values
66
- // returned by f. The returned function may be called concurrently.
67
- //
68
- // If f panics, the returned function will panic with the same value on every call.
69
- func OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
70
- var (
71
- once Once
72
- valid bool
73
- p any
74
- r1 T1
75
- r2 T2
76
- )
77
- return func() (T1, T2) {
78
- once.Do(func() {
79
- defer func() {
80
- p = recover()
81
- if !valid {
82
- panic(p)
83
- }
84
- }()
85
- r1, r2 = f()
86
- valid = true
87
- })
88
- if !valid {
89
- panic(p)
90
- }
91
- return r1, r2
92
- }
93
- }
94
-
95
- type rlocker struct {
96
- rw *RWMutex
97
- }
98
-
99
- func (r *rlocker) Lock() {}
100
-
101
- func (r *rlocker) Unlock() {}
102
-
103
- func (rw *RWMutex) RLocker() Locker {
104
- return &rlocker{rw: rw}
105
- }