gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/golang.org/x/tools/go/gcimporter15/gcimporter.go (about) 1 // Copyright 2011 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 // This file is a copy of $GOROOT/src/go/internal/gcimporter/gcimporter.go, 6 // but it also contains the original source-based importer code for Go1.6. 7 // Once we stop supporting 1.6, we can remove that code. 8 9 // Package gcimporter15 provides various functions for reading 10 // gc-generated object files that can be used to implement the 11 // Importer interface defined by the Go 1.5 standard library package. 12 // 13 // Deprecated: this package will be deleted in October 2017. 14 // New code should use golang.org/x/tools/go/gcexportdata. 15 // 16 package gcimporter // import "golang.org/x/tools/go/gcimporter15" 17 18 import ( 19 "bufio" 20 "errors" 21 "fmt" 22 "go/build" 23 exact "go/constant" 24 "go/token" 25 "go/types" 26 "io" 27 "io/ioutil" 28 "os" 29 "path/filepath" 30 "sort" 31 "strconv" 32 "strings" 33 "text/scanner" 34 ) 35 36 // debugging/development support 37 const debug = false 38 39 var pkgExts = [...]string{".a", ".o"} 40 41 // FindPkg returns the filename and unique package id for an import 42 // path based on package information provided by build.Import (using 43 // the build.Default build.Context). A relative srcDir is interpreted 44 // relative to the current working directory. 45 // If no file was found, an empty filename is returned. 46 // 47 func FindPkg(path, srcDir string) (filename, id string) { 48 if path == "" { 49 return 50 } 51 52 var noext string 53 switch { 54 default: 55 // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" 56 // Don't require the source files to be present. 57 if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 58 srcDir = abs 59 } 60 bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) 61 if bp.PkgObj == "" { 62 return 63 } 64 noext = strings.TrimSuffix(bp.PkgObj, ".a") 65 id = bp.ImportPath 66 67 case build.IsLocalImport(path): 68 // "./x" -> "/this/directory/x.ext", "/this/directory/x" 69 noext = filepath.Join(srcDir, path) 70 id = noext 71 72 case filepath.IsAbs(path): 73 // for completeness only - go/build.Import 74 // does not support absolute imports 75 // "/x" -> "/x.ext", "/x" 76 noext = path 77 id = path 78 } 79 80 if false { // for debugging 81 if path != id { 82 fmt.Printf("%s -> %s\n", path, id) 83 } 84 } 85 86 // try extensions 87 for _, ext := range pkgExts { 88 filename = noext + ext 89 if f, err := os.Stat(filename); err == nil && !f.IsDir() { 90 return 91 } 92 } 93 94 filename = "" // not found 95 return 96 } 97 98 // ImportData imports a package by reading the gc-generated export data, 99 // adds the corresponding package object to the packages map indexed by id, 100 // and returns the object. 101 // 102 // The packages map must contains all packages already imported. The data 103 // reader position must be the beginning of the export data section. The 104 // filename is only used in error messages. 105 // 106 // If packages[id] contains the completely imported package, that package 107 // can be used directly, and there is no need to call this function (but 108 // there is also no harm but for extra time used). 109 // 110 func ImportData(packages map[string]*types.Package, filename, id string, data io.Reader) (pkg *types.Package, err error) { 111 // support for parser error handling 112 defer func() { 113 switch r := recover().(type) { 114 case nil: 115 // nothing to do 116 case importError: 117 err = r 118 default: 119 panic(r) // internal error 120 } 121 }() 122 123 var p parser 124 p.init(filename, id, data, packages) 125 pkg = p.parseExport() 126 127 return 128 } 129 130 // Import imports a gc-generated package given its import path and srcDir, adds 131 // the corresponding package object to the packages map, and returns the object. 132 // The packages map must contain all packages already imported. 133 // 134 func Import(packages map[string]*types.Package, path, srcDir string) (pkg *types.Package, err error) { 135 filename, id := FindPkg(path, srcDir) 136 if filename == "" { 137 if path == "unsafe" { 138 return types.Unsafe, nil 139 } 140 err = fmt.Errorf("can't find import: %s", id) 141 return 142 } 143 144 // no need to re-import if the package was imported completely before 145 if pkg = packages[id]; pkg != nil && pkg.Complete() { 146 return 147 } 148 149 // open file 150 f, err := os.Open(filename) 151 if err != nil { 152 return 153 } 154 defer func() { 155 f.Close() 156 if err != nil { 157 // add file name to error 158 err = fmt.Errorf("reading export data: %s: %v", filename, err) 159 } 160 }() 161 162 var hdr string 163 buf := bufio.NewReader(f) 164 if hdr, err = FindExportData(buf); err != nil { 165 return 166 } 167 168 switch hdr { 169 case "$$\n": 170 return ImportData(packages, filename, id, buf) 171 case "$$B\n": 172 var data []byte 173 data, err = ioutil.ReadAll(buf) 174 if err == nil { 175 fset := token.NewFileSet() 176 _, pkg, err = BImportData(fset, packages, data, id) 177 return 178 } 179 default: 180 err = fmt.Errorf("unknown export data header: %q", hdr) 181 } 182 183 return 184 } 185 186 // ---------------------------------------------------------------------------- 187 // Parser 188 189 // TODO(gri) Imported objects don't have position information. 190 // Ideally use the debug table line info; alternatively 191 // create some fake position (or the position of the 192 // import). That way error messages referring to imported 193 // objects can print meaningful information. 194 195 // parser parses the exports inside a gc compiler-produced 196 // object/archive file and populates its scope with the results. 197 type parser struct { 198 scanner scanner.Scanner 199 tok rune // current token 200 lit string // literal string; only valid for Ident, Int, String tokens 201 id string // package id of imported package 202 sharedPkgs map[string]*types.Package // package id -> package object (across importer) 203 localPkgs map[string]*types.Package // package id -> package object (just this package) 204 } 205 206 func (p *parser) init(filename, id string, src io.Reader, packages map[string]*types.Package) { 207 p.scanner.Init(src) 208 p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) } 209 p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments 210 p.scanner.Whitespace = 1<<'\t' | 1<<' ' 211 p.scanner.Filename = filename // for good error messages 212 p.next() 213 p.id = id 214 p.sharedPkgs = packages 215 if debug { 216 // check consistency of packages map 217 for _, pkg := range packages { 218 if pkg.Name() == "" { 219 fmt.Printf("no package name for %s\n", pkg.Path()) 220 } 221 } 222 } 223 } 224 225 func (p *parser) next() { 226 p.tok = p.scanner.Scan() 227 switch p.tok { 228 case scanner.Ident, scanner.Int, scanner.Char, scanner.String, '·': 229 p.lit = p.scanner.TokenText() 230 default: 231 p.lit = "" 232 } 233 if debug { 234 fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit) 235 } 236 } 237 238 func declTypeName(pkg *types.Package, name string) *types.TypeName { 239 scope := pkg.Scope() 240 if obj := scope.Lookup(name); obj != nil { 241 return obj.(*types.TypeName) 242 } 243 obj := types.NewTypeName(token.NoPos, pkg, name, nil) 244 // a named type may be referred to before the underlying type 245 // is known - set it up 246 types.NewNamed(obj, nil, nil) 247 scope.Insert(obj) 248 return obj 249 } 250 251 // ---------------------------------------------------------------------------- 252 // Error handling 253 254 // Internal errors are boxed as importErrors. 255 type importError struct { 256 pos scanner.Position 257 err error 258 } 259 260 func (e importError) Error() string { 261 return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err) 262 } 263 264 func (p *parser) error(err interface{}) { 265 if s, ok := err.(string); ok { 266 err = errors.New(s) 267 } 268 // panic with a runtime.Error if err is not an error 269 panic(importError{p.scanner.Pos(), err.(error)}) 270 } 271 272 func (p *parser) errorf(format string, args ...interface{}) { 273 p.error(fmt.Sprintf(format, args...)) 274 } 275 276 func (p *parser) expect(tok rune) string { 277 lit := p.lit 278 if p.tok != tok { 279 p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit) 280 } 281 p.next() 282 return lit 283 } 284 285 func (p *parser) expectSpecial(tok string) { 286 sep := 'x' // not white space 287 i := 0 288 for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' { 289 sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token 290 p.next() 291 i++ 292 } 293 if i < len(tok) { 294 p.errorf("expected %q, got %q", tok, tok[0:i]) 295 } 296 } 297 298 func (p *parser) expectKeyword(keyword string) { 299 lit := p.expect(scanner.Ident) 300 if lit != keyword { 301 p.errorf("expected keyword %s, got %q", keyword, lit) 302 } 303 } 304 305 // ---------------------------------------------------------------------------- 306 // Qualified and unqualified names 307 308 // PackageId = string_lit . 309 // 310 func (p *parser) parsePackageId() string { 311 id, err := strconv.Unquote(p.expect(scanner.String)) 312 if err != nil { 313 p.error(err) 314 } 315 // id == "" stands for the imported package id 316 // (only known at time of package installation) 317 if id == "" { 318 id = p.id 319 } 320 return id 321 } 322 323 // PackageName = ident . 324 // 325 func (p *parser) parsePackageName() string { 326 return p.expect(scanner.Ident) 327 } 328 329 // dotIdentifier = ( ident | '·' ) { ident | int | '·' } . 330 func (p *parser) parseDotIdent() string { 331 ident := "" 332 if p.tok != scanner.Int { 333 sep := 'x' // not white space 334 for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' { 335 ident += p.lit 336 sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token 337 p.next() 338 } 339 } 340 if ident == "" { 341 p.expect(scanner.Ident) // use expect() for error handling 342 } 343 return ident 344 } 345 346 // QualifiedName = "@" PackageId "." ( "?" | dotIdentifier ) . 347 // 348 func (p *parser) parseQualifiedName() (id, name string) { 349 p.expect('@') 350 id = p.parsePackageId() 351 p.expect('.') 352 // Per rev f280b8a485fd (10/2/2013), qualified names may be used for anonymous fields. 353 if p.tok == '?' { 354 p.next() 355 } else { 356 name = p.parseDotIdent() 357 } 358 return 359 } 360 361 // getPkg returns the package for a given id. If the package is 362 // not found, create the package and add it to the p.localPkgs 363 // and p.sharedPkgs maps. name is the (expected) name of the 364 // package. If name == "", the package name is expected to be 365 // set later via an import clause in the export data. 366 // 367 // id identifies a package, usually by a canonical package path like 368 // "encoding/json" but possibly by a non-canonical import path like 369 // "./json". 370 // 371 func (p *parser) getPkg(id, name string) *types.Package { 372 // package unsafe is not in the packages maps - handle explicitly 373 if id == "unsafe" { 374 return types.Unsafe 375 } 376 377 pkg := p.localPkgs[id] 378 if pkg == nil { 379 // first import of id from this package 380 pkg = p.sharedPkgs[id] 381 if pkg == nil { 382 // first import of id by this importer; 383 // add (possibly unnamed) pkg to shared packages 384 pkg = types.NewPackage(id, name) 385 p.sharedPkgs[id] = pkg 386 } 387 // add (possibly unnamed) pkg to local packages 388 if p.localPkgs == nil { 389 p.localPkgs = make(map[string]*types.Package) 390 } 391 p.localPkgs[id] = pkg 392 } else if name != "" { 393 // package exists already and we have an expected package name; 394 // make sure names match or set package name if necessary 395 if pname := pkg.Name(); pname == "" { 396 pkg.SetName(name) 397 } else if pname != name { 398 p.errorf("%s package name mismatch: %s (given) vs %s (expected)", id, pname, name) 399 } 400 } 401 return pkg 402 } 403 404 // parseExportedName is like parseQualifiedName, but 405 // the package id is resolved to an imported *types.Package. 406 // 407 func (p *parser) parseExportedName() (pkg *types.Package, name string) { 408 id, name := p.parseQualifiedName() 409 pkg = p.getPkg(id, "") 410 return 411 } 412 413 // ---------------------------------------------------------------------------- 414 // Types 415 416 // BasicType = identifier . 417 // 418 func (p *parser) parseBasicType() types.Type { 419 id := p.expect(scanner.Ident) 420 obj := types.Universe.Lookup(id) 421 if obj, ok := obj.(*types.TypeName); ok { 422 return obj.Type() 423 } 424 p.errorf("not a basic type: %s", id) 425 return nil 426 } 427 428 // ArrayType = "[" int_lit "]" Type . 429 // 430 func (p *parser) parseArrayType(parent *types.Package) types.Type { 431 // "[" already consumed and lookahead known not to be "]" 432 lit := p.expect(scanner.Int) 433 p.expect(']') 434 elem := p.parseType(parent) 435 n, err := strconv.ParseInt(lit, 10, 64) 436 if err != nil { 437 p.error(err) 438 } 439 return types.NewArray(elem, n) 440 } 441 442 // MapType = "map" "[" Type "]" Type . 443 // 444 func (p *parser) parseMapType(parent *types.Package) types.Type { 445 p.expectKeyword("map") 446 p.expect('[') 447 key := p.parseType(parent) 448 p.expect(']') 449 elem := p.parseType(parent) 450 return types.NewMap(key, elem) 451 } 452 453 // Name = identifier | "?" | QualifiedName . 454 // 455 // For unqualified and anonymous names, the returned package is the parent 456 // package unless parent == nil, in which case the returned package is the 457 // package being imported. (The parent package is not nil if the the name 458 // is an unqualified struct field or interface method name belonging to a 459 // type declared in another package.) 460 // 461 // For qualified names, the returned package is nil (and not created if 462 // it doesn't exist yet) unless materializePkg is set (which creates an 463 // unnamed package with valid package path). In the latter case, a 464 // subsequent import clause is expected to provide a name for the package. 465 // 466 func (p *parser) parseName(parent *types.Package, materializePkg bool) (pkg *types.Package, name string) { 467 pkg = parent 468 if pkg == nil { 469 pkg = p.sharedPkgs[p.id] 470 } 471 switch p.tok { 472 case scanner.Ident: 473 name = p.lit 474 p.next() 475 case '?': 476 // anonymous 477 p.next() 478 case '@': 479 // exported name prefixed with package path 480 pkg = nil 481 var id string 482 id, name = p.parseQualifiedName() 483 if materializePkg { 484 pkg = p.getPkg(id, "") 485 } 486 default: 487 p.error("name expected") 488 } 489 return 490 } 491 492 func deref(typ types.Type) types.Type { 493 if p, _ := typ.(*types.Pointer); p != nil { 494 return p.Elem() 495 } 496 return typ 497 } 498 499 // Field = Name Type [ string_lit ] . 500 // 501 func (p *parser) parseField(parent *types.Package) (*types.Var, string) { 502 pkg, name := p.parseName(parent, true) 503 504 if name == "_" { 505 // Blank fields should be package-qualified because they 506 // are unexported identifiers, but gc does not qualify them. 507 // Assuming that the ident belongs to the current package 508 // causes types to change during re-exporting, leading 509 // to spurious "can't assign A to B" errors from go/types. 510 // As a workaround, pretend all blank fields belong 511 // to the same unique dummy package. 512 const blankpkg = "<_>" 513 pkg = p.getPkg(blankpkg, blankpkg) 514 } 515 516 typ := p.parseType(parent) 517 anonymous := false 518 if name == "" { 519 // anonymous field - typ must be T or *T and T must be a type name 520 switch typ := deref(typ).(type) { 521 case *types.Basic: // basic types are named types 522 pkg = nil // objects defined in Universe scope have no package 523 name = typ.Name() 524 case *types.Named: 525 name = typ.Obj().Name() 526 default: 527 p.errorf("anonymous field expected") 528 } 529 anonymous = true 530 } 531 tag := "" 532 if p.tok == scanner.String { 533 s := p.expect(scanner.String) 534 var err error 535 tag, err = strconv.Unquote(s) 536 if err != nil { 537 p.errorf("invalid struct tag %s: %s", s, err) 538 } 539 } 540 return types.NewField(token.NoPos, pkg, name, typ, anonymous), tag 541 } 542 543 // StructType = "struct" "{" [ FieldList ] "}" . 544 // FieldList = Field { ";" Field } . 545 // 546 func (p *parser) parseStructType(parent *types.Package) types.Type { 547 var fields []*types.Var 548 var tags []string 549 550 p.expectKeyword("struct") 551 p.expect('{') 552 for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { 553 if i > 0 { 554 p.expect(';') 555 } 556 fld, tag := p.parseField(parent) 557 if tag != "" && tags == nil { 558 tags = make([]string, i) 559 } 560 if tags != nil { 561 tags = append(tags, tag) 562 } 563 fields = append(fields, fld) 564 } 565 p.expect('}') 566 567 return types.NewStruct(fields, tags) 568 } 569 570 // Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] . 571 // 572 func (p *parser) parseParameter() (par *types.Var, isVariadic bool) { 573 _, name := p.parseName(nil, false) 574 // remove gc-specific parameter numbering 575 if i := strings.Index(name, "·"); i >= 0 { 576 name = name[:i] 577 } 578 if p.tok == '.' { 579 p.expectSpecial("...") 580 isVariadic = true 581 } 582 typ := p.parseType(nil) 583 if isVariadic { 584 typ = types.NewSlice(typ) 585 } 586 // ignore argument tag (e.g. "noescape") 587 if p.tok == scanner.String { 588 p.next() 589 } 590 // TODO(gri) should we provide a package? 591 par = types.NewVar(token.NoPos, nil, name, typ) 592 return 593 } 594 595 // Parameters = "(" [ ParameterList ] ")" . 596 // ParameterList = { Parameter "," } Parameter . 597 // 598 func (p *parser) parseParameters() (list []*types.Var, isVariadic bool) { 599 p.expect('(') 600 for p.tok != ')' && p.tok != scanner.EOF { 601 if len(list) > 0 { 602 p.expect(',') 603 } 604 par, variadic := p.parseParameter() 605 list = append(list, par) 606 if variadic { 607 if isVariadic { 608 p.error("... not on final argument") 609 } 610 isVariadic = true 611 } 612 } 613 p.expect(')') 614 615 return 616 } 617 618 // Signature = Parameters [ Result ] . 619 // Result = Type | Parameters . 620 // 621 func (p *parser) parseSignature(recv *types.Var) *types.Signature { 622 params, isVariadic := p.parseParameters() 623 624 // optional result type 625 var results []*types.Var 626 if p.tok == '(' { 627 var variadic bool 628 results, variadic = p.parseParameters() 629 if variadic { 630 p.error("... not permitted on result type") 631 } 632 } 633 634 return types.NewSignature(recv, types.NewTuple(params...), types.NewTuple(results...), isVariadic) 635 } 636 637 // InterfaceType = "interface" "{" [ MethodList ] "}" . 638 // MethodList = Method { ";" Method } . 639 // Method = Name Signature . 640 // 641 // The methods of embedded interfaces are always "inlined" 642 // by the compiler and thus embedded interfaces are never 643 // visible in the export data. 644 // 645 func (p *parser) parseInterfaceType(parent *types.Package) types.Type { 646 var methods []*types.Func 647 648 p.expectKeyword("interface") 649 p.expect('{') 650 for i := 0; p.tok != '}' && p.tok != scanner.EOF; i++ { 651 if i > 0 { 652 p.expect(';') 653 } 654 pkg, name := p.parseName(parent, true) 655 sig := p.parseSignature(nil) 656 methods = append(methods, types.NewFunc(token.NoPos, pkg, name, sig)) 657 } 658 p.expect('}') 659 660 // Complete requires the type's embedded interfaces to be fully defined, 661 // but we do not define any 662 return types.NewInterface(methods, nil).Complete() 663 } 664 665 // ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type . 666 // 667 func (p *parser) parseChanType(parent *types.Package) types.Type { 668 dir := types.SendRecv 669 if p.tok == scanner.Ident { 670 p.expectKeyword("chan") 671 if p.tok == '<' { 672 p.expectSpecial("<-") 673 dir = types.SendOnly 674 } 675 } else { 676 p.expectSpecial("<-") 677 p.expectKeyword("chan") 678 dir = types.RecvOnly 679 } 680 elem := p.parseType(parent) 681 return types.NewChan(dir, elem) 682 } 683 684 // Type = 685 // BasicType | TypeName | ArrayType | SliceType | StructType | 686 // PointerType | FuncType | InterfaceType | MapType | ChanType | 687 // "(" Type ")" . 688 // 689 // BasicType = ident . 690 // TypeName = ExportedName . 691 // SliceType = "[" "]" Type . 692 // PointerType = "*" Type . 693 // FuncType = "func" Signature . 694 // 695 func (p *parser) parseType(parent *types.Package) types.Type { 696 switch p.tok { 697 case scanner.Ident: 698 switch p.lit { 699 default: 700 return p.parseBasicType() 701 case "struct": 702 return p.parseStructType(parent) 703 case "func": 704 // FuncType 705 p.next() 706 return p.parseSignature(nil) 707 case "interface": 708 return p.parseInterfaceType(parent) 709 case "map": 710 return p.parseMapType(parent) 711 case "chan": 712 return p.parseChanType(parent) 713 } 714 case '@': 715 // TypeName 716 pkg, name := p.parseExportedName() 717 return declTypeName(pkg, name).Type() 718 case '[': 719 p.next() // look ahead 720 if p.tok == ']' { 721 // SliceType 722 p.next() 723 return types.NewSlice(p.parseType(parent)) 724 } 725 return p.parseArrayType(parent) 726 case '*': 727 // PointerType 728 p.next() 729 return types.NewPointer(p.parseType(parent)) 730 case '<': 731 return p.parseChanType(parent) 732 case '(': 733 // "(" Type ")" 734 p.next() 735 typ := p.parseType(parent) 736 p.expect(')') 737 return typ 738 } 739 p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit) 740 return nil 741 } 742 743 // ---------------------------------------------------------------------------- 744 // Declarations 745 746 // ImportDecl = "import" PackageName PackageId . 747 // 748 func (p *parser) parseImportDecl() { 749 p.expectKeyword("import") 750 name := p.parsePackageName() 751 p.getPkg(p.parsePackageId(), name) 752 } 753 754 // int_lit = [ "+" | "-" ] { "0" ... "9" } . 755 // 756 func (p *parser) parseInt() string { 757 s := "" 758 switch p.tok { 759 case '-': 760 s = "-" 761 p.next() 762 case '+': 763 p.next() 764 } 765 return s + p.expect(scanner.Int) 766 } 767 768 // number = int_lit [ "p" int_lit ] . 769 // 770 func (p *parser) parseNumber() (typ *types.Basic, val exact.Value) { 771 // mantissa 772 mant := exact.MakeFromLiteral(p.parseInt(), token.INT, 0) 773 if mant == nil { 774 panic("invalid mantissa") 775 } 776 777 if p.lit == "p" { 778 // exponent (base 2) 779 p.next() 780 exp, err := strconv.ParseInt(p.parseInt(), 10, 0) 781 if err != nil { 782 p.error(err) 783 } 784 if exp < 0 { 785 denom := exact.MakeInt64(1) 786 denom = exact.Shift(denom, token.SHL, uint(-exp)) 787 typ = types.Typ[types.UntypedFloat] 788 val = exact.BinaryOp(mant, token.QUO, denom) 789 return 790 } 791 if exp > 0 { 792 mant = exact.Shift(mant, token.SHL, uint(exp)) 793 } 794 typ = types.Typ[types.UntypedFloat] 795 val = mant 796 return 797 } 798 799 typ = types.Typ[types.UntypedInt] 800 val = mant 801 return 802 } 803 804 // ConstDecl = "const" ExportedName [ Type ] "=" Literal . 805 // Literal = bool_lit | int_lit | float_lit | complex_lit | rune_lit | string_lit . 806 // bool_lit = "true" | "false" . 807 // complex_lit = "(" float_lit "+" float_lit "i" ")" . 808 // rune_lit = "(" int_lit "+" int_lit ")" . 809 // string_lit = `"` { unicode_char } `"` . 810 // 811 func (p *parser) parseConstDecl() { 812 p.expectKeyword("const") 813 pkg, name := p.parseExportedName() 814 815 var typ0 types.Type 816 if p.tok != '=' { 817 // constant types are never structured - no need for parent type 818 typ0 = p.parseType(nil) 819 } 820 821 p.expect('=') 822 var typ types.Type 823 var val exact.Value 824 switch p.tok { 825 case scanner.Ident: 826 // bool_lit 827 if p.lit != "true" && p.lit != "false" { 828 p.error("expected true or false") 829 } 830 typ = types.Typ[types.UntypedBool] 831 val = exact.MakeBool(p.lit == "true") 832 p.next() 833 834 case '-', scanner.Int: 835 // int_lit 836 typ, val = p.parseNumber() 837 838 case '(': 839 // complex_lit or rune_lit 840 p.next() 841 if p.tok == scanner.Char { 842 p.next() 843 p.expect('+') 844 typ = types.Typ[types.UntypedRune] 845 _, val = p.parseNumber() 846 p.expect(')') 847 break 848 } 849 _, re := p.parseNumber() 850 p.expect('+') 851 _, im := p.parseNumber() 852 p.expectKeyword("i") 853 p.expect(')') 854 typ = types.Typ[types.UntypedComplex] 855 val = exact.BinaryOp(re, token.ADD, exact.MakeImag(im)) 856 857 case scanner.Char: 858 // rune_lit 859 typ = types.Typ[types.UntypedRune] 860 val = exact.MakeFromLiteral(p.lit, token.CHAR, 0) 861 p.next() 862 863 case scanner.String: 864 // string_lit 865 typ = types.Typ[types.UntypedString] 866 val = exact.MakeFromLiteral(p.lit, token.STRING, 0) 867 p.next() 868 869 default: 870 p.errorf("expected literal got %s", scanner.TokenString(p.tok)) 871 } 872 873 if typ0 == nil { 874 typ0 = typ 875 } 876 877 pkg.Scope().Insert(types.NewConst(token.NoPos, pkg, name, typ0, val)) 878 } 879 880 // TypeDecl = "type" ExportedName Type . 881 // 882 func (p *parser) parseTypeDecl() { 883 p.expectKeyword("type") 884 pkg, name := p.parseExportedName() 885 obj := declTypeName(pkg, name) 886 887 // The type object may have been imported before and thus already 888 // have a type associated with it. We still need to parse the type 889 // structure, but throw it away if the object already has a type. 890 // This ensures that all imports refer to the same type object for 891 // a given type declaration. 892 typ := p.parseType(pkg) 893 894 if name := obj.Type().(*types.Named); name.Underlying() == nil { 895 name.SetUnderlying(typ) 896 } 897 } 898 899 // VarDecl = "var" ExportedName Type . 900 // 901 func (p *parser) parseVarDecl() { 902 p.expectKeyword("var") 903 pkg, name := p.parseExportedName() 904 typ := p.parseType(pkg) 905 pkg.Scope().Insert(types.NewVar(token.NoPos, pkg, name, typ)) 906 } 907 908 // Func = Signature [ Body ] . 909 // Body = "{" ... "}" . 910 // 911 func (p *parser) parseFunc(recv *types.Var) *types.Signature { 912 sig := p.parseSignature(recv) 913 if p.tok == '{' { 914 p.next() 915 for i := 1; i > 0; p.next() { 916 switch p.tok { 917 case '{': 918 i++ 919 case '}': 920 i-- 921 } 922 } 923 } 924 return sig 925 } 926 927 // MethodDecl = "func" Receiver Name Func . 928 // Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" . 929 // 930 func (p *parser) parseMethodDecl() { 931 // "func" already consumed 932 p.expect('(') 933 recv, _ := p.parseParameter() // receiver 934 p.expect(')') 935 936 // determine receiver base type object 937 base := deref(recv.Type()).(*types.Named) 938 939 // parse method name, signature, and possibly inlined body 940 _, name := p.parseName(nil, false) 941 sig := p.parseFunc(recv) 942 943 // methods always belong to the same package as the base type object 944 pkg := base.Obj().Pkg() 945 946 // add method to type unless type was imported before 947 // and method exists already 948 // TODO(gri) This leads to a quadratic algorithm - ok for now because method counts are small. 949 base.AddMethod(types.NewFunc(token.NoPos, pkg, name, sig)) 950 } 951 952 // FuncDecl = "func" ExportedName Func . 953 // 954 func (p *parser) parseFuncDecl() { 955 // "func" already consumed 956 pkg, name := p.parseExportedName() 957 typ := p.parseFunc(nil) 958 pkg.Scope().Insert(types.NewFunc(token.NoPos, pkg, name, typ)) 959 } 960 961 // Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" . 962 // 963 func (p *parser) parseDecl() { 964 if p.tok == scanner.Ident { 965 switch p.lit { 966 case "import": 967 p.parseImportDecl() 968 case "const": 969 p.parseConstDecl() 970 case "type": 971 p.parseTypeDecl() 972 case "var": 973 p.parseVarDecl() 974 case "func": 975 p.next() // look ahead 976 if p.tok == '(' { 977 p.parseMethodDecl() 978 } else { 979 p.parseFuncDecl() 980 } 981 } 982 } 983 p.expect('\n') 984 } 985 986 // ---------------------------------------------------------------------------- 987 // Export 988 989 // Export = "PackageClause { Decl } "$$" . 990 // PackageClause = "package" PackageName [ "safe" ] "\n" . 991 // 992 func (p *parser) parseExport() *types.Package { 993 p.expectKeyword("package") 994 name := p.parsePackageName() 995 if p.tok == scanner.Ident && p.lit == "safe" { 996 // package was compiled with -u option - ignore 997 p.next() 998 } 999 p.expect('\n') 1000 1001 pkg := p.getPkg(p.id, name) 1002 1003 for p.tok != '$' && p.tok != scanner.EOF { 1004 p.parseDecl() 1005 } 1006 1007 if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' { 1008 // don't call next()/expect() since reading past the 1009 // export data may cause scanner errors (e.g. NUL chars) 1010 p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch) 1011 } 1012 1013 if n := p.scanner.ErrorCount; n != 0 { 1014 p.errorf("expected no scanner errors, got %d", n) 1015 } 1016 1017 // Record all locally referenced packages as imports. 1018 var imports []*types.Package 1019 for id, pkg2 := range p.localPkgs { 1020 if pkg2.Name() == "" { 1021 p.errorf("%s package has no name", id) 1022 } 1023 if id == p.id { 1024 continue // avoid self-edge 1025 } 1026 imports = append(imports, pkg2) 1027 } 1028 sort.Sort(byPath(imports)) 1029 pkg.SetImports(imports) 1030 1031 // package was imported completely and without errors 1032 pkg.MarkComplete() 1033 1034 return pkg 1035 } 1036 1037 type byPath []*types.Package 1038 1039 func (a byPath) Len() int { return len(a) } 1040 func (a byPath) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 1041 func (a byPath) Less(i, j int) bool { return a[i].Path() < a[j].Path() }