// findField returns the object with the given name if visible in the type's scope.
// If no such object is found, an error is reported and a bad object is returned instead.
func (tc *typechecker) findField(typ *Type, name *ast.Ident) (obj *ast.Object) {
	// TODO(gri) This is simplistic at the moment and ignores anonymous fields.
	obj = typ.Scope.Lookup(name.Name)
	if obj == nil {
		tc.Errorf(name.Pos(), "%s not declared", name.Name)
		obj = ast.NewObj(ast.Bad, name.Name)
	}
	return
}
// find returns the object with the given name if visible in the current scope hierarchy.
// If no such object is found, an error is reported and a bad object is returned instead.
func (tc *typechecker) find(name *ast.Ident) (obj *ast.Object) {
	for s := tc.topScope; s != nil && obj == nil; s = s.Outer {
		obj = s.Lookup(name.Name)
	}
	if obj == nil {
		tc.Errorf(name.Pos(), "%s not declared", name.Name)
		obj = ast.NewObj(ast.Bad, name.Name)
	}
	name.Obj = obj
	return
}
// declInScope declares an object of a given kind and name in scope and sets the object's Decl and N fields.
// It returns the newly allocated object. If an object with the same name already exists in scope, an error
// is reported and the object is not inserted.
func (tc *typechecker) declInScope(scope *ast.Scope, kind ast.ObjKind, name *ast.Ident, decl interface{}, n int) *ast.Object {
	obj := ast.NewObj(kind, name.Name)
	obj.Decl = decl
	//obj.N = n
	name.Obj = obj
	if name.Name != "_" {
		if alt := scope.Insert(obj); alt != nil {
			tc.Errorf(name.Pos(), "%s already declared at %s", name.Name, tc.fset.Position(alt.Pos()).String())
		}
	}
	return obj
}