gofront 1.6.1 → 1.8.0
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.
- package/README.md +45 -49
- package/package.json +12 -8
- package/src/backend/js/expressions.js +1627 -148
- package/src/backend/js/fmt-runtime.js +573 -0
- package/src/backend/js/index.js +508 -102
- package/src/backend/js/runtime.js +1997 -106
- package/src/backend/js/statements.js +931 -87
- package/src/backend/js/stdlib/bits.js +87 -14
- package/src/backend/js/stdlib/builder.js +41 -6
- package/src/backend/js/stdlib/bytes.js +253 -7
- package/src/backend/js/stdlib/errors.js +7 -1
- package/src/backend/js/stdlib/fmt.js +349 -10
- package/src/backend/js/stdlib/index.js +19 -2
- package/src/backend/js/stdlib/json.js +1167 -0
- package/src/backend/js/stdlib/maps.js +0 -8
- package/src/backend/js/stdlib/math.js +17 -1
- package/src/backend/js/stdlib/simd.js +34 -0
- package/src/backend/js/stdlib/slices.js +36 -6
- package/src/backend/js/stdlib/strconv.js +10 -5
- package/src/backend/js/stdlib/strings.js +83 -4
- package/src/backend/js/stdlib/testing.js +7 -0
- package/src/backend/js/stdlib/time.js +79 -55
- package/src/backend/js/stdlib/unicode.js +1 -1
- package/src/backend/js/stdlib/utf8.js +1 -1
- package/src/backend/js/templ.js +38 -76
- package/src/backend/js/type-info.js +272 -0
- package/src/backend/shared/fmt-types.js +188 -0
- package/src/backend/wasm/boundary.js +446 -72
- package/src/backend/wasm/emit-builtins.js +320 -13
- package/src/backend/wasm/emit-exprs.js +1404 -199
- package/src/backend/wasm/emit-maps.js +61 -13
- package/src/backend/wasm/emit-stmts.js +1359 -164
- package/src/backend/wasm/emit.js +518 -74
- package/src/backend/wasm/encode.js +128 -13
- package/src/backend/wasm/globals.js +452 -0
- package/src/backend/wasm/index.js +194 -2489
- package/src/backend/wasm/method-expr.js +381 -0
- package/src/backend/wasm/module-emitter.js +2240 -0
- package/src/backend/wasm/monomorph.js +62 -4
- package/src/backend/wasm/optimize.js +4 -2
- package/src/backend/wasm/prescan.js +397 -0
- package/src/backend/wasm/stdlib/bytes.js +1804 -127
- package/src/backend/wasm/stdlib/core.js +1574 -199
- package/src/backend/wasm/stdlib/index.js +3 -5
- package/src/backend/wasm/stdlib/io.js +1567 -150
- package/src/backend/wasm/stdlib/packages.js +2 -0
- package/src/backend/wasm/stdlib/simd.js +499 -0
- package/src/backend/wasm/stdlib/time.js +1041 -12
- package/src/backend/wasm/types.js +221 -15
- package/src/backend/wasm/variadic.js +93 -0
- package/src/backend/wasm/wat.js +84 -20
- package/src/{cli-core.js → cli/cli-core.js} +236 -10
- package/src/{test-runner.js → cli/test-runner.js} +332 -39
- package/src/{vendor.js → cli/vendor.js} +89 -15
- package/src/compiler.js +107 -269
- package/src/dts-parser.js +71 -14
- package/src/index.js +15 -169
- package/src/{lexer.js → lexer/lexer.js} +102 -55
- package/src/{tokens.js → lexer/tokens.js} +1 -0
- package/src/link/sourcemap.js +97 -0
- package/src/link/stdlib.js +515 -0
- package/src/link/wasm.js +294 -0
- package/src/lower/bounds.js +394 -0
- package/src/lower/boxing.js +1 -6
- package/src/lower/captures.js +176 -32
- package/src/lower/embedding.js +2 -1
- package/src/lower/index.js +26 -18
- package/src/lower/json-codecs.js +1398 -0
- package/src/lower/ownership.js +22 -1
- package/src/lower/range.js +86 -1
- package/src/lower/reachability.js +132 -0
- package/src/parser/declarations.js +58 -13
- package/src/parser/expressions.js +29 -7
- package/src/parser/index.js +2 -1
- package/src/parser/statements.js +37 -22
- package/src/parser/struct-tag.js +144 -0
- package/src/{templ-parser.js → parser/templ.js} +138 -15
- package/src/parser/types.js +130 -13
- package/src/resolver.js +22 -1
- package/src/typechecker/assignability.js +215 -11
- package/src/typechecker/const-fold.js +356 -0
- package/src/typechecker/constants.js +256 -0
- package/src/typechecker/expressions.js +960 -99
- package/src/typechecker/index.js +491 -72
- package/src/typechecker/init-order.js +330 -0
- package/src/typechecker/resolve.js +596 -52
- package/src/typechecker/statements.js +157 -17
- package/src/typechecker/stdlib/core.js +333 -55
- package/src/typechecker/stdlib/excluded.js +898 -0
- package/src/typechecker/stdlib/extended.js +359 -26
- package/src/typechecker/{stdlib.js → stdlib/index.js} +6 -4
- package/src/typechecker/stdlib/simd.js +123 -0
- package/src/typechecker/termination.js +1 -1
- package/src/typechecker/types.js +165 -26
- package/stdlib/bytes/iter.go +192 -0
- package/stdlib/bytes/search.go +240 -0
- package/stdlib/bytes/split.go +218 -0
- package/stdlib/cmp/cmp.go +65 -0
- package/stdlib/encoding/json/errors.go +31 -0
- package/stdlib/encoding/json/indent.go +71 -0
- package/stdlib/encoding/json/number.go +12 -0
- package/stdlib/encoding/json/stream.go +173 -0
- package/stdlib/errors/overlay.go +12 -0
- package/stdlib/hash/hash.go +53 -0
- package/stdlib/internal/jsonrt/dec.go +738 -0
- package/stdlib/internal/jsonrt/enc.go +366 -0
- package/stdlib/internal/jsonrt/indent.go +135 -0
- package/stdlib/internal/jsonrt/number.go +27 -0
- package/stdlib/internal/jsonrt/reader.go +73 -0
- package/stdlib/internal/jsonrt/scanner.go +649 -0
- package/stdlib/io/io.go +346 -0
- package/stdlib/iter/iter.go +18 -0
- package/stdlib/maps/iter.go +65 -0
- package/stdlib/math/extra.go +270 -0
- package/stdlib/slices/extra.go +73 -0
- package/stdlib/slices/iter.go +113 -0
- package/stdlib/sort/sort.go +561 -0
- package/stdlib/strconv/quote.go +341 -0
- package/stdlib/strings/extra.go +35 -0
- package/stdlib/strings/iter.go +122 -0
- package/stdlib/sync/extra.go +105 -0
- package/stdlib/unicode/unicode.go +112 -0
- package/stdlib/unicode/utf8/bytes.go +239 -0
- package/src/backend/wasm/const-fold.js +0 -205
- package/src/backend/wasm/emit-stdlib.js +0 -13
- /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
- /package/src/{colors.js → cli/colors.js} +0 -0
- /package/src/{dev-server.js → cli/dev-server.js} +0 -0
- /package/src/{minifier.js → cli/minifier.js} +0 -0
- /package/src/{project-config.js → cli/project-config.js} +0 -0
- /package/src/{pwa.js → cli/pwa.js} +0 -0
- /package/src/{templ-lexer.js → lexer/templ-lexer.js} +0 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
package strconv
|
|
6
|
+
|
|
7
|
+
import (
|
|
8
|
+
"unicode"
|
|
9
|
+
"unicode/utf8"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// IntSize is the size in bits of an int or uint value.
|
|
13
|
+
const IntSize = 64
|
|
14
|
+
|
|
15
|
+
const lowerhex = "0123456789abcdef"
|
|
16
|
+
|
|
17
|
+
// A NumError records a failed conversion.
|
|
18
|
+
type NumError struct {
|
|
19
|
+
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat, ParseComplex)
|
|
20
|
+
Num string // the input
|
|
21
|
+
Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func (e *NumError) Error() string {
|
|
25
|
+
return "strconv." + e.Func + ": parsing " + Quote(e.Num) + ": " + e.Err.Error()
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
func (e *NumError) Unwrap() error { return e.Err }
|
|
29
|
+
|
|
30
|
+
// IsPrint reports whether the rune is defined as printable by Go, with
|
|
31
|
+
// the same definition as unicode.IsPrint: letters, numbers, punctuation,
|
|
32
|
+
// symbols and ASCII space.
|
|
33
|
+
func IsPrint(r rune) bool {
|
|
34
|
+
if 0x20 <= r && r <= 0x7E {
|
|
35
|
+
return true
|
|
36
|
+
}
|
|
37
|
+
return unicode.IsPrint(r)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// IsGraphic reports whether the rune is defined as a Graphic by Unicode.
|
|
41
|
+
func IsGraphic(r rune) bool {
|
|
42
|
+
if 0x20 <= r && r <= 0x7E {
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
return unicode.IsGraphic(r)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func quoteWith(s string, quote byte, ASCIIonly, graphicOnly bool) string {
|
|
49
|
+
return string(appendQuotedWith(make([]byte, 0, 3*len(s)/2), s, quote, ASCIIonly, graphicOnly))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func quoteRuneWith(r rune, quote byte, ASCIIonly, graphicOnly bool) string {
|
|
53
|
+
return string(appendQuotedRuneWith(nil, r, quote, ASCIIonly, graphicOnly))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
func hexDigit(v int) byte {
|
|
57
|
+
return byte(lowerhex[v&0xF])
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func appendQuotedWith(buf []byte, s string, quote byte, ASCIIonly, graphicOnly bool) []byte {
|
|
61
|
+
buf = append(buf, quote)
|
|
62
|
+
for len(s) > 0 {
|
|
63
|
+
r, width := utf8.DecodeRuneInString(s)
|
|
64
|
+
if width == 1 && r == utf8.RuneError {
|
|
65
|
+
b0 := int(byte(s[0]))
|
|
66
|
+
buf = append(buf, byte('\\'), byte('x'), hexDigit(b0>>4), hexDigit(b0))
|
|
67
|
+
s = s[1:]
|
|
68
|
+
continue
|
|
69
|
+
}
|
|
70
|
+
buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly)
|
|
71
|
+
s = s[width:]
|
|
72
|
+
}
|
|
73
|
+
buf = append(buf, quote)
|
|
74
|
+
return buf
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
func appendQuotedRuneWith(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte {
|
|
78
|
+
buf = append(buf, quote)
|
|
79
|
+
if !utf8.ValidRune(r) {
|
|
80
|
+
r = utf8.RuneError
|
|
81
|
+
}
|
|
82
|
+
buf = appendEscapedRune(buf, r, quote, ASCIIonly, graphicOnly)
|
|
83
|
+
buf = append(buf, quote)
|
|
84
|
+
return buf
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
func appendEscapedRune(buf []byte, r rune, quote byte, ASCIIonly, graphicOnly bool) []byte {
|
|
88
|
+
if r == rune(quote) || r == '\\' {
|
|
89
|
+
buf = append(buf, byte('\\'), byte(r))
|
|
90
|
+
return buf
|
|
91
|
+
}
|
|
92
|
+
if ASCIIonly {
|
|
93
|
+
if r < utf8.RuneSelf && IsPrint(r) {
|
|
94
|
+
buf = append(buf, byte(r))
|
|
95
|
+
return buf
|
|
96
|
+
}
|
|
97
|
+
} else if IsPrint(r) || (graphicOnly && IsGraphic(r)) {
|
|
98
|
+
return utf8.AppendRune(buf, r)
|
|
99
|
+
}
|
|
100
|
+
switch r {
|
|
101
|
+
case '\a':
|
|
102
|
+
buf = append(buf, byte('\\'), byte('a'))
|
|
103
|
+
case '\b':
|
|
104
|
+
buf = append(buf, byte('\\'), byte('b'))
|
|
105
|
+
case '\f':
|
|
106
|
+
buf = append(buf, byte('\\'), byte('f'))
|
|
107
|
+
case '\n':
|
|
108
|
+
buf = append(buf, byte('\\'), byte('n'))
|
|
109
|
+
case '\r':
|
|
110
|
+
buf = append(buf, byte('\\'), byte('r'))
|
|
111
|
+
case '\t':
|
|
112
|
+
buf = append(buf, byte('\\'), byte('t'))
|
|
113
|
+
case '\v':
|
|
114
|
+
buf = append(buf, byte('\\'), byte('v'))
|
|
115
|
+
default:
|
|
116
|
+
switch {
|
|
117
|
+
case r < ' ' || r == 0x7f:
|
|
118
|
+
br := int(r)
|
|
119
|
+
buf = append(buf, byte('\\'), byte('x'), hexDigit(br>>4), hexDigit(br))
|
|
120
|
+
case !utf8.ValidRune(r):
|
|
121
|
+
r = 0xFFFD
|
|
122
|
+
buf = append(buf, byte('\\'), byte('u'))
|
|
123
|
+
for s := 12; s >= 0; s -= 4 {
|
|
124
|
+
buf = append(buf, hexDigit(int(r>>uint(s))))
|
|
125
|
+
}
|
|
126
|
+
case r < 0x10000:
|
|
127
|
+
buf = append(buf, byte('\\'), byte('u'))
|
|
128
|
+
for s := 12; s >= 0; s -= 4 {
|
|
129
|
+
buf = append(buf, hexDigit(int(r>>uint(s))))
|
|
130
|
+
}
|
|
131
|
+
default:
|
|
132
|
+
buf = append(buf, byte('\\'), byte('U'))
|
|
133
|
+
for s := 28; s >= 0; s -= 4 {
|
|
134
|
+
buf = append(buf, hexDigit(int(r>>uint(s))))
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return buf
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// QuoteRune returns a single-quoted Go character literal representing the rune.
|
|
142
|
+
func QuoteRune(r rune) string {
|
|
143
|
+
return quoteRuneWith(r, byte('\''), false, false)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// QuoteToASCII returns a double-quoted Go string literal representing s using ASCII escapes.
|
|
147
|
+
func QuoteToASCII(s string) string {
|
|
148
|
+
return quoteWith(s, byte('"'), true, false)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// QuoteRuneToASCII returns a single-quoted Go character literal representing the rune using ASCII escapes.
|
|
152
|
+
func QuoteRuneToASCII(r rune) string {
|
|
153
|
+
return quoteRuneWith(r, byte('\''), true, false)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// AppendQuote appends a double-quoted Go string literal representing s to dst.
|
|
157
|
+
func AppendQuote(dst []byte, s string) []byte {
|
|
158
|
+
return appendQuotedWith(dst, s, byte('"'), false, false)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// AppendQuoteToASCII appends a double-quoted Go string literal representing s using ASCII escapes to dst.
|
|
162
|
+
func AppendQuoteToASCII(dst []byte, s string) []byte {
|
|
163
|
+
return appendQuotedWith(dst, s, byte('"'), true, false)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// AppendQuoteRune appends a single-quoted Go character literal representing the rune to dst.
|
|
167
|
+
func AppendQuoteRune(dst []byte, r rune) []byte {
|
|
168
|
+
return appendQuotedRuneWith(dst, r, byte('\''), false, false)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// AppendQuoteRuneToASCII appends a single-quoted Go character literal representing the rune using ASCII escapes to dst.
|
|
172
|
+
func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
|
|
173
|
+
return appendQuotedRuneWith(dst, r, byte('\''), true, false)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// CanBackquote reports whether the string s can be represented unchanged as a single-line backquoted string.
|
|
177
|
+
func CanBackquote(s string) bool {
|
|
178
|
+
for len(s) > 0 {
|
|
179
|
+
r, wid := utf8.DecodeRuneInString(s)
|
|
180
|
+
s = s[wid:]
|
|
181
|
+
if wid > 1 {
|
|
182
|
+
if r == '\ufeff' {
|
|
183
|
+
return false
|
|
184
|
+
}
|
|
185
|
+
continue
|
|
186
|
+
}
|
|
187
|
+
if r == utf8.RuneError {
|
|
188
|
+
return false
|
|
189
|
+
}
|
|
190
|
+
if (r < ' ' && r != '\t') || r == '`' || r == '\u007F' {
|
|
191
|
+
return false
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return true
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
func unhex(b byte) (rune, bool) {
|
|
198
|
+
switch {
|
|
199
|
+
case byte('0') <= b && b <= byte('9'):
|
|
200
|
+
return rune(b - byte('0')), true
|
|
201
|
+
case byte('a') <= b && b <= byte('f'):
|
|
202
|
+
return rune(b - byte('a') + 10), true
|
|
203
|
+
case byte('A') <= b && b <= byte('F'):
|
|
204
|
+
return rune(b - byte('A') + 10), true
|
|
205
|
+
}
|
|
206
|
+
return 0, false
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
func unquoteHex(c byte, s string) (rune, bool, string, error) {
|
|
210
|
+
n := 0
|
|
211
|
+
switch c {
|
|
212
|
+
case byte('x'):
|
|
213
|
+
n = 2
|
|
214
|
+
case byte('u'):
|
|
215
|
+
n = 4
|
|
216
|
+
case byte('U'):
|
|
217
|
+
n = 8
|
|
218
|
+
}
|
|
219
|
+
if len(s) < n {
|
|
220
|
+
return 0, false, "", ErrSyntax
|
|
221
|
+
}
|
|
222
|
+
var v rune
|
|
223
|
+
for j := 0; j < n; j++ {
|
|
224
|
+
x, ok := unhex(byte(s[j]))
|
|
225
|
+
if !ok {
|
|
226
|
+
return 0, false, "", ErrSyntax
|
|
227
|
+
}
|
|
228
|
+
v = v<<4 | x
|
|
229
|
+
}
|
|
230
|
+
s = s[n:]
|
|
231
|
+
if c == byte('x') {
|
|
232
|
+
return v, false, s, nil
|
|
233
|
+
}
|
|
234
|
+
if !utf8.ValidRune(v) {
|
|
235
|
+
return 0, false, "", ErrSyntax
|
|
236
|
+
}
|
|
237
|
+
return v, true, s, nil
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
func unquoteOctal(c byte, s string) (rune, string, error) {
|
|
241
|
+
v := rune(c - byte('0'))
|
|
242
|
+
if len(s) < 2 {
|
|
243
|
+
return 0, "", ErrSyntax
|
|
244
|
+
}
|
|
245
|
+
for j := 0; j < 2; j++ {
|
|
246
|
+
b := byte(s[j])
|
|
247
|
+
if b < byte('0') || b > byte('7') {
|
|
248
|
+
return 0, "", ErrSyntax
|
|
249
|
+
}
|
|
250
|
+
v = (v << 3) | rune(b-byte('0'))
|
|
251
|
+
}
|
|
252
|
+
if v > 255 {
|
|
253
|
+
return 0, "", ErrSyntax
|
|
254
|
+
}
|
|
255
|
+
return v, s[2:], nil
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// UnquoteChar decodes the first character or byte in the escaped string or character literal represented by s.
|
|
259
|
+
func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error) {
|
|
260
|
+
if len(s) == 0 {
|
|
261
|
+
return 0, false, "", ErrSyntax
|
|
262
|
+
}
|
|
263
|
+
c := byte(s[0])
|
|
264
|
+
if c == quote && (quote == byte('\'') || quote == byte('"')) {
|
|
265
|
+
return 0, false, "", ErrSyntax
|
|
266
|
+
}
|
|
267
|
+
if rune(c) >= utf8.RuneSelf {
|
|
268
|
+
r, size := utf8.DecodeRuneInString(s)
|
|
269
|
+
return r, true, s[size:], nil
|
|
270
|
+
}
|
|
271
|
+
if c != byte('\\') {
|
|
272
|
+
return rune(c), false, s[1:], nil
|
|
273
|
+
}
|
|
274
|
+
if len(s) <= 1 {
|
|
275
|
+
return 0, false, "", ErrSyntax
|
|
276
|
+
}
|
|
277
|
+
esc := byte(s[1])
|
|
278
|
+
s = s[2:]
|
|
279
|
+
switch esc {
|
|
280
|
+
case byte('a'):
|
|
281
|
+
return '\a', false, s, nil
|
|
282
|
+
case byte('b'):
|
|
283
|
+
return '\b', false, s, nil
|
|
284
|
+
case byte('f'):
|
|
285
|
+
return '\f', false, s, nil
|
|
286
|
+
case byte('n'):
|
|
287
|
+
return '\n', false, s, nil
|
|
288
|
+
case byte('r'):
|
|
289
|
+
return '\r', false, s, nil
|
|
290
|
+
case byte('t'):
|
|
291
|
+
return '\t', false, s, nil
|
|
292
|
+
case byte('v'):
|
|
293
|
+
return '\v', false, s, nil
|
|
294
|
+
case byte('x'), byte('u'), byte('U'):
|
|
295
|
+
v, mb, rem, err := unquoteHex(esc, s)
|
|
296
|
+
return v, mb, rem, err
|
|
297
|
+
case byte('0'), byte('1'), byte('2'), byte('3'), byte('4'), byte('5'), byte('6'), byte('7'):
|
|
298
|
+
v, rem, err := unquoteOctal(esc, s)
|
|
299
|
+
return v, false, rem, err
|
|
300
|
+
case byte('\\'):
|
|
301
|
+
return '\\', false, s, nil
|
|
302
|
+
case byte('\''), byte('"'):
|
|
303
|
+
if esc != quote {
|
|
304
|
+
return 0, false, "", ErrSyntax
|
|
305
|
+
}
|
|
306
|
+
return rune(esc), false, s, nil
|
|
307
|
+
default:
|
|
308
|
+
return 0, false, "", ErrSyntax
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// QuotedPrefix returns the quoted string at the prefix of s.
|
|
313
|
+
func QuotedPrefix(s string) (string, error) {
|
|
314
|
+
if len(s) < 2 {
|
|
315
|
+
return "", ErrSyntax
|
|
316
|
+
}
|
|
317
|
+
quote := byte(s[0])
|
|
318
|
+
if quote != byte('"') && quote != byte('\'') && quote != byte('`') {
|
|
319
|
+
return "", ErrSyntax
|
|
320
|
+
}
|
|
321
|
+
if quote == byte('`') {
|
|
322
|
+
for i := 1; i < len(s); i++ {
|
|
323
|
+
if byte(s[i]) == byte('`') {
|
|
324
|
+
return s[:i+1], nil
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return "", ErrSyntax
|
|
328
|
+
}
|
|
329
|
+
rem := s[1:]
|
|
330
|
+
for len(rem) > 0 {
|
|
331
|
+
if byte(rem[0]) == quote {
|
|
332
|
+
return s[:len(s)-len(rem)+1], nil
|
|
333
|
+
}
|
|
334
|
+
_, _, next, err := UnquoteChar(rem, quote)
|
|
335
|
+
if err != nil {
|
|
336
|
+
return "", err
|
|
337
|
+
}
|
|
338
|
+
rem = next
|
|
339
|
+
}
|
|
340
|
+
return "", ErrSyntax
|
|
341
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
package unicode
|
|
6
|
+
|
|
7
|
+
const (
|
|
8
|
+
MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
|
|
9
|
+
ReplacementChar = '\uFFFD' // Represents invalid code points.
|
|
10
|
+
MaxASCII = '\u007F' // maximum ASCII value.
|
|
11
|
+
MaxLatin1 = '\u00FF' // maximum Latin-1 value.
|
|
12
|
+
UpperLower = MaxRune + 1
|
|
13
|
+
Version = "15.0.0"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// ToTitle maps the rune to title case.
|
|
17
|
+
func ToTitle(r rune) rune {
|
|
18
|
+
if r <= MaxASCII {
|
|
19
|
+
if 'a' <= r && r <= 'z' {
|
|
20
|
+
return r - ('a' - 'A')
|
|
21
|
+
}
|
|
22
|
+
return r
|
|
23
|
+
}
|
|
24
|
+
switch r {
|
|
25
|
+
case 0x1C4, 0x1C5, 0x1C6:
|
|
26
|
+
return 0x1C5
|
|
27
|
+
case 0x1C7, 0x1C8, 0x1C9:
|
|
28
|
+
return 0x1C8
|
|
29
|
+
case 0x1CA, 0x1CB, 0x1CC:
|
|
30
|
+
return 0x1CB
|
|
31
|
+
case 0x1F1, 0x1F2, 0x1F3:
|
|
32
|
+
return 0x1F2
|
|
33
|
+
}
|
|
34
|
+
if 0x10D0 <= r && r <= 0x10FF {
|
|
35
|
+
return r
|
|
36
|
+
}
|
|
37
|
+
return rune(ToUpper(int(r)))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type foldPair struct {
|
|
41
|
+
From uint16
|
|
42
|
+
To uint16
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var caseOrbit = []foldPair{
|
|
46
|
+
{0x004B, 0x006B}, {0x0053, 0x0073}, {0x006B, 0x212A}, {0x0073, 0x017F},
|
|
47
|
+
{0x00B5, 0x039C}, {0x00C5, 0x00E5}, {0x00DF, 0x1E9E}, {0x00E5, 0x212B},
|
|
48
|
+
{0x0130, 0x0130}, {0x0131, 0x0131}, {0x017F, 0x0053}, {0x01C4, 0x01C5},
|
|
49
|
+
{0x01C5, 0x01C6}, {0x01C6, 0x01C4}, {0x01C7, 0x01C8}, {0x01C8, 0x01C9},
|
|
50
|
+
{0x01C9, 0x01C7}, {0x01CA, 0x01CB}, {0x01CB, 0x01CC}, {0x01CC, 0x01CA},
|
|
51
|
+
{0x01F1, 0x01F2}, {0x01F2, 0x01F3}, {0x01F3, 0x01F1}, {0x0345, 0x0399},
|
|
52
|
+
{0x0392, 0x03B2}, {0x0395, 0x03B5}, {0x0398, 0x03B8}, {0x0399, 0x03B9},
|
|
53
|
+
{0x039A, 0x03BA}, {0x039C, 0x03BC}, {0x03A0, 0x03C0}, {0x03A1, 0x03C1},
|
|
54
|
+
{0x03A3, 0x03C2}, {0x03A6, 0x03C6}, {0x03A9, 0x03C9}, {0x03B2, 0x03D0},
|
|
55
|
+
{0x03B5, 0x03F5}, {0x03B8, 0x03D1}, {0x03B9, 0x1FBE}, {0x03BA, 0x03F0},
|
|
56
|
+
{0x03BC, 0x00B5}, {0x03C0, 0x03D6}, {0x03C1, 0x03F1}, {0x03C2, 0x03C3},
|
|
57
|
+
{0x03C3, 0x03A3}, {0x03C6, 0x03D5}, {0x03C9, 0x2126}, {0x03D0, 0x0392},
|
|
58
|
+
{0x03D1, 0x03F4}, {0x03D5, 0x03A6}, {0x03D6, 0x03A0}, {0x03F0, 0x039A},
|
|
59
|
+
{0x03F1, 0x03A1}, {0x03F4, 0x0398}, {0x03F5, 0x0395}, {0x0412, 0x0432},
|
|
60
|
+
{0x0414, 0x0434}, {0x041E, 0x043E}, {0x0421, 0x0441}, {0x0422, 0x0442},
|
|
61
|
+
{0x042A, 0x044A}, {0x0432, 0x1C80}, {0x0434, 0x1C81}, {0x043E, 0x1C82},
|
|
62
|
+
{0x0441, 0x1C83}, {0x0442, 0x1C84}, {0x044A, 0x1C86}, {0x0462, 0x0463},
|
|
63
|
+
{0x0463, 0x1C87}, {0x1C80, 0x0412}, {0x1C81, 0x0414}, {0x1C82, 0x041E},
|
|
64
|
+
{0x1C83, 0x0421}, {0x1C84, 0x1C85}, {0x1C85, 0x0422}, {0x1C86, 0x042A},
|
|
65
|
+
{0x1C87, 0x0462}, {0x1C88, 0xA64A}, {0x1E60, 0x1E61}, {0x1E61, 0x1E9B},
|
|
66
|
+
{0x1E9B, 0x1E60}, {0x1E9E, 0x00DF}, {0x1FBE, 0x0345}, {0x2126, 0x03A9},
|
|
67
|
+
{0x212A, 0x004B}, {0x212B, 0x00C5}, {0xA64A, 0xA64B}, {0xA64B, 0x1C88},
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func foldASCII(r rune) (rune, bool) {
|
|
71
|
+
if 'a' <= r && r <= 'z' {
|
|
72
|
+
if r != 'k' && r != 's' {
|
|
73
|
+
return r - ('a' - 'A'), true
|
|
74
|
+
}
|
|
75
|
+
} else if 'A' <= r && r <= 'Z' {
|
|
76
|
+
if r != 'K' && r != 'S' {
|
|
77
|
+
return r + ('a' - 'A'), true
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
return r, true
|
|
81
|
+
}
|
|
82
|
+
return r, false
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// SimpleFold iterates over Unicode code points equivalent under simple case folding.
|
|
86
|
+
func SimpleFold(r rune) rune {
|
|
87
|
+
if r < 0 || r > MaxRune {
|
|
88
|
+
return r
|
|
89
|
+
}
|
|
90
|
+
if r < 128 {
|
|
91
|
+
if folded, ok := foldASCII(r); ok {
|
|
92
|
+
return folded
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
lo := 0
|
|
96
|
+
hi := len(caseOrbit)
|
|
97
|
+
for lo < hi {
|
|
98
|
+
m := int(uint(lo+hi) >> 1)
|
|
99
|
+
if rune(caseOrbit[m].From) < r {
|
|
100
|
+
lo = m + 1
|
|
101
|
+
} else {
|
|
102
|
+
hi = m
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if lo < len(caseOrbit) && rune(caseOrbit[lo].From) == r {
|
|
106
|
+
return rune(caseOrbit[lo].To)
|
|
107
|
+
}
|
|
108
|
+
if l := rune(ToLower(int(r))); l != r {
|
|
109
|
+
return l
|
|
110
|
+
}
|
|
111
|
+
return rune(ToUpper(int(r)))
|
|
112
|
+
}
|