Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / golang.org / x / tools / go / internal / gcimporter / iimport.go
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Indexed package import.
6 // See cmd/compile/internal/gc/iexport.go for the export data format.
7
8 // This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
9
10 package gcimporter
11
12 import (
13         "bytes"
14         "encoding/binary"
15         "fmt"
16         "go/constant"
17         "go/token"
18         "go/types"
19         "io"
20         "sort"
21 )
22
23 type intReader struct {
24         *bytes.Reader
25         path string
26 }
27
28 func (r *intReader) int64() int64 {
29         i, err := binary.ReadVarint(r.Reader)
30         if err != nil {
31                 errorf("import %q: read varint error: %v", r.path, err)
32         }
33         return i
34 }
35
36 func (r *intReader) uint64() uint64 {
37         i, err := binary.ReadUvarint(r.Reader)
38         if err != nil {
39                 errorf("import %q: read varint error: %v", r.path, err)
40         }
41         return i
42 }
43
44 const predeclReserved = 32
45
46 type itag uint64
47
48 const (
49         // Types
50         definedType itag = iota
51         pointerType
52         sliceType
53         arrayType
54         chanType
55         mapType
56         signatureType
57         structType
58         interfaceType
59 )
60
61 // IImportData imports a package from the serialized package data
62 // and returns the number of bytes consumed and a reference to the package.
63 // If the export data version is not recognized or the format is otherwise
64 // compromised, an error is returned.
65 func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
66         const currentVersion = 0
67         version := -1
68         defer func() {
69                 if e := recover(); e != nil {
70                         if version > currentVersion {
71                                 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
72                         } else {
73                                 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
74                         }
75                 }
76         }()
77
78         r := &intReader{bytes.NewReader(data), path}
79
80         version = int(r.uint64())
81         switch version {
82         case currentVersion:
83         default:
84                 errorf("unknown iexport format version %d", version)
85         }
86
87         sLen := int64(r.uint64())
88         dLen := int64(r.uint64())
89
90         whence, _ := r.Seek(0, io.SeekCurrent)
91         stringData := data[whence : whence+sLen]
92         declData := data[whence+sLen : whence+sLen+dLen]
93         r.Seek(sLen+dLen, io.SeekCurrent)
94
95         p := iimporter{
96                 ipath: path,
97
98                 stringData:  stringData,
99                 stringCache: make(map[uint64]string),
100                 pkgCache:    make(map[uint64]*types.Package),
101
102                 declData: declData,
103                 pkgIndex: make(map[*types.Package]map[string]uint64),
104                 typCache: make(map[uint64]types.Type),
105
106                 fake: fakeFileSet{
107                         fset:  fset,
108                         files: make(map[string]*token.File),
109                 },
110         }
111
112         for i, pt := range predeclared() {
113                 p.typCache[uint64(i)] = pt
114         }
115
116         pkgList := make([]*types.Package, r.uint64())
117         for i := range pkgList {
118                 pkgPathOff := r.uint64()
119                 pkgPath := p.stringAt(pkgPathOff)
120                 pkgName := p.stringAt(r.uint64())
121                 _ = r.uint64() // package height; unused by go/types
122
123                 if pkgPath == "" {
124                         pkgPath = path
125                 }
126                 pkg := imports[pkgPath]
127                 if pkg == nil {
128                         pkg = types.NewPackage(pkgPath, pkgName)
129                         imports[pkgPath] = pkg
130                 } else if pkg.Name() != pkgName {
131                         errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
132                 }
133
134                 p.pkgCache[pkgPathOff] = pkg
135
136                 nameIndex := make(map[string]uint64)
137                 for nSyms := r.uint64(); nSyms > 0; nSyms-- {
138                         name := p.stringAt(r.uint64())
139                         nameIndex[name] = r.uint64()
140                 }
141
142                 p.pkgIndex[pkg] = nameIndex
143                 pkgList[i] = pkg
144         }
145         var localpkg *types.Package
146         for _, pkg := range pkgList {
147                 if pkg.Path() == path {
148                         localpkg = pkg
149                 }
150         }
151
152         names := make([]string, 0, len(p.pkgIndex[localpkg]))
153         for name := range p.pkgIndex[localpkg] {
154                 names = append(names, name)
155         }
156         sort.Strings(names)
157         for _, name := range names {
158                 p.doDecl(localpkg, name)
159         }
160
161         for _, typ := range p.interfaceList {
162                 typ.Complete()
163         }
164
165         // record all referenced packages as imports
166         list := append(([]*types.Package)(nil), pkgList[1:]...)
167         sort.Sort(byPath(list))
168         localpkg.SetImports(list)
169
170         // package was imported completely and without errors
171         localpkg.MarkComplete()
172
173         consumed, _ := r.Seek(0, io.SeekCurrent)
174         return int(consumed), localpkg, nil
175 }
176
177 type iimporter struct {
178         ipath string
179
180         stringData  []byte
181         stringCache map[uint64]string
182         pkgCache    map[uint64]*types.Package
183
184         declData []byte
185         pkgIndex map[*types.Package]map[string]uint64
186         typCache map[uint64]types.Type
187
188         fake          fakeFileSet
189         interfaceList []*types.Interface
190 }
191
192 func (p *iimporter) doDecl(pkg *types.Package, name string) {
193         // See if we've already imported this declaration.
194         if obj := pkg.Scope().Lookup(name); obj != nil {
195                 return
196         }
197
198         off, ok := p.pkgIndex[pkg][name]
199         if !ok {
200                 errorf("%v.%v not in index", pkg, name)
201         }
202
203         r := &importReader{p: p, currPkg: pkg}
204         r.declReader.Reset(p.declData[off:])
205
206         r.obj(name)
207 }
208
209 func (p *iimporter) stringAt(off uint64) string {
210         if s, ok := p.stringCache[off]; ok {
211                 return s
212         }
213
214         slen, n := binary.Uvarint(p.stringData[off:])
215         if n <= 0 {
216                 errorf("varint failed")
217         }
218         spos := off + uint64(n)
219         s := string(p.stringData[spos : spos+slen])
220         p.stringCache[off] = s
221         return s
222 }
223
224 func (p *iimporter) pkgAt(off uint64) *types.Package {
225         if pkg, ok := p.pkgCache[off]; ok {
226                 return pkg
227         }
228         path := p.stringAt(off)
229         errorf("missing package %q in %q", path, p.ipath)
230         return nil
231 }
232
233 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
234         if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
235                 return t
236         }
237
238         if off < predeclReserved {
239                 errorf("predeclared type missing from cache: %v", off)
240         }
241
242         r := &importReader{p: p}
243         r.declReader.Reset(p.declData[off-predeclReserved:])
244         t := r.doType(base)
245
246         if base == nil || !isInterface(t) {
247                 p.typCache[off] = t
248         }
249         return t
250 }
251
252 type importReader struct {
253         p          *iimporter
254         declReader bytes.Reader
255         currPkg    *types.Package
256         prevFile   string
257         prevLine   int64
258 }
259
260 func (r *importReader) obj(name string) {
261         tag := r.byte()
262         pos := r.pos()
263
264         switch tag {
265         case 'A':
266                 typ := r.typ()
267
268                 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
269
270         case 'C':
271                 typ, val := r.value()
272
273                 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
274
275         case 'F':
276                 sig := r.signature(nil)
277
278                 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
279
280         case 'T':
281                 // Types can be recursive. We need to setup a stub
282                 // declaration before recursing.
283                 obj := types.NewTypeName(pos, r.currPkg, name, nil)
284                 named := types.NewNamed(obj, nil, nil)
285                 r.declare(obj)
286
287                 underlying := r.p.typAt(r.uint64(), named).Underlying()
288                 named.SetUnderlying(underlying)
289
290                 if !isInterface(underlying) {
291                         for n := r.uint64(); n > 0; n-- {
292                                 mpos := r.pos()
293                                 mname := r.ident()
294                                 recv := r.param()
295                                 msig := r.signature(recv)
296
297                                 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
298                         }
299                 }
300
301         case 'V':
302                 typ := r.typ()
303
304                 r.declare(types.NewVar(pos, r.currPkg, name, typ))
305
306         default:
307                 errorf("unexpected tag: %v", tag)
308         }
309 }
310
311 func (r *importReader) declare(obj types.Object) {
312         obj.Pkg().Scope().Insert(obj)
313 }
314
315 func (r *importReader) value() (typ types.Type, val constant.Value) {
316         typ = r.typ()
317
318         switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
319         case types.IsBoolean:
320                 val = constant.MakeBool(r.bool())
321
322         case types.IsString:
323                 val = constant.MakeString(r.string())
324
325         case types.IsInteger:
326                 val = r.mpint(b)
327
328         case types.IsFloat:
329                 val = r.mpfloat(b)
330
331         case types.IsComplex:
332                 re := r.mpfloat(b)
333                 im := r.mpfloat(b)
334                 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
335
336         default:
337                 if b.Kind() == types.Invalid {
338                         val = constant.MakeUnknown()
339                         return
340                 }
341                 errorf("unexpected type %v", typ) // panics
342                 panic("unreachable")
343         }
344
345         return
346 }
347
348 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
349         if (b.Info() & types.IsUntyped) != 0 {
350                 return true, 64
351         }
352
353         switch b.Kind() {
354         case types.Float32, types.Complex64:
355                 return true, 3
356         case types.Float64, types.Complex128:
357                 return true, 7
358         }
359
360         signed = (b.Info() & types.IsUnsigned) == 0
361         switch b.Kind() {
362         case types.Int8, types.Uint8:
363                 maxBytes = 1
364         case types.Int16, types.Uint16:
365                 maxBytes = 2
366         case types.Int32, types.Uint32:
367                 maxBytes = 4
368         default:
369                 maxBytes = 8
370         }
371
372         return
373 }
374
375 func (r *importReader) mpint(b *types.Basic) constant.Value {
376         signed, maxBytes := intSize(b)
377
378         maxSmall := 256 - maxBytes
379         if signed {
380                 maxSmall = 256 - 2*maxBytes
381         }
382         if maxBytes == 1 {
383                 maxSmall = 256
384         }
385
386         n, _ := r.declReader.ReadByte()
387         if uint(n) < maxSmall {
388                 v := int64(n)
389                 if signed {
390                         v >>= 1
391                         if n&1 != 0 {
392                                 v = ^v
393                         }
394                 }
395                 return constant.MakeInt64(v)
396         }
397
398         v := -n
399         if signed {
400                 v = -(n &^ 1) >> 1
401         }
402         if v < 1 || uint(v) > maxBytes {
403                 errorf("weird decoding: %v, %v => %v", n, signed, v)
404         }
405
406         buf := make([]byte, v)
407         io.ReadFull(&r.declReader, buf)
408
409         // convert to little endian
410         // TODO(gri) go/constant should have a more direct conversion function
411         //           (e.g., once it supports a big.Float based implementation)
412         for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
413                 buf[i], buf[j] = buf[j], buf[i]
414         }
415
416         x := constant.MakeFromBytes(buf)
417         if signed && n&1 != 0 {
418                 x = constant.UnaryOp(token.SUB, x, 0)
419         }
420         return x
421 }
422
423 func (r *importReader) mpfloat(b *types.Basic) constant.Value {
424         x := r.mpint(b)
425         if constant.Sign(x) == 0 {
426                 return x
427         }
428
429         exp := r.int64()
430         switch {
431         case exp > 0:
432                 x = constant.Shift(x, token.SHL, uint(exp))
433         case exp < 0:
434                 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
435                 x = constant.BinaryOp(x, token.QUO, d)
436         }
437         return x
438 }
439
440 func (r *importReader) ident() string {
441         return r.string()
442 }
443
444 func (r *importReader) qualifiedIdent() (*types.Package, string) {
445         name := r.string()
446         pkg := r.pkg()
447         return pkg, name
448 }
449
450 func (r *importReader) pos() token.Pos {
451         delta := r.int64()
452         if delta != deltaNewFile {
453                 r.prevLine += delta
454         } else if l := r.int64(); l == -1 {
455                 r.prevLine += deltaNewFile
456         } else {
457                 r.prevFile = r.string()
458                 r.prevLine = l
459         }
460
461         if r.prevFile == "" && r.prevLine == 0 {
462                 return token.NoPos
463         }
464
465         return r.p.fake.pos(r.prevFile, int(r.prevLine))
466 }
467
468 func (r *importReader) typ() types.Type {
469         return r.p.typAt(r.uint64(), nil)
470 }
471
472 func isInterface(t types.Type) bool {
473         _, ok := t.(*types.Interface)
474         return ok
475 }
476
477 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
478 func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
479
480 func (r *importReader) doType(base *types.Named) types.Type {
481         switch k := r.kind(); k {
482         default:
483                 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
484                 return nil
485
486         case definedType:
487                 pkg, name := r.qualifiedIdent()
488                 r.p.doDecl(pkg, name)
489                 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
490         case pointerType:
491                 return types.NewPointer(r.typ())
492         case sliceType:
493                 return types.NewSlice(r.typ())
494         case arrayType:
495                 n := r.uint64()
496                 return types.NewArray(r.typ(), int64(n))
497         case chanType:
498                 dir := chanDir(int(r.uint64()))
499                 return types.NewChan(dir, r.typ())
500         case mapType:
501                 return types.NewMap(r.typ(), r.typ())
502         case signatureType:
503                 r.currPkg = r.pkg()
504                 return r.signature(nil)
505
506         case structType:
507                 r.currPkg = r.pkg()
508
509                 fields := make([]*types.Var, r.uint64())
510                 tags := make([]string, len(fields))
511                 for i := range fields {
512                         fpos := r.pos()
513                         fname := r.ident()
514                         ftyp := r.typ()
515                         emb := r.bool()
516                         tag := r.string()
517
518                         fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
519                         tags[i] = tag
520                 }
521                 return types.NewStruct(fields, tags)
522
523         case interfaceType:
524                 r.currPkg = r.pkg()
525
526                 embeddeds := make([]types.Type, r.uint64())
527                 for i := range embeddeds {
528                         _ = r.pos()
529                         embeddeds[i] = r.typ()
530                 }
531
532                 methods := make([]*types.Func, r.uint64())
533                 for i := range methods {
534                         mpos := r.pos()
535                         mname := r.ident()
536
537                         // TODO(mdempsky): Matches bimport.go, but I
538                         // don't agree with this.
539                         var recv *types.Var
540                         if base != nil {
541                                 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
542                         }
543
544                         msig := r.signature(recv)
545                         methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
546                 }
547
548                 typ := newInterface(methods, embeddeds)
549                 r.p.interfaceList = append(r.p.interfaceList, typ)
550                 return typ
551         }
552 }
553
554 func (r *importReader) kind() itag {
555         return itag(r.uint64())
556 }
557
558 func (r *importReader) signature(recv *types.Var) *types.Signature {
559         params := r.paramList()
560         results := r.paramList()
561         variadic := params.Len() > 0 && r.bool()
562         return types.NewSignature(recv, params, results, variadic)
563 }
564
565 func (r *importReader) paramList() *types.Tuple {
566         xs := make([]*types.Var, r.uint64())
567         for i := range xs {
568                 xs[i] = r.param()
569         }
570         return types.NewTuple(xs...)
571 }
572
573 func (r *importReader) param() *types.Var {
574         pos := r.pos()
575         name := r.ident()
576         typ := r.typ()
577         return types.NewParam(pos, r.currPkg, name, typ)
578 }
579
580 func (r *importReader) bool() bool {
581         return r.uint64() != 0
582 }
583
584 func (r *importReader) int64() int64 {
585         n, err := binary.ReadVarint(&r.declReader)
586         if err != nil {
587                 errorf("readVarint: %v", err)
588         }
589         return n
590 }
591
592 func (r *importReader) uint64() uint64 {
593         n, err := binary.ReadUvarint(&r.declReader)
594         if err != nil {
595                 errorf("readUvarint: %v", err)
596         }
597         return n
598 }
599
600 func (r *importReader) byte() byte {
601         x, err := r.declReader.ReadByte()
602         if err != nil {
603                 errorf("declReader.ReadByte: %v", err)
604         }
605         return x
606 }