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