本文整理汇总了Golang中go/ast.Object类的典型用法代码示例。如果您正苦于以下问题:Golang Object类的具体用法?Golang Object怎么用?Golang Object使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了Object类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: resolve
func (tc *typechecker) resolve(obj *ast.Object) {
// check for declaration cycles
if tc.cyclemap[obj] {
tc.Errorf(objPos(obj), "illegal cycle in declaration of %s", obj.Name)
obj.Kind = ast.Bad
return
}
tc.cyclemap[obj] = true
defer func() {
tc.cyclemap[obj] = false, false
}()
// resolve non-type objects
typ := obj.Type
if typ == nil {
switch obj.Kind {
case ast.Bad:
// ignore
case ast.Con:
tc.declConst(obj)
case ast.Var:
tc.declVar(obj)
//obj.Type = tc.typeFor(nil, obj.Decl.(*ast.ValueSpec).Type, false)
case ast.Fun:
obj.Type = ast.NewType(ast.Function)
t := obj.Decl.(*ast.FuncDecl).Type
tc.declSignature(obj.Type, nil, t.Params, t.Results)
default:
// type objects have non-nil types when resolve is called
if debug {
fmt.Printf("kind = %s\n", obj.Kind)
}
panic("unreachable")
}
return
}
// resolve type objects
if typ.Form == ast.Unresolved {
tc.typeFor(typ, typ.Obj.Decl.(*ast.TypeSpec).Type, false)
// provide types for all methods
for _, obj := range typ.Scope.Objects {
if obj.Kind == ast.Fun {
assert(obj.Type == nil)
obj.Type = ast.NewType(ast.Method)
f := obj.Decl.(*ast.FuncDecl)
t := f.Type
tc.declSignature(obj.Type, f.Recv, t.Params, t.Results)
}
}
}
}
示例2: objDoc
func objDoc(fset *token.FileSet, pkg *ast.Package, tabIndent bool, tabWidth int, obj *ast.Object) *Doc {
decl := obj.Decl
kind := obj.Kind.String()
tp := fset.Position(obj.Pos())
objSrc := ""
pkgName := ""
if pkg != nil && pkg.Name != "builtin" {
pkgName = pkg.Name
}
if obj.Kind == ast.Pkg {
pkgName = ""
doc := ""
// special-case `package name` is generated as a TypeSpec
if v, ok := obj.Decl.(*ast.TypeSpec); ok && v.Doc != nil {
doc = "/*\n" + v.Doc.Text() + "\n*/\n"
}
objSrc = doc + "package " + obj.Name
} else if af, ok := pkg.Files[tp.Filename]; ok {
switch decl.(type) {
case *ast.TypeSpec, *ast.ValueSpec, *ast.Field:
line := tp.Line - 1
for _, cg := range af.Comments {
cgp := fset.Position(cg.End())
if cgp.Filename == tp.Filename && cgp.Line == line {
switch v := decl.(type) {
case *ast.TypeSpec:
v.Doc = cg
case *ast.ValueSpec:
v.Doc = cg
case *ast.Field:
pkgName = ""
kind = "field"
}
break
}
}
}
}
if objSrc == "" {
objSrc, _ = printSrc(fset, decl, tabIndent, tabWidth)
}
return &Doc{
Src: objSrc,
Pkg: pkgName,
Name: obj.Name,
Kind: kind,
Fn: tp.Filename,
Row: tp.Line - 1,
Col: tp.Column - 1,
}
}
示例3: checkObj
// checkObj type checks an object.
func (c *checker) checkObj(obj *ast.Object, ref bool) {
if obj.Type != nil {
// object has already been type checked
return
}
switch obj.Kind {
case ast.Bad:
// ignore
case ast.Con:
// TODO(gri) complete this
case ast.Typ:
typ := &Name{Obj: obj}
obj.Type = typ // "mark" object so recursion terminates
typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
case ast.Var:
// TODO(gri) complete this
case ast.Fun:
// TODO(gri) complete this
default:
panic("unreachable")
}
}
示例4: valueSpec
func (check *checker) valueSpec(pos token.Pos, obj *ast.Object, lhs []*ast.Ident, typ ast.Expr, rhs []ast.Expr, iota int) {
if len(lhs) == 0 {
check.invalidAST(pos, "missing lhs in declaration")
return
}
// determine type for all of lhs, if any
// (but only set it for the object we typecheck!)
var t Type
if typ != nil {
t = check.typ(typ, false)
}
// len(lhs) > 0
if len(lhs) == len(rhs) {
// check only lhs and rhs corresponding to obj
var l, r ast.Expr
for i, name := range lhs {
if name.Obj == obj {
l = lhs[i]
r = rhs[i]
break
}
}
assert(l != nil)
obj.Type = t
check.assign1to1(l, r, nil, true, iota)
return
}
// there must be a type or initialization expressions
if t == nil && len(rhs) == 0 {
check.invalidAST(pos, "missing type or initialization expression")
t = Typ[Invalid]
}
// if we have a type, mark all of lhs
if t != nil {
for _, name := range lhs {
name.Obj.Type = t
}
}
// check initial values, if any
if len(rhs) > 0 {
// TODO(gri) should try to avoid this conversion
lhx := make([]ast.Expr, len(lhs))
for i, e := range lhs {
lhx[i] = e
}
check.assignNtoM(lhx, rhs, true, iota)
}
}
示例5: collectParams
func (check *checker) collectParams(list *ast.FieldList, variadicOk bool) (params ObjList, isVariadic bool) {
if list == nil {
return
}
var last *ast.Object
for i, field := range list.List {
ftype := field.Type
if t, _ := ftype.(*ast.Ellipsis); t != nil {
ftype = t.Elt
if variadicOk && i == len(list.List)-1 {
isVariadic = true
} else {
check.invalidAST(field.Pos(), "... not permitted")
// ok to continue
}
}
// the parser ensures that f.Tag is nil and we don't
// care if a constructed AST contains a non-nil tag
typ := check.typ(ftype, true)
if len(field.Names) > 0 {
// named parameter
for _, name := range field.Names {
obj := name.Obj
obj.Type = typ
params = append(params, obj)
last = obj
}
} else {
// anonymous parameter
obj := ast.NewObj(ast.Var, "")
obj.Type = typ
params = append(params, obj)
last = obj
}
}
// For a variadic function, change the last parameter's object type
// from T to []T (this is the type used inside the function), but
// keep a copy of the object with the original type T in the params
// list (this is the externally visible type).
if isVariadic {
// if isVariadic is set, last must exist and len(params) > 0
copy := *last
last.Type = &Slice{Elt: last.Type.(Type)}
params[len(params)-1] = ©
}
return
}
示例6: 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)
}
示例7: checkObj
// checkObj type checks an object.
func (c *checker) checkObj(obj *ast.Object, ref bool) {
if obj.Type != nil {
// object has already been type checked
return
}
switch obj.Kind {
case ast.Bad:
// ignore
case ast.Con:
// TODO(gri) complete this
case ast.Typ:
typ := &Name{Obj: obj}
obj.Type = typ // "mark" object so recursion terminates
typ.Underlying = Underlying(c.makeType(obj.Decl.(*ast.TypeSpec).Type, ref))
case ast.Var:
// TODO(gri) complete this
case ast.Fun:
fdecl := obj.Decl.(*ast.FuncDecl)
ftyp := c.makeType(fdecl.Type, ref).(*Func)
obj.Type = ftyp
if fdecl.Recv != nil {
recvField := fdecl.Recv.List[0]
if len(recvField.Names) > 0 {
ftyp.Recv = recvField.Names[0].Obj
} else {
ftyp.Recv = ast.NewObj(ast.Var, "_")
ftyp.Recv.Decl = recvField
}
c.checkObj(ftyp.Recv, ref)
// TODO(axw) add method to a list in the receiver type.
}
// TODO(axw) check function body, if non-nil.
default:
panic("unreachable")
}
}
示例8: 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)
}
示例9: valueSpec
func (check *checker) valueSpec(pos token.Pos, obj *ast.Object, lhs []*ast.Ident, typ ast.Expr, rhs []ast.Expr, iota int) {
if len(lhs) == 0 {
check.invalidAST(pos, "missing lhs in declaration")
return
}
var t Type
if typ != nil {
t = check.typ(typ, false)
}
// len(lhs) >= 1
if len(lhs) == len(rhs) {
// check only corresponding lhs and rhs
var l, r ast.Expr
for i, ident := range lhs {
if ident.Obj == obj {
l = lhs[i]
r = rhs[i]
break
}
}
assert(l != nil)
obj.Type = t
// check rhs
var x operand
check.expr(&x, r, t, iota)
// assign to lhs
check.assignment(l, &x, true)
return
}
if t != nil {
for _, name := range lhs {
name.Obj.Type = t
}
}
// check initial values, if any
if len(rhs) > 0 {
// TODO(gri) should try to avoid this conversion
lhx := make([]ast.Expr, len(lhs))
for i, e := range lhs {
lhx[i] = e
}
check.assignNtoM(lhx, rhs, true, iota)
}
}
示例10: maybeConvertUntyped
// convertUntyped takes an object, and, if it is untyped, gives it
// a named builtin type: bool, rune, int, float64, complex128 or string.
func maybeConvertUntyped(obj *ast.Object) bool {
switch obj.Type {
case Bool.Underlying:
obj.Type = Bool
case Rune.Underlying:
obj.Type = Rune
case Int.Underlying:
obj.Type = Int
case Float64.Underlying:
obj.Type = Float64
case Complex128.Underlying:
obj.Type = Complex128
case String.Underlying:
obj.Type = String
default:
return false
}
return true
}
示例11: 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")
}
}
示例12: 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
}
}
示例13: 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
//.........这里部分代码省略.........
示例14: 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")
}
}
示例15: 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
}