|
0 |
Description: use gcimporter15 again
|
|
1 |
Author: Thorsten Alteholz <debian@alteholz.de> and upstream
|
|
2 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/bexport.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/bexport.go
|
|
3 |
new file mode 100644
|
|
4 |
index 0000000..cbf8bc0
|
|
5 |
--- /dev/null
|
|
6 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/bexport.go
|
|
7 |
@@ -0,0 +1,828 @@
|
|
8 |
+// Copyright 2016 The Go Authors. All rights reserved.
|
|
9 |
+// Use of this source code is governed by a BSD-style
|
|
10 |
+// license that can be found in the LICENSE file.
|
|
11 |
+
|
|
12 |
+// Binary package export.
|
|
13 |
+// This file was derived from $GOROOT/src/cmd/compile/internal/gc/bexport.go;
|
|
14 |
+// see that file for specification of the format.
|
|
15 |
+
|
|
16 |
+package gcimporter
|
|
17 |
+
|
|
18 |
+import (
|
|
19 |
+ "bytes"
|
|
20 |
+ "encoding/binary"
|
|
21 |
+ "fmt"
|
|
22 |
+ "go/ast"
|
|
23 |
+ "go/constant"
|
|
24 |
+ "go/token"
|
|
25 |
+ "go/types"
|
|
26 |
+ "log"
|
|
27 |
+ "math"
|
|
28 |
+ "math/big"
|
|
29 |
+ "sort"
|
|
30 |
+ "strings"
|
|
31 |
+)
|
|
32 |
+
|
|
33 |
+// If debugFormat is set, each integer and string value is preceded by a marker
|
|
34 |
+// and position information in the encoding. This mechanism permits an importer
|
|
35 |
+// to recognize immediately when it is out of sync. The importer recognizes this
|
|
36 |
+// mode automatically (i.e., it can import export data produced with debugging
|
|
37 |
+// support even if debugFormat is not set at the time of import). This mode will
|
|
38 |
+// lead to massively larger export data (by a factor of 2 to 3) and should only
|
|
39 |
+// be enabled during development and debugging.
|
|
40 |
+//
|
|
41 |
+// NOTE: This flag is the first flag to enable if importing dies because of
|
|
42 |
+// (suspected) format errors, and whenever a change is made to the format.
|
|
43 |
+const debugFormat = false // default: false
|
|
44 |
+
|
|
45 |
+// If trace is set, debugging output is printed to std out.
|
|
46 |
+const trace = false // default: false
|
|
47 |
+
|
|
48 |
+// Current export format version. Increase with each format change.
|
|
49 |
+// 4: type name objects support type aliases, uses aliasTag
|
|
50 |
+// 3: Go1.8 encoding (same as version 2, aliasTag defined but never used)
|
|
51 |
+// 2: removed unused bool in ODCL export (compiler only)
|
|
52 |
+// 1: header format change (more regular), export package for _ struct fields
|
|
53 |
+// 0: Go1.7 encoding
|
|
54 |
+const exportVersion = 4
|
|
55 |
+
|
|
56 |
+// trackAllTypes enables cycle tracking for all types, not just named
|
|
57 |
+// types. The existing compiler invariants assume that unnamed types
|
|
58 |
+// that are not completely set up are not used, or else there are spurious
|
|
59 |
+// errors.
|
|
60 |
+// If disabled, only named types are tracked, possibly leading to slightly
|
|
61 |
+// less efficient encoding in rare cases. It also prevents the export of
|
|
62 |
+// some corner-case type declarations (but those are not handled correctly
|
|
63 |
+// with with the textual export format either).
|
|
64 |
+// TODO(gri) enable and remove once issues caused by it are fixed
|
|
65 |
+const trackAllTypes = false
|
|
66 |
+
|
|
67 |
+type exporter struct {
|
|
68 |
+ fset *token.FileSet
|
|
69 |
+ out bytes.Buffer
|
|
70 |
+
|
|
71 |
+ // object -> index maps, indexed in order of serialization
|
|
72 |
+ strIndex map[string]int
|
|
73 |
+ pkgIndex map[*types.Package]int
|
|
74 |
+ typIndex map[types.Type]int
|
|
75 |
+
|
|
76 |
+ // position encoding
|
|
77 |
+ posInfoFormat bool
|
|
78 |
+ prevFile string
|
|
79 |
+ prevLine int
|
|
80 |
+
|
|
81 |
+ // debugging support
|
|
82 |
+ written int // bytes written
|
|
83 |
+ indent int // for trace
|
|
84 |
+}
|
|
85 |
+
|
|
86 |
+// BExportData returns binary export data for pkg.
|
|
87 |
+// If no file set is provided, position info will be missing.
|
|
88 |
+func BExportData(fset *token.FileSet, pkg *types.Package) []byte {
|
|
89 |
+ p := exporter{
|
|
90 |
+ fset: fset,
|
|
91 |
+ strIndex: map[string]int{"": 0}, // empty string is mapped to 0
|
|
92 |
+ pkgIndex: make(map[*types.Package]int),
|
|
93 |
+ typIndex: make(map[types.Type]int),
|
|
94 |
+ posInfoFormat: true, // TODO(gri) might become a flag, eventually
|
|
95 |
+ }
|
|
96 |
+
|
|
97 |
+ // write version info
|
|
98 |
+ // The version string must start with "version %d" where %d is the version
|
|
99 |
+ // number. Additional debugging information may follow after a blank; that
|
|
100 |
+ // text is ignored by the importer.
|
|
101 |
+ p.rawStringln(fmt.Sprintf("version %d", exportVersion))
|
|
102 |
+ var debug string
|
|
103 |
+ if debugFormat {
|
|
104 |
+ debug = "debug"
|
|
105 |
+ }
|
|
106 |
+ p.rawStringln(debug) // cannot use p.bool since it's affected by debugFormat; also want to see this clearly
|
|
107 |
+ p.bool(trackAllTypes)
|
|
108 |
+ p.bool(p.posInfoFormat)
|
|
109 |
+
|
|
110 |
+ // --- generic export data ---
|
|
111 |
+
|
|
112 |
+ // populate type map with predeclared "known" types
|
|
113 |
+ for index, typ := range predeclared {
|
|
114 |
+ p.typIndex[typ] = index
|
|
115 |
+ }
|
|
116 |
+ if len(p.typIndex) != len(predeclared) {
|
|
117 |
+ log.Fatalf("gcimporter: duplicate entries in type map?")
|
|
118 |
+ }
|
|
119 |
+
|
|
120 |
+ // write package data
|
|
121 |
+ p.pkg(pkg, true)
|
|
122 |
+ if trace {
|
|
123 |
+ p.tracef("\n")
|
|
124 |
+ }
|
|
125 |
+
|
|
126 |
+ // write objects
|
|
127 |
+ objcount := 0
|
|
128 |
+ scope := pkg.Scope()
|
|
129 |
+ for _, name := range scope.Names() {
|
|
130 |
+ if !ast.IsExported(name) {
|
|
131 |
+ continue
|
|
132 |
+ }
|
|
133 |
+ if trace {
|
|
134 |
+ p.tracef("\n")
|
|
135 |
+ }
|
|
136 |
+ p.obj(scope.Lookup(name))
|
|
137 |
+ objcount++
|
|
138 |
+ }
|
|
139 |
+
|
|
140 |
+ // indicate end of list
|
|
141 |
+ if trace {
|
|
142 |
+ p.tracef("\n")
|
|
143 |
+ }
|
|
144 |
+ p.tag(endTag)
|
|
145 |
+
|
|
146 |
+ // for self-verification only (redundant)
|
|
147 |
+ p.int(objcount)
|
|
148 |
+
|
|
149 |
+ if trace {
|
|
150 |
+ p.tracef("\n")
|
|
151 |
+ }
|
|
152 |
+
|
|
153 |
+ // --- end of export data ---
|
|
154 |
+
|
|
155 |
+ return p.out.Bytes()
|
|
156 |
+}
|
|
157 |
+
|
|
158 |
+func (p *exporter) pkg(pkg *types.Package, emptypath bool) {
|
|
159 |
+ if pkg == nil {
|
|
160 |
+ log.Fatalf("gcimporter: unexpected nil pkg")
|
|
161 |
+ }
|
|
162 |
+
|
|
163 |
+ // if we saw the package before, write its index (>= 0)
|
|
164 |
+ if i, ok := p.pkgIndex[pkg]; ok {
|
|
165 |
+ p.index('P', i)
|
|
166 |
+ return
|
|
167 |
+ }
|
|
168 |
+
|
|
169 |
+ // otherwise, remember the package, write the package tag (< 0) and package data
|
|
170 |
+ if trace {
|
|
171 |
+ p.tracef("P%d = { ", len(p.pkgIndex))
|
|
172 |
+ defer p.tracef("} ")
|
|
173 |
+ }
|
|
174 |
+ p.pkgIndex[pkg] = len(p.pkgIndex)
|
|
175 |
+
|
|
176 |
+ p.tag(packageTag)
|
|
177 |
+ p.string(pkg.Name())
|
|
178 |
+ if emptypath {
|
|
179 |
+ p.string("")
|
|
180 |
+ } else {
|
|
181 |
+ p.string(pkg.Path())
|
|
182 |
+ }
|
|
183 |
+}
|
|
184 |
+
|
|
185 |
+func (p *exporter) obj(obj types.Object) {
|
|
186 |
+ switch obj := obj.(type) {
|
|
187 |
+ case *types.Const:
|
|
188 |
+ p.tag(constTag)
|
|
189 |
+ p.pos(obj)
|
|
190 |
+ p.qualifiedName(obj)
|
|
191 |
+ p.typ(obj.Type())
|
|
192 |
+ p.value(obj.Val())
|
|
193 |
+
|
|
194 |
+ case *types.TypeName:
|
|
195 |
+ if isAlias(obj) {
|
|
196 |
+ p.tag(aliasTag)
|
|
197 |
+ p.pos(obj)
|
|
198 |
+ p.qualifiedName(obj)
|
|
199 |
+ } else {
|
|
200 |
+ p.tag(typeTag)
|
|
201 |
+ }
|
|
202 |
+ p.typ(obj.Type())
|
|
203 |
+
|
|
204 |
+ case *types.Var:
|
|
205 |
+ p.tag(varTag)
|
|
206 |
+ p.pos(obj)
|
|
207 |
+ p.qualifiedName(obj)
|
|
208 |
+ p.typ(obj.Type())
|
|
209 |
+
|
|
210 |
+ case *types.Func:
|
|
211 |
+ p.tag(funcTag)
|
|
212 |
+ p.pos(obj)
|
|
213 |
+ p.qualifiedName(obj)
|
|
214 |
+ sig := obj.Type().(*types.Signature)
|
|
215 |
+ p.paramList(sig.Params(), sig.Variadic())
|
|
216 |
+ p.paramList(sig.Results(), false)
|
|
217 |
+
|
|
218 |
+ default:
|
|
219 |
+ log.Fatalf("gcimporter: unexpected object %v (%T)", obj, obj)
|
|
220 |
+ }
|
|
221 |
+}
|
|
222 |
+
|
|
223 |
+func (p *exporter) pos(obj types.Object) {
|
|
224 |
+ if !p.posInfoFormat {
|
|
225 |
+ return
|
|
226 |
+ }
|
|
227 |
+
|
|
228 |
+ file, line := p.fileLine(obj)
|
|
229 |
+ if file == p.prevFile {
|
|
230 |
+ // common case: write line delta
|
|
231 |
+ // delta == 0 means different file or no line change
|
|
232 |
+ delta := line - p.prevLine
|
|
233 |
+ p.int(delta)
|
|
234 |
+ if delta == 0 {
|
|
235 |
+ p.int(-1) // -1 means no file change
|
|
236 |
+ }
|
|
237 |
+ } else {
|
|
238 |
+ // different file
|
|
239 |
+ p.int(0)
|
|
240 |
+ // Encode filename as length of common prefix with previous
|
|
241 |
+ // filename, followed by (possibly empty) suffix. Filenames
|
|
242 |
+ // frequently share path prefixes, so this can save a lot
|
|
243 |
+ // of space and make export data size less dependent on file
|
|
244 |
+ // path length. The suffix is unlikely to be empty because
|
|
245 |
+ // file names tend to end in ".go".
|
|
246 |
+ n := commonPrefixLen(p.prevFile, file)
|
|
247 |
+ p.int(n) // n >= 0
|
|
248 |
+ p.string(file[n:]) // write suffix only
|
|
249 |
+ p.prevFile = file
|
|
250 |
+ p.int(line)
|
|
251 |
+ }
|
|
252 |
+ p.prevLine = line
|
|
253 |
+}
|
|
254 |
+
|
|
255 |
+func (p *exporter) fileLine(obj types.Object) (file string, line int) {
|
|
256 |
+ if p.fset != nil {
|
|
257 |
+ pos := p.fset.Position(obj.Pos())
|
|
258 |
+ file = pos.Filename
|
|
259 |
+ line = pos.Line
|
|
260 |
+ }
|
|
261 |
+ return
|
|
262 |
+}
|
|
263 |
+
|
|
264 |
+func commonPrefixLen(a, b string) int {
|
|
265 |
+ if len(a) > len(b) {
|
|
266 |
+ a, b = b, a
|
|
267 |
+ }
|
|
268 |
+ // len(a) <= len(b)
|
|
269 |
+ i := 0
|
|
270 |
+ for i < len(a) && a[i] == b[i] {
|
|
271 |
+ i++
|
|
272 |
+ }
|
|
273 |
+ return i
|
|
274 |
+}
|
|
275 |
+
|
|
276 |
+func (p *exporter) qualifiedName(obj types.Object) {
|
|
277 |
+ p.string(obj.Name())
|
|
278 |
+ p.pkg(obj.Pkg(), false)
|
|
279 |
+}
|
|
280 |
+
|
|
281 |
+func (p *exporter) typ(t types.Type) {
|
|
282 |
+ if t == nil {
|
|
283 |
+ log.Fatalf("gcimporter: nil type")
|
|
284 |
+ }
|
|
285 |
+
|
|
286 |
+ // Possible optimization: Anonymous pointer types *T where
|
|
287 |
+ // T is a named type are common. We could canonicalize all
|
|
288 |
+ // such types *T to a single type PT = *T. This would lead
|
|
289 |
+ // to at most one *T entry in typIndex, and all future *T's
|
|
290 |
+ // would be encoded as the respective index directly. Would
|
|
291 |
+ // save 1 byte (pointerTag) per *T and reduce the typIndex
|
|
292 |
+ // size (at the cost of a canonicalization map). We can do
|
|
293 |
+ // this later, without encoding format change.
|
|
294 |
+
|
|
295 |
+ // if we saw the type before, write its index (>= 0)
|
|
296 |
+ if i, ok := p.typIndex[t]; ok {
|
|
297 |
+ p.index('T', i)
|
|
298 |
+ return
|
|
299 |
+ }
|
|
300 |
+
|
|
301 |
+ // otherwise, remember the type, write the type tag (< 0) and type data
|
|
302 |
+ if trackAllTypes {
|
|
303 |
+ if trace {
|
|
304 |
+ p.tracef("T%d = {>\n", len(p.typIndex))
|
|
305 |
+ defer p.tracef("<\n} ")
|
|
306 |
+ }
|
|
307 |
+ p.typIndex[t] = len(p.typIndex)
|
|
308 |
+ }
|
|
309 |
+
|
|
310 |
+ switch t := t.(type) {
|
|
311 |
+ case *types.Named:
|
|
312 |
+ if !trackAllTypes {
|
|
313 |
+ // if we don't track all types, track named types now
|
|
314 |
+ p.typIndex[t] = len(p.typIndex)
|
|
315 |
+ }
|
|
316 |
+
|
|
317 |
+ p.tag(namedTag)
|
|
318 |
+ p.pos(t.Obj())
|
|
319 |
+ p.qualifiedName(t.Obj())
|
|
320 |
+ p.typ(t.Underlying())
|
|
321 |
+ if !types.IsInterface(t) {
|
|
322 |
+ p.assocMethods(t)
|
|
323 |
+ }
|
|
324 |
+
|
|
325 |
+ case *types.Array:
|
|
326 |
+ p.tag(arrayTag)
|
|
327 |
+ p.int64(t.Len())
|
|
328 |
+ p.typ(t.Elem())
|
|
329 |
+
|
|
330 |
+ case *types.Slice:
|
|
331 |
+ p.tag(sliceTag)
|
|
332 |
+ p.typ(t.Elem())
|
|
333 |
+
|
|
334 |
+ case *dddSlice:
|
|
335 |
+ p.tag(dddTag)
|
|
336 |
+ p.typ(t.elem)
|
|
337 |
+
|
|
338 |
+ case *types.Struct:
|
|
339 |
+ p.tag(structTag)
|
|
340 |
+ p.fieldList(t)
|
|
341 |
+
|
|
342 |
+ case *types.Pointer:
|
|
343 |
+ p.tag(pointerTag)
|
|
344 |
+ p.typ(t.Elem())
|
|
345 |
+
|
|
346 |
+ case *types.Signature:
|
|
347 |
+ p.tag(signatureTag)
|
|
348 |
+ p.paramList(t.Params(), t.Variadic())
|
|
349 |
+ p.paramList(t.Results(), false)
|
|
350 |
+
|
|
351 |
+ case *types.Interface:
|
|
352 |
+ p.tag(interfaceTag)
|
|
353 |
+ p.iface(t)
|
|
354 |
+
|
|
355 |
+ case *types.Map:
|
|
356 |
+ p.tag(mapTag)
|
|
357 |
+ p.typ(t.Key())
|
|
358 |
+ p.typ(t.Elem())
|
|
359 |
+
|
|
360 |
+ case *types.Chan:
|
|
361 |
+ p.tag(chanTag)
|
|
362 |
+ p.int(int(3 - t.Dir())) // hack
|
|
363 |
+ p.typ(t.Elem())
|
|
364 |
+
|
|
365 |
+ default:
|
|
366 |
+ log.Fatalf("gcimporter: unexpected type %T: %s", t, t)
|
|
367 |
+ }
|
|
368 |
+}
|
|
369 |
+
|
|
370 |
+func (p *exporter) assocMethods(named *types.Named) {
|
|
371 |
+ // Sort methods (for determinism).
|
|
372 |
+ var methods []*types.Func
|
|
373 |
+ for i := 0; i < named.NumMethods(); i++ {
|
|
374 |
+ methods = append(methods, named.Method(i))
|
|
375 |
+ }
|
|
376 |
+ sort.Sort(methodsByName(methods))
|
|
377 |
+
|
|
378 |
+ p.int(len(methods))
|
|
379 |
+
|
|
380 |
+ if trace && methods != nil {
|
|
381 |
+ p.tracef("associated methods {>\n")
|
|
382 |
+ }
|
|
383 |
+
|
|
384 |
+ for i, m := range methods {
|
|
385 |
+ if trace && i > 0 {
|
|
386 |
+ p.tracef("\n")
|
|
387 |
+ }
|
|
388 |
+
|
|
389 |
+ p.pos(m)
|
|
390 |
+ name := m.Name()
|
|
391 |
+ p.string(name)
|
|
392 |
+ if !exported(name) {
|
|
393 |
+ p.pkg(m.Pkg(), false)
|
|
394 |
+ }
|
|
395 |
+
|
|
396 |
+ sig := m.Type().(*types.Signature)
|
|
397 |
+ p.paramList(types.NewTuple(sig.Recv()), false)
|
|
398 |
+ p.paramList(sig.Params(), sig.Variadic())
|
|
399 |
+ p.paramList(sig.Results(), false)
|
|
400 |
+ p.int(0) // dummy value for go:nointerface pragma - ignored by importer
|
|
401 |
+ }
|
|
402 |
+
|
|
403 |
+ if trace && methods != nil {
|
|
404 |
+ p.tracef("<\n} ")
|
|
405 |
+ }
|
|
406 |
+}
|
|
407 |
+
|
|
408 |
+type methodsByName []*types.Func
|
|
409 |
+
|
|
410 |
+func (x methodsByName) Len() int { return len(x) }
|
|
411 |
+func (x methodsByName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
|
412 |
+func (x methodsByName) Less(i, j int) bool { return x[i].Name() < x[j].Name() }
|
|
413 |
+
|
|
414 |
+func (p *exporter) fieldList(t *types.Struct) {
|
|
415 |
+ if trace && t.NumFields() > 0 {
|
|
416 |
+ p.tracef("fields {>\n")
|
|
417 |
+ defer p.tracef("<\n} ")
|
|
418 |
+ }
|
|
419 |
+
|
|
420 |
+ p.int(t.NumFields())
|
|
421 |
+ for i := 0; i < t.NumFields(); i++ {
|
|
422 |
+ if trace && i > 0 {
|
|
423 |
+ p.tracef("\n")
|
|
424 |
+ }
|
|
425 |
+ p.field(t.Field(i))
|
|
426 |
+ p.string(t.Tag(i))
|
|
427 |
+ }
|
|
428 |
+}
|
|
429 |
+
|
|
430 |
+func (p *exporter) field(f *types.Var) {
|
|
431 |
+ if !f.IsField() {
|
|
432 |
+ log.Fatalf("gcimporter: field expected")
|
|
433 |
+ }
|
|
434 |
+
|
|
435 |
+ p.pos(f)
|
|
436 |
+ p.fieldName(f)
|
|
437 |
+ p.typ(f.Type())
|
|
438 |
+}
|
|
439 |
+
|
|
440 |
+func (p *exporter) iface(t *types.Interface) {
|
|
441 |
+ // TODO(gri): enable importer to load embedded interfaces,
|
|
442 |
+ // then emit Embeddeds and ExplicitMethods separately here.
|
|
443 |
+ p.int(0)
|
|
444 |
+
|
|
445 |
+ n := t.NumMethods()
|
|
446 |
+ if trace && n > 0 {
|
|
447 |
+ p.tracef("methods {>\n")
|
|
448 |
+ defer p.tracef("<\n} ")
|
|
449 |
+ }
|
|
450 |
+ p.int(n)
|
|
451 |
+ for i := 0; i < n; i++ {
|
|
452 |
+ if trace && i > 0 {
|
|
453 |
+ p.tracef("\n")
|
|
454 |
+ }
|
|
455 |
+ p.method(t.Method(i))
|
|
456 |
+ }
|
|
457 |
+}
|
|
458 |
+
|
|
459 |
+func (p *exporter) method(m *types.Func) {
|
|
460 |
+ sig := m.Type().(*types.Signature)
|
|
461 |
+ if sig.Recv() == nil {
|
|
462 |
+ log.Fatalf("gcimporter: method expected")
|
|
463 |
+ }
|
|
464 |
+
|
|
465 |
+ p.pos(m)
|
|
466 |
+ p.string(m.Name())
|
|
467 |
+ if m.Name() != "_" && !ast.IsExported(m.Name()) {
|
|
468 |
+ p.pkg(m.Pkg(), false)
|
|
469 |
+ }
|
|
470 |
+
|
|
471 |
+ // interface method; no need to encode receiver.
|
|
472 |
+ p.paramList(sig.Params(), sig.Variadic())
|
|
473 |
+ p.paramList(sig.Results(), false)
|
|
474 |
+}
|
|
475 |
+
|
|
476 |
+func (p *exporter) fieldName(f *types.Var) {
|
|
477 |
+ name := f.Name()
|
|
478 |
+
|
|
479 |
+ if f.Anonymous() {
|
|
480 |
+ // anonymous field - we distinguish between 3 cases:
|
|
481 |
+ // 1) field name matches base type name and is exported
|
|
482 |
+ // 2) field name matches base type name and is not exported
|
|
483 |
+ // 3) field name doesn't match base type name (alias name)
|
|
484 |
+ bname := basetypeName(f.Type())
|
|
485 |
+ if name == bname {
|
|
486 |
+ if ast.IsExported(name) {
|
|
487 |
+ name = "" // 1) we don't need to know the field name or package
|
|
488 |
+ } else {
|
|
489 |
+ name = "?" // 2) use unexported name "?" to force package export
|
|
490 |
+ }
|
|
491 |
+ } else {
|
|
492 |
+ // 3) indicate alias and export name as is
|
|
493 |
+ // (this requires an extra "@" but this is a rare case)
|
|
494 |
+ p.string("@")
|
|
495 |
+ }
|
|
496 |
+ }
|
|
497 |
+
|
|
498 |
+ p.string(name)
|
|
499 |
+ if name != "" && !ast.IsExported(name) {
|
|
500 |
+ p.pkg(f.Pkg(), false)
|
|
501 |
+ }
|
|
502 |
+}
|
|
503 |
+
|
|
504 |
+func basetypeName(typ types.Type) string {
|
|
505 |
+ switch typ := deref(typ).(type) {
|
|
506 |
+ case *types.Basic:
|
|
507 |
+ return typ.Name()
|
|
508 |
+ case *types.Named:
|
|
509 |
+ return typ.Obj().Name()
|
|
510 |
+ default:
|
|
511 |
+ return "" // unnamed type
|
|
512 |
+ }
|
|
513 |
+}
|
|
514 |
+
|
|
515 |
+func (p *exporter) paramList(params *types.Tuple, variadic bool) {
|
|
516 |
+ // use negative length to indicate unnamed parameters
|
|
517 |
+ // (look at the first parameter only since either all
|
|
518 |
+ // names are present or all are absent)
|
|
519 |
+ n := params.Len()
|
|
520 |
+ if n > 0 && params.At(0).Name() == "" {
|
|
521 |
+ n = -n
|
|
522 |
+ }
|
|
523 |
+ p.int(n)
|
|
524 |
+ for i := 0; i < params.Len(); i++ {
|
|
525 |
+ q := params.At(i)
|
|
526 |
+ t := q.Type()
|
|
527 |
+ if variadic && i == params.Len()-1 {
|
|
528 |
+ t = &dddSlice{t.(*types.Slice).Elem()}
|
|
529 |
+ }
|
|
530 |
+ p.typ(t)
|
|
531 |
+ if n > 0 {
|
|
532 |
+ name := q.Name()
|
|
533 |
+ p.string(name)
|
|
534 |
+ if name != "_" {
|
|
535 |
+ p.pkg(q.Pkg(), false)
|
|
536 |
+ }
|
|
537 |
+ }
|
|
538 |
+ p.string("") // no compiler-specific info
|
|
539 |
+ }
|
|
540 |
+}
|
|
541 |
+
|
|
542 |
+func (p *exporter) value(x constant.Value) {
|
|
543 |
+ if trace {
|
|
544 |
+ p.tracef("= ")
|
|
545 |
+ }
|
|
546 |
+
|
|
547 |
+ switch x.Kind() {
|
|
548 |
+ case constant.Bool:
|
|
549 |
+ tag := falseTag
|
|
550 |
+ if constant.BoolVal(x) {
|
|
551 |
+ tag = trueTag
|
|
552 |
+ }
|
|
553 |
+ p.tag(tag)
|
|
554 |
+
|
|
555 |
+ case constant.Int:
|
|
556 |
+ if v, exact := constant.Int64Val(x); exact {
|
|
557 |
+ // common case: x fits into an int64 - use compact encoding
|
|
558 |
+ p.tag(int64Tag)
|
|
559 |
+ p.int64(v)
|
|
560 |
+ return
|
|
561 |
+ }
|
|
562 |
+ // uncommon case: large x - use float encoding
|
|
563 |
+ // (powers of 2 will be encoded efficiently with exponent)
|
|
564 |
+ p.tag(floatTag)
|
|
565 |
+ p.float(constant.ToFloat(x))
|
|
566 |
+
|
|
567 |
+ case constant.Float:
|
|
568 |
+ p.tag(floatTag)
|
|
569 |
+ p.float(x)
|
|
570 |
+
|
|
571 |
+ case constant.Complex:
|
|
572 |
+ p.tag(complexTag)
|
|
573 |
+ p.float(constant.Real(x))
|
|
574 |
+ p.float(constant.Imag(x))
|
|
575 |
+
|
|
576 |
+ case constant.String:
|
|
577 |
+ p.tag(stringTag)
|
|
578 |
+ p.string(constant.StringVal(x))
|
|
579 |
+
|
|
580 |
+ case constant.Unknown:
|
|
581 |
+ // package contains type errors
|
|
582 |
+ p.tag(unknownTag)
|
|
583 |
+
|
|
584 |
+ default:
|
|
585 |
+ log.Fatalf("gcimporter: unexpected value %v (%T)", x, x)
|
|
586 |
+ }
|
|
587 |
+}
|
|
588 |
+
|
|
589 |
+func (p *exporter) float(x constant.Value) {
|
|
590 |
+ if x.Kind() != constant.Float {
|
|
591 |
+ log.Fatalf("gcimporter: unexpected constant %v, want float", x)
|
|
592 |
+ }
|
|
593 |
+ // extract sign (there is no -0)
|
|
594 |
+ sign := constant.Sign(x)
|
|
595 |
+ if sign == 0 {
|
|
596 |
+ // x == 0
|
|
597 |
+ p.int(0)
|
|
598 |
+ return
|
|
599 |
+ }
|
|
600 |
+ // x != 0
|
|
601 |
+
|
|
602 |
+ var f big.Float
|
|
603 |
+ if v, exact := constant.Float64Val(x); exact {
|
|
604 |
+ // float64
|
|
605 |
+ f.SetFloat64(v)
|
|
606 |
+ } else if num, denom := constant.Num(x), constant.Denom(x); num.Kind() == constant.Int {
|
|
607 |
+ // TODO(gri): add big.Rat accessor to constant.Value.
|
|
608 |
+ r := valueToRat(num)
|
|
609 |
+ f.SetRat(r.Quo(r, valueToRat(denom)))
|
|
610 |
+ } else {
|
|
611 |
+ // Value too large to represent as a fraction => inaccessible.
|
|
612 |
+ // TODO(gri): add big.Float accessor to constant.Value.
|
|
613 |
+ f.SetFloat64(math.MaxFloat64) // FIXME
|
|
614 |
+ }
|
|
615 |
+
|
|
616 |
+ // extract exponent such that 0.5 <= m < 1.0
|
|
617 |
+ var m big.Float
|
|
618 |
+ exp := f.MantExp(&m)
|
|
619 |
+
|
|
620 |
+ // extract mantissa as *big.Int
|
|
621 |
+ // - set exponent large enough so mant satisfies mant.IsInt()
|
|
622 |
+ // - get *big.Int from mant
|
|
623 |
+ m.SetMantExp(&m, int(m.MinPrec()))
|
|
624 |
+ mant, acc := m.Int(nil)
|
|
625 |
+ if acc != big.Exact {
|
|
626 |
+ log.Fatalf("gcimporter: internal error")
|
|
627 |
+ }
|
|
628 |
+
|
|
629 |
+ p.int(sign)
|
|
630 |
+ p.int(exp)
|
|
631 |
+ p.string(string(mant.Bytes()))
|
|
632 |
+}
|
|
633 |
+
|
|
634 |
+func valueToRat(x constant.Value) *big.Rat {
|
|
635 |
+ // Convert little-endian to big-endian.
|
|
636 |
+ // I can't believe this is necessary.
|
|
637 |
+ bytes := constant.Bytes(x)
|
|
638 |
+ for i := 0; i < len(bytes)/2; i++ {
|
|
639 |
+ bytes[i], bytes[len(bytes)-1-i] = bytes[len(bytes)-1-i], bytes[i]
|
|
640 |
+ }
|
|
641 |
+ return new(big.Rat).SetInt(new(big.Int).SetBytes(bytes))
|
|
642 |
+}
|
|
643 |
+
|
|
644 |
+func (p *exporter) bool(b bool) bool {
|
|
645 |
+ if trace {
|
|
646 |
+ p.tracef("[")
|
|
647 |
+ defer p.tracef("= %v] ", b)
|
|
648 |
+ }
|
|
649 |
+
|
|
650 |
+ x := 0
|
|
651 |
+ if b {
|
|
652 |
+ x = 1
|
|
653 |
+ }
|
|
654 |
+ p.int(x)
|
|
655 |
+ return b
|
|
656 |
+}
|
|
657 |
+
|
|
658 |
+// ----------------------------------------------------------------------------
|
|
659 |
+// Low-level encoders
|
|
660 |
+
|
|
661 |
+func (p *exporter) index(marker byte, index int) {
|
|
662 |
+ if index < 0 {
|
|
663 |
+ log.Fatalf("gcimporter: invalid index < 0")
|
|
664 |
+ }
|
|
665 |
+ if debugFormat {
|
|
666 |
+ p.marker('t')
|
|
667 |
+ }
|
|
668 |
+ if trace {
|
|
669 |
+ p.tracef("%c%d ", marker, index)
|
|
670 |
+ }
|
|
671 |
+ p.rawInt64(int64(index))
|
|
672 |
+}
|
|
673 |
+
|
|
674 |
+func (p *exporter) tag(tag int) {
|
|
675 |
+ if tag >= 0 {
|
|
676 |
+ log.Fatalf("gcimporter: invalid tag >= 0")
|
|
677 |
+ }
|
|
678 |
+ if debugFormat {
|
|
679 |
+ p.marker('t')
|
|
680 |
+ }
|
|
681 |
+ if trace {
|
|
682 |
+ p.tracef("%s ", tagString[-tag])
|
|
683 |
+ }
|
|
684 |
+ p.rawInt64(int64(tag))
|
|
685 |
+}
|
|
686 |
+
|
|
687 |
+func (p *exporter) int(x int) {
|
|
688 |
+ p.int64(int64(x))
|
|
689 |
+}
|
|
690 |
+
|
|
691 |
+func (p *exporter) int64(x int64) {
|
|
692 |
+ if debugFormat {
|
|
693 |
+ p.marker('i')
|
|
694 |
+ }
|
|
695 |
+ if trace {
|
|
696 |
+ p.tracef("%d ", x)
|
|
697 |
+ }
|
|
698 |
+ p.rawInt64(x)
|
|
699 |
+}
|
|
700 |
+
|
|
701 |
+func (p *exporter) string(s string) {
|
|
702 |
+ if debugFormat {
|
|
703 |
+ p.marker('s')
|
|
704 |
+ }
|
|
705 |
+ if trace {
|
|
706 |
+ p.tracef("%q ", s)
|
|
707 |
+ }
|
|
708 |
+ // if we saw the string before, write its index (>= 0)
|
|
709 |
+ // (the empty string is mapped to 0)
|
|
710 |
+ if i, ok := p.strIndex[s]; ok {
|
|
711 |
+ p.rawInt64(int64(i))
|
|
712 |
+ return
|
|
713 |
+ }
|
|
714 |
+ // otherwise, remember string and write its negative length and bytes
|
|
715 |
+ p.strIndex[s] = len(p.strIndex)
|
|
716 |
+ p.rawInt64(-int64(len(s)))
|
|
717 |
+ for i := 0; i < len(s); i++ {
|
|
718 |
+ p.rawByte(s[i])
|
|
719 |
+ }
|
|
720 |
+}
|
|
721 |
+
|
|
722 |
+// marker emits a marker byte and position information which makes
|
|
723 |
+// it easy for a reader to detect if it is "out of sync". Used for
|
|
724 |
+// debugFormat format only.
|
|
725 |
+func (p *exporter) marker(m byte) {
|
|
726 |
+ p.rawByte(m)
|
|
727 |
+ // Enable this for help tracking down the location
|
|
728 |
+ // of an incorrect marker when running in debugFormat.
|
|
729 |
+ if false && trace {
|
|
730 |
+ p.tracef("#%d ", p.written)
|
|
731 |
+ }
|
|
732 |
+ p.rawInt64(int64(p.written))
|
|
733 |
+}
|
|
734 |
+
|
|
735 |
+// rawInt64 should only be used by low-level encoders.
|
|
736 |
+func (p *exporter) rawInt64(x int64) {
|
|
737 |
+ var tmp [binary.MaxVarintLen64]byte
|
|
738 |
+ n := binary.PutVarint(tmp[:], x)
|
|
739 |
+ for i := 0; i < n; i++ {
|
|
740 |
+ p.rawByte(tmp[i])
|
|
741 |
+ }
|
|
742 |
+}
|
|
743 |
+
|
|
744 |
+// rawStringln should only be used to emit the initial version string.
|
|
745 |
+func (p *exporter) rawStringln(s string) {
|
|
746 |
+ for i := 0; i < len(s); i++ {
|
|
747 |
+ p.rawByte(s[i])
|
|
748 |
+ }
|
|
749 |
+ p.rawByte('\n')
|
|
750 |
+}
|
|
751 |
+
|
|
752 |
+// rawByte is the bottleneck interface to write to p.out.
|
|
753 |
+// rawByte escapes b as follows (any encoding does that
|
|
754 |
+// hides '$'):
|
|
755 |
+//
|
|
756 |
+// '$' => '|' 'S'
|
|
757 |
+// '|' => '|' '|'
|
|
758 |
+//
|
|
759 |
+// Necessary so other tools can find the end of the
|
|
760 |
+// export data by searching for "$$".
|
|
761 |
+// rawByte should only be used by low-level encoders.
|
|
762 |
+func (p *exporter) rawByte(b byte) {
|
|
763 |
+ switch b {
|
|
764 |
+ case '$':
|
|
765 |
+ // write '$' as '|' 'S'
|
|
766 |
+ b = 'S'
|
|
767 |
+ fallthrough
|
|
768 |
+ case '|':
|
|
769 |
+ // write '|' as '|' '|'
|
|
770 |
+ p.out.WriteByte('|')
|
|
771 |
+ p.written++
|
|
772 |
+ }
|
|
773 |
+ p.out.WriteByte(b)
|
|
774 |
+ p.written++
|
|
775 |
+}
|
|
776 |
+
|
|
777 |
+// tracef is like fmt.Printf but it rewrites the format string
|
|
778 |
+// to take care of indentation.
|
|
779 |
+func (p *exporter) tracef(format string, args ...interface{}) {
|
|
780 |
+ if strings.ContainsAny(format, "<>\n") {
|
|
781 |
+ var buf bytes.Buffer
|
|
782 |
+ for i := 0; i < len(format); i++ {
|
|
783 |
+ // no need to deal with runes
|
|
784 |
+ ch := format[i]
|
|
785 |
+ switch ch {
|
|
786 |
+ case '>':
|
|
787 |
+ p.indent++
|
|
788 |
+ continue
|
|
789 |
+ case '<':
|
|
790 |
+ p.indent--
|
|
791 |
+ continue
|
|
792 |
+ }
|
|
793 |
+ buf.WriteByte(ch)
|
|
794 |
+ if ch == '\n' {
|
|
795 |
+ for j := p.indent; j > 0; j-- {
|
|
796 |
+ buf.WriteString(". ")
|
|
797 |
+ }
|
|
798 |
+ }
|
|
799 |
+ }
|
|
800 |
+ format = buf.String()
|
|
801 |
+ }
|
|
802 |
+ fmt.Printf(format, args...)
|
|
803 |
+}
|
|
804 |
+
|
|
805 |
+// Debugging support.
|
|
806 |
+// (tagString is only used when tracing is enabled)
|
|
807 |
+var tagString = [...]string{
|
|
808 |
+ // Packages
|
|
809 |
+ -packageTag: "package",
|
|
810 |
+
|
|
811 |
+ // Types
|
|
812 |
+ -namedTag: "named type",
|
|
813 |
+ -arrayTag: "array",
|
|
814 |
+ -sliceTag: "slice",
|
|
815 |
+ -dddTag: "ddd",
|
|
816 |
+ -structTag: "struct",
|
|
817 |
+ -pointerTag: "pointer",
|
|
818 |
+ -signatureTag: "signature",
|
|
819 |
+ -interfaceTag: "interface",
|
|
820 |
+ -mapTag: "map",
|
|
821 |
+ -chanTag: "chan",
|
|
822 |
+
|
|
823 |
+ // Values
|
|
824 |
+ -falseTag: "false",
|
|
825 |
+ -trueTag: "true",
|
|
826 |
+ -int64Tag: "int64",
|
|
827 |
+ -floatTag: "float",
|
|
828 |
+ -fractionTag: "fraction",
|
|
829 |
+ -complexTag: "complex",
|
|
830 |
+ -stringTag: "string",
|
|
831 |
+ -unknownTag: "unknown",
|
|
832 |
+
|
|
833 |
+ // Type aliases
|
|
834 |
+ -aliasTag: "alias",
|
|
835 |
+}
|
|
836 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/bimport.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/bimport.go
|
|
837 |
new file mode 100644
|
|
838 |
index 0000000..6709e43
|
|
839 |
--- /dev/null
|
|
840 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/bimport.go
|
|
841 |
@@ -0,0 +1,996 @@
|
|
842 |
+// Copyright 2015 The Go Authors. All rights reserved.
|
|
843 |
+// Use of this source code is governed by a BSD-style
|
|
844 |
+// license that can be found in the LICENSE file.
|
|
845 |
+
|
|
846 |
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go.
|
|
847 |
+
|
|
848 |
+package gcimporter
|
|
849 |
+
|
|
850 |
+import (
|
|
851 |
+ "encoding/binary"
|
|
852 |
+ "fmt"
|
|
853 |
+ "go/constant"
|
|
854 |
+ "go/token"
|
|
855 |
+ "go/types"
|
|
856 |
+ "sort"
|
|
857 |
+ "strconv"
|
|
858 |
+ "strings"
|
|
859 |
+ "sync"
|
|
860 |
+ "unicode"
|
|
861 |
+ "unicode/utf8"
|
|
862 |
+)
|
|
863 |
+
|
|
864 |
+type importer struct {
|
|
865 |
+ imports map[string]*types.Package
|
|
866 |
+ data []byte
|
|
867 |
+ importpath string
|
|
868 |
+ buf []byte // for reading strings
|
|
869 |
+ version int // export format version
|
|
870 |
+
|
|
871 |
+ // object lists
|
|
872 |
+ strList []string // in order of appearance
|
|
873 |
+ pathList []string // in order of appearance
|
|
874 |
+ pkgList []*types.Package // in order of appearance
|
|
875 |
+ typList []types.Type // in order of appearance
|
|
876 |
+ interfaceList []*types.Interface // for delayed completion only
|
|
877 |
+ trackAllTypes bool
|
|
878 |
+
|
|
879 |
+ // position encoding
|
|
880 |
+ posInfoFormat bool
|
|
881 |
+ prevFile string
|
|
882 |
+ prevLine int
|
|
883 |
+ fset *token.FileSet
|
|
884 |
+ files map[string]*token.File
|
|
885 |
+
|
|
886 |
+ // debugging support
|
|
887 |
+ debugFormat bool
|
|
888 |
+ read int // bytes read
|
|
889 |
+}
|
|
890 |
+
|
|
891 |
+// BImportData imports a package from the serialized package data
|
|
892 |
+// and returns the number of bytes consumed and a reference to the package.
|
|
893 |
+// If the export data version is not recognized or the format is otherwise
|
|
894 |
+// compromised, an error is returned.
|
|
895 |
+func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
|
896 |
+ // catch panics and return them as errors
|
|
897 |
+ defer func() {
|
|
898 |
+ if e := recover(); e != nil {
|
|
899 |
+ // The package (filename) causing the problem is added to this
|
|
900 |
+ // error by a wrapper in the caller (Import in gcimporter.go).
|
|
901 |
+ // Return a (possibly nil or incomplete) package unchanged (see #16088).
|
|
902 |
+ err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e)
|
|
903 |
+ }
|
|
904 |
+ }()
|
|
905 |
+
|
|
906 |
+ p := importer{
|
|
907 |
+ imports: imports,
|
|
908 |
+ data: data,
|
|
909 |
+ importpath: path,
|
|
910 |
+ version: -1, // unknown version
|
|
911 |
+ strList: []string{""}, // empty string is mapped to 0
|
|
912 |
+ pathList: []string{""}, // empty string is mapped to 0
|
|
913 |
+ fset: fset,
|
|
914 |
+ files: make(map[string]*token.File),
|
|
915 |
+ }
|
|
916 |
+
|
|
917 |
+ // read version info
|
|
918 |
+ var versionstr string
|
|
919 |
+ if b := p.rawByte(); b == 'c' || b == 'd' {
|
|
920 |
+ // Go1.7 encoding; first byte encodes low-level
|
|
921 |
+ // encoding format (compact vs debug).
|
|
922 |
+ // For backward-compatibility only (avoid problems with
|
|
923 |
+ // old installed packages). Newly compiled packages use
|
|
924 |
+ // the extensible format string.
|
|
925 |
+ // TODO(gri) Remove this support eventually; after Go1.8.
|
|
926 |
+ if b == 'd' {
|
|
927 |
+ p.debugFormat = true
|
|
928 |
+ }
|
|
929 |
+ p.trackAllTypes = p.rawByte() == 'a'
|
|
930 |
+ p.posInfoFormat = p.int() != 0
|
|
931 |
+ versionstr = p.string()
|
|
932 |
+ if versionstr == "v1" {
|
|
933 |
+ p.version = 0
|
|
934 |
+ }
|
|
935 |
+ } else {
|
|
936 |
+ // Go1.8 extensible encoding
|
|
937 |
+ // read version string and extract version number (ignore anything after the version number)
|
|
938 |
+ versionstr = p.rawStringln(b)
|
|
939 |
+ if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
|
|
940 |
+ if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
|
|
941 |
+ p.version = v
|
|
942 |
+ }
|
|
943 |
+ }
|
|
944 |
+ }
|
|
945 |
+
|
|
946 |
+ // read version specific flags - extend as necessary
|
|
947 |
+ switch p.version {
|
|
948 |
+ // case 7:
|
|
949 |
+ // ...
|
|
950 |
+ // fallthrough
|
|
951 |
+ case 6, 5, 4, 3, 2, 1:
|
|
952 |
+ p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
|
|
953 |
+ p.trackAllTypes = p.int() != 0
|
|
954 |
+ p.posInfoFormat = p.int() != 0
|
|
955 |
+ case 0:
|
|
956 |
+ // Go1.7 encoding format - nothing to do here
|
|
957 |
+ default:
|
|
958 |
+ errorf("unknown export format version %d (%q)", p.version, versionstr)
|
|
959 |
+ }
|
|
960 |
+
|
|
961 |
+ // --- generic export data ---
|
|
962 |
+
|
|
963 |
+ // populate typList with predeclared "known" types
|
|
964 |
+ p.typList = append(p.typList, predeclared...)
|
|
965 |
+
|
|
966 |
+ // read package data
|
|
967 |
+ pkg = p.pkg()
|
|
968 |
+
|
|
969 |
+ // read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go)
|
|
970 |
+ objcount := 0
|
|
971 |
+ for {
|
|
972 |
+ tag := p.tagOrIndex()
|
|
973 |
+ if tag == endTag {
|
|
974 |
+ break
|
|
975 |
+ }
|
|
976 |
+ p.obj(tag)
|
|
977 |
+ objcount++
|
|
978 |
+ }
|
|
979 |
+
|
|
980 |
+ // self-verification
|
|
981 |
+ if count := p.int(); count != objcount {
|
|
982 |
+ errorf("got %d objects; want %d", objcount, count)
|
|
983 |
+ }
|
|
984 |
+
|
|
985 |
+ // ignore compiler-specific import data
|
|
986 |
+
|
|
987 |
+ // complete interfaces
|
|
988 |
+ // TODO(gri) re-investigate if we still need to do this in a delayed fashion
|
|
989 |
+ for _, typ := range p.interfaceList {
|
|
990 |
+ typ.Complete()
|
|
991 |
+ }
|
|
992 |
+
|
|
993 |
+ // record all referenced packages as imports
|
|
994 |
+ list := append(([]*types.Package)(nil), p.pkgList[1:]...)
|
|
995 |
+ sort.Sort(byPath(list))
|
|
996 |
+ pkg.SetImports(list)
|
|
997 |
+
|
|
998 |
+ // package was imported completely and without errors
|
|
999 |
+ pkg.MarkComplete()
|
|
1000 |
+
|
|
1001 |
+ return p.read, pkg, nil
|
|
1002 |
+}
|
|
1003 |
+
|
|
1004 |
+func errorf(format string, args ...interface{}) {
|
|
1005 |
+ panic(fmt.Sprintf(format, args...))
|
|
1006 |
+}
|
|
1007 |
+
|
|
1008 |
+func (p *importer) pkg() *types.Package {
|
|
1009 |
+ // if the package was seen before, i is its index (>= 0)
|
|
1010 |
+ i := p.tagOrIndex()
|
|
1011 |
+ if i >= 0 {
|
|
1012 |
+ return p.pkgList[i]
|
|
1013 |
+ }
|
|
1014 |
+
|
|
1015 |
+ // otherwise, i is the package tag (< 0)
|
|
1016 |
+ if i != packageTag {
|
|
1017 |
+ errorf("unexpected package tag %d version %d", i, p.version)
|
|
1018 |
+ }
|
|
1019 |
+
|
|
1020 |
+ // read package data
|
|
1021 |
+ name := p.string()
|
|
1022 |
+ var path string
|
|
1023 |
+ if p.version >= 5 {
|
|
1024 |
+ path = p.path()
|
|
1025 |
+ } else {
|
|
1026 |
+ path = p.string()
|
|
1027 |
+ }
|
|
1028 |
+ if p.version >= 6 {
|
|
1029 |
+ p.int() // package height; unused by go/types
|
|
1030 |
+ }
|
|
1031 |
+
|
|
1032 |
+ // we should never see an empty package name
|
|
1033 |
+ if name == "" {
|
|
1034 |
+ errorf("empty package name in import")
|
|
1035 |
+ }
|
|
1036 |
+
|
|
1037 |
+ // an empty path denotes the package we are currently importing;
|
|
1038 |
+ // it must be the first package we see
|
|
1039 |
+ if (path == "") != (len(p.pkgList) == 0) {
|
|
1040 |
+ errorf("package path %q for pkg index %d", path, len(p.pkgList))
|
|
1041 |
+ }
|
|
1042 |
+
|
|
1043 |
+ // if the package was imported before, use that one; otherwise create a new one
|
|
1044 |
+ if path == "" {
|
|
1045 |
+ path = p.importpath
|
|
1046 |
+ }
|
|
1047 |
+ pkg := p.imports[path]
|
|
1048 |
+ if pkg == nil {
|
|
1049 |
+ pkg = types.NewPackage(path, name)
|
|
1050 |
+ p.imports[path] = pkg
|
|
1051 |
+ } else if pkg.Name() != name {
|
|
1052 |
+ errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
|
|
1053 |
+ }
|
|
1054 |
+ p.pkgList = append(p.pkgList, pkg)
|
|
1055 |
+
|
|
1056 |
+ return pkg
|
|
1057 |
+}
|
|
1058 |
+
|
|
1059 |
+// objTag returns the tag value for each object kind.
|
|
1060 |
+func objTag(obj types.Object) int {
|
|
1061 |
+ switch obj.(type) {
|
|
1062 |
+ case *types.Const:
|
|
1063 |
+ return constTag
|
|
1064 |
+ case *types.TypeName:
|
|
1065 |
+ return typeTag
|
|
1066 |
+ case *types.Var:
|
|
1067 |
+ return varTag
|
|
1068 |
+ case *types.Func:
|
|
1069 |
+ return funcTag
|
|
1070 |
+ default:
|
|
1071 |
+ errorf("unexpected object: %v (%T)", obj, obj) // panics
|
|
1072 |
+ panic("unreachable")
|
|
1073 |
+ }
|
|
1074 |
+}
|
|
1075 |
+
|
|
1076 |
+func sameObj(a, b types.Object) bool {
|
|
1077 |
+ // Because unnamed types are not canonicalized, we cannot simply compare types for
|
|
1078 |
+ // (pointer) identity.
|
|
1079 |
+ // Ideally we'd check equality of constant values as well, but this is good enough.
|
|
1080 |
+ return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
|
|
1081 |
+}
|
|
1082 |
+
|
|
1083 |
+func (p *importer) declare(obj types.Object) {
|
|
1084 |
+ pkg := obj.Pkg()
|
|
1085 |
+ if alt := pkg.Scope().Insert(obj); alt != nil {
|
|
1086 |
+ // This can only trigger if we import a (non-type) object a second time.
|
|
1087 |
+ // Excluding type aliases, this cannot happen because 1) we only import a package
|
|
1088 |
+ // once; and b) we ignore compiler-specific export data which may contain
|
|
1089 |
+ // functions whose inlined function bodies refer to other functions that
|
|
1090 |
+ // were already imported.
|
|
1091 |
+ // However, type aliases require reexporting the original type, so we need
|
|
1092 |
+ // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
|
|
1093 |
+ // method importer.obj, switch case importing functions).
|
|
1094 |
+ // TODO(gri) review/update this comment once the gc compiler handles type aliases.
|
|
1095 |
+ if !sameObj(obj, alt) {
|
|
1096 |
+ errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
|
|
1097 |
+ }
|
|
1098 |
+ }
|
|
1099 |
+}
|
|
1100 |
+
|
|
1101 |
+func (p *importer) obj(tag int) {
|
|
1102 |
+ switch tag {
|
|
1103 |
+ case constTag:
|
|
1104 |
+ pos := p.pos()
|
|
1105 |
+ pkg, name := p.qualifiedName()
|
|
1106 |
+ typ := p.typ(nil)
|
|
1107 |
+ val := p.value()
|
|
1108 |
+ p.declare(types.NewConst(pos, pkg, name, typ, val))
|
|
1109 |
+
|
|
1110 |
+ case aliasTag:
|
|
1111 |
+ // TODO(gri) verify type alias hookup is correct
|
|
1112 |
+ pos := p.pos()
|
|
1113 |
+ pkg, name := p.qualifiedName()
|
|
1114 |
+ typ := p.typ(nil)
|
|
1115 |
+ p.declare(types.NewTypeName(pos, pkg, name, typ))
|
|
1116 |
+
|
|
1117 |
+ case typeTag:
|
|
1118 |
+ p.typ(nil)
|
|
1119 |
+
|
|
1120 |
+ case varTag:
|
|
1121 |
+ pos := p.pos()
|
|
1122 |
+ pkg, name := p.qualifiedName()
|
|
1123 |
+ typ := p.typ(nil)
|
|
1124 |
+ p.declare(types.NewVar(pos, pkg, name, typ))
|
|
1125 |
+
|
|
1126 |
+ case funcTag:
|
|
1127 |
+ pos := p.pos()
|
|
1128 |
+ pkg, name := p.qualifiedName()
|
|
1129 |
+ params, isddd := p.paramList()
|
|
1130 |
+ result, _ := p.paramList()
|
|
1131 |
+ sig := types.NewSignature(nil, params, result, isddd)
|
|
1132 |
+ p.declare(types.NewFunc(pos, pkg, name, sig))
|
|
1133 |
+
|
|
1134 |
+ default:
|
|
1135 |
+ errorf("unexpected object tag %d", tag)
|
|
1136 |
+ }
|
|
1137 |
+}
|
|
1138 |
+
|
|
1139 |
+const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
|
|
1140 |
+
|
|
1141 |
+func (p *importer) pos() token.Pos {
|
|
1142 |
+ if !p.posInfoFormat {
|
|
1143 |
+ return token.NoPos
|
|
1144 |
+ }
|
|
1145 |
+
|
|
1146 |
+ file := p.prevFile
|
|
1147 |
+ line := p.prevLine
|
|
1148 |
+ delta := p.int()
|
|
1149 |
+ line += delta
|
|
1150 |
+ if p.version >= 5 {
|
|
1151 |
+ if delta == deltaNewFile {
|
|
1152 |
+ if n := p.int(); n >= 0 {
|
|
1153 |
+ // file changed
|
|
1154 |
+ file = p.path()
|
|
1155 |
+ line = n
|
|
1156 |
+ }
|
|
1157 |
+ }
|
|
1158 |
+ } else {
|
|
1159 |
+ if delta == 0 {
|
|
1160 |
+ if n := p.int(); n >= 0 {
|
|
1161 |
+ // file changed
|
|
1162 |
+ file = p.prevFile[:n] + p.string()
|
|
1163 |
+ line = p.int()
|
|
1164 |
+ }
|
|
1165 |
+ }
|
|
1166 |
+ }
|
|
1167 |
+ p.prevFile = file
|
|
1168 |
+ p.prevLine = line
|
|
1169 |
+
|
|
1170 |
+ // Synthesize a token.Pos
|
|
1171 |
+
|
|
1172 |
+ // Since we don't know the set of needed file positions, we
|
|
1173 |
+ // reserve maxlines positions per file.
|
|
1174 |
+ const maxlines = 64 * 1024
|
|
1175 |
+ f := p.files[file]
|
|
1176 |
+ if f == nil {
|
|
1177 |
+ f = p.fset.AddFile(file, -1, maxlines)
|
|
1178 |
+ p.files[file] = f
|
|
1179 |
+ // Allocate the fake linebreak indices on first use.
|
|
1180 |
+ // TODO(adonovan): opt: save ~512KB using a more complex scheme?
|
|
1181 |
+ fakeLinesOnce.Do(func() {
|
|
1182 |
+ fakeLines = make([]int, maxlines)
|
|
1183 |
+ for i := range fakeLines {
|
|
1184 |
+ fakeLines[i] = i
|
|
1185 |
+ }
|
|
1186 |
+ })
|
|
1187 |
+ f.SetLines(fakeLines)
|
|
1188 |
+ }
|
|
1189 |
+
|
|
1190 |
+ if line > maxlines {
|
|
1191 |
+ line = 1
|
|
1192 |
+ }
|
|
1193 |
+
|
|
1194 |
+ // Treat the file as if it contained only newlines
|
|
1195 |
+ // and column=1: use the line number as the offset.
|
|
1196 |
+ return f.Pos(line - 1)
|
|
1197 |
+}
|
|
1198 |
+
|
|
1199 |
+var (
|
|
1200 |
+ fakeLines []int
|
|
1201 |
+ fakeLinesOnce sync.Once
|
|
1202 |
+)
|
|
1203 |
+
|
|
1204 |
+func (p *importer) qualifiedName() (pkg *types.Package, name string) {
|
|
1205 |
+ name = p.string()
|
|
1206 |
+ pkg = p.pkg()
|
|
1207 |
+ return
|
|
1208 |
+}
|
|
1209 |
+
|
|
1210 |
+func (p *importer) record(t types.Type) {
|
|
1211 |
+ p.typList = append(p.typList, t)
|
|
1212 |
+}
|
|
1213 |
+
|
|
1214 |
+// A dddSlice is a types.Type representing ...T parameters.
|
|
1215 |
+// It only appears for parameter types and does not escape
|
|
1216 |
+// the importer.
|
|
1217 |
+type dddSlice struct {
|
|
1218 |
+ elem types.Type
|
|
1219 |
+}
|
|
1220 |
+
|
|
1221 |
+func (t *dddSlice) Underlying() types.Type { return t }
|
|
1222 |
+func (t *dddSlice) String() string { return "..." + t.elem.String() }
|
|
1223 |
+
|
|
1224 |
+// parent is the package which declared the type; parent == nil means
|
|
1225 |
+// the package currently imported. The parent package is needed for
|
|
1226 |
+// exported struct fields and interface methods which don't contain
|
|
1227 |
+// explicit package information in the export data.
|
|
1228 |
+func (p *importer) typ(parent *types.Package) types.Type {
|
|
1229 |
+ // if the type was seen before, i is its index (>= 0)
|
|
1230 |
+ i := p.tagOrIndex()
|
|
1231 |
+ if i >= 0 {
|
|
1232 |
+ return p.typList[i]
|
|
1233 |
+ }
|
|
1234 |
+
|
|
1235 |
+ // otherwise, i is the type tag (< 0)
|
|
1236 |
+ switch i {
|
|
1237 |
+ case namedTag:
|
|
1238 |
+ // read type object
|
|
1239 |
+ pos := p.pos()
|
|
1240 |
+ parent, name := p.qualifiedName()
|
|
1241 |
+ scope := parent.Scope()
|
|
1242 |
+ obj := scope.Lookup(name)
|
|
1243 |
+
|
|
1244 |
+ // if the object doesn't exist yet, create and insert it
|
|
1245 |
+ if obj == nil {
|
|
1246 |
+ obj = types.NewTypeName(pos, parent, name, nil)
|
|
1247 |
+ scope.Insert(obj)
|
|
1248 |
+ }
|
|
1249 |
+
|
|
1250 |
+ if _, ok := obj.(*types.TypeName); !ok {
|
|
1251 |
+ errorf("pkg = %s, name = %s => %s", parent, name, obj)
|
|
1252 |
+ }
|
|
1253 |
+
|
|
1254 |
+ // associate new named type with obj if it doesn't exist yet
|
|
1255 |
+ t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
|
|
1256 |
+
|
|
1257 |
+ // but record the existing type, if any
|
|
1258 |
+ t := obj.Type().(*types.Named)
|
|
1259 |
+ p.record(t)
|
|
1260 |
+
|
|
1261 |
+ // read underlying type
|
|
1262 |
+ t0.SetUnderlying(p.typ(parent))
|
|
1263 |
+
|
|
1264 |
+ // interfaces don't have associated methods
|
|
1265 |
+ if types.IsInterface(t0) {
|
|
1266 |
+ return t
|
|
1267 |
+ }
|
|
1268 |
+
|
|
1269 |
+ // read associated methods
|
|
1270 |
+ for i := p.int(); i > 0; i-- {
|
|
1271 |
+ // TODO(gri) replace this with something closer to fieldName
|
|
1272 |
+ pos := p.pos()
|
|
1273 |
+ name := p.string()
|
|
1274 |
+ if !exported(name) {
|
|
1275 |
+ p.pkg()
|
|
1276 |
+ }
|
|
1277 |
+
|
|
1278 |
+ recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
|
|
1279 |
+ params, isddd := p.paramList()
|
|
1280 |
+ result, _ := p.paramList()
|
|
1281 |
+ p.int() // go:nointerface pragma - discarded
|
|
1282 |
+
|
|
1283 |
+ sig := types.NewSignature(recv.At(0), params, result, isddd)
|
|
1284 |
+ t0.AddMethod(types.NewFunc(pos, parent, name, sig))
|
|
1285 |
+ }
|
|
1286 |
+
|
|
1287 |
+ return t
|
|
1288 |
+
|
|
1289 |
+ case arrayTag:
|
|
1290 |
+ t := new(types.Array)
|
|
1291 |
+ if p.trackAllTypes {
|
|
1292 |
+ p.record(t)
|
|
1293 |
+ }
|
|
1294 |
+
|
|
1295 |
+ n := p.int64()
|
|
1296 |
+ *t = *types.NewArray(p.typ(parent), n)
|
|
1297 |
+ return t
|
|
1298 |
+
|
|
1299 |
+ case sliceTag:
|
|
1300 |
+ t := new(types.Slice)
|
|
1301 |
+ if p.trackAllTypes {
|
|
1302 |
+ p.record(t)
|
|
1303 |
+ }
|
|
1304 |
+
|
|
1305 |
+ *t = *types.NewSlice(p.typ(parent))
|
|
1306 |
+ return t
|
|
1307 |
+
|
|
1308 |
+ case dddTag:
|
|
1309 |
+ t := new(dddSlice)
|
|
1310 |
+ if p.trackAllTypes {
|
|
1311 |
+ p.record(t)
|
|
1312 |
+ }
|
|
1313 |
+
|
|
1314 |
+ t.elem = p.typ(parent)
|
|
1315 |
+ return t
|
|
1316 |
+
|
|
1317 |
+ case structTag:
|
|
1318 |
+ t := new(types.Struct)
|
|
1319 |
+ if p.trackAllTypes {
|
|
1320 |
+ p.record(t)
|
|
1321 |
+ }
|
|
1322 |
+
|
|
1323 |
+ *t = *types.NewStruct(p.fieldList(parent))
|
|
1324 |
+ return t
|
|
1325 |
+
|
|
1326 |
+ case pointerTag:
|
|
1327 |
+ t := new(types.Pointer)
|
|
1328 |
+ if p.trackAllTypes {
|
|
1329 |
+ p.record(t)
|
|
1330 |
+ }
|
|
1331 |
+
|
|
1332 |
+ *t = *types.NewPointer(p.typ(parent))
|
|
1333 |
+ return t
|
|
1334 |
+
|
|
1335 |
+ case signatureTag:
|
|
1336 |
+ t := new(types.Signature)
|
|
1337 |
+ if p.trackAllTypes {
|
|
1338 |
+ p.record(t)
|
|
1339 |
+ }
|
|
1340 |
+
|
|
1341 |
+ params, isddd := p.paramList()
|
|
1342 |
+ result, _ := p.paramList()
|
|
1343 |
+ *t = *types.NewSignature(nil, params, result, isddd)
|
|
1344 |
+ return t
|
|
1345 |
+
|
|
1346 |
+ case interfaceTag:
|
|
1347 |
+ // Create a dummy entry in the type list. This is safe because we
|
|
1348 |
+ // cannot expect the interface type to appear in a cycle, as any
|
|
1349 |
+ // such cycle must contain a named type which would have been
|
|
1350 |
+ // first defined earlier.
|
|
1351 |
+ n := len(p.typList)
|
|
1352 |
+ if p.trackAllTypes {
|
|
1353 |
+ p.record(nil)
|
|
1354 |
+ }
|
|
1355 |
+
|
|
1356 |
+ var embeddeds []*types.Named
|
|
1357 |
+ for n := p.int(); n > 0; n-- {
|
|
1358 |
+ p.pos()
|
|
1359 |
+ embeddeds = append(embeddeds, p.typ(parent).(*types.Named))
|
|
1360 |
+ }
|
|
1361 |
+
|
|
1362 |
+ t := types.NewInterface(p.methodList(parent), embeddeds)
|
|
1363 |
+ p.interfaceList = append(p.interfaceList, t)
|
|
1364 |
+ if p.trackAllTypes {
|
|
1365 |
+ p.typList[n] = t
|
|
1366 |
+ }
|
|
1367 |
+ return t
|
|
1368 |
+
|
|
1369 |
+ case mapTag:
|
|
1370 |
+ t := new(types.Map)
|
|
1371 |
+ if p.trackAllTypes {
|
|
1372 |
+ p.record(t)
|
|
1373 |
+ }
|
|
1374 |
+
|
|
1375 |
+ key := p.typ(parent)
|
|
1376 |
+ val := p.typ(parent)
|
|
1377 |
+ *t = *types.NewMap(key, val)
|
|
1378 |
+ return t
|
|
1379 |
+
|
|
1380 |
+ case chanTag:
|
|
1381 |
+ t := new(types.Chan)
|
|
1382 |
+ if p.trackAllTypes {
|
|
1383 |
+ p.record(t)
|
|
1384 |
+ }
|
|
1385 |
+
|
|
1386 |
+ var dir types.ChanDir
|
|
1387 |
+ // tag values must match the constants in cmd/compile/internal/gc/go.go
|
|
1388 |
+ switch d := p.int(); d {
|
|
1389 |
+ case 1 /* Crecv */ :
|
|
1390 |
+ dir = types.RecvOnly
|
|
1391 |
+ case 2 /* Csend */ :
|
|
1392 |
+ dir = types.SendOnly
|
|
1393 |
+ case 3 /* Cboth */ :
|
|
1394 |
+ dir = types.SendRecv
|
|
1395 |
+ default:
|
|
1396 |
+ errorf("unexpected channel dir %d", d)
|
|
1397 |
+ }
|
|
1398 |
+ val := p.typ(parent)
|
|
1399 |
+ *t = *types.NewChan(dir, val)
|
|
1400 |
+ return t
|
|
1401 |
+
|
|
1402 |
+ default:
|
|
1403 |
+ errorf("unexpected type tag %d", i) // panics
|
|
1404 |
+ panic("unreachable")
|
|
1405 |
+ }
|
|
1406 |
+}
|
|
1407 |
+
|
|
1408 |
+func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
|
|
1409 |
+ if n := p.int(); n > 0 {
|
|
1410 |
+ fields = make([]*types.Var, n)
|
|
1411 |
+ tags = make([]string, n)
|
|
1412 |
+ for i := range fields {
|
|
1413 |
+ fields[i], tags[i] = p.field(parent)
|
|
1414 |
+ }
|
|
1415 |
+ }
|
|
1416 |
+ return
|
|
1417 |
+}
|
|
1418 |
+
|
|
1419 |
+func (p *importer) field(parent *types.Package) (*types.Var, string) {
|
|
1420 |
+ pos := p.pos()
|
|
1421 |
+ pkg, name, alias := p.fieldName(parent)
|
|
1422 |
+ typ := p.typ(parent)
|
|
1423 |
+ tag := p.string()
|
|
1424 |
+
|
|
1425 |
+ anonymous := false
|
|
1426 |
+ if name == "" {
|
|
1427 |
+ // anonymous field - typ must be T or *T and T must be a type name
|
|
1428 |
+ switch typ := deref(typ).(type) {
|
|
1429 |
+ case *types.Basic: // basic types are named types
|
|
1430 |
+ pkg = nil // // objects defined in Universe scope have no package
|
|
1431 |
+ name = typ.Name()
|
|
1432 |
+ case *types.Named:
|
|
1433 |
+ name = typ.Obj().Name()
|
|
1434 |
+ default:
|
|
1435 |
+ errorf("named base type expected")
|
|
1436 |
+ }
|
|
1437 |
+ anonymous = true
|
|
1438 |
+ } else if alias {
|
|
1439 |
+ // anonymous field: we have an explicit name because it's an alias
|
|
1440 |
+ anonymous = true
|
|
1441 |
+ }
|
|
1442 |
+
|
|
1443 |
+ return types.NewField(pos, pkg, name, typ, anonymous), tag
|
|
1444 |
+}
|
|
1445 |
+
|
|
1446 |
+func (p *importer) methodList(parent *types.Package) (methods []*types.Func) {
|
|
1447 |
+ if n := p.int(); n > 0 {
|
|
1448 |
+ methods = make([]*types.Func, n)
|
|
1449 |
+ for i := range methods {
|
|
1450 |
+ methods[i] = p.method(parent)
|
|
1451 |
+ }
|
|
1452 |
+ }
|
|
1453 |
+ return
|
|
1454 |
+}
|
|
1455 |
+
|
|
1456 |
+func (p *importer) method(parent *types.Package) *types.Func {
|
|
1457 |
+ pos := p.pos()
|
|
1458 |
+ pkg, name, _ := p.fieldName(parent)
|
|
1459 |
+ params, isddd := p.paramList()
|
|
1460 |
+ result, _ := p.paramList()
|
|
1461 |
+ sig := types.NewSignature(nil, params, result, isddd)
|
|
1462 |
+ return types.NewFunc(pos, pkg, name, sig)
|
|
1463 |
+}
|
|
1464 |
+
|
|
1465 |
+func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
|
|
1466 |
+ name = p.string()
|
|
1467 |
+ pkg = parent
|
|
1468 |
+ if pkg == nil {
|
|
1469 |
+ // use the imported package instead
|
|
1470 |
+ pkg = p.pkgList[0]
|
|
1471 |
+ }
|
|
1472 |
+ if p.version == 0 && name == "_" {
|
|
1473 |
+ // version 0 didn't export a package for _ fields
|
|
1474 |
+ return
|
|
1475 |
+ }
|
|
1476 |
+ switch name {
|
|
1477 |
+ case "":
|
|
1478 |
+ // 1) field name matches base type name and is exported: nothing to do
|
|
1479 |
+ case "?":
|
|
1480 |
+ // 2) field name matches base type name and is not exported: need package
|
|
1481 |
+ name = ""
|
|
1482 |
+ pkg = p.pkg()
|
|
1483 |
+ case "@":
|
|
1484 |
+ // 3) field name doesn't match type name (alias)
|
|
1485 |
+ name = p.string()
|
|
1486 |
+ alias = true
|
|
1487 |
+ fallthrough
|
|
1488 |
+ default:
|
|
1489 |
+ if !exported(name) {
|
|
1490 |
+ pkg = p.pkg()
|
|
1491 |
+ }
|
|
1492 |
+ }
|
|
1493 |
+ return
|
|
1494 |
+}
|
|
1495 |
+
|
|
1496 |
+func (p *importer) paramList() (*types.Tuple, bool) {
|
|
1497 |
+ n := p.int()
|
|
1498 |
+ if n == 0 {
|
|
1499 |
+ return nil, false
|
|
1500 |
+ }
|
|
1501 |
+ // negative length indicates unnamed parameters
|
|
1502 |
+ named := true
|
|
1503 |
+ if n < 0 {
|
|
1504 |
+ n = -n
|
|
1505 |
+ named = false
|
|
1506 |
+ }
|
|
1507 |
+ // n > 0
|
|
1508 |
+ params := make([]*types.Var, n)
|
|
1509 |
+ isddd := false
|
|
1510 |
+ for i := range params {
|
|
1511 |
+ params[i], isddd = p.param(named)
|
|
1512 |
+ }
|
|
1513 |
+ return types.NewTuple(params...), isddd
|
|
1514 |
+}
|
|
1515 |
+
|
|
1516 |
+func (p *importer) param(named bool) (*types.Var, bool) {
|
|
1517 |
+ t := p.typ(nil)
|
|
1518 |
+ td, isddd := t.(*dddSlice)
|
|
1519 |
+ if isddd {
|
|
1520 |
+ t = types.NewSlice(td.elem)
|
|
1521 |
+ }
|
|
1522 |
+
|
|
1523 |
+ var pkg *types.Package
|
|
1524 |
+ var name string
|
|
1525 |
+ if named {
|
|
1526 |
+ name = p.string()
|
|
1527 |
+ if name == "" {
|
|
1528 |
+ errorf("expected named parameter")
|
|
1529 |
+ }
|
|
1530 |
+ if name != "_" {
|
|
1531 |
+ pkg = p.pkg()
|
|
1532 |
+ }
|
|
1533 |
+ if i := strings.Index(name, "·"); i > 0 {
|
|
1534 |
+ name = name[:i] // cut off gc-specific parameter numbering
|
|
1535 |
+ }
|
|
1536 |
+ }
|
|
1537 |
+
|
|
1538 |
+ // read and discard compiler-specific info
|
|
1539 |
+ p.string()
|
|
1540 |
+
|
|
1541 |
+ return types.NewVar(token.NoPos, pkg, name, t), isddd
|
|
1542 |
+}
|
|
1543 |
+
|
|
1544 |
+func exported(name string) bool {
|
|
1545 |
+ ch, _ := utf8.DecodeRuneInString(name)
|
|
1546 |
+ return unicode.IsUpper(ch)
|
|
1547 |
+}
|
|
1548 |
+
|
|
1549 |
+func (p *importer) value() constant.Value {
|
|
1550 |
+ switch tag := p.tagOrIndex(); tag {
|
|
1551 |
+ case falseTag:
|
|
1552 |
+ return constant.MakeBool(false)
|
|
1553 |
+ case trueTag:
|
|
1554 |
+ return constant.MakeBool(true)
|
|
1555 |
+ case int64Tag:
|
|
1556 |
+ return constant.MakeInt64(p.int64())
|
|
1557 |
+ case floatTag:
|
|
1558 |
+ return p.float()
|
|
1559 |
+ case complexTag:
|
|
1560 |
+ re := p.float()
|
|
1561 |
+ im := p.float()
|
|
1562 |
+ return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
|
|
1563 |
+ case stringTag:
|
|
1564 |
+ return constant.MakeString(p.string())
|
|
1565 |
+ case unknownTag:
|
|
1566 |
+ return constant.MakeUnknown()
|
|
1567 |
+ default:
|
|
1568 |
+ errorf("unexpected value tag %d", tag) // panics
|
|
1569 |
+ panic("unreachable")
|
|
1570 |
+ }
|
|
1571 |
+}
|
|
1572 |
+
|
|
1573 |
+func (p *importer) float() constant.Value {
|
|
1574 |
+ sign := p.int()
|
|
1575 |
+ if sign == 0 {
|
|
1576 |
+ return constant.MakeInt64(0)
|
|
1577 |
+ }
|
|
1578 |
+
|
|
1579 |
+ exp := p.int()
|
|
1580 |
+ mant := []byte(p.string()) // big endian
|
|
1581 |
+
|
|
1582 |
+ // remove leading 0's if any
|
|
1583 |
+ for len(mant) > 0 && mant[0] == 0 {
|
|
1584 |
+ mant = mant[1:]
|
|
1585 |
+ }
|
|
1586 |
+
|
|
1587 |
+ // convert to little endian
|
|
1588 |
+ // TODO(gri) go/constant should have a more direct conversion function
|
|
1589 |
+ // (e.g., once it supports a big.Float based implementation)
|
|
1590 |
+ for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
|
|
1591 |
+ mant[i], mant[j] = mant[j], mant[i]
|
|
1592 |
+ }
|
|
1593 |
+
|
|
1594 |
+ // adjust exponent (constant.MakeFromBytes creates an integer value,
|
|
1595 |
+ // but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
|
|
1596 |
+ exp -= len(mant) << 3
|
|
1597 |
+ if len(mant) > 0 {
|
|
1598 |
+ for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
|
|
1599 |
+ exp++
|
|
1600 |
+ }
|
|
1601 |
+ }
|
|
1602 |
+
|
|
1603 |
+ x := constant.MakeFromBytes(mant)
|
|
1604 |
+ switch {
|
|
1605 |
+ case exp < 0:
|
|
1606 |
+ d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
|
|
1607 |
+ x = constant.BinaryOp(x, token.QUO, d)
|
|
1608 |
+ case exp > 0:
|
|
1609 |
+ x = constant.Shift(x, token.SHL, uint(exp))
|
|
1610 |
+ }
|
|
1611 |
+
|
|
1612 |
+ if sign < 0 {
|
|
1613 |
+ x = constant.UnaryOp(token.SUB, x, 0)
|
|
1614 |
+ }
|
|
1615 |
+ return x
|
|
1616 |
+}
|
|
1617 |
+
|
|
1618 |
+// ----------------------------------------------------------------------------
|
|
1619 |
+// Low-level decoders
|
|
1620 |
+
|
|
1621 |
+func (p *importer) tagOrIndex() int {
|
|
1622 |
+ if p.debugFormat {
|
|
1623 |
+ p.marker('t')
|
|
1624 |
+ }
|
|
1625 |
+
|
|
1626 |
+ return int(p.rawInt64())
|
|
1627 |
+}
|
|
1628 |
+
|
|
1629 |
+func (p *importer) int() int {
|
|
1630 |
+ x := p.int64()
|
|
1631 |
+ if int64(int(x)) != x {
|
|
1632 |
+ errorf("exported integer too large")
|
|
1633 |
+ }
|
|
1634 |
+ return int(x)
|
|
1635 |
+}
|
|
1636 |
+
|
|
1637 |
+func (p *importer) int64() int64 {
|
|
1638 |
+ if p.debugFormat {
|
|
1639 |
+ p.marker('i')
|
|
1640 |
+ }
|
|
1641 |
+
|
|
1642 |
+ return p.rawInt64()
|
|
1643 |
+}
|
|
1644 |
+
|
|
1645 |
+func (p *importer) path() string {
|
|
1646 |
+ if p.debugFormat {
|
|
1647 |
+ p.marker('p')
|
|
1648 |
+ }
|
|
1649 |
+ // if the path was seen before, i is its index (>= 0)
|
|
1650 |
+ // (the empty string is at index 0)
|
|
1651 |
+ i := p.rawInt64()
|
|
1652 |
+ if i >= 0 {
|
|
1653 |
+ return p.pathList[i]
|
|
1654 |
+ }
|
|
1655 |
+ // otherwise, i is the negative path length (< 0)
|
|
1656 |
+ a := make([]string, -i)
|
|
1657 |
+ for n := range a {
|
|
1658 |
+ a[n] = p.string()
|
|
1659 |
+ }
|
|
1660 |
+ s := strings.Join(a, "/")
|
|
1661 |
+ p.pathList = append(p.pathList, s)
|
|
1662 |
+ return s
|
|
1663 |
+}
|
|
1664 |
+
|
|
1665 |
+func (p *importer) string() string {
|
|
1666 |
+ if p.debugFormat {
|
|
1667 |
+ p.marker('s')
|
|
1668 |
+ }
|
|
1669 |
+ // if the string was seen before, i is its index (>= 0)
|
|
1670 |
+ // (the empty string is at index 0)
|
|
1671 |
+ i := p.rawInt64()
|
|
1672 |
+ if i >= 0 {
|
|
1673 |
+ return p.strList[i]
|
|
1674 |
+ }
|
|
1675 |
+ // otherwise, i is the negative string length (< 0)
|
|
1676 |
+ if n := int(-i); n <= cap(p.buf) {
|
|
1677 |
+ p.buf = p.buf[:n]
|
|
1678 |
+ } else {
|
|
1679 |
+ p.buf = make([]byte, n)
|
|
1680 |
+ }
|
|
1681 |
+ for i := range p.buf {
|
|
1682 |
+ p.buf[i] = p.rawByte()
|
|
1683 |
+ }
|
|
1684 |
+ s := string(p.buf)
|
|
1685 |
+ p.strList = append(p.strList, s)
|
|
1686 |
+ return s
|
|
1687 |
+}
|
|
1688 |
+
|
|
1689 |
+func (p *importer) marker(want byte) {
|
|
1690 |
+ if got := p.rawByte(); got != want {
|
|
1691 |
+ errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
|
|
1692 |
+ }
|
|
1693 |
+
|
|
1694 |
+ pos := p.read
|
|
1695 |
+ if n := int(p.rawInt64()); n != pos {
|
|
1696 |
+ errorf("incorrect position: got %d; want %d", n, pos)
|
|
1697 |
+ }
|
|
1698 |
+}
|
|
1699 |
+
|
|
1700 |
+// rawInt64 should only be used by low-level decoders.
|
|
1701 |
+func (p *importer) rawInt64() int64 {
|
|
1702 |
+ i, err := binary.ReadVarint(p)
|
|
1703 |
+ if err != nil {
|
|
1704 |
+ errorf("read error: %v", err)
|
|
1705 |
+ }
|
|
1706 |
+ return i
|
|
1707 |
+}
|
|
1708 |
+
|
|
1709 |
+// rawStringln should only be used to read the initial version string.
|
|
1710 |
+func (p *importer) rawStringln(b byte) string {
|
|
1711 |
+ p.buf = p.buf[:0]
|
|
1712 |
+ for b != '\n' {
|
|
1713 |
+ p.buf = append(p.buf, b)
|
|
1714 |
+ b = p.rawByte()
|
|
1715 |
+ }
|
|
1716 |
+ return string(p.buf)
|
|
1717 |
+}
|
|
1718 |
+
|
|
1719 |
+// needed for binary.ReadVarint in rawInt64
|
|
1720 |
+func (p *importer) ReadByte() (byte, error) {
|
|
1721 |
+ return p.rawByte(), nil
|
|
1722 |
+}
|
|
1723 |
+
|
|
1724 |
+// byte is the bottleneck interface for reading p.data.
|
|
1725 |
+// It unescapes '|' 'S' to '$' and '|' '|' to '|'.
|
|
1726 |
+// rawByte should only be used by low-level decoders.
|
|
1727 |
+func (p *importer) rawByte() byte {
|
|
1728 |
+ b := p.data[0]
|
|
1729 |
+ r := 1
|
|
1730 |
+ if b == '|' {
|
|
1731 |
+ b = p.data[1]
|
|
1732 |
+ r = 2
|
|
1733 |
+ switch b {
|
|
1734 |
+ case 'S':
|
|
1735 |
+ b = '$'
|
|
1736 |
+ case '|':
|
|
1737 |
+ // nothing to do
|
|
1738 |
+ default:
|
|
1739 |
+ errorf("unexpected escape sequence in export data")
|
|
1740 |
+ }
|
|
1741 |
+ }
|
|
1742 |
+ p.data = p.data[r:]
|
|
1743 |
+ p.read += r
|
|
1744 |
+ return b
|
|
1745 |
+
|
|
1746 |
+}
|
|
1747 |
+
|
|
1748 |
+// ----------------------------------------------------------------------------
|
|
1749 |
+// Export format
|
|
1750 |
+
|
|
1751 |
+// Tags. Must be < 0.
|
|
1752 |
+const (
|
|
1753 |
+ // Objects
|
|
1754 |
+ packageTag = -(iota + 1)
|
|
1755 |
+ constTag
|
|
1756 |
+ typeTag
|
|
1757 |
+ varTag
|
|
1758 |
+ funcTag
|
|
1759 |
+ endTag
|
|
1760 |
+
|
|
1761 |
+ // Types
|
|
1762 |
+ namedTag
|
|
1763 |
+ arrayTag
|
|
1764 |
+ sliceTag
|
|
1765 |
+ dddTag
|
|
1766 |
+ structTag
|
|
1767 |
+ pointerTag
|
|
1768 |
+ signatureTag
|
|
1769 |
+ interfaceTag
|
|
1770 |
+ mapTag
|
|
1771 |
+ chanTag
|
|
1772 |
+
|
|
1773 |
+ // Values
|
|
1774 |
+ falseTag
|
|
1775 |
+ trueTag
|
|
1776 |
+ int64Tag
|
|
1777 |
+ floatTag
|
|
1778 |
+ fractionTag // not used by gc
|
|
1779 |
+ complexTag
|
|
1780 |
+ stringTag
|
|
1781 |
+ nilTag // only used by gc (appears in exported inlined function bodies)
|
|
1782 |
+ unknownTag // not used by gc (only appears in packages with errors)
|
|
1783 |
+
|
|
1784 |
+ // Type aliases
|
|
1785 |
+ aliasTag
|
|
1786 |
+)
|
|
1787 |
+
|
|
1788 |
+var predeclared = []types.Type{
|
|
1789 |
+ // basic types
|
|
1790 |
+ types.Typ[types.Bool],
|
|
1791 |
+ types.Typ[types.Int],
|
|
1792 |
+ types.Typ[types.Int8],
|
|
1793 |
+ types.Typ[types.Int16],
|
|
1794 |
+ types.Typ[types.Int32],
|
|
1795 |
+ types.Typ[types.Int64],
|
|
1796 |
+ types.Typ[types.Uint],
|
|
1797 |
+ types.Typ[types.Uint8],
|
|
1798 |
+ types.Typ[types.Uint16],
|
|
1799 |
+ types.Typ[types.Uint32],
|
|
1800 |
+ types.Typ[types.Uint64],
|
|
1801 |
+ types.Typ[types.Uintptr],
|
|
1802 |
+ types.Typ[types.Float32],
|
|
1803 |
+ types.Typ[types.Float64],
|
|
1804 |
+ types.Typ[types.Complex64],
|
|
1805 |
+ types.Typ[types.Complex128],
|
|
1806 |
+ types.Typ[types.String],
|
|
1807 |
+
|
|
1808 |
+ // basic type aliases
|
|
1809 |
+ types.Universe.Lookup("byte").Type(),
|
|
1810 |
+ types.Universe.Lookup("rune").Type(),
|
|
1811 |
+
|
|
1812 |
+ // error
|
|
1813 |
+ types.Universe.Lookup("error").Type(),
|
|
1814 |
+
|
|
1815 |
+ // untyped types
|
|
1816 |
+ types.Typ[types.UntypedBool],
|
|
1817 |
+ types.Typ[types.UntypedInt],
|
|
1818 |
+ types.Typ[types.UntypedRune],
|
|
1819 |
+ types.Typ[types.UntypedFloat],
|
|
1820 |
+ types.Typ[types.UntypedComplex],
|
|
1821 |
+ types.Typ[types.UntypedString],
|
|
1822 |
+ types.Typ[types.UntypedNil],
|
|
1823 |
+
|
|
1824 |
+ // package unsafe
|
|
1825 |
+ types.Typ[types.UnsafePointer],
|
|
1826 |
+
|
|
1827 |
+ // invalid type
|
|
1828 |
+ types.Typ[types.Invalid], // only appears in packages with errors
|
|
1829 |
+
|
|
1830 |
+ // used internally by gc; never used by this package or in .a files
|
|
1831 |
+ anyType{},
|
|
1832 |
+}
|
|
1833 |
+
|
|
1834 |
+type anyType struct{}
|
|
1835 |
+
|
|
1836 |
+func (t anyType) Underlying() types.Type { return t }
|
|
1837 |
+func (t anyType) String() string { return "any" }
|
|
1838 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go
|
|
1839 |
new file mode 100644
|
|
1840 |
index 0000000..f33dc56
|
|
1841 |
--- /dev/null
|
|
1842 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/exportdata.go
|
|
1843 |
@@ -0,0 +1,93 @@
|
|
1844 |
+// Copyright 2011 The Go Authors. All rights reserved.
|
|
1845 |
+// Use of this source code is governed by a BSD-style
|
|
1846 |
+// license that can be found in the LICENSE file.
|
|
1847 |
+
|
|
1848 |
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/exportdata.go.
|
|
1849 |
+
|
|
1850 |
+// This file implements FindExportData.
|
|
1851 |
+
|
|
1852 |
+package gcimporter
|
|
1853 |
+
|
|
1854 |
+import (
|
|
1855 |
+ "bufio"
|
|
1856 |
+ "fmt"
|
|
1857 |
+ "io"
|
|
1858 |
+ "strconv"
|
|
1859 |
+ "strings"
|
|
1860 |
+)
|
|
1861 |
+
|
|
1862 |
+func readGopackHeader(r *bufio.Reader) (name string, size int, err error) {
|
|
1863 |
+ // See $GOROOT/include/ar.h.
|
|
1864 |
+ hdr := make([]byte, 16+12+6+6+8+10+2)
|
|
1865 |
+ _, err = io.ReadFull(r, hdr)
|
|
1866 |
+ if err != nil {
|
|
1867 |
+ return
|
|
1868 |
+ }
|
|
1869 |
+ // leave for debugging
|
|
1870 |
+ if false {
|
|
1871 |
+ fmt.Printf("header: %s", hdr)
|
|
1872 |
+ }
|
|
1873 |
+ s := strings.TrimSpace(string(hdr[16+12+6+6+8:][:10]))
|
|
1874 |
+ size, err = strconv.Atoi(s)
|
|
1875 |
+ if err != nil || hdr[len(hdr)-2] != '`' || hdr[len(hdr)-1] != '\n' {
|
|
1876 |
+ err = fmt.Errorf("invalid archive header")
|
|
1877 |
+ return
|
|
1878 |
+ }
|
|
1879 |
+ name = strings.TrimSpace(string(hdr[:16]))
|
|
1880 |
+ return
|
|
1881 |
+}
|
|
1882 |
+
|
|
1883 |
+// FindExportData positions the reader r at the beginning of the
|
|
1884 |
+// export data section of an underlying GC-created object/archive
|
|
1885 |
+// file by reading from it. The reader must be positioned at the
|
|
1886 |
+// start of the file before calling this function. The hdr result
|
|
1887 |
+// is the string before the export data, either "$$" or "$$B".
|
|
1888 |
+//
|
|
1889 |
+func FindExportData(r *bufio.Reader) (hdr string, err error) {
|
|
1890 |
+ // Read first line to make sure this is an object file.
|
|
1891 |
+ line, err := r.ReadSlice('\n')
|
|
1892 |
+ if err != nil {
|
|
1893 |
+ err = fmt.Errorf("can't find export data (%v)", err)
|
|
1894 |
+ return
|
|
1895 |
+ }
|
|
1896 |
+
|
|
1897 |
+ if string(line) == "!<arch>\n" {
|
|
1898 |
+ // Archive file. Scan to __.PKGDEF.
|
|
1899 |
+ var name string
|
|
1900 |
+ if name, _, err = readGopackHeader(r); err != nil {
|
|
1901 |
+ return
|
|
1902 |
+ }
|
|
1903 |
+
|
|
1904 |
+ // First entry should be __.PKGDEF.
|
|
1905 |
+ if name != "__.PKGDEF" {
|
|
1906 |
+ err = fmt.Errorf("go archive is missing __.PKGDEF")
|
|
1907 |
+ return
|
|
1908 |
+ }
|
|
1909 |
+
|
|
1910 |
+ // Read first line of __.PKGDEF data, so that line
|
|
1911 |
+ // is once again the first line of the input.
|
|
1912 |
+ if line, err = r.ReadSlice('\n'); err != nil {
|
|
1913 |
+ err = fmt.Errorf("can't find export data (%v)", err)
|
|
1914 |
+ return
|
|
1915 |
+ }
|
|
1916 |
+ }
|
|
1917 |
+
|
|
1918 |
+ // Now at __.PKGDEF in archive or still at beginning of file.
|
|
1919 |
+ // Either way, line should begin with "go object ".
|
|
1920 |
+ if !strings.HasPrefix(string(line), "go object ") {
|
|
1921 |
+ err = fmt.Errorf("not a Go object file")
|
|
1922 |
+ return
|
|
1923 |
+ }
|
|
1924 |
+
|
|
1925 |
+ // Skip over object header to export data.
|
|
1926 |
+ // Begins after first line starting with $$.
|
|
1927 |
+ for line[0] != '$' {
|
|
1928 |
+ if line, err = r.ReadSlice('\n'); err != nil {
|
|
1929 |
+ err = fmt.Errorf("can't find export data (%v)", err)
|
|
1930 |
+ return
|
|
1931 |
+ }
|
|
1932 |
+ }
|
|
1933 |
+ hdr = string(line)
|
|
1934 |
+
|
|
1935 |
+ return
|
|
1936 |
+}
|
|
1937 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go
|
|
1938 |
new file mode 100644
|
|
1939 |
index 0000000..6fbc9d7
|
|
1940 |
--- /dev/null
|
|
1941 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/gcimporter.go
|
|
1942 |
@@ -0,0 +1,1041 @@
|
|
1943 |
+// Copyright 2011 The Go Authors. All rights reserved.
|
|
1944 |
+// Use of this source code is governed by a BSD-style
|
|
1945 |
+// license that can be found in the LICENSE file.
|
|
1946 |
+
|
|
1947 |
+// This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go,
|
|
1948 |
+// but it also contains the original source-based importer code for Go1.6.
|
|
1949 |
+// Once we stop supporting 1.6, we can remove that code.
|
|
1950 |
+
|
|
1951 |
+// Package gcimporter15 provides various functions for reading
|
|
1952 |
+// gc-generated object files that can be used to implement the
|
|
1953 |
+// Importer interface defined by the Go 1.5 standard library package.
|
|
1954 |
+//
|
|
1955 |
+// Deprecated: this package will be deleted in October 2017.
|
|
1956 |
+// New code should use golang.org/x/tools/go/gcexportdata.
|
|
1957 |
+//
|
|
1958 |
+package gcimporter // import "golang.org/x/tools/go/gcimporter15"
|
|
1959 |
+
|
|
1960 |
+import (
|
|
1961 |
+ "bufio"
|
|
1962 |
+ "errors"
|
|
1963 |
+ "fmt"
|
|
1964 |
+ "go/build"
|
|
1965 |
+ exact "go/constant"
|
|
1966 |
+ "go/token"
|
|
1967 |
+ "go/types"
|
|
1968 |
+ "io"
|
|
1969 |
+ "io/ioutil"
|
|
1970 |
+ "os"
|
|
1971 |
+ "path/filepath"
|
|
1972 |
+ "sort"
|
|
1973 |
+ "strconv"
|
|
1974 |
+ "strings"
|
|
1975 |
+ "text/scanner"
|
|
1976 |
+)
|
|
1977 |
+
|
|
1978 |
+// debugging/development support
|
|
1979 |
+const debug = false
|
|
1980 |
+
|
|
1981 |
+var pkgExts = [...]string{".a", ".o"}
|
|
1982 |
+
|
|
1983 |
+// FindPkg returns the filename and unique package id for an import
|
|
1984 |
+// path based on package information provided by build.Import (using
|
|
1985 |
+// the build.Default build.Context). A relative srcDir is interpreted
|
|
1986 |
+// relative to the current working directory.
|
|
1987 |
+// If no file was found, an empty filename is returned.
|
|
1988 |
+//
|
|
1989 |
+func FindPkg(path, srcDir string) (filename, id string) {
|
|
1990 |
+ if path == "" {
|
|
1991 |
+ return
|
|
1992 |
+ }
|
|
1993 |
+
|
|
1994 |
+ var noext string
|
|
1995 |
+ switch {
|
|
1996 |
+ default:
|
|
1997 |
+ // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
|
|
1998 |
+ // Don't require the source files to be present.
|
|
1999 |
+ if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282
|
|
2000 |
+ srcDir = abs
|
|
2001 |
+ }
|
|
2002 |
+ bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
|
|
2003 |
+ if bp.PkgObj == "" {
|
|
2004 |
+ return
|
|
2005 |
+ }
|
|
2006 |
+ noext = strings.TrimSuffix(bp.PkgObj, ".a")
|
|
2007 |
+ id = bp.ImportPath
|
|
2008 |
+
|
|
2009 |
+ case build.IsLocalImport(path):
|
|
2010 |
+ // "./x" -> "/this/directory/x.ext", "/this/directory/x"
|
|
2011 |
+ noext = filepath.Join(srcDir, path)
|
|
2012 |
+ id = noext
|
|
2013 |
+
|
|
2014 |
+ case filepath.IsAbs(path):
|
|
2015 |
+ // for completeness only - go/build.Import
|
|
2016 |
+ // does not support absolute imports
|
|
2017 |
+ // "/x" -> "/x.ext", "/x"
|
|
2018 |
+ noext = path
|
|
2019 |
+ id = path
|
|
2020 |
+ }
|
|
2021 |
+
|
|
2022 |
+ if false { // for debugging
|
|
2023 |
+ if path != id {
|
|
2024 |
+ fmt.Printf("%s -> %s\n", path, id)
|
|
2025 |
+ }
|
|
2026 |
+ }
|
|
2027 |
+
|
|
2028 |
+ // try extensions
|
|
2029 |
+ for _, ext := range pkgExts {
|
|
2030 |
+ filename = noext + ext
|
|
2031 |
+ if f, err := os.Stat(filename); err == nil && !f.IsDir() {
|
|
2032 |
+ return
|
|
2033 |
+ }
|
|
2034 |
+ }
|
|
2035 |
+
|
|
2036 |
+ filename = "" // not found
|
|
2037 |
+ return
|
|
2038 |
+}
|
|
2039 |
+
|
|
2040 |
+// ImportData imports a package by reading the gc-generated export data,
|
|
2041 |
+// adds the corresponding package object to the packages map indexed by id,
|
|
2042 |
+// and returns the object.
|
|
2043 |
+//
|
|
2044 |
+// The packages map must contains all packages already imported. The data
|
|
2045 |
+// reader position must be the beginning of the export data section. The
|
|
2046 |
+// filename is only used in error messages.
|
|
2047 |
+//
|
|
2048 |
+// If packages[id] contains the completely imported package, that package
|
|
2049 |
+// can be used directly, and there is no need to call this function (but
|
|
2050 |
+// there is also no harm but for extra time used).
|
|
2051 |
+//
|
|
2052 |
+func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) {
|
|
2053 |
+ // support for parser error handling
|
|
2054 |
+ defer func() {
|
|
2055 |
+ switch r := recover().(type) {
|
|
2056 |
+ case nil:
|
|
2057 |
+ // nothing to do
|
|
2058 |
+ case importError:
|
|
2059 |
+ err = r
|
|
2060 |
+ default:
|
|
2061 |
+ panic(r) // internal error
|
|
2062 |
+ }
|
|
2063 |
+ }()
|
|
2064 |
+
|
|
2065 |
+ var p parser
|
|
2066 |
+ p.init(filename, id, data, packages)
|
|
2067 |
+ pkg = p.parseExport()
|
|
2068 |
+
|
|
2069 |
+ return
|
|
2070 |
+}
|
|
2071 |
+
|
|
2072 |
+// Import imports a gc-generated package given its import path and srcDir, adds
|
|
2073 |
+// the corresponding package object to the packages map, and returns the object.
|
|
2074 |
+// The packages map must contain all packages already imported.
|
|
2075 |
+//
|
|
2076 |
+func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) {
|
|
2077 |
+ filename, id := FindPkg(path, srcDir)
|
|
2078 |
+ if filename == "" {
|
|
2079 |
+ if path == "unsafe" {
|
|
2080 |
+ return types.Unsafe, nil
|
|
2081 |
+ }
|
|
2082 |
+ err = fmt.Errorf("can't find import: %s", id)
|
|
2083 |
+ return
|
|
2084 |
+ }
|
|
2085 |
+
|
|
2086 |
+ // no need to re-import if the package was imported completely before
|
|
2087 |
+ if pkg = packages[id]; pkg != nil && pkg.Complete() {
|
|
2088 |
+ return
|
|
2089 |
+ }
|
|
2090 |
+
|
|
2091 |
+ // open file
|
|
2092 |
+ f, err := os.Open(filename)
|
|
2093 |
+ if err != nil {
|
|
2094 |
+ return
|
|
2095 |
+ }
|
|
2096 |
+ defer func() {
|
|
2097 |
+ f.Close()
|
|
2098 |
+ if err != nil {
|
|
2099 |
+ // add file name to error
|
|
2100 |
+ err = fmt.Errorf("reading export data: %s: %v", filename, err)
|
|
2101 |
+ }
|
|
2102 |
+ }()
|
|
2103 |
+
|
|
2104 |
+ var hdr string
|
|
2105 |
+ buf := bufio.NewReader(f)
|
|
2106 |
+ if hdr, err = FindExportData(buf); err != nil {
|
|
2107 |
+ return
|
|
2108 |
+ }
|
|
2109 |
+
|
|
2110 |
+ switch hdr {
|
|
2111 |
+ case "$$\n":
|
|
2112 |
+ return ImportData(packages, filename, id, buf)
|
|
2113 |
+ case "$$B\n":
|
|
2114 |
+ var data []byte
|
|
2115 |
+ data, err = ioutil.ReadAll(buf)
|
|
2116 |
+ if err == nil {
|
|
2117 |
+ fset := token.NewFileSet()
|
|
2118 |
+ _, pkg, err = BImportData(fset, packages, data, id)
|
|
2119 |
+ return
|
|
2120 |
+ }
|
|
2121 |
+ default:
|
|
2122 |
+ err = fmt.Errorf("unknown export data header: %q", hdr)
|
|
2123 |
+ }
|
|
2124 |
+
|
|
2125 |
+ return
|
|
2126 |
+}
|
|
2127 |
+
|
|
2128 |
+// ----------------------------------------------------------------------------
|
|
2129 |
+// Parser
|
|
2130 |
+
|
|
2131 |
+// TODO(gri) Imported objects don't have position information.
|
|
2132 |
+// Ideally use the debug table line info; alternatively
|
|
2133 |
+// create some fake position (or the position of the
|
|
2134 |
+// import). That way error messages referring to imported
|
|
2135 |
+// objects can print meaningful information.
|
|
2136 |
+
|
|
2137 |
+// parser parses the exports inside a gc compiler-produced
|
|
2138 |
+// object/archive file and populates its scope with the results.
|
|
2139 |
+type parser struct {
|
|
2140 |
+ scanner scanner.Scanner
|
|
2141 |
+ tok rune // current token
|
|
2142 |
+ lit string // literal string; only valid for Ident, Int, String tokens
|
|
2143 |
+ id string // package id of imported package
|
|
2144 |
+ sharedPkgs map[string]*types.Package // package id -> package object (across importer)
|
|
2145 |
+ localPkgs map[string]*types.Package // package id -> package object (just this package)
|
|
2146 |
+}
|
|
2147 |
+
|
|
2148 |
+func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) {
|
|
2149 |
+ p.scanner.Init(src)
|
|
2150 |
+ p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
|
|
2151 |
+ p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
|
|
2152 |
+ p.scanner.Whitespace = 1<<'\t' | 1<<' '
|
|
2153 |
+ p.scanner.Filename = filename // for good error messages
|
|
2154 |
+ p.next()
|
|
2155 |
+ p.id = id
|
|
2156 |
+ p.sharedPkgs = packages
|
|
2157 |
+ if debug {
|
|
2158 |
+ // check consistency of packages map
|
|
2159 |
+ for _, pkg := range packages {
|
|
2160 |
+ if pkg.Name() == "" {
|
|
2161 |
+ fmt.Printf("no package name for %s\n", pkg.Path())
|
|
2162 |
+ }
|
|
2163 |
+ }
|
|
2164 |
+ }
|
|
2165 |
+}
|
|
2166 |
+
|
|
2167 |
+func (p *parser) next() {
|
|
2168 |
+ p.tok = p.scanner.Scan()
|
|
2169 |
+ switch p.tok {
|
|
2170 |
+ case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·':
|
|
2171 |
+ p.lit = p.scanner.TokenText()
|
|
2172 |
+ default:
|
|
2173 |
+ p.lit = ""
|
|
2174 |
+ }
|
|
2175 |
+ if debug {
|
|
2176 |
+ fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
|
|
2177 |
+ }
|
|
2178 |
+}
|
|
2179 |
+
|
|
2180 |
+func declTypeName(pkg *types.Package, name string) *types.TypeName {
|
|
2181 |
+ scope := pkg.Scope()
|
|
2182 |
+ if obj := scope.Lookup(name); obj != nil {
|
|
2183 |
+ return obj.(*types.TypeName)
|
|
2184 |
+ }
|
|
2185 |
+ obj := types.NewTypeName(token.NoPos, pkg, name, nil)
|
|
2186 |
+ // a named type may be referred to before the underlying type
|
|
2187 |
+ // is known - set it up
|
|
2188 |
+ types.NewNamed(obj, nil, nil)
|
|
2189 |
+ scope.Insert(obj)
|
|
2190 |
+ return obj
|
|
2191 |
+}
|
|
2192 |
+
|
|
2193 |
+// ----------------------------------------------------------------------------
|
|
2194 |
+// Error handling
|
|
2195 |
+
|
|
2196 |
+// Internal errors are boxed as importErrors.
|
|
2197 |
+type importError struct {
|
|
2198 |
+ pos scanner.Position
|
|
2199 |
+ err error
|
|
2200 |
+}
|
|
2201 |
+
|
|
2202 |
+func (e importError) Error() string {
|
|
2203 |
+ return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
|
|
2204 |
+}
|
|
2205 |
+
|
|
2206 |
+func (p *parser) error(err interface{}) {
|
|
2207 |
+ if s, ok := err.(string); ok {
|
|
2208 |
+ err = errors.New(s)
|
|
2209 |
+ }
|
|
2210 |
+ // panic with a runtime.Error if err is not an error
|
|
2211 |
+ panic(importError{p.scanner.Pos(), err.(error)})
|
|
2212 |
+}
|
|
2213 |
+
|
|
2214 |
+func (p *parser) errorf(format string, args ...interface{}) {
|
|
2215 |
+ p.error(fmt.Sprintf(format, args...))
|
|
2216 |
+}
|
|
2217 |
+
|
|
2218 |
+func (p *parser) expect(tok rune) string {
|
|
2219 |
+ lit := p.lit
|
|
2220 |
+ if p.tok != tok {
|
|
2221 |
+ p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
|
|
2222 |
+ }
|
|
2223 |
+ p.next()
|
|
2224 |
+ return lit
|
|
2225 |
+}
|
|
2226 |
+
|
|
2227 |
+func (p *parser) expectSpecial(tok string) {
|
|
2228 |
+ sep := 'x' // not white space
|
|
2229 |
+ i := 0
|
|
2230 |
+ for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
|
|
2231 |
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
|
|
2232 |
+ p.next()
|
|
2233 |
+ i++
|
|
2234 |
+ }
|
|
2235 |
+ if i < len(tok) {
|
|
2236 |
+ p.errorf("expected %q, got %q", tok, tok[0:i])
|
|
2237 |
+ }
|
|
2238 |
+}
|
|
2239 |
+
|
|
2240 |
+func (p *parser) expectKeyword(keyword string) {
|
|
2241 |
+ lit := p.expect(scanner.Ident)
|
|
2242 |
+ if lit != keyword {
|
|
2243 |
+ p.errorf("expected keyword %s, got %q", keyword, lit)
|
|
2244 |
+ }
|
|
2245 |
+}
|
|
2246 |
+
|
|
2247 |
+// ----------------------------------------------------------------------------
|
|
2248 |
+// Qualified and unqualified names
|
|
2249 |
+
|
|
2250 |
+// PackageId = string_lit .
|
|
2251 |
+//
|
|
2252 |
+func (p *parser) parsePackageId() string {
|
|
2253 |
+ id, err := strconv.Unquote(p.expect(scanner.String))
|
|
2254 |
+ if err != nil {
|
|
2255 |
+ p.error(err)
|
|
2256 |
+ }
|
|
2257 |
+ // id == "" stands for the imported package id
|
|
2258 |
+ // (only known at time of package installation)
|
|
2259 |
+ if id == "" {
|
|
2260 |
+ id = p.id
|
|
2261 |
+ }
|
|
2262 |
+ return id
|
|
2263 |
+}
|
|
2264 |
+
|
|
2265 |
+// PackageName = ident .
|
|
2266 |
+//
|
|
2267 |
+func (p *parser) parsePackageName() string {
|
|
2268 |
+ return p.expect(scanner.Ident)
|
|
2269 |
+}
|
|
2270 |
+
|
|
2271 |
+// dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
|
|
2272 |
+func (p *parser) parseDotIdent() string {
|
|
2273 |
+ ident := ""
|
|
2274 |
+ if p.tok != scanner.Int {
|
|
2275 |
+ sep := 'x' // not white space
|
|
2276 |
+ for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
|
|
2277 |
+ ident += p.lit
|
|
2278 |
+ sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
|
|
2279 |
+ p.next()
|
|
2280 |
+ }
|
|
2281 |
+ }
|
|
2282 |
+ if ident == "" {
|
|
2283 |
+ p.expect(scanner.Ident) // use expect() for error handling
|
|
2284 |
+ }
|
|
2285 |
+ return ident
|
|
2286 |
+}
|
|
2287 |
+
|
|
2288 |
+// QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) .
|
|
2289 |
+//
|
|
2290 |
+func (p *parser) parseQualifiedName() (id, name string) {
|
|
2291 |
+ p.expect('@')
|
|
2292 |
+ id = p.parsePackageId()
|
|
2293 |
+ p.expect('.')
|
|
2294 |
+ // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields.
|
|
2295 |
+ if p.tok == '?' {
|
|
2296 |
+ p.next()
|
|
2297 |
+ } else {
|
|
2298 |
+ name = p.parseDotIdent()
|
|
2299 |
+ }
|
|
2300 |
+ return
|
|
2301 |
+}
|
|
2302 |
+
|
|
2303 |
+// getPkg returns the package for a given id. If the package is
|
|
2304 |
+// not found, create the package and add it to the p.localPkgs
|
|
2305 |
+// and p.sharedPkgs maps. name is the (expected) name of the
|
|
2306 |
+// package. If name == "", the package name is expected to be
|
|
2307 |
+// set later via an import clause in the export data.
|
|
2308 |
+//
|
|
2309 |
+// id identifies a package, usually by a canonical package path like
|
|
2310 |
+// "encoding/json" but possibly by a non-canonical import path like
|
|
2311 |
+// "./json".
|
|
2312 |
+//
|
|
2313 |
+func (p *parser) getPkg(id, name string) *types.Package {
|
|
2314 |
+ // package unsafe is not in the packages maps - handle explicitly
|
|
2315 |
+ if id == "unsafe" {
|
|
2316 |
+ return types.Unsafe
|
|
2317 |
+ }
|
|
2318 |
+
|
|
2319 |
+ pkg := p.localPkgs[id]
|
|
2320 |
+ if pkg == nil {
|
|
2321 |
+ // first import of id from this package
|
|
2322 |
+ pkg = p.sharedPkgs[id]
|
|
2323 |
+ if pkg == nil {
|
|
2324 |
+ // first import of id by this importer;
|
|
2325 |
+ // add (possibly unnamed) pkg to shared packages
|
|
2326 |
+ pkg = types.NewPackage(id, name)
|
|
2327 |
+ p.sharedPkgs[id] = pkg
|
|
2328 |
+ }
|
|
2329 |
+ // add (possibly unnamed) pkg to local packages
|
|
2330 |
+ if p.localPkgs == nil {
|
|
2331 |
+ p.localPkgs = make(map[string]*types.Package)
|
|
2332 |
+ }
|
|
2333 |
+ p.localPkgs[id] = pkg
|
|
2334 |
+ } else if name != "" {
|
|
2335 |
+ // package exists already and we have an expected package name;
|
|
2336 |
+ // make sure names match or set package name if necessary
|
|
2337 |
+ if pname := pkg.Name(); pname == "" {
|
|
2338 |
+ pkg.SetName(name)
|
|
2339 |
+ } else if pname != name {
|
|
2340 |
+ p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name)
|
|
2341 |
+ }
|
|
2342 |
+ }
|
|
2343 |
+ return pkg
|
|
2344 |
+}
|
|
2345 |
+
|
|
2346 |
+// parseExportedName is like parseQualifiedName, but
|
|
2347 |
+// the package id is resolved to an imported *types.Package.
|
|
2348 |
+//
|
|
2349 |
+func (p *parser) parseExportedName() (pkg *types.Package, name string) {
|
|
2350 |
+ id, name := p.parseQualifiedName()
|
|
2351 |
+ pkg = p.getPkg(id, "")
|
|
2352 |
+ return
|
|
2353 |
+}
|
|
2354 |
+
|
|
2355 |
+// ----------------------------------------------------------------------------
|
|
2356 |
+// Types
|
|
2357 |
+
|
|
2358 |
+// BasicType = identifier .
|
|
2359 |
+//
|
|
2360 |
+func (p *parser) parseBasicType() types.Type {
|
|
2361 |
+ id := p.expect(scanner.Ident)
|
|
2362 |
+ obj := types.Universe.Lookup(id)
|
|
2363 |
+ if obj, ok := obj.(*types.TypeName); ok {
|
|
2364 |
+ return obj.Type()
|
|
2365 |
+ }
|
|
2366 |
+ p.errorf("not a basic type: %s", id)
|
|
2367 |
+ return nil
|
|
2368 |
+}
|
|
2369 |
+
|
|
2370 |
+// ArrayType = "[" int_lit "]" Type .
|
|
2371 |
+//
|
|
2372 |
+func (p *parser) parseArrayType(parent *types.Package) types.Type {
|
|
2373 |
+ // "[" already consumed and lookahead known not to be "]"
|
|
2374 |
+ lit := p.expect(scanner.Int)
|
|
2375 |
+ p.expect(']')
|
|
2376 |
+ elem := p.parseType(parent)
|
|
2377 |
+ n, err := strconv.ParseInt(lit, 10, 64)
|
|
2378 |
+ if err != nil {
|
|
2379 |
+ p.error(err)
|
|
2380 |
+ }
|
|
2381 |
+ return types.NewArray(elem, n)
|
|
2382 |
+}
|
|
2383 |
+
|
|
2384 |
+// MapType = "map" "[" Type "]" Type .
|
|
2385 |
+//
|
|
2386 |
+func (p *parser) parseMapType(parent *types.Package) types.Type {
|
|
2387 |
+ p.expectKeyword("map")
|
|
2388 |
+ p.expect('[')
|
|
2389 |
+ key := p.parseType(parent)
|
|
2390 |
+ p.expect(']')
|
|
2391 |
+ elem := p.parseType(parent)
|
|
2392 |
+ return types.NewMap(key, elem)
|
|
2393 |
+}
|
|
2394 |
+
|
|
2395 |
+// Name = identifier | "?" | QualifiedName .
|
|
2396 |
+//
|
|
2397 |
+// For unqualified and anonymous names, the returned package is the parent
|
|
2398 |
+// package unless parent == nil, in which case the returned package is the
|
|
2399 |
+// package being imported. (The parent package is not nil if the the name
|
|
2400 |
+// is an unqualified struct field or interface method name belonging to a
|
|
2401 |
+// type declared in another package.)
|
|
2402 |
+//
|
|
2403 |
+// For qualified names, the returned package is nil (and not created if
|
|
2404 |
+// it doesn't exist yet) unless materializePkg is set (which creates an
|
|
2405 |
+// unnamed package with valid package path). In the latter case, a
|
|
2406 |
+// subsequent import clause is expected to provide a name for the package.
|
|
2407 |
+//
|
|
2408 |
+func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) {
|
|
2409 |
+ pkg = parent
|
|
2410 |
+ if pkg == nil {
|
|
2411 |
+ pkg = p.sharedPkgs[p.id]
|
|
2412 |
+ }
|
|
2413 |
+ switch p.tok {
|
|
2414 |
+ case scanner.Ident:
|
|
2415 |
+ name = p.lit
|
|
2416 |
+ p.next()
|
|
2417 |
+ case '?':
|
|
2418 |
+ // anonymous
|
|
2419 |
+ p.next()
|
|
2420 |
+ case '@':
|
|
2421 |
+ // exported name prefixed with package path
|
|
2422 |
+ pkg = nil
|
|
2423 |
+ var id string
|
|
2424 |
+ id, name = p.parseQualifiedName()
|
|
2425 |
+ if materializePkg {
|
|
2426 |
+ pkg = p.getPkg(id, "")
|
|
2427 |
+ }
|
|
2428 |
+ default:
|
|
2429 |
+ p.error("name expected")
|
|
2430 |
+ }
|
|
2431 |
+ return
|
|
2432 |
+}
|
|
2433 |
+
|
|
2434 |
+func deref(typ types.Type) types.Type {
|
|
2435 |
+ if p, _ := typ.(*types.Pointer); p != nil {
|
|
2436 |
+ return p.Elem()
|
|
2437 |
+ }
|
|
2438 |
+ return typ
|
|
2439 |
+}
|
|
2440 |
+
|
|
2441 |
+// Field = Name Type [ string_lit ] .
|
|
2442 |
+//
|
|
2443 |
+func (p *parser) parseField(parent *types.Package) (*types.Var, string) {
|
|
2444 |
+ pkg, name := p.parseName(parent, true)
|
|
2445 |
+
|
|
2446 |
+ if name == "_" {
|
|
2447 |
+ // Blank fields should be package-qualified because they
|
|
2448 |
+ // are unexported identifiers, but gc does not qualify them.
|
|
2449 |
+ // Assuming that the ident belongs to the current package
|
|
2450 |
+ // causes types to change during re-exporting, leading
|
|
2451 |
+ // to spurious "can't assign A to B" errors from go/types.
|
|
2452 |
+ // As a workaround, pretend all blank fields belong
|
|
2453 |
+ // to the same unique dummy package.
|
|
2454 |
+ const blankpkg = "<_>"
|
|
2455 |
+ pkg = p.getPkg(blankpkg, blankpkg)
|
|
2456 |
+ }
|
|
2457 |
+
|
|
2458 |
+ typ := p.parseType(parent)
|
|
2459 |
+ anonymous := false
|
|
2460 |
+ if name == "" {
|
|
2461 |
+ // anonymous field - typ must be T or *T and T must be a type name
|
|
2462 |
+ switch typ := deref(typ).(type) {
|
|
2463 |
+ case *types.Basic: // basic types are named types
|
|
2464 |
+ pkg = nil // objects defined in Universe scope have no package
|
|
2465 |
+ name = typ.Name()
|
|
2466 |
+ case *types.Named:
|
|
2467 |
+ name = typ.Obj().Name()
|
|
2468 |
+ default:
|
|
2469 |
+ p.errorf("anonymous field expected")
|
|
2470 |
+ }
|
|
2471 |
+ anonymous = true
|
|
2472 |
+ }
|
|
2473 |
+ tag := ""
|
|
2474 |
+ if p.tok == scanner.String {
|
|
2475 |
+ s := p.expect(scanner.String)
|
|
2476 |
+ var err error
|
|
2477 |
+ tag, err = strconv.Unquote(s)
|
|
2478 |
+ if err != nil {
|
|
2479 |
+ p.errorf("invalid struct tag %s: %s", s, err)
|
|
2480 |
+ }
|
|
2481 |
+ }
|
|
2482 |
+ return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag
|
|
2483 |
+}
|
|
2484 |
+
|
|
2485 |
+// StructType = "struct" "{" [ FieldList ] "}" .
|
|
2486 |
+// FieldList = Field { ";" Field } .
|
|
2487 |
+//
|
|
2488 |
+func (p *parser) parseStructType(parent *types.Package) types.Type {
|
|
2489 |
+ var fields []*types.Var
|
|
2490 |
+ var tags []string
|
|
2491 |
+
|
|
2492 |
+ p.expectKeyword("struct")
|
|
2493 |
+ p.expect('{')
|
|
2494 |
+ for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
|
|
2495 |
+ if i > 0 {
|
|
2496 |
+ p.expect(';')
|
|
2497 |
+ }
|
|
2498 |
+ fld, tag := p.parseField(parent)
|
|
2499 |
+ if tag != "" && tags == nil {
|
|
2500 |
+ tags = make([]string, i)
|
|
2501 |
+ }
|
|
2502 |
+ if tags != nil {
|
|
2503 |
+ tags = append(tags, tag)
|
|
2504 |
+ }
|
|
2505 |
+ fields = append(fields, fld)
|
|
2506 |
+ }
|
|
2507 |
+ p.expect('}')
|
|
2508 |
+
|
|
2509 |
+ return types.NewStruct(fields, tags)
|
|
2510 |
+}
|
|
2511 |
+
|
|
2512 |
+// Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
|
|
2513 |
+//
|
|
2514 |
+func (p *parser) parseParameter() (par *types.Var, isVariadic bool) {
|
|
2515 |
+ _, name := p.parseName(nil, false)
|
|
2516 |
+ // remove gc-specific parameter numbering
|
|
2517 |
+ if i := strings.Index(name, "·"); i >= 0 {
|
|
2518 |
+ name = name[:i]
|
|
2519 |
+ }
|
|
2520 |
+ if p.tok == '.' {
|
|
2521 |
+ p.expectSpecial("...")
|
|
2522 |
+ isVariadic = true
|
|
2523 |
+ }
|
|
2524 |
+ typ := p.parseType(nil)
|
|
2525 |
+ if isVariadic {
|
|
2526 |
+ typ = types.NewSlice(typ)
|
|
2527 |
+ }
|
|
2528 |
+ // ignore argument tag (e.g. "noescape")
|
|
2529 |
+ if p.tok == scanner.String {
|
|
2530 |
+ p.next()
|
|
2531 |
+ }
|
|
2532 |
+ // TODO(gri) should we provide a package?
|
|
2533 |
+ par = types.NewVar(token.NoPos, nil, name, typ)
|
|
2534 |
+ return
|
|
2535 |
+}
|
|
2536 |
+
|
|
2537 |
+// Parameters = "(" [ ParameterList ] ")" .
|
|
2538 |
+// ParameterList = { Parameter "," } Parameter .
|
|
2539 |
+//
|
|
2540 |
+func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) {
|
|
2541 |
+ p.expect('(')
|
|
2542 |
+ for p.tok != ')' && p.tok != scanner.EOF {
|
|
2543 |
+ if len(list) > 0 {
|
|
2544 |
+ p.expect(',')
|
|
2545 |
+ }
|
|
2546 |
+ par, variadic := p.parseParameter()
|
|
2547 |
+ list = append(list, par)
|
|
2548 |
+ if variadic {
|
|
2549 |
+ if isVariadic {
|
|
2550 |
+ p.error("... not on final argument")
|
|
2551 |
+ }
|
|
2552 |
+ isVariadic = true
|
|
2553 |
+ }
|
|
2554 |
+ }
|
|
2555 |
+ p.expect(')')
|
|
2556 |
+
|
|
2557 |
+ return
|
|
2558 |
+}
|
|
2559 |
+
|
|
2560 |
+// Signature = Parameters [ Result ] .
|
|
2561 |
+// Result = Type | Parameters .
|
|
2562 |
+//
|
|
2563 |
+func (p *parser) parseSignature(recv *types.Var) *types.Signature {
|
|
2564 |
+ params, isVariadic := p.parseParameters()
|
|
2565 |
+
|
|
2566 |
+ // optional result type
|
|
2567 |
+ var results []*types.Var
|
|
2568 |
+ if p.tok == '(' {
|
|
2569 |
+ var variadic bool
|
|
2570 |
+ results, variadic = p.parseParameters()
|
|
2571 |
+ if variadic {
|
|
2572 |
+ p.error("... not permitted on result type")
|
|
2573 |
+ }
|
|
2574 |
+ }
|
|
2575 |
+
|
|
2576 |
+ return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic)
|
|
2577 |
+}
|
|
2578 |
+
|
|
2579 |
+// InterfaceType = "interface" "{" [ MethodList ] "}" .
|
|
2580 |
+// MethodList = Method { ";" Method } .
|
|
2581 |
+// Method = Name Signature .
|
|
2582 |
+//
|
|
2583 |
+// The methods of embedded interfaces are always "inlined"
|
|
2584 |
+// by the compiler and thus embedded interfaces are never
|
|
2585 |
+// visible in the export data.
|
|
2586 |
+//
|
|
2587 |
+func (p *parser) parseInterfaceType(parent *types.Package) types.Type {
|
|
2588 |
+ var methods []*types.Func
|
|
2589 |
+
|
|
2590 |
+ p.expectKeyword("interface")
|
|
2591 |
+ p.expect('{')
|
|
2592 |
+ for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ {
|
|
2593 |
+ if i > 0 {
|
|
2594 |
+ p.expect(';')
|
|
2595 |
+ }
|
|
2596 |
+ pkg, name := p.parseName(parent, true)
|
|
2597 |
+ sig := p.parseSignature(nil)
|
|
2598 |
+ methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig))
|
|
2599 |
+ }
|
|
2600 |
+ p.expect('}')
|
|
2601 |
+
|
|
2602 |
+ // Complete requires the type's embedded interfaces to be fully defined,
|
|
2603 |
+ // but we do not define any
|
|
2604 |
+ return types.NewInterface(methods, nil).Complete()
|
|
2605 |
+}
|
|
2606 |
+
|
|
2607 |
+// ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
|
|
2608 |
+//
|
|
2609 |
+func (p *parser) parseChanType(parent *types.Package) types.Type {
|
|
2610 |
+ dir := types.SendRecv
|
|
2611 |
+ if p.tok == scanner.Ident {
|
|
2612 |
+ p.expectKeyword("chan")
|
|
2613 |
+ if p.tok == '<' {
|
|
2614 |
+ p.expectSpecial("<-")
|
|
2615 |
+ dir = types.SendOnly
|
|
2616 |
+ }
|
|
2617 |
+ } else {
|
|
2618 |
+ p.expectSpecial("<-")
|
|
2619 |
+ p.expectKeyword("chan")
|
|
2620 |
+ dir = types.RecvOnly
|
|
2621 |
+ }
|
|
2622 |
+ elem := p.parseType(parent)
|
|
2623 |
+ return types.NewChan(dir, elem)
|
|
2624 |
+}
|
|
2625 |
+
|
|
2626 |
+// Type =
|
|
2627 |
+// BasicType | TypeName | ArrayType | SliceType | StructType |
|
|
2628 |
+// PointerType | FuncType | InterfaceType | MapType | ChanType |
|
|
2629 |
+// "(" Type ")" .
|
|
2630 |
+//
|
|
2631 |
+// BasicType = ident .
|
|
2632 |
+// TypeName = ExportedName .
|
|
2633 |
+// SliceType = "[" "]" Type .
|
|
2634 |
+// PointerType = "*" Type .
|
|
2635 |
+// FuncType = "func" Signature .
|
|
2636 |
+//
|
|
2637 |
+func (p *parser) parseType(parent *types.Package) types.Type {
|
|
2638 |
+ switch p.tok {
|
|
2639 |
+ case scanner.Ident:
|
|
2640 |
+ switch p.lit {
|
|
2641 |
+ default:
|
|
2642 |
+ return p.parseBasicType()
|
|
2643 |
+ case "struct":
|
|
2644 |
+ return p.parseStructType(parent)
|
|
2645 |
+ case "func":
|
|
2646 |
+ // FuncType
|
|
2647 |
+ p.next()
|
|
2648 |
+ return p.parseSignature(nil)
|
|
2649 |
+ case "interface":
|
|
2650 |
+ return p.parseInterfaceType(parent)
|
|
2651 |
+ case "map":
|
|
2652 |
+ return p.parseMapType(parent)
|
|
2653 |
+ case "chan":
|
|
2654 |
+ return p.parseChanType(parent)
|
|
2655 |
+ }
|
|
2656 |
+ case '@':
|
|
2657 |
+ // TypeName
|
|
2658 |
+ pkg, name := p.parseExportedName()
|
|
2659 |
+ return declTypeName(pkg, name).Type()
|
|
2660 |
+ case '[':
|
|
2661 |
+ p.next() // look ahead
|
|
2662 |
+ if p.tok == ']' {
|
|
2663 |
+ // SliceType
|
|
2664 |
+ p.next()
|
|
2665 |
+ return types.NewSlice(p.parseType(parent))
|
|
2666 |
+ }
|
|
2667 |
+ return p.parseArrayType(parent)
|
|
2668 |
+ case '*':
|
|
2669 |
+ // PointerType
|
|
2670 |
+ p.next()
|
|
2671 |
+ return types.NewPointer(p.parseType(parent))
|
|
2672 |
+ case '<':
|
|
2673 |
+ return p.parseChanType(parent)
|
|
2674 |
+ case '(':
|
|
2675 |
+ // "(" Type ")"
|
|
2676 |
+ p.next()
|
|
2677 |
+ typ := p.parseType(parent)
|
|
2678 |
+ p.expect(')')
|
|
2679 |
+ return typ
|
|
2680 |
+ }
|
|
2681 |
+ p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
|
|
2682 |
+ return nil
|
|
2683 |
+}
|
|
2684 |
+
|
|
2685 |
+// ----------------------------------------------------------------------------
|
|
2686 |
+// Declarations
|
|
2687 |
+
|
|
2688 |
+// ImportDecl = "import" PackageName PackageId .
|
|
2689 |
+//
|
|
2690 |
+func (p *parser) parseImportDecl() {
|
|
2691 |
+ p.expectKeyword("import")
|
|
2692 |
+ name := p.parsePackageName()
|
|
2693 |
+ p.getPkg(p.parsePackageId(), name)
|
|
2694 |
+}
|
|
2695 |
+
|
|
2696 |
+// int_lit = [ "+" | "-" ] { "0" ... "9" } .
|
|
2697 |
+//
|
|
2698 |
+func (p *parser) parseInt() string {
|
|
2699 |
+ s := ""
|
|
2700 |
+ switch p.tok {
|
|
2701 |
+ case '-':
|
|
2702 |
+ s = "-"
|
|
2703 |
+ p.next()
|
|
2704 |
+ case '+':
|
|
2705 |
+ p.next()
|
|
2706 |
+ }
|
|
2707 |
+ return s + p.expect(scanner.Int)
|
|
2708 |
+}
|
|
2709 |
+
|
|
2710 |
+// number = int_lit [ "p" int_lit ] .
|
|
2711 |
+//
|
|
2712 |
+func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) {
|
|
2713 |
+ // mantissa
|
|
2714 |
+ mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0)
|
|
2715 |
+ if mant == nil {
|
|
2716 |
+ panic("invalid mantissa")
|
|
2717 |
+ }
|
|
2718 |
+
|
|
2719 |
+ if p.lit == "p" {
|
|
2720 |
+ // exponent (base 2)
|
|
2721 |
+ p.next()
|
|
2722 |
+ exp, err := strconv.ParseInt(p.parseInt(), 10, 0)
|
|
2723 |
+ if err != nil {
|
|
2724 |
+ p.error(err)
|
|
2725 |
+ }
|
|
2726 |
+ if exp < 0 {
|
|
2727 |
+ denom := exact.MakeInt64(1)
|
|
2728 |
+ denom = exact.Shift(denom, token.SHL, uint(-exp))
|
|
2729 |
+ typ = types.Typ[types.UntypedFloat]
|
|
2730 |
+ val = exact.BinaryOp(mant, token.QUO, denom)
|
|
2731 |
+ return
|
|
2732 |
+ }
|
|
2733 |
+ if exp > 0 {
|
|
2734 |
+ mant = exact.Shift(mant, token.SHL, uint(exp))
|
|
2735 |
+ }
|
|
2736 |
+ typ = types.Typ[types.UntypedFloat]
|
|
2737 |
+ val = mant
|
|
2738 |
+ return
|
|
2739 |
+ }
|
|
2740 |
+
|
|
2741 |
+ typ = types.Typ[types.UntypedInt]
|
|
2742 |
+ val = mant
|
|
2743 |
+ return
|
|
2744 |
+}
|
|
2745 |
+
|
|
2746 |
+// ConstDecl = "const" ExportedName [ Type ] "=" Literal .
|
|
2747 |
+// Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit .
|
|
2748 |
+// bool_lit = "true" | "false" .
|
|
2749 |
+// complex_lit = "(" float_lit "+" float_lit "i" ")" .
|
|
2750 |
+// rune_lit = "(" int_lit "+" int_lit ")" .
|
|
2751 |
+// string_lit = `"` { unicode_char } `"` .
|
|
2752 |
+//
|
|
2753 |
+func (p *parser) parseConstDecl() {
|
|
2754 |
+ p.expectKeyword("const")
|
|
2755 |
+ pkg, name := p.parseExportedName()
|
|
2756 |
+
|
|
2757 |
+ var typ0 types.Type
|
|
2758 |
+ if p.tok != '=' {
|
|
2759 |
+ // constant types are never structured - no need for parent type
|
|
2760 |
+ typ0 = p.parseType(nil)
|
|
2761 |
+ }
|
|
2762 |
+
|
|
2763 |
+ p.expect('=')
|
|
2764 |
+ var typ types.Type
|
|
2765 |
+ var val exact.Value
|
|
2766 |
+ switch p.tok {
|
|
2767 |
+ case scanner.Ident:
|
|
2768 |
+ // bool_lit
|
|
2769 |
+ if p.lit != "true" && p.lit != "false" {
|
|
2770 |
+ p.error("expected true or false")
|
|
2771 |
+ }
|
|
2772 |
+ typ = types.Typ[types.UntypedBool]
|
|
2773 |
+ val = exact.MakeBool(p.lit == "true")
|
|
2774 |
+ p.next()
|
|
2775 |
+
|
|
2776 |
+ case '-', scanner.Int:
|
|
2777 |
+ // int_lit
|
|
2778 |
+ typ, val = p.parseNumber()
|
|
2779 |
+
|
|
2780 |
+ case '(':
|
|
2781 |
+ // complex_lit or rune_lit
|
|
2782 |
+ p.next()
|
|
2783 |
+ if p.tok == scanner.Char {
|
|
2784 |
+ p.next()
|
|
2785 |
+ p.expect('+')
|
|
2786 |
+ typ = types.Typ[types.UntypedRune]
|
|
2787 |
+ _, val = p.parseNumber()
|
|
2788 |
+ p.expect(')')
|
|
2789 |
+ break
|
|
2790 |
+ }
|
|
2791 |
+ _, re := p.parseNumber()
|
|
2792 |
+ p.expect('+')
|
|
2793 |
+ _, im := p.parseNumber()
|
|
2794 |
+ p.expectKeyword("i")
|
|
2795 |
+ p.expect(')')
|
|
2796 |
+ typ = types.Typ[types.UntypedComplex]
|
|
2797 |
+ val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im))
|
|
2798 |
+
|
|
2799 |
+ case scanner.Char:
|
|
2800 |
+ // rune_lit
|
|
2801 |
+ typ = types.Typ[types.UntypedRune]
|
|
2802 |
+ val = exact.MakeFromLiteral(p.lit, token.CHAR, 0)
|
|
2803 |
+ p.next()
|
|
2804 |
+
|
|
2805 |
+ case scanner.String:
|
|
2806 |
+ // string_lit
|
|
2807 |
+ typ = types.Typ[types.UntypedString]
|
|
2808 |
+ val = exact.MakeFromLiteral(p.lit, token.STRING, 0)
|
|
2809 |
+ p.next()
|
|
2810 |
+
|
|
2811 |
+ default:
|
|
2812 |
+ p.errorf("expected literal got %s", scanner.TokenString(p.tok))
|
|
2813 |
+ }
|
|
2814 |
+
|
|
2815 |
+ if typ0 == nil {
|
|
2816 |
+ typ0 = typ
|
|
2817 |
+ }
|
|
2818 |
+
|
|
2819 |
+ pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val))
|
|
2820 |
+}
|
|
2821 |
+
|
|
2822 |
+// TypeDecl = "type" ExportedName Type .
|
|
2823 |
+//
|
|
2824 |
+func (p *parser) parseTypeDecl() {
|
|
2825 |
+ p.expectKeyword("type")
|
|
2826 |
+ pkg, name := p.parseExportedName()
|
|
2827 |
+ obj := declTypeName(pkg, name)
|
|
2828 |
+
|
|
2829 |
+ // The type object may have been imported before and thus already
|
|
2830 |
+ // have a type associated with it. We still need to parse the type
|
|
2831 |
+ // structure, but throw it away if the object already has a type.
|
|
2832 |
+ // This ensures that all imports refer to the same type object for
|
|
2833 |
+ // a given type declaration.
|
|
2834 |
+ typ := p.parseType(pkg)
|
|
2835 |
+
|
|
2836 |
+ if name := obj.Type().(*types.Named); name.Underlying() == nil {
|
|
2837 |
+ name.SetUnderlying(typ)
|
|
2838 |
+ }
|
|
2839 |
+}
|
|
2840 |
+
|
|
2841 |
+// VarDecl = "var" ExportedName Type .
|
|
2842 |
+//
|
|
2843 |
+func (p *parser) parseVarDecl() {
|
|
2844 |
+ p.expectKeyword("var")
|
|
2845 |
+ pkg, name := p.parseExportedName()
|
|
2846 |
+ typ := p.parseType(pkg)
|
|
2847 |
+ pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ))
|
|
2848 |
+}
|
|
2849 |
+
|
|
2850 |
+// Func = Signature [ Body ] .
|
|
2851 |
+// Body = "{" ... "}" .
|
|
2852 |
+//
|
|
2853 |
+func (p *parser) parseFunc(recv *types.Var) *types.Signature {
|
|
2854 |
+ sig := p.parseSignature(recv)
|
|
2855 |
+ if p.tok == '{' {
|
|
2856 |
+ p.next()
|
|
2857 |
+ for i := 1; i > 0; p.next() {
|
|
2858 |
+ switch p.tok {
|
|
2859 |
+ case '{':
|
|
2860 |
+ i++
|
|
2861 |
+ case '}':
|
|
2862 |
+ i--
|
|
2863 |
+ }
|
|
2864 |
+ }
|
|
2865 |
+ }
|
|
2866 |
+ return sig
|
|
2867 |
+}
|
|
2868 |
+
|
|
2869 |
+// MethodDecl = "func" Receiver Name Func .
|
|
2870 |
+// Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" .
|
|
2871 |
+//
|
|
2872 |
+func (p *parser) parseMethodDecl() {
|
|
2873 |
+ // "func" already consumed
|
|
2874 |
+ p.expect('(')
|
|
2875 |
+ recv, _ := p.parseParameter() // receiver
|
|
2876 |
+ p.expect(')')
|
|
2877 |
+
|
|
2878 |
+ // determine receiver base type object
|
|
2879 |
+ base := deref(recv.Type()).(*types.Named)
|
|
2880 |
+
|
|
2881 |
+ // parse method name, signature, and possibly inlined body
|
|
2882 |
+ _, name := p.parseName(nil, false)
|
|
2883 |
+ sig := p.parseFunc(recv)
|
|
2884 |
+
|
|
2885 |
+ // methods always belong to the same package as the base type object
|
|
2886 |
+ pkg := base.Obj().Pkg()
|
|
2887 |
+
|
|
2888 |
+ // add method to type unless type was imported before
|
|
2889 |
+ // and method exists already
|
|
2890 |
+ // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small.
|
|
2891 |
+ base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig))
|
|
2892 |
+}
|
|
2893 |
+
|
|
2894 |
+// FuncDecl = "func" ExportedName Func .
|
|
2895 |
+//
|
|
2896 |
+func (p *parser) parseFuncDecl() {
|
|
2897 |
+ // "func" already consumed
|
|
2898 |
+ pkg, name := p.parseExportedName()
|
|
2899 |
+ typ := p.parseFunc(nil)
|
|
2900 |
+ pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ))
|
|
2901 |
+}
|
|
2902 |
+
|
|
2903 |
+// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
|
|
2904 |
+//
|
|
2905 |
+func (p *parser) parseDecl() {
|
|
2906 |
+ if p.tok == scanner.Ident {
|
|
2907 |
+ switch p.lit {
|
|
2908 |
+ case "import":
|
|
2909 |
+ p.parseImportDecl()
|
|
2910 |
+ case "const":
|
|
2911 |
+ p.parseConstDecl()
|
|
2912 |
+ case "type":
|
|
2913 |
+ p.parseTypeDecl()
|
|
2914 |
+ case "var":
|
|
2915 |
+ p.parseVarDecl()
|
|
2916 |
+ case "func":
|
|
2917 |
+ p.next() // look ahead
|
|
2918 |
+ if p.tok == '(' {
|
|
2919 |
+ p.parseMethodDecl()
|
|
2920 |
+ } else {
|
|
2921 |
+ p.parseFuncDecl()
|
|
2922 |
+ }
|
|
2923 |
+ }
|
|
2924 |
+ }
|
|
2925 |
+ p.expect('\n')
|
|
2926 |
+}
|
|
2927 |
+
|
|
2928 |
+// ----------------------------------------------------------------------------
|
|
2929 |
+// Export
|
|
2930 |
+
|
|
2931 |
+// Export = "PackageClause { Decl } "$$" .
|
|
2932 |
+// PackageClause = "package" PackageName [ "safe" ] "\n" .
|
|
2933 |
+//
|
|
2934 |
+func (p *parser) parseExport() *types.Package {
|
|
2935 |
+ p.expectKeyword("package")
|
|
2936 |
+ name := p.parsePackageName()
|
|
2937 |
+ if p.tok == scanner.Ident && p.lit == "safe" {
|
|
2938 |
+ // package was compiled with -u option - ignore
|
|
2939 |
+ p.next()
|
|
2940 |
+ }
|
|
2941 |
+ p.expect('\n')
|
|
2942 |
+
|
|
2943 |
+ pkg := p.getPkg(p.id, name)
|
|
2944 |
+
|
|
2945 |
+ for p.tok != '$' && p.tok != scanner.EOF {
|
|
2946 |
+ p.parseDecl()
|
|
2947 |
+ }
|
|
2948 |
+
|
|
2949 |
+ if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
|
|
2950 |
+ // don't call next()/expect() since reading past the
|
|
2951 |
+ // export data may cause scanner errors (e.g. NUL chars)
|
|
2952 |
+ p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
|
|
2953 |
+ }
|
|
2954 |
+
|
|
2955 |
+ if n := p.scanner.ErrorCount; n != 0 {
|
|
2956 |
+ p.errorf("expected no scanner errors, got %d", n)
|
|
2957 |
+ }
|
|
2958 |
+
|
|
2959 |
+ // Record all locally referenced packages as imports.
|
|
2960 |
+ var imports []*types.Package
|
|
2961 |
+ for id, pkg2 := range p.localPkgs {
|
|
2962 |
+ if pkg2.Name() == "" {
|
|
2963 |
+ p.errorf("%s package has no name", id)
|
|
2964 |
+ }
|
|
2965 |
+ if id == p.id {
|
|
2966 |
+ continue // avoid self-edge
|
|
2967 |
+ }
|
|
2968 |
+ imports = append(imports, pkg2)
|
|
2969 |
+ }
|
|
2970 |
+ sort.Sort(byPath(imports))
|
|
2971 |
+ pkg.SetImports(imports)
|
|
2972 |
+
|
|
2973 |
+ // package was imported completely and without errors
|
|
2974 |
+ pkg.MarkComplete()
|
|
2975 |
+
|
|
2976 |
+ return pkg
|
|
2977 |
+}
|
|
2978 |
+
|
|
2979 |
+type byPath []*types.Package
|
|
2980 |
+
|
|
2981 |
+func (a byPath) Len() int { return len(a) }
|
|
2982 |
+func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
2983 |
+func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }
|
|
2984 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go
|
|
2985 |
new file mode 100644
|
|
2986 |
index 0000000..225ffee
|
|
2987 |
--- /dev/null
|
|
2988 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias18.go
|
|
2989 |
@@ -0,0 +1,13 @@
|
|
2990 |
+// Copyright 2017 The Go Authors. All rights reserved.
|
|
2991 |
+// Use of this source code is governed by a BSD-style
|
|
2992 |
+// license that can be found in the LICENSE file.
|
|
2993 |
+
|
|
2994 |
+// +build !go1.9
|
|
2995 |
+
|
|
2996 |
+package gcimporter
|
|
2997 |
+
|
|
2998 |
+import "go/types"
|
|
2999 |
+
|
|
3000 |
+func isAlias(obj *types.TypeName) bool {
|
|
3001 |
+ return false // there are no type aliases before Go 1.9
|
|
3002 |
+}
|
|
3003 |
diff --git a/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go b/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go
|
|
3004 |
new file mode 100644
|
|
3005 |
index 0000000..c2025d8
|
|
3006 |
--- /dev/null
|
|
3007 |
+++ b/compiler/vendor/golang.org/x/tools/go/gcimporter15/isAlias19.go
|
|
3008 |
@@ -0,0 +1,13 @@
|
|
3009 |
+// Copyright 2017 The Go Authors. All rights reserved.
|
|
3010 |
+// Use of this source code is governed by a BSD-style
|
|
3011 |
+// license that can be found in the LICENSE file.
|
|
3012 |
+
|
|
3013 |
+// +build go1.9
|
|
3014 |
+
|
|
3015 |
+package gcimporter
|
|
3016 |
+
|
|
3017 |
+import "go/types"
|
|
3018 |
+
|
|
3019 |
+func isAlias(obj *types.TypeName) bool {
|
|
3020 |
+ return obj.IsAlias()
|
|
3021 |
+}
|