gofront 1.8.0 → 1.9.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.
Files changed (177) hide show
  1. package/README.md +3 -3
  2. package/package.json +5 -4
  3. package/src/backend/js/expressions.js +849 -371
  4. package/src/backend/js/index.js +241 -147
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +512 -2547
  7. package/src/backend/js/statements.js +506 -103
  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 +177 -13
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +63 -171
  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 +643 -256
  16. package/src/backend/wasm/emit-exprs.js +124 -57
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-stmts.js +325 -75
  19. package/src/backend/wasm/emit.js +104 -13
  20. package/src/backend/wasm/globals.js +47 -8
  21. package/src/backend/wasm/glue.js +2 -4
  22. package/src/backend/wasm/index.js +36 -530
  23. package/src/backend/wasm/method-expr.js +12 -1
  24. package/src/backend/wasm/module-emitter.js +92 -717
  25. package/src/backend/wasm/monomorph.js +103 -6
  26. package/src/backend/wasm/natives.js +596 -0
  27. package/src/backend/wasm/prescan.js +5 -153
  28. package/src/backend/wasm/prune-funcs.js +89 -0
  29. package/src/backend/wasm/stdlib/index.js +2 -32
  30. package/src/backend/wasm/types.js +68 -20
  31. package/src/backend/wasm/variadic.js +3 -3
  32. package/src/cli/cli-core.js +5 -1
  33. package/src/cli/test-runner.js +115 -342
  34. package/src/compiler.js +108 -130
  35. package/src/lexer/lexer.js +105 -11
  36. package/src/lexer/templ-lexer.js +61 -18
  37. package/src/lexer/tokens.js +1 -0
  38. package/src/link/stdlib.js +354 -132
  39. package/src/link/type-names.js +148 -0
  40. package/src/link/wasm.js +30 -6
  41. package/src/lower/bounds.js +153 -0
  42. package/src/lower/captures.js +92 -33
  43. package/src/lower/embedding.js +32 -3
  44. package/src/lower/errors-as.js +196 -0
  45. package/src/lower/fmt-formatters.js +905 -0
  46. package/src/lower/functions.js +2 -0
  47. package/src/lower/gen-types.js +274 -0
  48. package/src/lower/index.js +7 -1
  49. package/src/lower/json-codecs.js +228 -247
  50. package/src/lower/ownership.js +25 -7
  51. package/src/lower/reachability.js +69 -51
  52. package/src/lower/walk.js +12 -0
  53. package/src/parser/declarations.js +28 -5
  54. package/src/parser/expressions.js +86 -16
  55. package/src/parser/statements.js +1 -0
  56. package/src/parser/templ.js +44 -5
  57. package/src/parser/types.js +1 -0
  58. package/src/resolver.js +1 -2
  59. package/src/typechecker/assignability.js +124 -11
  60. package/src/typechecker/const-fold.js +70 -27
  61. package/src/typechecker/constants.js +32 -6
  62. package/src/typechecker/expressions.js +326 -98
  63. package/src/typechecker/index.js +208 -33
  64. package/src/typechecker/init-order.js +136 -40
  65. package/src/typechecker/operand-text.js +40 -0
  66. package/src/typechecker/resolve.js +192 -36
  67. package/src/typechecker/statements.js +122 -11
  68. package/src/typechecker/stdlib/excluded.js +9 -5
  69. package/src/typechecker/stdlib/index.js +25 -9
  70. package/src/typechecker/termination.js +10 -1
  71. package/src/typechecker/types.js +203 -573
  72. package/stdlib/bytes/buffer.go +479 -0
  73. package/stdlib/bytes/bytes.go +1010 -0
  74. package/stdlib/bytes/reader.go +161 -0
  75. package/stdlib/context/context.go +115 -0
  76. package/stdlib/crypto/rand/rand.go +34 -0
  77. package/stdlib/crypto/sha256/sha256.go +249 -0
  78. package/stdlib/encoding/base64/base64.go +331 -0
  79. package/stdlib/encoding/binary/binary.go +332 -0
  80. package/stdlib/encoding/hex/hex.go +140 -0
  81. package/stdlib/encoding/json/json.go +62 -0
  82. package/stdlib/errors/errors.go +174 -0
  83. package/stdlib/fmt/errors.go +110 -0
  84. package/stdlib/fmt/format.go +732 -0
  85. package/stdlib/fmt/print.go +1232 -0
  86. package/stdlib/gom/gom.go +293 -0
  87. package/stdlib/html/html.go +251 -0
  88. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  89. package/stdlib/internal/jsonrt/dec.go +171 -38
  90. package/stdlib/internal/jsonrt/enc.go +186 -36
  91. package/stdlib/internal/jsonrt/scanner.go +17 -8
  92. package/stdlib/io/io.go +157 -1
  93. package/stdlib/maps/maps.go +131 -0
  94. package/stdlib/math/bits/bits.go +507 -0
  95. package/stdlib/math/extra.go +16 -14
  96. package/stdlib/math/math.go +439 -0
  97. package/stdlib/math/rand/rand.go +297 -0
  98. package/stdlib/os/os.go +93 -0
  99. package/stdlib/path/filepath/filepath.go +47 -0
  100. package/stdlib/path/path.go +394 -0
  101. package/stdlib/regexp/regexp.go +231 -0
  102. package/stdlib/slices/slices.go +526 -0
  103. package/stdlib/slices/sort.go +209 -0
  104. package/stdlib/slices/zsort_cmp.go +480 -0
  105. package/stdlib/slices/zsort_ordered.go +482 -0
  106. package/stdlib/sort/sort.go +391 -452
  107. package/stdlib/sort/zsort_func.go +480 -0
  108. package/stdlib/sort/zsort_iface.go +480 -0
  109. package/stdlib/strconv/float.go +1699 -0
  110. package/stdlib/strconv/isprint.go +752 -0
  111. package/stdlib/strconv/quote.go +235 -50
  112. package/stdlib/strconv/strconv.go +616 -0
  113. package/stdlib/strings/builder.go +95 -0
  114. package/stdlib/strings/reader.go +163 -0
  115. package/stdlib/strings/replacer.go +102 -0
  116. package/stdlib/strings/strings.go +807 -0
  117. package/stdlib/sync/sync.go +268 -0
  118. package/stdlib/testing/async_js.go +61 -0
  119. package/stdlib/testing/benchmark.go +297 -0
  120. package/stdlib/testing/testing.go +523 -0
  121. package/stdlib/time/duration.go +233 -0
  122. package/stdlib/time/format.go +745 -0
  123. package/stdlib/time/parse.go +790 -0
  124. package/stdlib/time/sleep_js.go +63 -0
  125. package/stdlib/time/time.go +834 -0
  126. package/stdlib/unicode/unicode.go +141 -3
  127. package/stdlib/unicode/utf8/utf8.go +464 -0
  128. package/src/backend/js/fmt-runtime.js +0 -573
  129. package/src/backend/js/stdlib/base64.js +0 -12
  130. package/src/backend/js/stdlib/binary.js +0 -102
  131. package/src/backend/js/stdlib/bits.js +0 -119
  132. package/src/backend/js/stdlib/builder.js +0 -98
  133. package/src/backend/js/stdlib/bytes.js +0 -368
  134. package/src/backend/js/stdlib/errors.js +0 -45
  135. package/src/backend/js/stdlib/fmt.js +0 -517
  136. package/src/backend/js/stdlib/gom.js +0 -155
  137. package/src/backend/js/stdlib/hex.js +0 -17
  138. package/src/backend/js/stdlib/html.js +0 -20
  139. package/src/backend/js/stdlib/io.js +0 -137
  140. package/src/backend/js/stdlib/json.js +0 -1167
  141. package/src/backend/js/stdlib/maps.js +0 -37
  142. package/src/backend/js/stdlib/math.js +0 -85
  143. package/src/backend/js/stdlib/os.js +0 -13
  144. package/src/backend/js/stdlib/path.js +0 -48
  145. package/src/backend/js/stdlib/rand.js +0 -32
  146. package/src/backend/js/stdlib/regexp.js +0 -54
  147. package/src/backend/js/stdlib/sha256.js +0 -12
  148. package/src/backend/js/stdlib/shared.js +0 -17
  149. package/src/backend/js/stdlib/simd.js +0 -34
  150. package/src/backend/js/stdlib/slices.js +0 -107
  151. package/src/backend/js/stdlib/sort.js +0 -30
  152. package/src/backend/js/stdlib/strconv.js +0 -79
  153. package/src/backend/js/stdlib/strings.js +0 -301
  154. package/src/backend/js/stdlib/sync.js +0 -13
  155. package/src/backend/js/stdlib/testing.js +0 -41
  156. package/src/backend/js/stdlib/time.js +0 -152
  157. package/src/backend/js/stdlib/unicode.js +0 -25
  158. package/src/backend/js/stdlib/utf8.js +0 -26
  159. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  160. package/src/backend/wasm/stdlib/core.js +0 -10278
  161. package/src/backend/wasm/stdlib/io.js +0 -3578
  162. package/src/backend/wasm/stdlib/packages.js +0 -2402
  163. package/src/backend/wasm/stdlib/pure.js +0 -720
  164. package/src/backend/wasm/stdlib/time.js +0 -2229
  165. package/src/typechecker/stdlib/core.js +0 -1079
  166. package/src/typechecker/stdlib/extended.js +0 -1210
  167. package/stdlib/bytes/iter.go +0 -192
  168. package/stdlib/bytes/search.go +0 -240
  169. package/stdlib/bytes/split.go +0 -218
  170. package/stdlib/errors/overlay.go +0 -12
  171. package/stdlib/maps/iter.go +0 -65
  172. package/stdlib/slices/extra.go +0 -73
  173. package/stdlib/slices/iter.go +0 -113
  174. package/stdlib/strings/extra.go +0 -35
  175. package/stdlib/strings/iter.go +0 -122
  176. package/stdlib/sync/extra.go +0 -105
  177. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -0,0 +1,1232 @@
1
+ // Copyright 2009 The Go Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style
3
+ // license that can be found in the LICENSE file.
4
+
5
+ //go:build gofront
6
+
7
+ //gofront:target both
8
+
9
+ // Package fmt formats values like the real package.
10
+ //
11
+ // Where Go's fmt asks reflection for the type of an operand, this package
12
+ // reads a description of it (fmtrt.Arg). The compiler writes the description
13
+ // for operands whose type it knows at the call and for the types a package
14
+ // stores in interfaces; see internal/fmtrt.
15
+ package fmt
16
+
17
+ import (
18
+ "internal/fmtrt"
19
+ "io"
20
+ "os"
21
+ "unicode/utf8"
22
+ )
23
+
24
+ // Stringer is implemented by any value that has a String method, which
25
+ // defines the “native” format for that value.
26
+ type Stringer interface {
27
+ String() string
28
+ }
29
+
30
+ // GoStringer is implemented by any value that has a GoString method, which
31
+ // defines the Go syntax for that value.
32
+ type GoStringer interface {
33
+ GoString() string
34
+ }
35
+
36
+ const (
37
+ commaSpaceString = ", "
38
+ nilAngleString = "<nil>"
39
+ nilParenString = "(nil)"
40
+ nilString = "nil"
41
+ mapString = "map["
42
+ percentBangString = "%!"
43
+ missingString = "(MISSING)"
44
+ badIndexString = "(BADINDEX)"
45
+ panicString = "(PANIC="
46
+ extraString = "%!(EXTRA "
47
+ badWidthString = "%!(BADWIDTH)"
48
+ badPrecString = "%!(BADPREC)"
49
+ noVerbString = "%!(NOVERB)"
50
+ invReflectString = "<invalid reflect.Value>"
51
+ )
52
+
53
+ // pp is the printer state.
54
+ type pp struct {
55
+ fmt fmtState
56
+
57
+ // erroring is set when printing an error string to guard against calling handleMethods.
58
+ erroring bool
59
+ // panicking is set by catchPanic to avoid infinite panic, recover, panic, ... recursion.
60
+ panicking bool
61
+ // wrapErrs is set by Errorf: %w is valid only there.
62
+ wrapErrs bool
63
+ // reordered records whether the format used an explicit argument index.
64
+ reordered bool
65
+ // goodArgNum records whether the current verb's argument index was valid.
66
+ goodArgNum bool
67
+ // wrappedErrs holds the argument numbers of the %w verbs.
68
+ wrappedErrs []int
69
+ }
70
+
71
+ func newPrinter() *pp {
72
+ p := &pp{}
73
+ p.fmt.buf = make([]byte, 64)
74
+ return p
75
+ }
76
+
77
+ func (p *pp) writeString(s string) {
78
+ p.fmt.putString(s)
79
+ }
80
+
81
+ func (p *pp) writeByte(c byte) {
82
+ p.fmt.putByte(c)
83
+ }
84
+
85
+ func (p *pp) writeRune(r rune) {
86
+ if r >= 0 && r < 0x80 {
87
+ p.fmt.putByte(byte(r))
88
+ return
89
+ }
90
+ p.fmt.putString(string(r))
91
+ }
92
+
93
+ // Fprintf formats according to a format specifier and writes to w.
94
+ func Fprintf(w io.Writer, format string, a ...any) (n int, err error) {
95
+ p := newPrinter()
96
+ p.doPrintf(format, a)
97
+ n, err = w.Write(p.fmt.bytes())
98
+ return
99
+ }
100
+
101
+ // Printf formats according to a format specifier and writes to standard output.
102
+ func Printf(format string, a ...any) (n int, err error) {
103
+ return Fprintf(os.Stdout, format, a...)
104
+ }
105
+
106
+ // Sprintf formats according to a format specifier and returns the resulting string.
107
+ func Sprintf(format string, a ...any) string {
108
+ p := newPrinter()
109
+ p.doPrintf(format, a)
110
+ return string(p.fmt.bytes())
111
+ }
112
+
113
+ // Appendf formats according to a format specifier, appends the result to the
114
+ // byte slice, and returns the updated slice.
115
+ func Appendf(b []byte, format string, a ...any) []byte {
116
+ p := newPrinter()
117
+ p.doPrintf(format, a)
118
+ return append(b, p.fmt.bytes()...)
119
+ }
120
+
121
+ // Fprint formats using the default formats for its operands and writes to w.
122
+ // Spaces are added between operands when neither is a string.
123
+ func Fprint(w io.Writer, a ...any) (n int, err error) {
124
+ p := newPrinter()
125
+ p.doPrint(a)
126
+ n, err = w.Write(p.fmt.bytes())
127
+ return
128
+ }
129
+
130
+ // Print formats using the default formats for its operands and writes to standard output.
131
+ func Print(a ...any) (n int, err error) {
132
+ return Fprint(os.Stdout, a...)
133
+ }
134
+
135
+ // Sprint formats using the default formats for its operands and returns the resulting string.
136
+ func Sprint(a ...any) string {
137
+ p := newPrinter()
138
+ p.doPrint(a)
139
+ return string(p.fmt.bytes())
140
+ }
141
+
142
+ // Append formats using the default formats for its operands, appends the result to
143
+ // the byte slice, and returns the updated slice.
144
+ func Append(b []byte, a ...any) []byte {
145
+ p := newPrinter()
146
+ p.doPrint(a)
147
+ return append(b, p.fmt.bytes()...)
148
+ }
149
+
150
+ // Fprintln formats using the default formats for its operands and writes to w.
151
+ // Spaces are always added between operands and a newline is appended.
152
+ func Fprintln(w io.Writer, a ...any) (n int, err error) {
153
+ p := newPrinter()
154
+ p.doPrintln(a)
155
+ n, err = w.Write(p.fmt.bytes())
156
+ return
157
+ }
158
+
159
+ // Println formats using the default formats for its operands and writes to standard output.
160
+ func Println(a ...any) (n int, err error) {
161
+ return Fprintln(os.Stdout, a...)
162
+ }
163
+
164
+ // Sprintln formats using the default formats for its operands and returns the resulting string.
165
+ func Sprintln(a ...any) string {
166
+ p := newPrinter()
167
+ p.doPrintln(a)
168
+ return string(p.fmt.bytes())
169
+ }
170
+
171
+ // Appendln formats using the default formats for its operands, appends the result
172
+ // to the byte slice, and returns the updated slice.
173
+ func Appendln(b []byte, a ...any) []byte {
174
+ p := newPrinter()
175
+ p.doPrintln(a)
176
+ return append(b, p.fmt.bytes()...)
177
+ }
178
+
179
+ // describe turns an operand into its description. An operand the compiler
180
+ // described is returned as it is; any other is described by its dynamic
181
+ // type, through the lookups of the packages that registered one.
182
+ func describe(arg any) fmtrt.Arg {
183
+ switch f := arg.(type) {
184
+ case fmtrt.Arg:
185
+ return f
186
+ case nil:
187
+ return fmtrt.Arg{K: fmtrt.KInterface}
188
+ case bool:
189
+ return fmtrt.Arg{K: fmtrt.KBool, T: "bool", B: f}
190
+ case int:
191
+ return fmtrt.Arg{K: fmtrt.KInt, T: "int", I: int64(f)}
192
+ case int8:
193
+ return fmtrt.Arg{K: fmtrt.KInt, T: "int8", Size: 8, I: int64(f)}
194
+ case int16:
195
+ return fmtrt.Arg{K: fmtrt.KInt, T: "int16", Size: 16, I: int64(f)}
196
+ case int32:
197
+ return fmtrt.Arg{K: fmtrt.KInt, T: "int32", Size: 32, I: int64(f)}
198
+ case int64:
199
+ return fmtrt.Arg{K: fmtrt.KInt, T: "int64", Size: 64, I: f}
200
+ case uint:
201
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint", U: uint64(f)}
202
+ case uint8:
203
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint8", Size: 8, U: uint64(f)}
204
+ case uint16:
205
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint16", Size: 16, U: uint64(f)}
206
+ case uint32:
207
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint32", Size: 32, U: uint64(f)}
208
+ case uint64:
209
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint64", Size: 64, U: f}
210
+ case uintptr:
211
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uintptr", U: uint64(f)}
212
+ // float64 first: on JS a float32 and a float64 are the same number, and a
213
+ // float32 that reaches here without its description is far rarer.
214
+ case float64:
215
+ return fmtrt.Arg{K: fmtrt.KFloat, T: "float64", Size: 64, R: f}
216
+ case float32:
217
+ return fmtrt.Arg{K: fmtrt.KFloat, T: "float32", Size: 32, R: float64(f)}
218
+ case complex128:
219
+ return fmtrt.Arg{K: fmtrt.KComplex, T: "complex128", Size: 128, R: real(f), Im: imag(f)}
220
+ case complex64:
221
+ return fmtrt.Arg{K: fmtrt.KComplex, T: "complex64", Size: 64, R: float64(real(f)), Im: float64(imag(f))}
222
+ case string:
223
+ return fmtrt.Arg{K: fmtrt.KString, T: "string", S: f}
224
+ case []byte:
225
+ return bytesArg(f, "[]uint8")
226
+ }
227
+ // A value with String, GoString or Error methods is formatted through
228
+ // them for the verbs that call them; a verb that does not (%d) formats it
229
+ // by its fields, which printDesc then asks the registered lookups for.
230
+ e, isErr := arg.(error)
231
+ s, isStr := arg.(Stringer)
232
+ g, isGo := arg.(GoStringer)
233
+ if isErr || isStr || isGo {
234
+ a := fmtrt.Arg{K: fmtrt.KNone, V: arg}
235
+ if isErr {
236
+ a.Err = e
237
+ }
238
+ if isStr {
239
+ a.Str = s
240
+ }
241
+ if isGo {
242
+ a.GoStr = g
243
+ }
244
+ return a
245
+ }
246
+ if a, ok := fmtrt.Lookup(arg); ok {
247
+ return a
248
+ }
249
+ return fmtrt.Arg{K: fmtrt.KNone, V: arg}
250
+ }
251
+
252
+ // typeName is the type %T prints: the one the operand was described with, else
253
+ // the one a registered lookup gives its value, else the one a value of the
254
+ // standard library names itself.
255
+ func typeName(a fmtrt.Arg) string {
256
+ if a.T != "" || a.V == nil {
257
+ return a.T
258
+ }
259
+ if d, ok := fmtrt.Lookup(a.V); ok && d.T != "" {
260
+ return d.T
261
+ }
262
+ if n, ok := a.V.(interface{ GofrontTypeName() string }); ok {
263
+ return n.GofrontTypeName()
264
+ }
265
+ return ""
266
+ }
267
+
268
+ // bytesArg describes a []byte.
269
+ func bytesArg(b []byte, typ string) fmtrt.Arg {
270
+ return fmtrt.Arg{
271
+ K: fmtrt.KSlice, T: typ, Nil: b == nil, Ptr: b, N: len(b), IsBytes: true, Bytes: b,
272
+ Elem: func(i int) fmtrt.Arg {
273
+ return fmtrt.Arg{K: fmtrt.KUint, T: "uint8", Size: 8, U: uint64(b[i])}
274
+ },
275
+ }
276
+ }
277
+
278
+ func (p *pp) doPrint(a []any) {
279
+ prevString := false
280
+ for argNum, arg := range a {
281
+ d := describe(arg)
282
+ isString := d.K == fmtrt.KString
283
+ // Add a space between two non-string arguments.
284
+ if argNum > 0 && !isString && !prevString {
285
+ p.writeByte(' ')
286
+ }
287
+ p.printArg(d, 'v')
288
+ prevString = isString
289
+ }
290
+ }
291
+
292
+ // doPrintln is like doPrint but always adds a space between arguments
293
+ // and a newline after the last argument.
294
+ func (p *pp) doPrintln(a []any) {
295
+ for argNum, arg := range a {
296
+ if argNum > 0 {
297
+ p.writeByte(' ')
298
+ }
299
+ p.printArg(describe(arg), 'v')
300
+ }
301
+ p.writeByte('\n')
302
+ }
303
+
304
+ func (p *pp) badVerb(verb rune, a fmtrt.Arg) {
305
+ p.erroring = true
306
+ p.writeString(percentBangString)
307
+ p.writeRune(verb)
308
+ p.writeByte('(')
309
+ if a.K == fmtrt.KInterface && a.V == nil {
310
+ p.writeString(nilAngleString)
311
+ } else {
312
+ p.writeString(typeName(a))
313
+ p.writeByte('=')
314
+ p.printDesc(a, 'v', 0, false)
315
+ }
316
+ p.writeByte(')')
317
+ p.erroring = false
318
+ }
319
+
320
+ func (p *pp) fmtBool(v bool, verb rune, a fmtrt.Arg) {
321
+ switch verb {
322
+ case 't', 'v':
323
+ p.fmt.fmtBoolean(v)
324
+ default:
325
+ p.badVerb(verb, a)
326
+ }
327
+ }
328
+
329
+ // fmt0x64 formats a uint64 in hexadecimal and prefixes it with 0x or
330
+ // not, as requested, by temporarily setting the sharp flag.
331
+ func (p *pp) fmt0x64(v uint64, leading0x bool) {
332
+ sharp := p.fmt.sharp
333
+ p.fmt.sharp = leading0x
334
+ p.fmt.fmtInteger(v, 16, unsigned, 'v', ldigits)
335
+ p.fmt.sharp = sharp
336
+ }
337
+
338
+ // fmtInteger formats a signed or unsigned integer.
339
+ func (p *pp) fmtInteger(v uint64, isSigned bool, verb rune, a fmtrt.Arg) {
340
+ switch verb {
341
+ case 'v':
342
+ if p.fmt.sharpV && !isSigned {
343
+ p.fmt0x64(v, true)
344
+ } else {
345
+ p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
346
+ }
347
+ case 'd':
348
+ p.fmt.fmtInteger(v, 10, isSigned, verb, ldigits)
349
+ case 'b':
350
+ p.fmt.fmtInteger(v, 2, isSigned, verb, ldigits)
351
+ case 'o', 'O':
352
+ p.fmt.fmtInteger(v, 8, isSigned, verb, ldigits)
353
+ case 'x':
354
+ p.fmt.fmtInteger(v, 16, isSigned, verb, ldigits)
355
+ case 'X':
356
+ p.fmt.fmtInteger(v, 16, isSigned, verb, udigits)
357
+ case 'c':
358
+ p.fmt.fmtC(v)
359
+ case 'q':
360
+ p.fmt.fmtQc(v)
361
+ case 'U':
362
+ p.fmt.fmtUnicode(v)
363
+ default:
364
+ p.badVerb(verb, a)
365
+ }
366
+ }
367
+
368
+ // fmtFloat formats a float. The format is the verb's default; the size is 32 or 64.
369
+ func (p *pp) fmtFloat(v float64, size int, verb rune, a fmtrt.Arg) {
370
+ switch verb {
371
+ case 'v':
372
+ p.fmt.fmtFloat(v, size, 'g', -1)
373
+ case 'b', 'g', 'G', 'x', 'X':
374
+ p.fmt.fmtFloat(v, size, verb, -1)
375
+ case 'f', 'e', 'E':
376
+ p.fmt.fmtFloat(v, size, verb, 6)
377
+ case 'F':
378
+ p.fmt.fmtFloat(v, size, 'f', 6)
379
+ default:
380
+ p.badVerb(verb, a)
381
+ }
382
+ }
383
+
384
+ // fmtComplex formats a complex number v with
385
+ // r = real(v) and j = imag(v) as (r+ji) using
386
+ // fmtFloat for r and j formatting.
387
+ func (p *pp) fmtComplex(re, im float64, size int, verb rune, a fmtrt.Arg) {
388
+ // Make sure any unsupported verbs are found before the
389
+ // calls to fmtFloat to not generate an incorrect error string.
390
+ switch verb {
391
+ case 'v', 'b', 'g', 'G', 'x', 'X', 'f', 'F', 'e', 'E':
392
+ oldPlus := p.fmt.plus
393
+ p.writeByte('(')
394
+ p.fmtFloat(re, size/2, verb, a)
395
+ // Imaginary part always has a sign.
396
+ p.fmt.plus = true
397
+ p.fmtFloat(im, size/2, verb, a)
398
+ p.writeString("i)")
399
+ p.fmt.plus = oldPlus
400
+ default:
401
+ p.badVerb(verb, a)
402
+ }
403
+ }
404
+
405
+ func (p *pp) fmtString(v string, verb rune, a fmtrt.Arg) {
406
+ switch verb {
407
+ case 'v':
408
+ if p.fmt.sharpV {
409
+ p.fmt.fmtQ(v)
410
+ } else {
411
+ p.fmt.fmtS(v)
412
+ }
413
+ case 's':
414
+ p.fmt.fmtS(v)
415
+ case 'x':
416
+ p.fmt.fmtSx(v, ldigits)
417
+ case 'X':
418
+ p.fmt.fmtSx(v, udigits)
419
+ case 'q':
420
+ p.fmt.fmtQ(v)
421
+ default:
422
+ p.badVerb(verb, a)
423
+ }
424
+ }
425
+
426
+ func (p *pp) fmtBytes(v []byte, verb rune, a fmtrt.Arg) {
427
+ switch verb {
428
+ case 'v', 'd':
429
+ if p.fmt.sharpV {
430
+ p.writeString(a.T)
431
+ if v == nil {
432
+ p.writeString(nilParenString)
433
+ return
434
+ }
435
+ p.writeByte('{')
436
+ for i, c := range v {
437
+ if i > 0 {
438
+ p.writeString(commaSpaceString)
439
+ }
440
+ p.fmt0x64(uint64(c), true)
441
+ }
442
+ p.writeByte('}')
443
+ } else {
444
+ p.writeByte('[')
445
+ for i, c := range v {
446
+ if i > 0 {
447
+ p.writeByte(' ')
448
+ }
449
+ p.fmt.fmtInteger(uint64(c), 10, unsigned, verb, ldigits)
450
+ }
451
+ p.writeByte(']')
452
+ }
453
+ case 's':
454
+ p.fmt.fmtBs(v)
455
+ case 'x':
456
+ p.fmt.fmtBx(v, ldigits)
457
+ case 'X':
458
+ p.fmt.fmtBx(v, udigits)
459
+ case 'q':
460
+ p.fmt.fmtQ(string(v))
461
+ default:
462
+ p.printElems(a, verb, 0, false)
463
+ }
464
+ }
465
+
466
+ func (p *pp) fmtPointer(a fmtrt.Arg, verb rune) {
467
+ var u uint64
468
+ switch a.K {
469
+ case fmtrt.KChan, fmtrt.KFunc, fmtrt.KPtr, fmtrt.KUnsafePtr, fmtrt.KMap, fmtrt.KSlice:
470
+ if !a.Nil {
471
+ u = fmtrt.ArgPtrID(a)
472
+ }
473
+ default:
474
+ p.badVerb(verb, a)
475
+ return
476
+ }
477
+
478
+ switch verb {
479
+ case 'v':
480
+ if p.fmt.sharpV {
481
+ p.writeByte('(')
482
+ p.writeString(a.T)
483
+ p.writeString(")(")
484
+ if u == 0 {
485
+ p.writeString(nilString)
486
+ } else {
487
+ p.fmt0x64(u, true)
488
+ }
489
+ p.writeByte(')')
490
+ } else {
491
+ if u == 0 {
492
+ p.fmt.padString(nilAngleString)
493
+ } else {
494
+ p.fmt0x64(u, !p.fmt.sharp)
495
+ }
496
+ }
497
+ case 'p':
498
+ p.fmt0x64(u, !p.fmt.sharp)
499
+ case 'b', 'o', 'd', 'x', 'X':
500
+ p.fmtInteger(u, unsigned, verb, a)
501
+ default:
502
+ p.badVerb(verb, a)
503
+ }
504
+ }
505
+
506
+ // callMethod runs f, one of the String, GoString or Error methods of the
507
+ // operand, and writes the string it returns. A panic in the method is
508
+ // reported in the output; a nil receiver prints as <nil>.
509
+ func (p *pp) callMethod(a fmtrt.Arg, verb rune, method string, f func() string) {
510
+ defer func() {
511
+ if err := recover(); err != nil {
512
+ // If it's a nil pointer, just say "<nil>". The likeliest causes are a
513
+ // Stringer that fails to guard against nil or a nil pointer for a
514
+ // value receiver, and in either case, "<nil>" is a nice result.
515
+ if a.K == fmtrt.KPtr && a.Nil {
516
+ p.writeString(nilAngleString)
517
+ return
518
+ }
519
+ // Otherwise print a concise panic message. Most of the time the panic
520
+ // value will print itself nicely.
521
+ if p.panicking {
522
+ // Nested panics; the recursion in printArg cannot succeed.
523
+ panic(err)
524
+ }
525
+
526
+ oldFlags := p.fmt.saveFlags()
527
+ // For this output we want default behavior.
528
+ p.fmt.clearflags()
529
+
530
+ p.writeString(percentBangString)
531
+ p.writeRune(verb)
532
+ p.writeString(panicString)
533
+ p.writeString(method)
534
+ p.writeString(" method: ")
535
+ p.panicking = true
536
+ p.printArg(describe(err), 'v')
537
+ p.panicking = false
538
+ p.writeByte(')')
539
+
540
+ p.fmt.restoreFlags(oldFlags)
541
+ }
542
+ }()
543
+ if method == "GoString" {
544
+ p.fmt.fmtS(f())
545
+ return
546
+ }
547
+ p.fmtString(f(), verb, a)
548
+ }
549
+
550
+ // handleMethods calls the String, GoString or Error method of the operand.
551
+ // A value reached through an unexported field (ro) answers only to Error:
552
+ // reflection cannot call its other methods.
553
+ func (p *pp) handleMethods(a fmtrt.Arg, verb rune, ro bool) (handled bool) {
554
+ if p.erroring {
555
+ return
556
+ }
557
+ if verb == 'w' {
558
+ // It is invalid to use %w other than with Errorf or with a non-error arg.
559
+ if a.Err == nil || !p.wrapErrs {
560
+ p.badVerb(verb, a)
561
+ return true
562
+ }
563
+ // Format the error as %v.
564
+ verb = 'v'
565
+ }
566
+ // If we're doing Go syntax and the argument knows how to supply it, take care of it now.
567
+ if p.fmt.sharpV {
568
+ if a.GoStr != nil && !ro {
569
+ handled = true
570
+ p.callMethod(a, verb, "GoString", func() string { return a.GoStr.GoString() })
571
+ return
572
+ }
573
+ } else {
574
+ // If a string is acceptable according to the format, see if
575
+ // the value satisfies one of the string-valued interfaces.
576
+ // Println etc. set verb to %v, which is "stringable".
577
+ switch verb {
578
+ case 'v', 's', 'x', 'X', 'q':
579
+ // Is it an error or Stringer?
580
+ // The duplication in the bodies is necessary:
581
+ // setting handled and deferring catchPanic
582
+ // must happen before calling the method.
583
+ if a.Err != nil {
584
+ handled = true
585
+ p.callMethod(a, verb, "Error", func() string { return a.Err.Error() })
586
+ return
587
+ }
588
+ if a.Str != nil && !ro {
589
+ handled = true
590
+ p.callMethod(a, verb, "String", func() string { return a.Str.String() })
591
+ return
592
+ }
593
+ }
594
+ }
595
+ return false
596
+ }
597
+
598
+ func (p *pp) printArg(a fmtrt.Arg, verb rune) {
599
+ if a.K == fmtrt.KInterface && a.V == nil && a.T == "" {
600
+ switch verb {
601
+ case 'T', 'v':
602
+ p.fmt.padString(nilAngleString)
603
+ default:
604
+ p.badVerb(verb, a)
605
+ }
606
+ return
607
+ }
608
+
609
+ // Special processing considerations.
610
+ // %T (the value's type) and %p (its address) are special; we always do them first.
611
+ switch verb {
612
+ case 'T':
613
+ p.fmt.fmtS(typeName(a))
614
+ return
615
+ case 'p':
616
+ p.fmtPointer(a, 'p')
617
+ return
618
+ }
619
+ p.printDesc(a, verb, 0, false)
620
+ }
621
+
622
+ // printDesc formats one described value. depth is how deeply it is nested in
623
+ // the operand: a pointer prints as the value it points to only at depth 0.
624
+ func (p *pp) printDesc(a fmtrt.Arg, verb rune, depth int, ro bool) {
625
+ if a.K == fmtrt.KInterface {
626
+ if a.V == nil {
627
+ p.writeString(nilAngleString)
628
+ return
629
+ }
630
+ // An operand held in an interface at the top level is the operand
631
+ // itself: Go's printArg reflects on its dynamic value.
632
+ if depth > 0 {
633
+ depth++
634
+ }
635
+ p.printDesc(describe(a.V), verb, depth, ro)
636
+ return
637
+ }
638
+ if p.handleMethods(a, verb, ro) {
639
+ return
640
+ }
641
+ switch a.K {
642
+ case fmtrt.KBool:
643
+ p.fmtBool(a.B, verb, a)
644
+ case fmtrt.KInt:
645
+ p.fmtInteger(uint64(a.I), signed, verb, a)
646
+ case fmtrt.KUint:
647
+ p.fmtInteger(a.U, unsigned, verb, a)
648
+ case fmtrt.KFloat:
649
+ p.fmtFloat(a.R, a.Size, verb, a)
650
+ case fmtrt.KComplex:
651
+ p.fmtComplex(a.R, a.Im, a.Size, verb, a)
652
+ case fmtrt.KString:
653
+ p.fmtString(a.S, verb, a)
654
+ case fmtrt.KMap:
655
+ p.printMap(a, verb, depth, ro)
656
+ case fmtrt.KStruct:
657
+ p.printStruct(a, verb, depth, ro)
658
+ case fmtrt.KArray, fmtrt.KSlice:
659
+ if a.IsBytes {
660
+ switch verb {
661
+ case 's', 'q', 'x', 'X', 'v', 'd':
662
+ p.fmtBytes(a.Bytes, verb, a)
663
+ return
664
+ }
665
+ }
666
+ p.printElems(a, verb, depth, ro)
667
+ case fmtrt.KPtr:
668
+ // pointer to array or slice or struct? ok at top level
669
+ // but not embedded (avoid loops)
670
+ if depth == 0 && !a.Nil && a.Inner != nil {
671
+ p.writeByte('&')
672
+ p.printDesc(a.Inner(), verb, depth+1, ro)
673
+ return
674
+ }
675
+ p.fmtPointer(a, verb)
676
+ case fmtrt.KChan, fmtrt.KFunc, fmtrt.KUnsafePtr:
677
+ p.fmtPointer(a, verb)
678
+ default:
679
+ // A value whose methods did not apply: describe it by its fields.
680
+ if a.K == fmtrt.KNone && a.V != nil && (a.Err != nil || a.Str != nil || a.GoStr != nil) {
681
+ if d, ok := fmtrt.Lookup(a.V); ok {
682
+ d.Err, d.Str, d.GoStr = a.Err, a.Str, a.GoStr
683
+ p.printDesc(d, verb, depth, ro)
684
+ return
685
+ }
686
+ }
687
+ // The error errors.New returns is a pointer to a struct of a package
688
+ // that fmt cannot spell: it prints itself.
689
+ if f, ok := a.V.(interface{ GofrontFmt(rune) string }); ok && depth == 0 {
690
+ p.writeString(f.GofrontFmt(verb))
691
+ return
692
+ }
693
+ // A value of a type no generated description covers. What reaches
694
+ // here is a nil func in an interface, which has no type to look up,
695
+ // and prints as nil.
696
+ if a.V == nil || verb == 'v' {
697
+ p.writeString(nilAngleString)
698
+ return
699
+ }
700
+ p.writeString(percentBangString)
701
+ p.writeRune(verb)
702
+ p.writeString("(unknown)")
703
+ }
704
+ }
705
+
706
+ // isExported reports whether a field name is exported.
707
+ func isExported(name string) bool {
708
+ return name != "" && name[0] >= 'A' && name[0] <= 'Z'
709
+ }
710
+
711
+ func (p *pp) printStruct(a fmtrt.Arg, verb rune, depth int, ro bool) {
712
+ if p.fmt.sharpV {
713
+ p.writeString(a.T)
714
+ }
715
+ p.writeByte('{')
716
+ for i := 0; i < a.N; i++ {
717
+ if i > 0 {
718
+ if p.fmt.sharpV {
719
+ p.writeString(commaSpaceString)
720
+ } else {
721
+ p.writeByte(' ')
722
+ }
723
+ }
724
+ name, f := a.Field(i)
725
+ if p.fmt.plusV || p.fmt.sharpV {
726
+ if name != "" {
727
+ p.writeString(name)
728
+ p.writeByte(':')
729
+ }
730
+ }
731
+ p.printDesc(f, verb, depth+1, ro || !isExported(name))
732
+ }
733
+ p.writeByte('}')
734
+ }
735
+
736
+ func (p *pp) printElems(a fmtrt.Arg, verb rune, depth int, ro bool) {
737
+ if p.fmt.sharpV {
738
+ p.writeString(a.T)
739
+ if a.K == fmtrt.KSlice && a.Nil {
740
+ p.writeString(nilParenString)
741
+ return
742
+ }
743
+ p.writeByte('{')
744
+ for i := 0; i < a.N; i++ {
745
+ if i > 0 {
746
+ p.writeString(commaSpaceString)
747
+ }
748
+ p.printDesc(a.Elem(i), verb, depth+1, ro)
749
+ }
750
+ p.writeByte('}')
751
+ return
752
+ }
753
+ p.writeByte('[')
754
+ for i := 0; i < a.N; i++ {
755
+ if i > 0 {
756
+ p.writeByte(' ')
757
+ }
758
+ p.printDesc(a.Elem(i), verb, depth+1, ro)
759
+ }
760
+ p.writeByte(']')
761
+ }
762
+
763
+ func (p *pp) printMap(a fmtrt.Arg, verb rune, depth int, ro bool) {
764
+ if p.fmt.sharpV {
765
+ p.writeString(a.T)
766
+ if a.Nil {
767
+ p.writeString(nilParenString)
768
+ return
769
+ }
770
+ p.writeByte('{')
771
+ } else {
772
+ p.writeString(mapString)
773
+ }
774
+ entries := sortedEntries(a.Entries())
775
+ for i, e := range entries {
776
+ if i > 0 {
777
+ if p.fmt.sharpV {
778
+ p.writeString(commaSpaceString)
779
+ } else {
780
+ p.writeByte(' ')
781
+ }
782
+ }
783
+ p.printDesc(e.Key, verb, depth+1, ro)
784
+ p.writeByte(':')
785
+ p.printDesc(e.Val, verb, depth+1, ro)
786
+ }
787
+ if p.fmt.sharpV {
788
+ p.writeByte('}')
789
+ } else {
790
+ p.writeByte(']')
791
+ }
792
+ }
793
+
794
+ // sortedEntries orders map entries like internal/fmtsort: by key, with
795
+ // structs and arrays compared field by field.
796
+ func sortedEntries(es []fmtrt.Entry) []fmtrt.Entry {
797
+ if len(es) < 2 {
798
+ return es
799
+ }
800
+ return mergeEntries(es, make([]fmtrt.Entry, len(es)))
801
+ }
802
+
803
+ // mergeEntries is a stable merge sort of es using tmp as scratch space. It
804
+ // keeps fmt from importing slices, whose source every fmt user would
805
+ // otherwise have to parse and check.
806
+ func mergeEntries(es, tmp []fmtrt.Entry) []fmtrt.Entry {
807
+ if len(es) < 2 {
808
+ return es
809
+ }
810
+ mid := len(es) / 2
811
+ left := mergeEntries(es[:mid], tmp[:mid])
812
+ right := mergeEntries(es[mid:], tmp[mid:])
813
+ i, j, k := 0, 0, 0
814
+ for i < len(left) && j < len(right) {
815
+ if compareArgs(right[j].Key, left[i].Key) < 0 {
816
+ tmp[k] = right[j]
817
+ j++
818
+ } else {
819
+ tmp[k] = left[i]
820
+ i++
821
+ }
822
+ k++
823
+ }
824
+ for i < len(left) {
825
+ tmp[k] = left[i]
826
+ i++
827
+ k++
828
+ }
829
+ for j < len(right) {
830
+ tmp[k] = right[j]
831
+ j++
832
+ k++
833
+ }
834
+ copy(es, tmp[:k])
835
+ return es
836
+ }
837
+
838
+ func compareInt(a, b int64) int {
839
+ if a < b {
840
+ return -1
841
+ }
842
+ if a > b {
843
+ return 1
844
+ }
845
+ return 0
846
+ }
847
+
848
+ func compareUint(a, b uint64) int {
849
+ if a < b {
850
+ return -1
851
+ }
852
+ if a > b {
853
+ return 1
854
+ }
855
+ return 0
856
+ }
857
+
858
+ func compareFloat(a, b float64) int {
859
+ switch {
860
+ case a < b:
861
+ return -1
862
+ case a > b:
863
+ return 1
864
+ case a == b:
865
+ return 0
866
+ }
867
+ // NaN compares less than non-NaN floats.
868
+ switch {
869
+ case a != a && b != b:
870
+ return 0
871
+ case a != a:
872
+ return -1
873
+ }
874
+ return 1
875
+ }
876
+
877
+ // compareArgs is the order fmt prints map keys in.
878
+ func compareArgs(a, b fmtrt.Arg) int {
879
+ if a.K == fmtrt.KInterface || b.K == fmtrt.KInterface {
880
+ // nil sorts before everything else.
881
+ if a.V == nil || b.V == nil {
882
+ return compareInt(boolInt(a.V != nil), boolInt(b.V != nil))
883
+ }
884
+ x, y := describe(a.V), describe(b.V)
885
+ if x.T != y.T {
886
+ // Values of different types: the order of Go's type descriptors,
887
+ // which this mirrors for the common cases, a named type before its
888
+ // underlying type and strings before numbers.
889
+ if x.K != y.K {
890
+ return compareInt(int64(y.K), int64(x.K))
891
+ }
892
+ if x.T < y.T {
893
+ return -1
894
+ }
895
+ return 1
896
+ }
897
+ return compareArgs(x, y)
898
+ }
899
+ if a.K != b.K {
900
+ return compareInt(int64(a.K), int64(b.K))
901
+ }
902
+ switch a.K {
903
+ case fmtrt.KBool:
904
+ return compareInt(boolInt(a.B), boolInt(b.B))
905
+ case fmtrt.KInt:
906
+ return compareInt(a.I, b.I)
907
+ case fmtrt.KUint:
908
+ return compareUint(a.U, b.U)
909
+ case fmtrt.KFloat:
910
+ return compareFloat(a.R, b.R)
911
+ case fmtrt.KComplex:
912
+ if c := compareFloat(a.R, b.R); c != 0 {
913
+ return c
914
+ }
915
+ return compareFloat(a.Im, b.Im)
916
+ case fmtrt.KString:
917
+ if a.S < b.S {
918
+ return -1
919
+ }
920
+ if a.S > b.S {
921
+ return 1
922
+ }
923
+ return 0
924
+ case fmtrt.KPtr, fmtrt.KChan, fmtrt.KUnsafePtr:
925
+ return compareUint(fmtrt.ArgPtrID(a), fmtrt.ArgPtrID(b))
926
+ case fmtrt.KStruct:
927
+ for i := 0; i < a.N; i++ {
928
+ _, x := a.Field(i)
929
+ _, y := b.Field(i)
930
+ if c := compareArgs(x, y); c != 0 {
931
+ return c
932
+ }
933
+ }
934
+ case fmtrt.KArray:
935
+ for i := 0; i < a.N; i++ {
936
+ if c := compareArgs(a.Elem(i), b.Elem(i)); c != 0 {
937
+ return c
938
+ }
939
+ }
940
+ }
941
+ return 0
942
+ }
943
+
944
+ func boolInt(b bool) int64 {
945
+ if b {
946
+ return 1
947
+ }
948
+ return 0
949
+ }
950
+
951
+ // tooLarge reports whether the magnitude of the integer is
952
+ // too large to be used as a formatting width or precision.
953
+ func tooLarge(x int) bool {
954
+ const max int = 1e6
955
+ return x > max || x < -max
956
+ }
957
+
958
+ // parsenum converts ASCII to integer. num is 0 (and isnum is false) if no number present.
959
+ func parsenum(s string, start, end int) (num int, isnum bool, newi int) {
960
+ if start >= end {
961
+ return 0, false, end
962
+ }
963
+ for newi = start; newi < end && '0' <= s[newi] && s[newi] <= '9'; newi++ {
964
+ if tooLarge(num) {
965
+ return 0, false, end // Overflow; crazy long number most likely.
966
+ }
967
+ num = num*10 + int(s[newi]-'0')
968
+ isnum = true
969
+ }
970
+ return
971
+ }
972
+
973
+ // intFromArg reads the integer operand of a * width or precision.
974
+ func intFromArg(a []any, argNum int) (num int, isInt bool, newArgNum int) {
975
+ newArgNum = argNum
976
+ if argNum < len(a) {
977
+ d := describe(a[argNum])
978
+ switch d.K {
979
+ case fmtrt.KInt:
980
+ if int64(int(d.I)) == d.I {
981
+ num = int(d.I)
982
+ isInt = true
983
+ }
984
+ case fmtrt.KUint:
985
+ if int64(d.U) >= 0 && uint64(int(d.U)) == d.U {
986
+ num = int(d.U)
987
+ isInt = true
988
+ }
989
+ }
990
+ newArgNum = argNum + 1
991
+ if tooLarge(num) {
992
+ num = 0
993
+ isInt = false
994
+ }
995
+ }
996
+ return
997
+ }
998
+
999
+ // parseArgNumber returns the value of the bracketed number, minus 1
1000
+ // (explicit argument numbers are one-indexed but we want zero-indexed).
1001
+ // The opening bracket is known to be present at format[0].
1002
+ // The returned values are the index, the number of bytes to consume
1003
+ // up to the closing paren, if present, and whether the number parsed
1004
+ // ok. The bytes to consume will be 1 if no closing paren is present.
1005
+ func parseArgNumber(format string) (index int, wid int, ok bool) {
1006
+ // There must be at least 3 bytes: [n].
1007
+ if len(format) < 3 {
1008
+ return 0, 1, false
1009
+ }
1010
+
1011
+ // Find closing bracket.
1012
+ for i := 1; i < len(format); i++ {
1013
+ if format[i] == ']' {
1014
+ width, ok, newi := parsenum(format, 1, i)
1015
+ if !ok || newi != i {
1016
+ return 0, i + 1, false
1017
+ }
1018
+ return width - 1, i + 1, true // arg numbers are one-indexed and skip paren.
1019
+ }
1020
+ }
1021
+ return 0, 1, false
1022
+ }
1023
+
1024
+ // argNumber returns the next argument to evaluate, which is either the value of the passed-in
1025
+ // argNum or the value of the bracketed integer that begins format[i:]. It also returns
1026
+ // the new value of i, that is, the index of the next byte of the format to process.
1027
+ func (p *pp) argNumber(argNum int, format string, i int, numArgs int) (newArgNum, newi int, found bool) {
1028
+ if len(format) <= i || format[i] != '[' {
1029
+ return argNum, i, false
1030
+ }
1031
+ p.reordered = true
1032
+ index, wid, ok := parseArgNumber(format[i:])
1033
+ if ok && 0 <= index && index < numArgs {
1034
+ return index, i + wid, true
1035
+ }
1036
+ p.goodArgNum = false
1037
+ return argNum, i + wid, ok
1038
+ }
1039
+
1040
+ func (p *pp) badArgNum(verb rune) {
1041
+ p.writeString(percentBangString)
1042
+ p.writeRune(verb)
1043
+ p.writeString(badIndexString)
1044
+ }
1045
+
1046
+ func (p *pp) missingArg(verb rune) {
1047
+ p.writeString(percentBangString)
1048
+ p.writeRune(verb)
1049
+ p.writeString(missingString)
1050
+ }
1051
+
1052
+ func (p *pp) doPrintf(format string, a []any) {
1053
+ end := len(format)
1054
+ argNum := 0 // we process one argument per non-trivial format
1055
+ afterIndex := false // previous item in format was an index like [3].
1056
+ p.reordered = false
1057
+ formatLoop:
1058
+ for i := 0; i < end; {
1059
+ p.goodArgNum = true
1060
+ lasti := i
1061
+ for i < end && format[i] != '%' {
1062
+ i++
1063
+ }
1064
+ if i > lasti {
1065
+ p.writeString(format[lasti:i])
1066
+ }
1067
+ if i >= end {
1068
+ // done processing format string
1069
+ break
1070
+ }
1071
+
1072
+ // Process one verb
1073
+ i++
1074
+
1075
+ // Do we have flags?
1076
+ p.fmt.clearflags()
1077
+ simpleFormat:
1078
+ for ; i < end; i++ {
1079
+ c := format[i]
1080
+ switch c {
1081
+ case '#':
1082
+ p.fmt.sharp = true
1083
+ case '0':
1084
+ p.fmt.zero = true
1085
+ case '+':
1086
+ p.fmt.plus = true
1087
+ case '-':
1088
+ p.fmt.minus = true
1089
+ case ' ':
1090
+ p.fmt.space = true
1091
+ default:
1092
+ // Fast path for common case of ascii lower case simple verbs
1093
+ // without precision or width or argument indices.
1094
+ if 'a' <= c && c <= 'z' && argNum < len(a) {
1095
+ switch c {
1096
+ case 'w':
1097
+ p.wrappedErrs = append(p.wrappedErrs, argNum)
1098
+ fallthrough
1099
+ case 'v':
1100
+ // Go syntax
1101
+ p.fmt.sharpV = p.fmt.sharp
1102
+ p.fmt.sharp = false
1103
+ // Struct-field syntax
1104
+ p.fmt.plusV = p.fmt.plus
1105
+ p.fmt.plus = false
1106
+ }
1107
+ p.printArg(describe(a[argNum]), rune(c))
1108
+ argNum++
1109
+ i++
1110
+ continue formatLoop
1111
+ }
1112
+ // Format is more complex than simple flags and a verb or is malformed.
1113
+ break simpleFormat
1114
+ }
1115
+ }
1116
+
1117
+ // Do we have an explicit argument index?
1118
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
1119
+
1120
+ // Do we have width?
1121
+ if i < end && format[i] == '*' {
1122
+ i++
1123
+ p.fmt.wid, p.fmt.widPresent, argNum = intFromArg(a, argNum)
1124
+
1125
+ if !p.fmt.widPresent {
1126
+ p.writeString(badWidthString)
1127
+ }
1128
+
1129
+ // We have a negative width, so take its value and ensure
1130
+ // that the minus flag is set
1131
+ if p.fmt.wid < 0 {
1132
+ p.fmt.wid = -p.fmt.wid
1133
+ p.fmt.minus = true
1134
+ p.fmt.zero = false // Do not pad with zeros to the right.
1135
+ }
1136
+ afterIndex = false
1137
+ } else {
1138
+ p.fmt.wid, p.fmt.widPresent, i = parsenum(format, i, end)
1139
+ if afterIndex && p.fmt.widPresent { // "%[3]2d"
1140
+ p.goodArgNum = false
1141
+ }
1142
+ }
1143
+
1144
+ // Do we have precision?
1145
+ if i+1 <= end && format[i] == '.' {
1146
+ i++
1147
+ if afterIndex { // "%[3].2d"
1148
+ p.goodArgNum = false
1149
+ }
1150
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
1151
+ if i < end && format[i] == '*' {
1152
+ i++
1153
+ p.fmt.prec, p.fmt.precPresent, argNum = intFromArg(a, argNum)
1154
+ // Negative precision arguments don't make sense
1155
+ if p.fmt.prec < 0 {
1156
+ p.fmt.prec = 0
1157
+ p.fmt.precPresent = false
1158
+ }
1159
+ if !p.fmt.precPresent {
1160
+ p.writeString(badPrecString)
1161
+ }
1162
+ afterIndex = false
1163
+ } else {
1164
+ p.fmt.prec, p.fmt.precPresent, i = parsenum(format, i, end)
1165
+ if !p.fmt.precPresent {
1166
+ p.fmt.prec = 0
1167
+ p.fmt.precPresent = true
1168
+ }
1169
+ }
1170
+ }
1171
+
1172
+ if !afterIndex {
1173
+ argNum, i, afterIndex = p.argNumber(argNum, format, i, len(a))
1174
+ }
1175
+
1176
+ if i >= end {
1177
+ p.writeString(noVerbString)
1178
+ break
1179
+ }
1180
+
1181
+ verb, size := rune(format[i]), 1
1182
+ if verb >= utf8.RuneSelf {
1183
+ verb, size = utf8.DecodeRuneInString(format[i:])
1184
+ }
1185
+ i += size
1186
+
1187
+ switch {
1188
+ case verb == '%': // Percent does not absorb operands and ignores f.wid and f.prec.
1189
+ p.writeByte('%')
1190
+ case !p.goodArgNum:
1191
+ p.badArgNum(verb)
1192
+ case argNum >= len(a): // No argument left over to print for the current verb.
1193
+ p.missingArg(verb)
1194
+ case verb == 'w':
1195
+ p.wrappedErrs = append(p.wrappedErrs, argNum)
1196
+ fallthrough
1197
+ case verb == 'v':
1198
+ // Go syntax
1199
+ p.fmt.sharpV = p.fmt.sharp
1200
+ p.fmt.sharp = false
1201
+ // Struct-field syntax
1202
+ p.fmt.plusV = p.fmt.plus
1203
+ p.fmt.plus = false
1204
+ fallthrough
1205
+ default:
1206
+ p.printArg(describe(a[argNum]), verb)
1207
+ argNum++
1208
+ }
1209
+ }
1210
+
1211
+ // Check for extra arguments unless the call accessed the arguments
1212
+ // out of order, in which case it's too expensive to detect if they've all
1213
+ // been used and arguably OK if they're not.
1214
+ if !p.reordered && argNum < len(a) {
1215
+ p.fmt.clearflags()
1216
+ p.writeString(extraString)
1217
+ for i, arg := range a[argNum:] {
1218
+ if i > 0 {
1219
+ p.writeString(commaSpaceString)
1220
+ }
1221
+ if arg == nil {
1222
+ p.writeString(nilAngleString)
1223
+ } else {
1224
+ d := describe(arg)
1225
+ p.writeString(d.T)
1226
+ p.writeByte('=')
1227
+ p.printArg(d, 'v')
1228
+ }
1229
+ }
1230
+ p.writeByte(')')
1231
+ }
1232
+ }