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.
- package/README.md +3 -3
- package/package.json +6 -5
- package/src/backend/js/expressions.js +1157 -408
- package/src/backend/js/index.js +327 -153
- package/src/backend/js/natives.js +383 -0
- package/src/backend/js/runtime.js +559 -2552
- package/src/backend/js/statements.js +670 -158
- package/src/backend/js/stdlib/index.js +45 -93
- package/src/backend/js/templ.js +32 -45
- package/src/backend/js/type-info.js +298 -19
- package/src/backend/shared/fixed-float.js +20 -0
- package/src/backend/shared/fmt-types.js +91 -170
- package/src/backend/shared/host-unicode.js +36 -0
- package/src/backend/wasm/boundary.js +490 -965
- package/src/backend/wasm/emit-builtins.js +884 -256
- package/src/backend/wasm/emit-exprs.js +185 -77
- package/src/backend/wasm/emit-maps.js +17 -367
- package/src/backend/wasm/emit-shared.js +4 -1
- package/src/backend/wasm/emit-stmts.js +524 -240
- package/src/backend/wasm/emit.js +176 -38
- package/src/backend/wasm/globals.js +48 -8
- package/src/backend/wasm/glue.js +2 -4
- package/src/backend/wasm/index.js +44 -530
- package/src/backend/wasm/method-expr.js +12 -1
- package/src/backend/wasm/module-emitter.js +299 -770
- package/src/backend/wasm/monomorph.js +139 -8
- package/src/backend/wasm/natives.js +600 -0
- package/src/backend/wasm/prescan.js +5 -153
- package/src/backend/wasm/prune-funcs.js +89 -0
- package/src/backend/wasm/stdlib/index.js +2 -32
- package/src/backend/wasm/types.js +97 -20
- package/src/backend/wasm/variadic.js +9 -4
- package/src/cli/cli-core.js +5 -1
- package/src/cli/test-runner.js +115 -342
- package/src/compiler.js +113 -130
- package/src/lexer/lexer.js +106 -11
- package/src/lexer/templ-lexer.js +61 -18
- package/src/lexer/tokens.js +1 -0
- package/src/link/stdlib.js +355 -132
- package/src/link/type-names.js +204 -0
- package/src/link/wasm.js +30 -6
- package/src/lower/bounds.js +153 -0
- package/src/lower/captures.js +92 -33
- package/src/lower/embedding.js +62 -5
- package/src/lower/errors-as.js +196 -0
- package/src/lower/fmt-formatters.js +929 -0
- package/src/lower/functions.js +225 -7
- package/src/lower/gen-types.js +293 -0
- package/src/lower/index.js +14 -2
- package/src/lower/json-codecs.js +334 -245
- package/src/lower/ownership.js +25 -7
- package/src/lower/reachability.js +69 -51
- package/src/lower/walk.js +12 -0
- package/src/parser/declarations.js +30 -5
- package/src/parser/expressions.js +111 -57
- package/src/parser/statements.js +108 -0
- package/src/parser/templ.js +44 -5
- package/src/parser/types.js +12 -0
- package/src/resolver.js +1 -2
- package/src/typechecker/assignability.js +214 -19
- package/src/typechecker/const-fold.js +70 -27
- package/src/typechecker/constants.js +156 -8
- package/src/typechecker/expressions.js +490 -108
- package/src/typechecker/index.js +346 -42
- package/src/typechecker/init-order.js +136 -40
- package/src/typechecker/operand-text.js +41 -0
- package/src/typechecker/resolve.js +490 -65
- package/src/typechecker/statements.js +288 -27
- package/src/typechecker/stdlib/excluded.js +9 -5
- package/src/typechecker/stdlib/index.js +25 -9
- package/src/typechecker/termination.js +10 -1
- package/src/typechecker/types.js +287 -575
- package/stdlib/bytes/buffer.go +479 -0
- package/stdlib/bytes/bytes.go +1010 -0
- package/stdlib/bytes/reader.go +161 -0
- package/stdlib/context/context.go +115 -0
- package/stdlib/crypto/rand/rand.go +34 -0
- package/stdlib/crypto/sha256/sha256.go +249 -0
- package/stdlib/encoding/base64/base64.go +331 -0
- package/stdlib/encoding/binary/binary.go +332 -0
- package/stdlib/encoding/hex/hex.go +140 -0
- package/stdlib/encoding/json/json.go +62 -0
- package/stdlib/errors/errors.go +174 -0
- package/stdlib/fmt/errors.go +110 -0
- package/stdlib/fmt/format.go +732 -0
- package/stdlib/fmt/print.go +1232 -0
- package/stdlib/gom/gom.go +293 -0
- package/stdlib/html/html.go +251 -0
- package/stdlib/internal/fmtrt/fmtrt.go +163 -0
- package/stdlib/internal/jsonrt/dec.go +171 -38
- package/stdlib/internal/jsonrt/enc.go +186 -36
- package/stdlib/internal/jsonrt/scanner.go +17 -8
- package/stdlib/io/io.go +157 -1
- package/stdlib/maps/maps.go +131 -0
- package/stdlib/math/bits/bits.go +507 -0
- package/stdlib/math/extra.go +16 -14
- package/stdlib/math/math.go +439 -0
- package/stdlib/math/rand/rand.go +297 -0
- package/stdlib/os/os.go +93 -0
- package/stdlib/path/filepath/filepath.go +47 -0
- package/stdlib/path/path.go +394 -0
- package/stdlib/regexp/regexp.go +231 -0
- package/stdlib/slices/slices.go +526 -0
- package/stdlib/slices/sort.go +209 -0
- package/stdlib/slices/zsort_cmp.go +480 -0
- package/stdlib/slices/zsort_ordered.go +482 -0
- package/stdlib/sort/sort.go +391 -452
- package/stdlib/sort/zsort_func.go +480 -0
- package/stdlib/sort/zsort_iface.go +480 -0
- package/stdlib/strconv/float.go +1699 -0
- package/stdlib/strconv/isprint.go +752 -0
- package/stdlib/strconv/quote.go +235 -50
- package/stdlib/strconv/strconv.go +616 -0
- package/stdlib/strings/builder.go +95 -0
- package/stdlib/strings/reader.go +163 -0
- package/stdlib/strings/replacer.go +102 -0
- package/stdlib/strings/strings.go +807 -0
- package/stdlib/sync/sync.go +268 -0
- package/stdlib/testing/async_js.go +61 -0
- package/stdlib/testing/benchmark.go +297 -0
- package/stdlib/testing/testing.go +523 -0
- package/stdlib/time/duration.go +233 -0
- package/stdlib/time/format.go +745 -0
- package/stdlib/time/parse.go +790 -0
- package/stdlib/time/sleep_js.go +63 -0
- package/stdlib/time/time.go +834 -0
- package/stdlib/unicode/unicode.go +141 -3
- package/stdlib/unicode/utf8/utf8.go +464 -0
- package/src/backend/js/fmt-runtime.js +0 -573
- package/src/backend/js/stdlib/base64.js +0 -12
- package/src/backend/js/stdlib/binary.js +0 -102
- package/src/backend/js/stdlib/bits.js +0 -119
- package/src/backend/js/stdlib/builder.js +0 -98
- package/src/backend/js/stdlib/bytes.js +0 -368
- package/src/backend/js/stdlib/errors.js +0 -45
- package/src/backend/js/stdlib/fmt.js +0 -517
- package/src/backend/js/stdlib/gom.js +0 -155
- package/src/backend/js/stdlib/hex.js +0 -17
- package/src/backend/js/stdlib/html.js +0 -20
- package/src/backend/js/stdlib/io.js +0 -137
- package/src/backend/js/stdlib/json.js +0 -1167
- package/src/backend/js/stdlib/maps.js +0 -37
- package/src/backend/js/stdlib/math.js +0 -85
- package/src/backend/js/stdlib/os.js +0 -13
- package/src/backend/js/stdlib/path.js +0 -48
- package/src/backend/js/stdlib/rand.js +0 -32
- package/src/backend/js/stdlib/regexp.js +0 -54
- package/src/backend/js/stdlib/sha256.js +0 -12
- package/src/backend/js/stdlib/shared.js +0 -17
- package/src/backend/js/stdlib/simd.js +0 -34
- package/src/backend/js/stdlib/slices.js +0 -107
- package/src/backend/js/stdlib/sort.js +0 -30
- package/src/backend/js/stdlib/strconv.js +0 -79
- package/src/backend/js/stdlib/strings.js +0 -301
- package/src/backend/js/stdlib/sync.js +0 -13
- package/src/backend/js/stdlib/testing.js +0 -41
- package/src/backend/js/stdlib/time.js +0 -152
- package/src/backend/js/stdlib/unicode.js +0 -25
- package/src/backend/js/stdlib/utf8.js +0 -26
- package/src/backend/wasm/stdlib/bytes.js +0 -6716
- package/src/backend/wasm/stdlib/core.js +0 -10278
- package/src/backend/wasm/stdlib/io.js +0 -3578
- package/src/backend/wasm/stdlib/packages.js +0 -2402
- package/src/backend/wasm/stdlib/pure.js +0 -720
- package/src/backend/wasm/stdlib/time.js +0 -2229
- package/src/typechecker/stdlib/core.js +0 -1079
- package/src/typechecker/stdlib/extended.js +0 -1210
- package/stdlib/bytes/iter.go +0 -192
- package/stdlib/bytes/search.go +0 -240
- package/stdlib/bytes/split.go +0 -218
- package/stdlib/errors/overlay.go +0 -12
- package/stdlib/maps/iter.go +0 -65
- package/stdlib/slices/extra.go +0 -73
- package/stdlib/slices/iter.go +0 -113
- package/stdlib/strings/extra.go +0 -35
- package/stdlib/strings/iter.go +0 -122
- package/stdlib/sync/extra.go +0 -105
- package/stdlib/unicode/utf8/bytes.go +0 -239
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Package strconv implements conversions to and from string representations
|
|
6
|
+
// of basic data types, written in Go over the real package's algorithms.
|
|
7
|
+
// Float formatting and parsing keep a host fast path as natives.
|
|
8
|
+
package strconv
|
|
9
|
+
|
|
10
|
+
import (
|
|
11
|
+
"errors"
|
|
12
|
+
"math/bits"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// IntSize is the size in bits of an int or uint value.
|
|
16
|
+
const IntSize = 64
|
|
17
|
+
|
|
18
|
+
const maxUint64 = 1<<64 - 1
|
|
19
|
+
|
|
20
|
+
// ErrRange indicates that a value is out of range for the target type.
|
|
21
|
+
var ErrRange = errors.New("value out of range")
|
|
22
|
+
|
|
23
|
+
// ErrSyntax indicates that a value does not have the right syntax for the target type.
|
|
24
|
+
var ErrSyntax = errors.New("invalid syntax")
|
|
25
|
+
|
|
26
|
+
// A NumError records a failed conversion.
|
|
27
|
+
type NumError struct {
|
|
28
|
+
Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat, ParseComplex)
|
|
29
|
+
Num string // the input
|
|
30
|
+
Err error // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func (e *NumError) Error() string {
|
|
34
|
+
return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
func (e *NumError) Unwrap() error { return e.Err }
|
|
38
|
+
|
|
39
|
+
func syntaxError(fn, str string) *NumError {
|
|
40
|
+
return &NumError{fn, str, ErrSyntax}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func rangeError(fn, str string) *NumError {
|
|
44
|
+
return &NumError{fn, str, ErrRange}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func baseError(fn, str string, base int) *NumError {
|
|
48
|
+
return &NumError{fn, str, errors.New("invalid base " + Itoa(base))}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func bitSizeError(fn, str string, bitSize int) *NumError {
|
|
52
|
+
return &NumError{fn, str, errors.New("invalid bit size " + Itoa(bitSize))}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The parsers report one of these codes; toError turns it into the
|
|
56
|
+
// *NumError the package's API promises.
|
|
57
|
+
type parseCode int
|
|
58
|
+
|
|
59
|
+
const (
|
|
60
|
+
codeNone parseCode = iota
|
|
61
|
+
codeRange
|
|
62
|
+
codeSyntax
|
|
63
|
+
codeBase
|
|
64
|
+
codeBitSize
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
func toError(fn, s string, base, bitSize int, code parseCode) error {
|
|
68
|
+
switch code {
|
|
69
|
+
case codeNone:
|
|
70
|
+
return nil
|
|
71
|
+
case codeSyntax:
|
|
72
|
+
return syntaxError(fn, s)
|
|
73
|
+
case codeRange:
|
|
74
|
+
return rangeError(fn, s)
|
|
75
|
+
case codeBase:
|
|
76
|
+
return baseError(fn, s, base)
|
|
77
|
+
case codeBitSize:
|
|
78
|
+
return bitSizeError(fn, s, bitSize)
|
|
79
|
+
}
|
|
80
|
+
return nil
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ParseBool returns the boolean value represented by the string.
|
|
84
|
+
// It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False.
|
|
85
|
+
// Any other value returns an error.
|
|
86
|
+
func ParseBool(str string) (bool, error) {
|
|
87
|
+
switch str {
|
|
88
|
+
case "1", "t", "T", "true", "TRUE", "True":
|
|
89
|
+
return true, nil
|
|
90
|
+
case "0", "f", "F", "false", "FALSE", "False":
|
|
91
|
+
return false, nil
|
|
92
|
+
}
|
|
93
|
+
return false, syntaxError("ParseBool", str)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// FormatBool returns "true" or "false" according to the value of b.
|
|
97
|
+
func FormatBool(b bool) string {
|
|
98
|
+
if b {
|
|
99
|
+
return "true"
|
|
100
|
+
}
|
|
101
|
+
return "false"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// AppendBool appends "true" or "false", according to the value of b,
|
|
105
|
+
// to dst and returns the extended buffer.
|
|
106
|
+
func AppendBool(dst []byte, b bool) []byte {
|
|
107
|
+
if b {
|
|
108
|
+
return append(dst, "true"...)
|
|
109
|
+
}
|
|
110
|
+
return append(dst, "false"...)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// lower(c) is a lower-case letter if and only if
|
|
114
|
+
// c is either that lower-case letter or the equivalent upper-case letter.
|
|
115
|
+
// Instead of writing c == 'x' || c == 'X' one can write lower(c) == 'x'.
|
|
116
|
+
// Note that lower of non-letters can produce other non-letters.
|
|
117
|
+
func lowerS(c byte) byte {
|
|
118
|
+
return c | ('x' - 'X')
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
func lower(c byte) byte {
|
|
122
|
+
return c | ('x' - 'X')
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ParseUint is like [ParseInt] but for unsigned numbers.
|
|
126
|
+
//
|
|
127
|
+
// A sign prefix is not permitted.
|
|
128
|
+
func ParseUint(s string, base int, bitSize int) (uint64, error) {
|
|
129
|
+
x, code := parseUint(s, base, bitSize)
|
|
130
|
+
if code != codeNone {
|
|
131
|
+
return x, toError("ParseUint", s, base, bitSize, code)
|
|
132
|
+
}
|
|
133
|
+
return x, nil
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ParseInt interprets a string s in the given base (0, 2 to 36) and
|
|
137
|
+
// bit size (0 to 64) and returns the corresponding value i.
|
|
138
|
+
//
|
|
139
|
+
// The string may begin with a leading sign: "+" or "-".
|
|
140
|
+
//
|
|
141
|
+
// If the base argument is 0, the true base is implied by the string's
|
|
142
|
+
// prefix following the sign (if present): 2 for "0b", 8 for "0" or "0o",
|
|
143
|
+
// 16 for "0x", and 10 otherwise. Also, for argument base 0 only,
|
|
144
|
+
// underscore characters are permitted as defined by the Go syntax for
|
|
145
|
+
// integer literals.
|
|
146
|
+
//
|
|
147
|
+
// The bitSize argument specifies the integer type
|
|
148
|
+
// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
|
|
149
|
+
// correspond to int, int8, int16, int32, and int64.
|
|
150
|
+
// If bitSize is below 0 or above 64, an error is returned.
|
|
151
|
+
//
|
|
152
|
+
// The errors that ParseInt returns have concrete type [*NumError]
|
|
153
|
+
// and include err.Num = s. If s is empty or contains invalid
|
|
154
|
+
// digits, err.Err = [ErrSyntax] and the returned value is 0;
|
|
155
|
+
// if the value corresponding to s cannot be represented by a
|
|
156
|
+
// signed integer of the given size, err.Err = [ErrRange] and the
|
|
157
|
+
// returned value is the maximum magnitude integer of the
|
|
158
|
+
// appropriate bitSize and sign.
|
|
159
|
+
func ParseInt(s string, base int, bitSize int) (i int64, err error) {
|
|
160
|
+
x, code := parseInt(s, base, bitSize)
|
|
161
|
+
if code != codeNone {
|
|
162
|
+
return x, toError("ParseInt", s, base, bitSize, code)
|
|
163
|
+
}
|
|
164
|
+
return x, nil
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Atoi is equivalent to ParseInt(s, 10, 0), converted to type int.
|
|
168
|
+
func Atoi(s string) (int, error) {
|
|
169
|
+
x, code := atoi(s)
|
|
170
|
+
if code != codeNone {
|
|
171
|
+
return x, toError("Atoi", s, 0, 0, code)
|
|
172
|
+
}
|
|
173
|
+
return x, nil
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func parseUint(s string, base int, bitSize int) (uint64, parseCode) {
|
|
177
|
+
if s == "" {
|
|
178
|
+
return 0, codeSyntax
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
base0 := base == 0
|
|
182
|
+
|
|
183
|
+
s0 := s
|
|
184
|
+
switch {
|
|
185
|
+
case 2 <= base && base <= 36:
|
|
186
|
+
// valid base; nothing to do
|
|
187
|
+
|
|
188
|
+
case base == 0:
|
|
189
|
+
// Look for octal, hex prefix.
|
|
190
|
+
base = 10
|
|
191
|
+
if s[0] == '0' {
|
|
192
|
+
switch {
|
|
193
|
+
case len(s) >= 3 && lowerS(s[1]) == 'b':
|
|
194
|
+
base = 2
|
|
195
|
+
s = s[2:]
|
|
196
|
+
case len(s) >= 3 && lowerS(s[1]) == 'o':
|
|
197
|
+
base = 8
|
|
198
|
+
s = s[2:]
|
|
199
|
+
case len(s) >= 3 && lowerS(s[1]) == 'x':
|
|
200
|
+
base = 16
|
|
201
|
+
s = s[2:]
|
|
202
|
+
default:
|
|
203
|
+
base = 8
|
|
204
|
+
s = s[1:]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
default:
|
|
209
|
+
return 0, codeBase
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if bitSize == 0 {
|
|
213
|
+
bitSize = IntSize
|
|
214
|
+
} else if bitSize < 0 || bitSize > 64 {
|
|
215
|
+
return 0, codeBitSize
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Cutoff is the smallest number such that cutoff*base > maxUint64.
|
|
219
|
+
// Use compile-time constants for common cases.
|
|
220
|
+
var cutoff uint64
|
|
221
|
+
switch base {
|
|
222
|
+
case 10:
|
|
223
|
+
cutoff = maxUint64/10 + 1
|
|
224
|
+
case 16:
|
|
225
|
+
cutoff = maxUint64/16 + 1
|
|
226
|
+
default:
|
|
227
|
+
cutoff = ^uint64(0)/uint64(base) + 1
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
maxVal := uint64(1)<<uint(bitSize) - 1
|
|
231
|
+
|
|
232
|
+
underscores := false
|
|
233
|
+
var n uint64
|
|
234
|
+
for _, c := range []byte(s) {
|
|
235
|
+
var d byte
|
|
236
|
+
switch {
|
|
237
|
+
case c == '_' && base0:
|
|
238
|
+
underscores = true
|
|
239
|
+
continue
|
|
240
|
+
case '0' <= c && c <= '9':
|
|
241
|
+
d = c - '0'
|
|
242
|
+
case 'a' <= lower(c) && lower(c) <= 'z':
|
|
243
|
+
d = lower(c) - 'a' + 10
|
|
244
|
+
default:
|
|
245
|
+
return 0, codeSyntax
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if d >= byte(base) {
|
|
249
|
+
return 0, codeSyntax
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if n >= cutoff {
|
|
253
|
+
// n*base overflows
|
|
254
|
+
return maxVal, codeRange
|
|
255
|
+
}
|
|
256
|
+
n *= uint64(base)
|
|
257
|
+
|
|
258
|
+
n1 := n + uint64(d)
|
|
259
|
+
if n1 < n || n1 > maxVal {
|
|
260
|
+
// n+d overflows
|
|
261
|
+
return maxVal, codeRange
|
|
262
|
+
}
|
|
263
|
+
n = n1
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if underscores && !underscoreOK(s0) {
|
|
267
|
+
return 0, codeSyntax
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return n, codeNone
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
func parseInt(s string, base int, bitSize int) (i int64, code parseCode) {
|
|
274
|
+
if s == "" {
|
|
275
|
+
return 0, codeSyntax
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Pick off leading sign.
|
|
279
|
+
neg := false
|
|
280
|
+
switch s[0] {
|
|
281
|
+
case '+':
|
|
282
|
+
s = s[1:]
|
|
283
|
+
case '-':
|
|
284
|
+
s = s[1:]
|
|
285
|
+
neg = true
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Convert unsigned and check range.
|
|
289
|
+
var un uint64
|
|
290
|
+
un, code = parseUint(s, base, bitSize)
|
|
291
|
+
if code != codeNone && code != codeRange {
|
|
292
|
+
return 0, code
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if bitSize == 0 {
|
|
296
|
+
bitSize = IntSize
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
cutoff := uint64(1 << uint(bitSize-1))
|
|
300
|
+
if !neg && un >= cutoff {
|
|
301
|
+
return int64(cutoff - 1), codeRange
|
|
302
|
+
}
|
|
303
|
+
if neg && un > cutoff {
|
|
304
|
+
return -int64(cutoff), codeRange
|
|
305
|
+
}
|
|
306
|
+
n := int64(un)
|
|
307
|
+
if neg {
|
|
308
|
+
n = -n
|
|
309
|
+
}
|
|
310
|
+
return n, codeNone
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
func atoi(s string) (int, parseCode) {
|
|
314
|
+
sLen := len(s)
|
|
315
|
+
if 0 < sLen && sLen < 19 {
|
|
316
|
+
// Fast path for small integers that fit int type.
|
|
317
|
+
s0 := s
|
|
318
|
+
if s[0] == '-' || s[0] == '+' {
|
|
319
|
+
s = s[1:]
|
|
320
|
+
if len(s) < 1 {
|
|
321
|
+
return 0, codeSyntax
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
n := 0
|
|
326
|
+
for _, ch := range []byte(s) {
|
|
327
|
+
ch -= '0'
|
|
328
|
+
if ch > 9 {
|
|
329
|
+
return 0, codeSyntax
|
|
330
|
+
}
|
|
331
|
+
n = n*10 + int(ch)
|
|
332
|
+
}
|
|
333
|
+
if s0[0] == '-' {
|
|
334
|
+
n = -n
|
|
335
|
+
}
|
|
336
|
+
return n, codeNone
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// Slow path for invalid, big, or underscored integers.
|
|
340
|
+
i64, code := parseInt(s, 10, 0)
|
|
341
|
+
return int(i64), code
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// underscoreOK reports whether the underscores in s are allowed.
|
|
345
|
+
// Checking them in this one function lets all the parsers skip over them simply.
|
|
346
|
+
// Underscore must appear only between digits or between a base prefix and a digit.
|
|
347
|
+
func underscoreOK(s string) bool {
|
|
348
|
+
// saw tracks the last character (class) we saw:
|
|
349
|
+
// ^ for beginning of number,
|
|
350
|
+
// 0 for a digit or base prefix,
|
|
351
|
+
// _ for an underscore,
|
|
352
|
+
// ! for none of the above.
|
|
353
|
+
saw := '^'
|
|
354
|
+
i := 0
|
|
355
|
+
|
|
356
|
+
// Optional sign.
|
|
357
|
+
if len(s) >= 1 && (s[0] == '-' || s[0] == '+') {
|
|
358
|
+
s = s[1:]
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Optional base prefix.
|
|
362
|
+
hex := false
|
|
363
|
+
if len(s) >= 2 && s[0] == '0' && (lowerS(s[1]) == 'b' || lowerS(s[1]) == 'o' || lowerS(s[1]) == 'x') {
|
|
364
|
+
i = 2
|
|
365
|
+
saw = '0' // base prefix counts as a digit for "underscore as digit separator"
|
|
366
|
+
hex = lowerS(s[1]) == 'x'
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Number proper.
|
|
370
|
+
for ; i < len(s); i++ {
|
|
371
|
+
// Digits are always okay.
|
|
372
|
+
if '0' <= s[i] && s[i] <= '9' || hex && 'a' <= lowerS(s[i]) && lowerS(s[i]) <= 'f' {
|
|
373
|
+
saw = '0'
|
|
374
|
+
continue
|
|
375
|
+
}
|
|
376
|
+
// Underscore must follow digit.
|
|
377
|
+
if s[i] == '_' {
|
|
378
|
+
if saw != '0' {
|
|
379
|
+
return false
|
|
380
|
+
}
|
|
381
|
+
saw = '_'
|
|
382
|
+
continue
|
|
383
|
+
}
|
|
384
|
+
// Underscore must also be followed by digit.
|
|
385
|
+
if saw == '_' {
|
|
386
|
+
return false
|
|
387
|
+
}
|
|
388
|
+
// Saw non-digit, non-underscore.
|
|
389
|
+
saw = '!'
|
|
390
|
+
}
|
|
391
|
+
return saw != '_'
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// FormatUint returns the string representation of i in the given base,
|
|
395
|
+
// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
|
|
396
|
+
// for digit values >= 10.
|
|
397
|
+
func FormatUint(i uint64, base int) string {
|
|
398
|
+
if base == 10 {
|
|
399
|
+
if i < nSmalls {
|
|
400
|
+
return small(int(i))
|
|
401
|
+
}
|
|
402
|
+
var a [24]byte
|
|
403
|
+
j := formatBase10(a[:], i)
|
|
404
|
+
return string(a[j:])
|
|
405
|
+
}
|
|
406
|
+
_, s := formatBits(nil, i, base, false, false)
|
|
407
|
+
return s
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// FormatInt returns the string representation of i in the given base,
|
|
411
|
+
// for 2 <= base <= 36. The result uses the lower-case letters 'a' to 'z'
|
|
412
|
+
// for digit values >= 10.
|
|
413
|
+
func FormatInt(i int64, base int) string {
|
|
414
|
+
if base == 10 {
|
|
415
|
+
if 0 <= i && i < nSmalls {
|
|
416
|
+
return small(int(i))
|
|
417
|
+
}
|
|
418
|
+
var a [24]byte
|
|
419
|
+
u := uint64(i)
|
|
420
|
+
if i < 0 {
|
|
421
|
+
u = -u
|
|
422
|
+
}
|
|
423
|
+
j := formatBase10(a[:], u)
|
|
424
|
+
if i < 0 {
|
|
425
|
+
j--
|
|
426
|
+
a[j] = '-'
|
|
427
|
+
}
|
|
428
|
+
return string(a[j:])
|
|
429
|
+
}
|
|
430
|
+
_, s := formatBits(nil, uint64(i), base, i < 0, false)
|
|
431
|
+
return s
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// Itoa is equivalent to [FormatInt](int64(i), 10).
|
|
435
|
+
func Itoa(i int) string {
|
|
436
|
+
return FormatInt(int64(i), 10)
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// AppendInt appends the string form of the integer i,
|
|
440
|
+
// as generated by [FormatInt], to dst and returns the extended buffer.
|
|
441
|
+
func AppendInt(dst []byte, i int64, base int) []byte {
|
|
442
|
+
u := uint64(i)
|
|
443
|
+
if i < 0 {
|
|
444
|
+
dst = append(dst, '-')
|
|
445
|
+
u = -u
|
|
446
|
+
}
|
|
447
|
+
return AppendUint(dst, u, base)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// AppendUint appends the string form of the unsigned integer i,
|
|
451
|
+
// as generated by [FormatUint], to dst and returns the extended buffer.
|
|
452
|
+
func AppendUint(dst []byte, i uint64, base int) []byte {
|
|
453
|
+
if base == 10 {
|
|
454
|
+
if i < nSmalls {
|
|
455
|
+
return append(dst, small(int(i))...)
|
|
456
|
+
}
|
|
457
|
+
var a [24]byte
|
|
458
|
+
j := formatBase10(a[:], i)
|
|
459
|
+
return append(dst, a[j:]...)
|
|
460
|
+
}
|
|
461
|
+
dst, _ = formatBits(dst, i, base, false, true)
|
|
462
|
+
return dst
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
func digitAt(i uint) byte {
|
|
466
|
+
return byte(digits[i])
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
const digits = "0123456789abcdefghijklmnopqrstuvwxyz"
|
|
470
|
+
|
|
471
|
+
// formatBits computes the string representation of u in the given base.
|
|
472
|
+
// If neg is set, u is treated as negative int64 value. If append_ is
|
|
473
|
+
// set, the string is appended to dst and the resulting byte slice is
|
|
474
|
+
// returned as the first result value; otherwise the string is returned
|
|
475
|
+
// as the second result value.
|
|
476
|
+
// The caller is expected to have handled base 10 separately for speed.
|
|
477
|
+
func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) {
|
|
478
|
+
if base < 2 || base == 10 || base > len(digits) {
|
|
479
|
+
panic("strconv: illegal AppendInt/FormatInt base")
|
|
480
|
+
}
|
|
481
|
+
// 2 <= base && base <= len(digits)
|
|
482
|
+
|
|
483
|
+
var a [64 + 1]byte // +1 for sign of 64bit value in base 2
|
|
484
|
+
i := len(a)
|
|
485
|
+
if neg {
|
|
486
|
+
u = -u
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// convert bits
|
|
490
|
+
// We use uint values where we can because those will
|
|
491
|
+
// fit into a single register even on a 32bit machine.
|
|
492
|
+
if isPowerOfTwo(base) {
|
|
493
|
+
// Use shifts and masks instead of / and %.
|
|
494
|
+
shift := uint(bits.TrailingZeros(uint(base)))
|
|
495
|
+
b := uint64(base)
|
|
496
|
+
m := b - 1 // == 1<<shift - 1
|
|
497
|
+
for u >= b {
|
|
498
|
+
i--
|
|
499
|
+
a[i] = digitAt(uint(u & m))
|
|
500
|
+
u >>= shift
|
|
501
|
+
}
|
|
502
|
+
// u < base
|
|
503
|
+
i--
|
|
504
|
+
a[i] = digitAt(uint(u))
|
|
505
|
+
} else {
|
|
506
|
+
// general case
|
|
507
|
+
b := uint64(base)
|
|
508
|
+
for u >= b {
|
|
509
|
+
i--
|
|
510
|
+
// Avoid using r = a%b in addition to q = a/b
|
|
511
|
+
// since 64bit division and modulo operations
|
|
512
|
+
// are calculated by runtime functions on 32bit machines.
|
|
513
|
+
q := u / b
|
|
514
|
+
a[i] = digitAt(uint(u-q*b))
|
|
515
|
+
u = q
|
|
516
|
+
}
|
|
517
|
+
// u < base
|
|
518
|
+
i--
|
|
519
|
+
a[i] = digitAt(uint(u))
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// add sign, if any
|
|
523
|
+
if neg {
|
|
524
|
+
i--
|
|
525
|
+
a[i] = '-'
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if append_ {
|
|
529
|
+
d = append(dst, a[i:]...)
|
|
530
|
+
return
|
|
531
|
+
}
|
|
532
|
+
s = string(a[i:])
|
|
533
|
+
return
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
func isPowerOfTwo(x int) bool {
|
|
537
|
+
return x&(x-1) == 0
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const nSmalls = 100
|
|
541
|
+
|
|
542
|
+
// smalls is the formatting of 00..99 concatenated.
|
|
543
|
+
// It is then padded out with 56 x's to 256 bytes,
|
|
544
|
+
// so that smalls[x&0xFF] has no bounds check.
|
|
545
|
+
const smalls = "00010203040506070809" +
|
|
546
|
+
"10111213141516171819" +
|
|
547
|
+
"20212223242526272829" +
|
|
548
|
+
"30313233343536373839" +
|
|
549
|
+
"40414243444546474849" +
|
|
550
|
+
"50515253545556575859" +
|
|
551
|
+
"60616263646566676869" +
|
|
552
|
+
"70717273747576777879" +
|
|
553
|
+
"80818283848586878889" +
|
|
554
|
+
"90919293949596979899"
|
|
555
|
+
|
|
556
|
+
// small returns the string for an i with 0 <= i < nSmalls.
|
|
557
|
+
func small(i int) string {
|
|
558
|
+
if i < 10 {
|
|
559
|
+
return digits[i : i+1]
|
|
560
|
+
}
|
|
561
|
+
return smalls[i*2 : i*2+2]
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// formatBase10 formats the decimal representation of u into the tail of a
|
|
565
|
+
// and returns the offset of the first byte written to a. That is, after
|
|
566
|
+
//
|
|
567
|
+
// i := formatBase10(a, u)
|
|
568
|
+
//
|
|
569
|
+
// the decimal representation is in a[i:].
|
|
570
|
+
func formatBase10(a []byte, u uint64) int {
|
|
571
|
+
// Split into 9-digit chunks that fit in uint32s
|
|
572
|
+
// and convert each chunk using uint32 math instead of uint64 math.
|
|
573
|
+
// The obvious way to write the outer loop is "for u >= 1e9", but most numbers are small,
|
|
574
|
+
// so the setup for the comparison u >= 1e9 is usually pure overhead.
|
|
575
|
+
// Instead, we approximate it by u>>29 != 0, which is usually faster and good enough.
|
|
576
|
+
i := len(a)
|
|
577
|
+
for u>>29 != 0 {
|
|
578
|
+
var lo uint32
|
|
579
|
+
u, lo = u/1000000000, uint32(u%1000000000)
|
|
580
|
+
|
|
581
|
+
// Convert 9 digits.
|
|
582
|
+
for range 4 {
|
|
583
|
+
var dd uint32
|
|
584
|
+
lo, dd = lo/100, (lo%100)*2
|
|
585
|
+
i -= 2
|
|
586
|
+
a[i+0], a[i+1] = byte(smalls[dd+0]), byte(smalls[dd+1])
|
|
587
|
+
}
|
|
588
|
+
i--
|
|
589
|
+
a[i] = byte(smalls[lo*2+1])
|
|
590
|
+
|
|
591
|
+
// If we'd been using u >= 1e9 then we would be guaranteed that u/1e9 > 0,
|
|
592
|
+
// but since we used u>>29 != 0, u/1e9 might be 0, so we might be done.
|
|
593
|
+
// (If u is now 0, then at the start we had 2²⁹ ≤ u < 10⁹, so it was still correct
|
|
594
|
+
// to write 9 digits; we have not accidentally written any leading zeros.)
|
|
595
|
+
if u == 0 {
|
|
596
|
+
return i
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Convert final chunk, at most 8 digits.
|
|
601
|
+
lo := uint32(u)
|
|
602
|
+
for lo >= 100 {
|
|
603
|
+
var dd uint32
|
|
604
|
+
lo, dd = lo/100, (lo%100)*2
|
|
605
|
+
i -= 2
|
|
606
|
+
a[i+0], a[i+1] = byte(smalls[dd+0]), byte(smalls[dd+1])
|
|
607
|
+
}
|
|
608
|
+
i--
|
|
609
|
+
dd := lo * 2
|
|
610
|
+
a[i] = byte(smalls[dd+1])
|
|
611
|
+
if lo >= 10 {
|
|
612
|
+
i--
|
|
613
|
+
a[i] = byte(smalls[dd+0])
|
|
614
|
+
}
|
|
615
|
+
return i
|
|
616
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//go:build gofront
|
|
2
|
+
|
|
3
|
+
//gofront:target both
|
|
4
|
+
|
|
5
|
+
// Builder written in Go over the real package's algorithm. GoFront strings
|
|
6
|
+
// are host strings, so Len and Cap count the UTF-8 bytes the builder holds,
|
|
7
|
+
// the same as in Go.
|
|
8
|
+
package strings
|
|
9
|
+
|
|
10
|
+
import "unicode/utf8"
|
|
11
|
+
|
|
12
|
+
// A Builder is used to efficiently build a string using [Builder.Write] methods.
|
|
13
|
+
// It minimizes memory copying. The zero value is ready to use.
|
|
14
|
+
// Do not copy a non-zero Builder.
|
|
15
|
+
type Builder struct {
|
|
16
|
+
addr *Builder // of receiver, to detect copies by value
|
|
17
|
+
|
|
18
|
+
buf []byte
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func (b *Builder) copyCheck() {
|
|
22
|
+
if b.addr == nil {
|
|
23
|
+
b.addr = b
|
|
24
|
+
} else if b.addr != b {
|
|
25
|
+
panic("strings: illegal use of non-zero Builder copied by value")
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// String returns the accumulated string.
|
|
30
|
+
func (b *Builder) String() string {
|
|
31
|
+
return string(b.buf)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Len returns the number of accumulated bytes; b.Len() == len(b.String()).
|
|
35
|
+
func (b *Builder) Len() int { return len(b.buf) }
|
|
36
|
+
|
|
37
|
+
// Cap returns the capacity of the builder's underlying byte slice. It is the
|
|
38
|
+
// total space allocated for the string being built and includes any bytes
|
|
39
|
+
// already written.
|
|
40
|
+
func (b *Builder) Cap() int { return cap(b.buf) }
|
|
41
|
+
|
|
42
|
+
// Reset resets the [Builder] to be empty.
|
|
43
|
+
func (b *Builder) Reset() {
|
|
44
|
+
b.addr = nil
|
|
45
|
+
b.buf = nil
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Grow grows b's capacity, if necessary, to guarantee space for
|
|
49
|
+
// another n bytes. After Grow(n), at least n bytes can be written to b
|
|
50
|
+
// without another allocation. If n is negative, Grow panics.
|
|
51
|
+
func (b *Builder) Grow(n int) {
|
|
52
|
+
b.copyCheck()
|
|
53
|
+
if n < 0 {
|
|
54
|
+
panic("strings.Builder.Grow: negative count")
|
|
55
|
+
}
|
|
56
|
+
if cap(b.buf)-len(b.buf) < n {
|
|
57
|
+
nb := make([]byte, len(b.buf), 2*cap(b.buf)+n)
|
|
58
|
+
copy(nb, b.buf)
|
|
59
|
+
b.buf = nb
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Write appends the contents of p to b's buffer.
|
|
64
|
+
// Write always returns len(p), nil.
|
|
65
|
+
func (b *Builder) Write(p []byte) (int, error) {
|
|
66
|
+
b.copyCheck()
|
|
67
|
+
b.buf = append(b.buf, p...)
|
|
68
|
+
return len(p), nil
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// WriteByte appends the byte c to b's buffer.
|
|
72
|
+
// The returned error is always nil.
|
|
73
|
+
func (b *Builder) WriteByte(c byte) error {
|
|
74
|
+
b.copyCheck()
|
|
75
|
+
b.buf = append(b.buf, c)
|
|
76
|
+
return nil
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// WriteRune appends the UTF-8 encoding of Unicode code point r to b's buffer.
|
|
80
|
+
// It returns the length of r and a nil error.
|
|
81
|
+
func (b *Builder) WriteRune(r rune) (int, error) {
|
|
82
|
+
b.copyCheck()
|
|
83
|
+
n := len(b.buf)
|
|
84
|
+
b.buf = utf8.AppendRune(b.buf, r)
|
|
85
|
+
return len(b.buf) - n, nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// WriteString appends the contents of s to b's buffer.
|
|
89
|
+
// It returns the length of s and a nil error.
|
|
90
|
+
func (b *Builder) WriteString(s string) (int, error) {
|
|
91
|
+
b.copyCheck()
|
|
92
|
+
n := len(b.buf)
|
|
93
|
+
b.buf = append(b.buf, s...)
|
|
94
|
+
return len(b.buf) - n, nil
|
|
95
|
+
}
|