mirror of
https://github.com/golang/go
synced 2024-09-25 11:20:13 -06:00
go/types: Pkg *Package field for all objects
The field is nil for predeclared (universe) objects and parameter/result variables. R=adonovan CC=golang-dev https://golang.org/cl/7312093
This commit is contained in:
parent
86d509b463
commit
95aaca6708
@ -70,7 +70,7 @@ func (check *checker) lookup(ident *ast.Ident) Object {
|
||||
}
|
||||
|
||||
if obj = check.objects[astObj]; obj == nil {
|
||||
obj = newObj(astObj)
|
||||
obj = newObj(check.pkg, astObj)
|
||||
check.objects[astObj] = obj
|
||||
}
|
||||
check.register(ident, obj)
|
||||
@ -346,7 +346,7 @@ func (check *checker) assocMethod(meth *ast.FuncDecl) {
|
||||
scope = new(Scope)
|
||||
check.methods[tname] = scope
|
||||
}
|
||||
check.declareIdent(scope, meth.Name, &Func{Name: meth.Name.Name, decl: meth})
|
||||
check.declareIdent(scope, meth.Name, &Func{Pkg: check.pkg, Name: meth.Name.Name, decl: meth})
|
||||
}
|
||||
|
||||
func (check *checker) decl(decl ast.Decl) {
|
||||
@ -378,7 +378,7 @@ func (check *checker) decl(decl ast.Decl) {
|
||||
// since they are not in any scope. Create a dummy object for them.
|
||||
if d.Name.Name == "init" {
|
||||
assert(obj == nil) // all other functions should have an object
|
||||
obj = &Func{Name: d.Name.Name, decl: d}
|
||||
obj = &Func{Pkg: check.pkg, Name: d.Name.Name, decl: d}
|
||||
check.register(d.Name, obj)
|
||||
}
|
||||
check.object(obj, false)
|
||||
@ -403,8 +403,9 @@ func check(ctxt *Context, fset *token.FileSet, files []*ast.File) (pkg *Package,
|
||||
conversions: make(map[*ast.CallExpr]bool),
|
||||
}
|
||||
|
||||
// handle panics
|
||||
// set results and handle panics
|
||||
defer func() {
|
||||
pkg = check.pkg
|
||||
switch p := recover().(type) {
|
||||
case nil, bailout:
|
||||
// normal return or early exit
|
||||
@ -422,8 +423,7 @@ func check(ctxt *Context, fset *token.FileSet, files []*ast.File) (pkg *Package,
|
||||
if imp == nil {
|
||||
imp = GcImport
|
||||
}
|
||||
pkg, methods := check.resolve(imp)
|
||||
check.pkg = pkg
|
||||
methods := check.resolve(imp)
|
||||
|
||||
// associate methods with types
|
||||
for _, m := range methods {
|
||||
|
@ -238,6 +238,7 @@ func TestCheck(t *testing.T) {
|
||||
// the construction of the Universe var.
|
||||
if !testBuiltinsDeclared {
|
||||
testBuiltinsDeclared = true
|
||||
// Pkg == nil for Universe objects
|
||||
def(&Func{Name: "assert", Type: &builtin{_Assert, "assert", 1, false, true}})
|
||||
def(&Func{Name: "trace", Type: &builtin{_Trace, "trace", 0, true, true}})
|
||||
}
|
||||
|
@ -197,23 +197,25 @@ func (p *gcParser) next() {
|
||||
}
|
||||
}
|
||||
|
||||
func declConst(scope *Scope, name string) *Const {
|
||||
func declConst(pkg *Package, name string) *Const {
|
||||
// the constant may have been imported before - if it exists
|
||||
// already in the respective scope, return that constant
|
||||
scope := pkg.Scope
|
||||
if obj := scope.Lookup(name); obj != nil {
|
||||
return obj.(*Const)
|
||||
}
|
||||
// otherwise create a new constant and insert it into the scope
|
||||
obj := &Const{Name: name}
|
||||
obj := &Const{Pkg: pkg, Name: name}
|
||||
scope.Insert(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
func declTypeName(scope *Scope, name string) *TypeName {
|
||||
func declTypeName(pkg *Package, name string) *TypeName {
|
||||
scope := pkg.Scope
|
||||
if obj := scope.Lookup(name); obj != nil {
|
||||
return obj.(*TypeName)
|
||||
}
|
||||
obj := &TypeName{Name: name}
|
||||
obj := &TypeName{Pkg: pkg, Name: name}
|
||||
// a named type may be referred to before the underlying type
|
||||
// is known - set it up
|
||||
obj.Type = &NamedType{Obj: obj}
|
||||
@ -221,20 +223,22 @@ func declTypeName(scope *Scope, name string) *TypeName {
|
||||
return obj
|
||||
}
|
||||
|
||||
func declVar(scope *Scope, name string) *Var {
|
||||
func declVar(pkg *Package, name string) *Var {
|
||||
scope := pkg.Scope
|
||||
if obj := scope.Lookup(name); obj != nil {
|
||||
return obj.(*Var)
|
||||
}
|
||||
obj := &Var{Name: name}
|
||||
obj := &Var{Pkg: pkg, Name: name}
|
||||
scope.Insert(obj)
|
||||
return obj
|
||||
}
|
||||
|
||||
func declFunc(scope *Scope, name string) *Func {
|
||||
func declFunc(pkg *Package, name string) *Func {
|
||||
scope := pkg.Scope
|
||||
if obj := scope.Lookup(name); obj != nil {
|
||||
return obj.(*Func)
|
||||
}
|
||||
obj := &Func{Name: name}
|
||||
obj := &Func{Pkg: pkg, Name: name}
|
||||
scope.Insert(obj)
|
||||
return obj
|
||||
}
|
||||
@ -507,7 +511,7 @@ func (p *gcParser) parseParameter() (par *Var, isVariadic bool) {
|
||||
if p.tok == scanner.String {
|
||||
p.next()
|
||||
}
|
||||
par = &Var{Name: name, Type: typ}
|
||||
par = &Var{Name: name, Type: typ} // Pkg == nil
|
||||
return
|
||||
}
|
||||
|
||||
@ -637,7 +641,7 @@ func (p *gcParser) parseType() Type {
|
||||
case '@':
|
||||
// TypeName
|
||||
pkg, name := p.parseExportedName()
|
||||
return declTypeName(pkg.Scope, name).Type
|
||||
return declTypeName(pkg, name).Type
|
||||
case '[':
|
||||
p.next() // look ahead
|
||||
if p.tok == ']' {
|
||||
@ -740,7 +744,7 @@ func (p *gcParser) parseNumber() (x operand) {
|
||||
func (p *gcParser) parseConstDecl() {
|
||||
p.expectKeyword("const")
|
||||
pkg, name := p.parseExportedName()
|
||||
obj := declConst(pkg.Scope, name)
|
||||
obj := declConst(pkg, name)
|
||||
var x operand
|
||||
if p.tok != '=' {
|
||||
obj.Type = p.parseType()
|
||||
@ -806,7 +810,7 @@ func (p *gcParser) parseConstDecl() {
|
||||
func (p *gcParser) parseTypeDecl() {
|
||||
p.expectKeyword("type")
|
||||
pkg, name := p.parseExportedName()
|
||||
obj := declTypeName(pkg.Scope, name)
|
||||
obj := declTypeName(pkg, name)
|
||||
|
||||
// The type object may have been imported before and thus already
|
||||
// have a type associated with it. We still need to parse the type
|
||||
@ -825,7 +829,7 @@ func (p *gcParser) parseTypeDecl() {
|
||||
func (p *gcParser) parseVarDecl() {
|
||||
p.expectKeyword("var")
|
||||
pkg, name := p.parseExportedName()
|
||||
obj := declVar(pkg.Scope, name)
|
||||
obj := declVar(pkg, name)
|
||||
obj.Type = p.parseType()
|
||||
}
|
||||
|
||||
@ -886,7 +890,7 @@ func (p *gcParser) parseFuncDecl() {
|
||||
// "func" already consumed
|
||||
pkg, name := p.parseExportedName()
|
||||
typ := p.parseFunc()
|
||||
declFunc(pkg.Scope, name).Type = typ
|
||||
declFunc(pkg, name).Type = typ
|
||||
}
|
||||
|
||||
// Decl = [ ImportDecl | ConstDecl | TypeDecl | VarDecl | FuncDecl | MethodDecl ] "\n" .
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
// All objects implement the Object interface.
|
||||
//
|
||||
type Object interface {
|
||||
GetPkg() *Package
|
||||
GetName() string
|
||||
GetType() Type
|
||||
GetPos() token.Pos
|
||||
@ -34,6 +35,7 @@ type Package struct {
|
||||
|
||||
// A Const represents a declared constant.
|
||||
type Const struct {
|
||||
Pkg *Package
|
||||
Name string
|
||||
Type Type
|
||||
Val interface{}
|
||||
@ -43,6 +45,7 @@ type Const struct {
|
||||
|
||||
// A TypeName represents a declared type.
|
||||
type TypeName struct {
|
||||
Pkg *Package
|
||||
Name string
|
||||
Type Type // *NamedType or *Basic
|
||||
|
||||
@ -51,6 +54,7 @@ type TypeName struct {
|
||||
|
||||
// A Variable represents a declared variable (including function parameters and results).
|
||||
type Var struct {
|
||||
Pkg *Package // nil for parameters
|
||||
Name string
|
||||
Type Type
|
||||
|
||||
@ -60,12 +64,19 @@ type Var struct {
|
||||
|
||||
// A Func represents a declared function.
|
||||
type Func struct {
|
||||
Pkg *Package
|
||||
Name string
|
||||
Type Type // *Signature or *Builtin
|
||||
|
||||
decl *ast.FuncDecl
|
||||
}
|
||||
|
||||
func (obj *Package) GetPkg() *Package { return obj }
|
||||
func (obj *Const) GetPkg() *Package { return obj.Pkg }
|
||||
func (obj *TypeName) GetPkg() *Package { return obj.Pkg }
|
||||
func (obj *Var) GetPkg() *Package { return obj.Pkg }
|
||||
func (obj *Func) GetPkg() *Package { return obj.Pkg }
|
||||
|
||||
func (obj *Package) GetName() string { return obj.Name }
|
||||
func (obj *Const) GetName() string { return obj.Name }
|
||||
func (obj *TypeName) GetName() string { return obj.Name }
|
||||
@ -126,7 +137,8 @@ func (*Func) anObject() {}
|
||||
// TODO(gri) Once we do identifier resolution completely in
|
||||
// in the typechecker, this functionality can go.
|
||||
//
|
||||
func newObj(astObj *ast.Object) Object {
|
||||
func newObj(pkg *Package, astObj *ast.Object) Object {
|
||||
assert(pkg != nil)
|
||||
name := astObj.Name
|
||||
typ, _ := astObj.Type.(Type)
|
||||
switch astObj.Kind {
|
||||
@ -135,18 +147,18 @@ func newObj(astObj *ast.Object) Object {
|
||||
case ast.Pkg:
|
||||
unreachable()
|
||||
case ast.Con:
|
||||
return &Const{Name: name, Type: typ, Val: astObj.Data, spec: astObj.Decl.(*ast.ValueSpec)}
|
||||
return &Const{Pkg: pkg, Name: name, Type: typ, Val: astObj.Data, spec: astObj.Decl.(*ast.ValueSpec)}
|
||||
case ast.Typ:
|
||||
return &TypeName{Name: name, Type: typ, spec: astObj.Decl.(*ast.TypeSpec)}
|
||||
return &TypeName{Pkg: pkg, Name: name, Type: typ, spec: astObj.Decl.(*ast.TypeSpec)}
|
||||
case ast.Var:
|
||||
switch astObj.Decl.(type) {
|
||||
case *ast.Field, *ast.ValueSpec, *ast.AssignStmt: // these are ok
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
return &Var{Name: name, Type: typ, decl: astObj.Decl}
|
||||
return &Var{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl}
|
||||
case ast.Fun:
|
||||
return &Func{Name: name, Type: typ, decl: astObj.Decl.(*ast.FuncDecl)}
|
||||
return &Func{Pkg: pkg, Name: name, Type: typ, decl: astObj.Decl.(*ast.FuncDecl)}
|
||||
case ast.Lbl:
|
||||
unreachable() // for now
|
||||
}
|
||||
|
@ -36,8 +36,9 @@ func (check *checker) resolveIdent(scope *Scope, ident *ast.Ident) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (check *checker) resolve(importer Importer) (pkg *Package, methods []*ast.FuncDecl) {
|
||||
pkg = &Package{Scope: &Scope{Outer: Universe}, Imports: make(map[string]*Package)}
|
||||
func (check *checker) resolve(importer Importer) (methods []*ast.FuncDecl) {
|
||||
pkg := &Package{Scope: &Scope{Outer: Universe}, Imports: make(map[string]*Package)}
|
||||
check.pkg = pkg
|
||||
|
||||
// complete package scope
|
||||
i := 0
|
||||
|
@ -116,14 +116,14 @@ func TestResolveQualifiedIdents(t *testing.T) {
|
||||
for _, list := range x.Fields.List {
|
||||
for _, f := range list.Names {
|
||||
assert(idents[f] == nil)
|
||||
idents[f] = &Var{Name: f.Name}
|
||||
idents[f] = &Var{Pkg: pkg, Name: f.Name}
|
||||
}
|
||||
}
|
||||
case *ast.InterfaceType:
|
||||
for _, list := range x.Methods.List {
|
||||
for _, f := range list.Names {
|
||||
assert(idents[f] == nil)
|
||||
idents[f] = &Func{Name: f.Name}
|
||||
idents[f] = &Func{Pkg: pkg, Name: f.Name}
|
||||
}
|
||||
}
|
||||
case *ast.CompositeLit:
|
||||
@ -131,7 +131,7 @@ func TestResolveQualifiedIdents(t *testing.T) {
|
||||
if kv, ok := e.(*ast.KeyValueExpr); ok {
|
||||
if k, ok := kv.Key.(*ast.Ident); ok {
|
||||
assert(idents[k] == nil)
|
||||
idents[k] = &Var{Name: k.Name}
|
||||
idents[k] = &Var{Pkg: pkg, Name: k.Name}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ func (check *checker) stmt(s ast.Stmt) {
|
||||
}
|
||||
name := ast.NewIdent(res.Name)
|
||||
name.NamePos = s.Pos()
|
||||
check.register(name, &Var{Name: res.Name, Type: res.Type})
|
||||
check.register(name, &Var{Name: res.Name, Type: res.Type}) // Pkg == nil
|
||||
lhs[i] = name
|
||||
}
|
||||
if len(s.Results) > 0 || !named {
|
||||
|
@ -55,10 +55,10 @@ var aliases = [...]*Basic{
|
||||
}
|
||||
|
||||
var predeclaredConstants = [...]*Const{
|
||||
{"true", Typ[UntypedBool], true, nil},
|
||||
{"false", Typ[UntypedBool], false, nil},
|
||||
{"iota", Typ[UntypedInt], zeroConst, nil},
|
||||
{"nil", Typ[UntypedNil], nilConst, nil},
|
||||
{nil, "true", Typ[UntypedBool], true, nil},
|
||||
{nil, "false", Typ[UntypedBool], false, nil},
|
||||
{nil, "iota", Typ[UntypedInt], zeroConst, nil},
|
||||
{nil, "nil", Typ[UntypedNil], nilConst, nil},
|
||||
}
|
||||
|
||||
var predeclaredFunctions = [...]*builtin{
|
||||
@ -130,6 +130,15 @@ func def(obj Object) {
|
||||
scope := Universe
|
||||
if ast.IsExported(name) {
|
||||
scope = Unsafe.Scope
|
||||
// set Pkg field
|
||||
switch obj := obj.(type) {
|
||||
case *TypeName:
|
||||
obj.Pkg = Unsafe
|
||||
case *Func:
|
||||
obj.Pkg = Unsafe
|
||||
default:
|
||||
unreachable()
|
||||
}
|
||||
}
|
||||
if scope.Insert(obj) != nil {
|
||||
panic("internal error: double declaration")
|
||||
|
Loading…
Reference in New Issue
Block a user