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.
5 // This file implements an ast.Importer for gc generated object files.
6 // TODO(gri) Eventually move this into a separate package outside types.
24 const trace = false // set to true for debugging
27 pkgRoot = filepath.Join(runtime.GOROOT(), "pkg", runtime.GOOS+"_"+runtime.GOARCH)
28 pkgExts = [...]string{".a", ".5", ".6", ".8"}
31 // findPkg returns the filename and package id for an import path.
32 // If no file was found, an empty filename is returned.
33 func findPkg(path string) (filename, id string) {
42 // "x" -> "$GOROOT/pkg/$GOOS_$GOARCH/x.ext", "x"
43 noext = filepath.Join(pkgRoot, path)
46 // "./x" -> "/this/directory/x.ext", "/this/directory/x"
47 cwd, err := os.Getwd()
51 noext = filepath.Join(cwd, path)
55 // "/x" -> "/x.ext", "/x"
60 for _, ext := range pkgExts {
61 filename = noext + ext
62 if f, err := os.Stat(filename); err == nil && !f.IsDir() {
67 filename = "" // not found
71 // gcParser parses the exports inside a gc compiler-produced
72 // object/archive file and populates its scope with the results.
73 type gcParser struct {
74 scanner scanner.Scanner
75 tok rune // current token
76 lit string // literal string; only valid for Ident, Int, String tokens
77 id string // package id of imported package
78 imports map[string]*ast.Object // package id -> package object
81 func (p *gcParser) init(filename, id string, src io.Reader, imports map[string]*ast.Object) {
83 p.scanner.Error = func(_ *scanner.Scanner, msg string) { p.error(msg) }
84 p.scanner.Mode = scanner.ScanIdents | scanner.ScanInts | scanner.ScanChars | scanner.ScanStrings | scanner.ScanComments | scanner.SkipComments
85 p.scanner.Whitespace = 1<<'\t' | 1<<' '
86 p.scanner.Filename = filename // for good error messages
92 func (p *gcParser) next() {
93 p.tok = p.scanner.Scan()
95 case scanner.Ident, scanner.Int, scanner.String:
96 p.lit = p.scanner.TokenText()
101 fmt.Printf("%s: %q -> %q\n", scanner.TokenString(p.tok), p.scanner.TokenText(), p.lit)
105 // GcImporter implements the ast.Importer signature.
106 func GcImporter(imports map[string]*ast.Object, path string) (pkg *ast.Object, err error) {
107 if path == "unsafe" {
112 if r := recover(); r != nil {
113 err = r.(importError) // will re-panic if r is not an importError
115 panic(err) // force a stack trace
120 filename, id := findPkg(path)
122 err = errors.New("can't find import: " + id)
126 if pkg = imports[id]; pkg != nil {
127 return // package was imported before
130 buf, err := ExportData(filename)
137 fmt.Printf("importing %s (%s)\n", id, filename)
141 p.init(filename, id, buf, imports)
142 pkg = p.parseExport()
146 // Declare inserts a named object of the given kind in scope.
147 func (p *gcParser) declare(scope *ast.Scope, kind ast.ObjKind, name string) *ast.Object {
148 // the object may have been imported before - if it exists
149 // already in the respective package scope, return that object
150 if obj := scope.Lookup(name); obj != nil {
151 assert(obj.Kind == kind)
155 // otherwise create a new object and insert it into the package scope
156 obj := ast.NewObj(kind, name)
157 if scope.Insert(obj) != nil {
158 p.errorf("already declared: %v %s", kind, obj.Name)
161 // a new type object is a named type and may be referred
162 // to before the underlying type is known - set it up
164 obj.Type = &Name{Obj: obj}
170 // ----------------------------------------------------------------------------
173 // Internal errors are boxed as importErrors.
174 type importError struct {
179 func (e importError) Error() string {
180 return fmt.Sprintf("import error %s (byte offset = %d): %s", e.pos, e.pos.Offset, e.err)
183 func (p *gcParser) error(err interface{}) {
184 if s, ok := err.(string); ok {
187 // panic with a runtime.Error if err is not an error
188 panic(importError{p.scanner.Pos(), err.(error)})
191 func (p *gcParser) errorf(format string, args ...interface{}) {
192 p.error(fmt.Sprintf(format, args...))
195 func (p *gcParser) expect(tok rune) string {
199 p.errorf("expected %s, got %s (%s)", scanner.TokenString(tok), scanner.TokenString(p.tok), lit)
205 func (p *gcParser) expectSpecial(tok string) {
206 sep := 'x' // not white space
208 for i < len(tok) && p.tok == rune(tok[i]) && sep > ' ' {
209 sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
214 p.errorf("expected %q, got %q", tok, tok[0:i])
218 func (p *gcParser) expectKeyword(keyword string) {
219 lit := p.expect(scanner.Ident)
221 p.errorf("expected keyword %s, got %q", keyword, lit)
225 // ----------------------------------------------------------------------------
226 // Import declarations
228 // ImportPath = string_lit .
230 func (p *gcParser) parsePkgId() *ast.Object {
231 id, err := strconv.Unquote(p.expect(scanner.String))
238 // id == "" stands for the imported package id
239 // (only known at time of package installation)
242 // package unsafe is not in the imports map - handle explicitly
248 scope = ast.NewScope(nil)
249 pkg = ast.NewObj(ast.Pkg, "")
257 // dotIdentifier = ( ident | '·' ) { ident | int | '·' } .
258 func (p *gcParser) parseDotIdent() string {
260 if p.tok != scanner.Int {
261 sep := 'x' // not white space
262 for (p.tok == scanner.Ident || p.tok == scanner.Int || p.tok == '·') && sep > ' ' {
264 sep = p.scanner.Peek() // if sep <= ' ', there is white space before the next token
269 p.expect(scanner.Ident) // use expect() for error handling
274 // ExportedName = "@" ImportPath "." dotIdentifier .
276 func (p *gcParser) parseExportedName() (*ast.Object, string) {
278 pkg := p.parsePkgId()
280 name := p.parseDotIdent()
284 // ----------------------------------------------------------------------------
287 // BasicType = identifier .
289 func (p *gcParser) parseBasicType() Type {
290 id := p.expect(scanner.Ident)
291 obj := Universe.Lookup(id)
292 if obj == nil || obj.Kind != ast.Typ {
293 p.errorf("not a basic type: %s", id)
295 return obj.Type.(Type)
298 // ArrayType = "[" int_lit "]" Type .
300 func (p *gcParser) parseArrayType() Type {
301 // "[" already consumed and lookahead known not to be "]"
302 lit := p.expect(scanner.Int)
305 n, err := strconv.ParseUint(lit, 10, 64)
309 return &Array{Len: n, Elt: elt}
312 // MapType = "map" "[" Type "]" Type .
314 func (p *gcParser) parseMapType() Type {
315 p.expectKeyword("map")
320 return &Map{Key: key, Elt: elt}
323 // Name = identifier | "?" | ExportedName .
325 func (p *gcParser) parseName() (name string) {
334 // exported name prefixed with package path
335 _, name = p.parseExportedName()
337 p.error("name expected")
342 // Field = Name Type [ string_lit ] .
344 func (p *gcParser) parseField() (fld *ast.Object, tag string) {
345 name := p.parseName()
346 ftyp := p.parseType()
348 // anonymous field - ftyp must be T or *T and T must be a type name
349 if _, ok := Deref(ftyp).(*Name); !ok {
350 p.errorf("anonymous field expected")
353 if p.tok == scanner.String {
354 tag = p.expect(scanner.String)
356 fld = ast.NewObj(ast.Var, name)
361 // StructType = "struct" "{" [ FieldList ] "}" .
362 // FieldList = Field { ";" Field } .
364 func (p *gcParser) parseStructType() Type {
365 var fields []*ast.Object
368 parseField := func() {
369 fld, tag := p.parseField()
370 fields = append(fields, fld)
371 tags = append(tags, tag)
374 p.expectKeyword("struct")
385 return &Struct{Fields: fields, Tags: tags}
388 // Parameter = ( identifier | "?" ) [ "..." ] Type [ string_lit ] .
390 func (p *gcParser) parseParameter() (par *ast.Object, isVariadic bool) {
391 name := p.parseName()
393 name = "_" // cannot access unnamed identifiers
396 p.expectSpecial("...")
399 ptyp := p.parseType()
400 // ignore argument tag
401 if p.tok == scanner.String {
402 p.expect(scanner.String)
404 par = ast.NewObj(ast.Var, name)
409 // Parameters = "(" [ ParameterList ] ")" .
410 // ParameterList = { Parameter "," } Parameter .
412 func (p *gcParser) parseParameters() (list []*ast.Object, isVariadic bool) {
413 parseParameter := func() {
414 par, variadic := p.parseParameter()
415 list = append(list, par)
418 p.error("... not on final argument")
437 // Signature = Parameters [ Result ] .
438 // Result = Type | Parameters .
440 func (p *gcParser) parseSignature() *Func {
441 params, isVariadic := p.parseParameters()
443 // optional result type
444 var results []*ast.Object
446 case scanner.Ident, '[', '*', '<', '@':
447 // single, unnamed result
448 result := ast.NewObj(ast.Var, "_")
449 result.Type = p.parseType()
450 results = []*ast.Object{result}
452 // named or multiple result(s)
454 results, variadic = p.parseParameters()
456 p.error("... not permitted on result type")
460 return &Func{Params: params, Results: results, IsVariadic: isVariadic}
463 // MethodSpec = ( identifier | ExportedName ) Signature .
465 func (p *gcParser) parseMethodSpec() *ast.Object {
466 if p.tok == scanner.Ident {
467 p.expect(scanner.Ident)
469 p.parseExportedName()
473 // TODO(gri) compute method object
474 return ast.NewObj(ast.Fun, "_")
477 // InterfaceType = "interface" "{" [ MethodList ] "}" .
478 // MethodList = MethodSpec { ";" MethodSpec } .
480 func (p *gcParser) parseInterfaceType() Type {
483 parseMethod := func() {
484 meth := p.parseMethodSpec()
485 methods = append(methods, meth)
488 p.expectKeyword("interface")
500 return &Interface{Methods: methods}
503 // ChanType = ( "chan" [ "<-" ] | "<-" "chan" ) Type .
505 func (p *gcParser) parseChanType() Type {
506 dir := ast.SEND | ast.RECV
507 if p.tok == scanner.Ident {
508 p.expectKeyword("chan")
510 p.expectSpecial("<-")
514 p.expectSpecial("<-")
515 p.expectKeyword("chan")
519 return &Chan{Dir: dir, Elt: elt}
523 // BasicType | TypeName | ArrayType | SliceType | StructType |
524 // PointerType | FuncType | InterfaceType | MapType | ChanType |
526 // BasicType = ident .
527 // TypeName = ExportedName .
528 // SliceType = "[" "]" Type .
529 // PointerType = "*" Type .
530 // FuncType = "func" Signature .
532 func (p *gcParser) parseType() Type {
537 return p.parseBasicType()
539 return p.parseStructType()
543 return p.parseSignature()
545 return p.parseInterfaceType()
547 return p.parseMapType()
549 return p.parseChanType()
553 pkg, name := p.parseExportedName()
554 return p.declare(pkg.Data.(*ast.Scope), ast.Typ, name).Type.(Type)
556 p.next() // look ahead
560 return &Slice{Elt: p.parseType()}
562 return p.parseArrayType()
566 return &Pointer{Base: p.parseType()}
568 return p.parseChanType()
576 p.errorf("expected type, got %s (%q)", scanner.TokenString(p.tok), p.lit)
580 // ----------------------------------------------------------------------------
583 // ImportDecl = "import" identifier string_lit .
585 func (p *gcParser) parseImportDecl() {
586 p.expectKeyword("import")
587 // The identifier has no semantic meaning in the import data.
588 // It exists so that error messages can print the real package
589 // name: binary.ByteOrder instead of "encoding/binary".ByteOrder.
590 name := p.expect(scanner.Ident)
591 pkg := p.parsePkgId()
592 assert(pkg.Name == "" || pkg.Name == name)
596 // int_lit = [ "+" | "-" ] { "0" ... "9" } .
598 func (p *gcParser) parseInt() (sign, val string) {
606 val = p.expect(scanner.Int)
610 // number = int_lit [ "p" int_lit ] .
612 func (p *gcParser) parseNumber() Const {
614 sign, val := p.parseInt()
615 mant, ok := new(big.Int).SetString(sign+val, 10)
621 sign, val = p.parseInt()
622 exp64, err := strconv.ParseUint(val, 10, 0)
628 denom := big.NewInt(1)
629 denom.Lsh(denom, exp)
630 return Const{new(big.Rat).SetFrac(mant, denom)}
635 return Const{new(big.Rat).SetInt(mant)}
641 // ConstDecl = "const" ExportedName [ Type ] "=" Literal .
642 // Literal = bool_lit | int_lit | float_lit | complex_lit | string_lit .
643 // bool_lit = "true" | "false" .
644 // complex_lit = "(" float_lit "+" float_lit ")" .
645 // rune_lit = "(" int_lit "+" int_lit ")" .
646 // string_lit = `"` { unicode_char } `"` .
648 func (p *gcParser) parseConstDecl() {
649 p.expectKeyword("const")
650 pkg, name := p.parseExportedName()
651 obj := p.declare(pkg.Data.(*ast.Scope), ast.Con, name)
655 obj.Type = p.parseType()
661 if p.lit != "true" && p.lit != "false" {
662 p.error("expected true or false")
664 x = Const{p.lit == "true"}
665 typ = Bool.Underlying
667 case '-', scanner.Int:
671 if _, ok := x.val.(*big.Rat); ok {
672 typ = Float64.Underlying
675 // complex_lit or rune_lit
677 if p.tok == scanner.Char {
685 re := p.parseNumber()
687 im := p.parseNumber()
689 x = Const{cmplx{re.val.(*big.Rat), im.val.(*big.Rat)}}
690 typ = Complex128.Underlying
696 x = MakeConst(token.STRING, p.lit)
698 typ = String.Underlying
701 p.errorf("expected literal got %s", scanner.TokenString(p.tok))
709 // TypeDecl = "type" ExportedName Type .
711 func (p *gcParser) parseTypeDecl() {
712 p.expectKeyword("type")
713 pkg, name := p.parseExportedName()
714 obj := p.declare(pkg.Data.(*ast.Scope), ast.Typ, name)
716 // The type object may have been imported before and thus already
717 // have a type associated with it. We still need to parse the type
718 // structure, but throw it away if the object already has a type.
719 // This ensures that all imports refer to the same type object for
720 // a given type declaration.
723 if name := obj.Type.(*Name); name.Underlying == nil {
724 assert(Underlying(typ) == typ)
725 name.Underlying = typ
729 // VarDecl = "var" ExportedName Type .
731 func (p *gcParser) parseVarDecl() {
732 p.expectKeyword("var")
733 pkg, name := p.parseExportedName()
734 obj := p.declare(pkg.Data.(*ast.Scope), ast.Var, name)
735 obj.Type = p.parseType()
738 // FuncBody = "{" ... "}" .
740 func (p *gcParser) parseFuncBody() {
742 for i := 1; i > 0; p.next() {
752 // FuncDecl = "func" ExportedName Signature [ FuncBody ] .
754 func (p *gcParser) parseFuncDecl() {
755 // "func" already consumed
756 pkg, name := p.parseExportedName()
757 obj := p.declare(pkg.Data.(*ast.Scope), ast.Fun, name)
758 obj.Type = p.parseSignature()
764 // MethodDecl = "func" Receiver Name Signature .
765 // Receiver = "(" ( identifier | "?" ) [ "*" ] ExportedName ")" [ FuncBody ].
767 func (p *gcParser) parseMethodDecl() {
768 // "func" already consumed
770 p.parseParameter() // receiver
772 p.parseName() // unexported method names in imports are qualified with their package.
779 // Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
781 func (p *gcParser) parseDecl() {
792 p.next() // look ahead
802 // ----------------------------------------------------------------------------
805 // Export = "PackageClause { Decl } "$$" .
806 // PackageClause = "package" identifier [ "safe" ] "\n" .
808 func (p *gcParser) parseExport() *ast.Object {
809 p.expectKeyword("package")
810 name := p.expect(scanner.Ident)
812 // A package is safe if it was compiled with the -u flag,
813 // which disables the unsafe package.
814 // TODO(gri) remember "safe" package
815 p.expectKeyword("safe")
819 assert(p.imports[p.id] == nil)
820 pkg := ast.NewObj(ast.Pkg, name)
821 pkg.Data = ast.NewScope(nil)
822 p.imports[p.id] = pkg
824 for p.tok != '$' && p.tok != scanner.EOF {
828 if ch := p.scanner.Peek(); p.tok != '$' || ch != '$' {
829 // don't call next()/expect() since reading past the
830 // export data may cause scanner errors (e.g. NUL chars)
831 p.errorf("expected '$$', got %s %c", scanner.TokenString(p.tok), ch)
834 if n := p.scanner.ErrorCount; n != 0 {
835 p.errorf("expected no scanner errors, got %d", n)