本文整理汇总了Golang中go/ast.Object.Data方法的典型用法代码示例。如果您正苦于以下问题:Golang Object.Data方法的具体用法?Golang Object.Data怎么用?Golang Object.Data使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类go/ast.Object
的用法示例。
在下文中一共展示了Object.Data方法的10个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: assocMethod
// assocMethod associates a method declaration with the respective
// receiver base type. meth.Recv must exist.
//
func (check *checker) assocMethod(meth *ast.FuncDecl) {
// The receiver type is one of the following (enforced by parser):
// - *ast.Ident
// - *ast.StarExpr{*ast.Ident}
// - *ast.BadExpr (parser error)
typ := meth.Recv.List[0].Type
if ptr, ok := typ.(*ast.StarExpr); ok {
typ = ptr.X
}
// determine receiver base type object (or nil if error)
var obj *ast.Object
if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
obj = ident.Obj
if obj.Kind != ast.Typ {
check.errorf(ident.Pos(), "%s is not a type", ident.Name)
obj = nil
}
// TODO(gri) determine if obj was defined in this package
/*
if check.notLocal(obj) {
check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
obj = nil
}
*/
} else {
// If it's not an identifier or the identifier wasn't declared/resolved,
// the parser/resolver already reported an error. Nothing to do here.
}
// determine base type scope (or nil if error)
var scope *ast.Scope
if obj != nil {
if obj.Data != nil {
scope = obj.Data.(*ast.Scope)
} else {
scope = ast.NewScope(nil)
obj.Data = scope
}
} else {
// use a dummy scope so that meth can be declared in
// presence of an error and get an associated object
// (always use a new scope so that we don't get double
// declaration errors)
scope = ast.NewScope(nil)
}
check.declare(scope, ast.Fun, meth.Name, meth)
}
示例2: assocMethod
// assocMethod associates a method declaration with the respective
// receiver base type. meth.Recv must exist.
//
func (check *checker) assocMethod(meth *ast.FuncDecl) {
// The receiver type is one of the following (enforced by parser):
// - *ast.Ident
// - *ast.StarExpr{*ast.Ident}
// - *ast.BadExpr (parser error)
typ := meth.Recv.List[0].Type
if ptr, ok := typ.(*ast.StarExpr); ok {
typ = ptr.X
}
// determine receiver base type object
var obj *ast.Object
if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
obj = ident.Obj
if obj.Kind != ast.Typ {
check.errorf(ident.Pos(), "%s is not a type", ident.Name)
return // ignore this method
}
// TODO(gri) determine if obj was defined in this package
/*
if check.notLocal(obj) {
check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
return // ignore this method
}
*/
} else {
// If it's not an identifier or the identifier wasn't declared/resolved,
// the parser/resolver already reported an error. Nothing to do here.
return // ignore this method
}
// declare method in receiver base type scope
var scope *ast.Scope
if obj.Data != nil {
scope = obj.Data.(*ast.Scope)
} else {
scope = ast.NewScope(nil)
obj.Data = scope
}
check.declare(scope, ast.Fun, meth.Name, meth)
}
示例3: object
// object typechecks an object by assigning it a type; obj.Type must be nil.
// Callers must check obj.Type before calling object; this eliminates a call
// for each identifier that has been typechecked already, a common scenario.
//
func (check *checker) object(obj *ast.Object, cycleOk bool) {
assert(obj.Type == nil)
switch obj.Kind {
case ast.Bad, ast.Pkg:
// nothing to do
case ast.Con, ast.Var:
// The obj.Data field for constants and variables is initialized
// to the respective (hypothetical, for variables) iota value by
// the parser. The object's fields can be in one of the following
// states:
// Type != nil => the constant value is Data
// Type == nil => the object is not typechecked yet, and Data can be:
// Data is int => Data is the value of iota for this declaration
// Data == nil => the object's expression is being evaluated
if obj.Data == nil {
check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
obj.Type = Typ[Invalid]
return
}
spec := obj.Decl.(*ast.ValueSpec)
iota := obj.Data.(int)
obj.Data = nil
// determine initialization expressions
values := spec.Values
if len(values) == 0 && obj.Kind == ast.Con {
values = check.initexprs[spec]
}
check.valueSpec(spec.Pos(), obj, spec.Names, spec.Type, values, iota)
case ast.Typ:
typ := &NamedType{Obj: obj}
obj.Type = typ // "mark" object so recursion terminates
typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
// typecheck associated method signatures
if obj.Data != nil {
scope := obj.Data.(*ast.Scope)
switch t := typ.Underlying.(type) {
case *Struct:
// struct fields must not conflict with methods
for _, f := range t.Fields {
if m := scope.Lookup(f.Name); m != nil {
check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
// ok to continue
}
}
case *Interface:
// methods cannot be associated with an interface type
for _, m := range scope.Objects {
recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
// ok to continue
}
}
// typecheck method signatures
for _, obj := range scope.Objects {
mdecl := obj.Decl.(*ast.FuncDecl)
sig := check.typ(mdecl.Type, cycleOk).(*Signature)
params, _ := check.collectParams(mdecl.Recv, false)
sig.Recv = params[0] // the parser/assocMethod ensure there is exactly one parameter
obj.Type = sig
check.later(obj, sig, mdecl.Body)
}
}
case ast.Fun:
fdecl := obj.Decl.(*ast.FuncDecl)
// methods are typechecked when their receivers are typechecked
if fdecl.Recv == nil {
sig := check.typ(fdecl.Type, cycleOk).(*Signature)
if obj.Name == "init" && (len(sig.Params) != 0 || len(sig.Results) != 0) {
check.errorf(fdecl.Pos(), "func init must have no arguments and no return values")
// ok to continue
}
obj.Type = sig
check.later(obj, sig, fdecl.Body)
}
default:
panic("unreachable")
}
}
示例4: VisitValueSpec
func (c *compiler) VisitValueSpec(valspec *ast.ValueSpec, isconst bool) {
var value_type types.Type
if valspec.Type != nil {
value_type = c.GetType(valspec.Type)
}
var iota_obj *ast.Object = types.Universe.Lookup("iota")
defer func(data interface{}) {
iota_obj.Data = data
}(iota_obj.Data)
for i, name_ := range valspec.Names {
// We may resolve constants in the process of resolving others.
obj := name_.Obj
if _, isvalue := (obj.Data).(Value); isvalue {
continue
}
// Set iota if necessary.
if isconst {
if iota_, isint := (name_.Obj.Data).(int); isint {
iota_value := c.NewConstValue(token.INT, strconv.Itoa(iota_))
iota_obj.Data = iota_value
// Con objects with an iota have an embedded ValueSpec
// in the Decl field. We'll just pull it out and use it
// for evaluating the expression below.
valspec = (name_.Obj.Decl).(*ast.ValueSpec)
}
}
// Expression may have side-effects, so compute it regardless of
// whether it'll be assigned to a name.
var expr ast.Expr
if i < len(valspec.Values) && valspec.Values[i] != nil {
expr = valspec.Values[i]
}
// For constants, we just pass the ConstValue around. Otherwise, we
// will convert it to an LLVMValue.
var value Value
name := name_.String()
if !isconst {
ispackagelevel := len(c.functions) == 0
if !ispackagelevel {
// Visit the expression.
var init_ Value
if expr != nil {
init_ = c.VisitExpr(expr)
if value_type == nil {
value_type = init_.Type()
}
}
// The variable should be allocated on the stack if it's
// declared inside a function.
var llvm_init llvm.Value
stack_value := c.builder.CreateAlloca(
c.types.ToLLVM(value_type), name)
if init_ == nil {
// If no initialiser was specified, set it to the
// zero value.
llvm_init = llvm.ConstNull(c.types.ToLLVM(value_type))
} else {
llvm_init = init_.Convert(value_type).LLVMValue()
}
c.builder.CreateStore(llvm_init, stack_value)
llvm_value := c.NewLLVMValue(stack_value, &types.Pointer{Base: value_type})
value = llvm_value.makePointee()
} else { // ispackagelevel
// Set the initialiser. If it's a non-const value, then
// we'll have to do the assignment in a global constructor
// function.
export := name_.IsExported()
value = c.createGlobal(expr, value_type, name, export)
}
} else { // isconst
value = c.VisitExpr(expr).(ConstValue)
if value_type != nil {
value = value.Convert(value_type)
}
}
if name != "_" {
obj.Data = value
}
}
}
示例5: object
// object typechecks an object by assigning it a type; obj.Type must be nil.
// Callers must check obj.Type before calling object; this eliminates a call
// for each identifier that has been typechecked already, a common scenario.
//
func (check *checker) object(obj *ast.Object, cycleOk bool) {
assert(obj.Type == nil)
switch obj.Kind {
case ast.Bad, ast.Pkg:
// nothing to do
case ast.Con, ast.Var:
// The obj.Data field for constants and variables is initialized
// to the respective (hypothetical, for variables) iota value by
// the parser. The object's fields can be in one of the following
// states:
// Type != nil => the constant value is Data
// Type == nil => the object is not typechecked yet, and Data can be:
// Data is int => Data is the value of iota for this declaration
// Data == nil => the object's expression is being evaluated
if obj.Data == nil {
check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
obj.Type = Typ[Invalid]
return
}
spec := obj.Decl.(*ast.ValueSpec)
iota := obj.Data.(int)
obj.Data = nil
// determine initialization expressions
values := spec.Values
if len(values) == 0 && obj.Kind == ast.Con {
values = check.initexprs[spec]
}
check.valueSpec(spec.Pos(), obj, spec.Names, spec.Type, values, iota)
case ast.Typ:
typ := &NamedType{Obj: obj}
obj.Type = typ // "mark" object so recursion terminates
typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
// typecheck associated method signatures
if obj.Data != nil {
scope := obj.Data.(*ast.Scope)
switch t := typ.Underlying.(type) {
case *Struct:
// struct fields must not conflict with methods
for _, f := range t.Fields {
if m := scope.Lookup(f.Name); m != nil {
check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
}
}
// ok to continue
case *Interface:
// methods cannot be associated with an interface type
for _, m := range scope.Objects {
recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
}
// ok to continue
}
// typecheck method signatures
for _, m := range scope.Objects {
mdecl := m.Decl.(*ast.FuncDecl)
// TODO(gri) At the moment, the receiver is type-checked when checking
// the method body. Also, we don't properly track if the receiver is
// a pointer (i.e., currently, method sets are too large). FIX THIS.
mtyp := check.typ(mdecl.Type, cycleOk).(*Signature)
m.Type = mtyp
}
}
case ast.Fun:
fdecl := obj.Decl.(*ast.FuncDecl)
if fdecl.Recv != nil {
// This will ensure that the method base type is
// type-checked
check.collectFields(token.FUNC, fdecl.Recv, true)
}
ftyp := check.typ(fdecl.Type, cycleOk).(*Signature)
obj.Type = ftyp
check.function(ftyp, fdecl.Body)
default:
panic("unreachable")
}
}
示例6: Resolve
func (c *compiler) Resolve(obj *ast.Object) Value {
if obj.Kind == ast.Pkg {
return nil
} else if obj.Kind == ast.Typ {
return TypeValue{obj.Type.(types.Type)}
}
value, isvalue := (obj.Data).(Value)
if isvalue {
return value
}
switch obj.Kind {
case ast.Con:
if obj.Decl != nil {
valspec := obj.Decl.(*ast.ValueSpec)
c.VisitValueSpec(valspec, true)
value = (obj.Data).(Value)
} else if obj == types.Nil {
return NilValue{c}
} else {
var typ types.Type
switch x := obj.Type.(type) {
case *types.Basic:
typ = x
case *types.Name:
typ = x.Underlying.(*types.Basic)
default:
panic(fmt.Sprintf("unreachable (%T)", x))
}
value = ConstValue{(obj.Data.(types.Const)), c, typ}
obj.Data = value
}
case ast.Fun:
var funcdecl *ast.FuncDecl
if obj.Decl != nil {
funcdecl = obj.Decl.(*ast.FuncDecl)
} else {
funcdecl = &ast.FuncDecl{
Name: &ast.Ident{Name: obj.Name, Obj: obj},
}
}
value = c.VisitFuncProtoDecl(funcdecl)
obj.Data = value
case ast.Var:
switch x := (obj.Decl).(type) {
case *ast.ValueSpec:
c.VisitValueSpec(x, false)
case *ast.Field:
// No-op. Fields will be yielded for function
// arg/recv/ret. We update the .Data field of the
// object when we enter the function definition.
if obj.Data == nil {
panic("expected obj.Data value")
}
}
// If it's an external variable, we'll need to create a global
// value reference here.
if obj.Data == nil {
module := c.module.Module
t := obj.Type.(types.Type)
name := c.pkgmap[obj] + "." + obj.Name
g := llvm.AddGlobal(module, c.types.ToLLVM(t), name)
g.SetLinkage(llvm.AvailableExternallyLinkage)
obj.Data = c.NewLLVMValue(g, t)
}
value = (obj.Data).(Value)
}
return value
}
示例7: Resolve
func (c *compiler) Resolve(obj *ast.Object) Value {
if obj.Kind == ast.Pkg {
return nil
} else if obj.Kind == ast.Typ {
return TypeValue{obj.Type.(types.Type)}
}
value, isvalue := (obj.Data).(Value)
if isvalue {
return value
}
switch obj.Kind {
case ast.Con:
if obj.Decl != nil {
valspec := obj.Decl.(*ast.ValueSpec)
c.VisitValueSpec(valspec, true)
value = (obj.Data).(Value)
} else if obj == types.Nil {
return NilValue{c}
} else {
typ := obj.Type.(types.Type)
value = ConstValue{(obj.Data.(types.Const)), c, typ}
obj.Data = value
}
case ast.Fun:
var funcdecl *ast.FuncDecl
if obj.Decl != nil {
funcdecl = obj.Decl.(*ast.FuncDecl)
} else {
funcdecl = &ast.FuncDecl{
Name: &ast.Ident{Name: obj.Name, Obj: obj},
}
}
value = c.VisitFuncProtoDecl(funcdecl)
obj.Data = value
case ast.Var:
switch x := (obj.Decl).(type) {
case *ast.ValueSpec:
c.VisitValueSpec(x, false)
case *ast.Field:
// No-op. Fields will be yielded for function
// arg/recv/ret. We update the .Data field of the
// object when we enter the function definition.
if obj.Data == nil {
panic("expected obj.Data value")
}
}
// If it's an external variable, we'll need to create a global
// value reference here. It may be possible for multiple objects
// to refer to the same variable.
if obj.Data == nil {
module := c.module.Module
t := obj.Type.(types.Type)
name := c.pkgmap[obj] + "." + obj.Name
g := module.NamedGlobal(name)
if g.IsNil() {
g = llvm.AddGlobal(module, c.types.ToLLVM(t), name)
}
obj.Data = c.NewLLVMValue(g, &types.Pointer{Base: t}).makePointee()
}
value = (obj.Data).(Value)
}
return value
}
示例8: check
func check(fset *token.FileSet, pkg *ast.Package, types map[ast.Expr]Type) error {
var check checker
check.fset = fset
check.pkg = pkg
check.types = types
// Compute sorted list of file names so that
// package file iterations are reproducible (needed for testing).
filenames := make([]string, len(pkg.Files))
{
i := 0
for filename := range pkg.Files {
filenames[i] = filename
i++
}
sort.Strings(filenames)
}
// Associate methods with types
// TODO(gri) All other objects are resolved by the parser.
// Consider doing this in the parser (and provide the info
// in the AST. In the long-term (might require Go 1 API
// changes) it's probably easier to do all the resolution
// in one place in the type checker. See also comment
// with checker.declare.
for _, filename := range filenames {
file := pkg.Files[filename]
for _, decl := range file.Decls {
if meth, ok := decl.(*ast.FuncDecl); ok && meth.Recv != nil {
// The receiver type is one of the following (enforced by parser):
// - *ast.Ident
// - *ast.StarExpr{*ast.Ident}
// - *ast.BadExpr (parser error)
typ := meth.Recv.List[0].Type
if ptr, ok := typ.(*ast.StarExpr); ok {
typ = ptr.X
}
// determine receiver base type object (or nil if error)
var obj *ast.Object
if ident, ok := typ.(*ast.Ident); ok && ident.Obj != nil {
obj = ident.Obj
if obj.Kind != ast.Typ {
check.errorf(ident.Pos(), "%s is not a type", ident.Name)
obj = nil
}
// TODO(gri) determine if obj was defined in this package
/*
if check.notLocal(obj) {
check.errorf(ident.Pos(), "cannot define methods on non-local type %s", ident.Name)
obj = nil
}
*/
} else {
// If it's not an identifier or the identifier wasn't declared/resolved,
// the parser/resolver already reported an error. Nothing to do here.
}
// determine base type scope (or nil if error)
var scope *ast.Scope
if obj != nil {
if obj.Data != nil {
scope = obj.Data.(*ast.Scope)
} else {
scope = ast.NewScope(nil)
obj.Data = scope
}
} else {
// use a dummy scope so that meth can be declared in
// presence of an error and get an associated object
// (always use a new scope so that we don't get double
// declaration errors)
scope = ast.NewScope(nil)
}
check.declare(scope, ast.Fun, meth.Name, meth)
}
}
}
// Sort objects so that we get reproducible error
// positions (this is only needed for testing).
// TODO(gri): Consider ast.Scope implementation that
// provides both a list and a map for fast lookup.
// Would permit the use of scopes instead of ObjMaps
// elsewhere.
list := make(ObjList, len(pkg.Scope.Objects))
{
i := 0
for _, obj := range pkg.Scope.Objects {
list[i] = obj
i++
}
list.Sort()
}
// Check global objects.
for _, obj := range list {
check.obj(obj, false)
}
// TODO(gri) Missing pieces:
// - blank (_) objects and init functions are not in scopes but should be type-checked
//.........这里部分代码省略.........
示例9: obj
// obj type checks an object.
func (check *checker) obj(obj *ast.Object, cycleOk bool) {
if trace {
fmt.Printf("obj(%s)\n", obj.Name)
}
if obj.Type != nil {
// object has already been type checked
return
}
switch obj.Kind {
case ast.Bad, ast.Pkg:
// nothing to do
case ast.Con:
if obj.Data == nil {
check.errorf(obj.Pos(), "illegal cycle in initialization of %s", obj.Name)
return
}
spec, ok := obj.Decl.(*ast.ValueSpec)
assert(ok)
// The Data stored with the constant is the value of iota for that
// ast.ValueSpec. Use it for the evaluation of the initialization
// expressions.
iota := obj.Data.(int)
obj.Data = nil
check.decl(spec.Pos(), obj, spec.Names, spec.Type, check.specValues(spec), iota)
case ast.Var:
// TODO(gri) missing cycle detection
spec, ok := obj.Decl.(*ast.ValueSpec)
if !ok {
// TODO(gri) the assertion fails for "x, y := 1, 2, 3" it seems
fmt.Printf("var = %s\n", obj.Name)
}
assert(ok)
check.decl(spec.Pos(), obj, spec.Names, spec.Type, spec.Values, 0)
case ast.Typ:
typ := &NamedType{Obj: obj}
obj.Type = typ // "mark" object so recursion terminates
typ.Underlying = underlying(check.typ(obj.Decl.(*ast.TypeSpec).Type, cycleOk))
// collect associated methods, if any
if obj.Data != nil {
scope := obj.Data.(*ast.Scope)
// struct fields must not conflict with methods
if t, ok := typ.Underlying.(*Struct); ok {
for _, f := range t.Fields {
if m := scope.Lookup(f.Name); m != nil {
check.errorf(m.Pos(), "type %s has both field and method named %s", obj.Name, f.Name)
}
}
}
// collect methods
methods := make(ObjList, len(scope.Objects))
i := 0
for _, m := range scope.Objects {
methods[i] = m
i++
}
methods.Sort()
typ.Methods = methods
// methods cannot be associated with an interface type
// (do this check after sorting for reproducible error positions - needed for testing)
if _, ok := typ.Underlying.(*Interface); ok {
for _, m := range methods {
recv := m.Decl.(*ast.FuncDecl).Recv.List[0].Type
check.errorf(recv.Pos(), "invalid receiver type %s (%s is an interface type)", obj.Name, obj.Name)
}
}
}
case ast.Fun:
fdecl := obj.Decl.(*ast.FuncDecl)
ftyp := check.typ(fdecl.Type, cycleOk).(*Signature)
obj.Type = ftyp
if fdecl.Recv != nil {
// TODO(gri) handle method receiver
}
check.stmt(fdecl.Body)
default:
panic("unreachable")
}
}
示例10: VisitValueSpec
func (c *compiler) VisitValueSpec(valspec *ast.ValueSpec, isconst bool) {
// Check if the value-spec has already been visited (referenced
// before definition visited.)
if len(valspec.Names) > 0 {
if _, ok := valspec.Names[0].Obj.Data.(Value); ok {
return
}
}
var iotaObj *ast.Object = types.Universe.Lookup("iota")
defer func(data interface{}) {
iotaObj.Data = data
}(iotaObj.Data)
pkgname, ispackagelevel := c.pkgmap[valspec.Names[0].Obj]
if ispackagelevel && !isconst {
c.createGlobals(valspec.Names, valspec.Values, pkgname)
return
}
var values []Value
if len(valspec.Values) == 1 && len(valspec.Names) > 1 {
values = c.destructureExpr(valspec.Values[0])
} else if len(valspec.Values) > 0 {
values = make([]Value, len(valspec.Names))
for i, name_ := range valspec.Names {
if isconst {
if iota_, isint := (name_.Obj.Data).(int); isint {
iotaValue := c.NewConstValue(token.INT, strconv.Itoa(iota_))
iotaObj.Data = iotaValue
}
}
values[i] = c.VisitExpr(valspec.Values[i])
}
}
for i, name := range valspec.Names {
if name.Name == "_" {
continue
}
// For constants, we just pass the ConstValue around. Otherwise, we
// will convert it to an LLVMValue.
var value Value
if isconst {
value = values[i].Convert(name.Obj.Type.(types.Type))
} else {
// The variable should be allocated on the stack if it's
// declared inside a function.
var llvmInit llvm.Value
typ := name.Obj.Type.(types.Type)
ptr := c.builder.CreateAlloca(c.types.ToLLVM(typ), name.Name)
if values == nil || values[i] == nil {
// If no initialiser was specified, set it to the
// zero value.
llvmInit = llvm.ConstNull(c.types.ToLLVM(typ))
} else {
llvmInit = values[i].Convert(typ).LLVMValue()
}
c.builder.CreateStore(llvmInit, ptr)
value = c.NewLLVMValue(ptr, &types.Pointer{Base: typ}).makePointee()
}
name.Obj.Data = value
}
}