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