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