}
if obj = check.objects[astObj]; obj == nil {
- obj = newObj(astObj)
+ obj = newObj(check.pkg, astObj)
check.objects[astObj] = obj
}
check.register(ident, obj)
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) {
// 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)
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
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 {
// 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}})
}
}
}
-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}
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
}
if p.tok == scanner.String {
p.next()
}
- par = &Var{Name: name, Type: typ}
+ par = &Var{Name: name, Type: typ} // Pkg == nil
return
}
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 == ']' {
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()
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
func (p *gcParser) parseVarDecl() {
p.expectKeyword("var")
pkg, name := p.parseExportedName()
- obj := declVar(pkg.Scope, name)
+ obj := declVar(pkg, name)
obj.Type = p.parseType()
}
// "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" .
// All objects implement the Object interface.
//
type Object interface {
+ GetPkg() *Package
GetName() string
GetType() Type
GetPos() token.Pos
// A Const represents a declared constant.
type Const struct {
+ Pkg *Package
Name string
Type Type
Val interface{}
// A TypeName represents a declared type.
type TypeName struct {
+ Pkg *Package
Name string
Type Type // *NamedType or *Basic
// A Variable represents a declared variable (including function parameters and results).
type Var struct {
+ Pkg *Package // nil for parameters
Name string
Type Type
// 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 }
// 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 {
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
}
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
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:
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}
}
}
}
}
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 {
}
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{
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")