gopy/bind/symbols.go

1042 lines
22 KiB
Go

// Copyright 2015 The go-python Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package bind
import (
"fmt"
"go/types"
"hash/fnv"
"reflect"
"sort"
"strings"
"sync"
)
var (
universeMutex sync.Mutex
universe *symtab
)
func hash(s string) string {
h := fnv.New32a()
h.Write([]byte(s))
return fmt.Sprintf("0x%d", h.Sum32())
}
// symkind describes the kinds of symbol
type symkind int
const (
skConst symkind = 1 << iota
skVar
skFunc
skType
skArray
skBasic
skInterface
skMap
skNamed
skPointer
skSignature
skSlice
skStruct
skString
)
var (
symkinds = map[string]symkind{
"const": skConst,
"var": skVar,
"func": skFunc,
"type": skType,
"array": skArray,
"basic": skBasic,
"interface": skInterface,
"map": skMap,
"named": skNamed,
"pointer": skPointer,
"signature": skSignature,
"slice": skSlice,
"struct": skStruct,
"string": skString,
}
)
func (k symkind) String() string {
str := []string{}
for n, v := range symkinds {
if (k & v) != 0 {
str = append(str, n)
}
}
sort.Strings(str)
return strings.Join(str, "|")
}
// symbol is an exported symbol in a go package
type symbol struct {
kind symkind
gopkg *types.Package
goobj types.Object
gotyp types.Type
doc string
id string // mangled name of entity (eg: <pkg>_<name>)
goname string // name of go entity
cgoname string // name of entity for cgo
cpyname string // name of entity for cpython
pysig string // type string for doc-signatures
go2py string // name of go->py converter function
py2go string // name of py->go converter function
zval string // zero value representation
}
func isPrivate(s string) bool {
return (strings.ToLower(s[0:1]) == s[0:1])
}
func (s symbol) isType() bool {
return (s.kind & skType) != 0
}
func (s symbol) isNamed() bool {
return (s.kind & skNamed) != 0
}
func (s symbol) isBasic() bool {
return (s.kind & skBasic) != 0
}
func (s symbol) isArray() bool {
return (s.kind & skArray) != 0
}
func (s symbol) isInterface() bool {
return (s.kind & skInterface) != 0
}
func (s symbol) isSignature() bool {
return (s.kind & skSignature) != 0
}
func (s symbol) isMap() bool {
return (s.kind & skMap) != 0
}
func (s symbol) isPySequence() bool {
return s.isArray() || s.isSlice() || s.isMap()
}
func (s symbol) isSlice() bool {
return (s.kind & skSlice) != 0
}
func (s symbol) isStruct() bool {
return (s.kind & skStruct) != 0
}
func (s symbol) isPointer() bool {
return (s.kind & skPointer) != 0
}
func (s symbol) isPtrOrIface() bool {
return s.isPointer() || s.isInterface()
}
func (s symbol) nonPointerName() string {
if s.isPointer() {
return s.goname[1:]
}
return s.goname
}
func (s symbol) hasHandle() bool {
return !s.isBasic()
}
func (s symbol) hasConverter() bool {
return (s.go2py != "" || s.py2go != "")
}
func (s symbol) pkgname() string {
if s.gopkg == nil {
return ""
}
return s.gopkg.Name()
}
func (s symbol) GoType() types.Type {
if s.goobj != nil {
return s.goobj.Type()
}
return s.gotyp
}
func (s symbol) cgotypename() string {
typ := s.gotyp
switch typ := typ.(type) {
case *types.Basic:
n := typ.Name()
if strings.HasPrefix(n, "untyped ") {
n = string(n[len("untyped "):])
}
return n
case *types.Named:
obj := s.goobj
switch typ.Underlying().(type) {
case *types.Struct:
return s.cgoname
case *types.Interface:
if obj.Name() == "error" {
return "error"
}
}
}
return s.cgoname
}
func (s symbol) gofmt() string {
return types.TypeString(
s.GoType(),
func(*types.Package) string { return s.pkgname() },
)
}
// symtab is a table of symbols in a go package
type symtab struct {
pkg *types.Package
syms map[string]*symbol
parent *symtab
}
func newSymtab(pkg *types.Package, parent *symtab) *symtab {
if parent == nil {
parent = universe
}
s := &symtab{
pkg: pkg,
syms: make(map[string]*symbol),
parent: parent,
}
return s
}
func (sym *symtab) names() []string {
names := make([]string, 0, len(sym.syms))
for n := range sym.syms {
names = append(names, n)
}
sort.Strings(names)
return names
}
func (sym *symtab) sym(n string) *symbol {
s, ok := sym.syms[n]
if ok {
return s
}
if sym.parent != nil {
return sym.parent.sym(n)
}
return nil
}
func (sym *symtab) typeof(n string) *symbol {
s := sym.sym(n)
switch s.kind {
case skVar, skConst:
tname := sym.typename(s.goobj.Type(), nil)
return sym.sym(tname)
case skFunc:
//FIXME(sbinet): really?
return s
case skType:
return s
default:
panic(fmt.Errorf("unhandled symbol kind (%v)", s.kind))
}
}
func (sym *symtab) typename(t types.Type, pkg *types.Package) string {
if pkg == nil {
return types.TypeString(t, nil)
}
return types.TypeString(t, types.RelativeTo(pkg))
}
func (sym *symtab) symtype(t types.Type) *symbol {
tname := sym.typename(t, nil)
return sym.sym(tname)
}
func (sym *symtab) addSymbol(obj types.Object) {
fn := types.ObjectString(obj, nil)
n := obj.Name()
pkg := obj.Pkg()
id := n
if pkg != nil {
id = pkg.Name() + "_" + n
}
switch obj.(type) {
case *types.Const:
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
kind: skConst,
id: id,
goname: n,
cgoname: "cgo_const_" + id,
cpyname: "cpy_const_" + id,
}
sym.addType(obj, obj.Type())
case *types.Var:
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
kind: skVar,
id: id,
goname: n,
cgoname: "cgo_var_" + id,
cpyname: "cpy_var_" + id,
}
sym.addType(obj, obj.Type())
case *types.Func:
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
kind: skFunc,
id: id,
goname: n,
cgoname: "cgo_func_" + id,
cpyname: "cpy_func_" + id,
}
sig := obj.Type().Underlying().(*types.Signature)
sym.processTuple(sig.Params())
sym.processTuple(sig.Results())
case *types.TypeName:
sym.addType(obj, obj.Type())
default:
panic(fmt.Errorf("gopy: handled object [%#v]", obj))
}
}
func (sym *symtab) processTuple(tuple *types.Tuple) {
if tuple == nil {
return
}
for i := 0; i < tuple.Len(); i++ {
ivar := tuple.At(i)
ityp := ivar.Type()
isym := sym.symtype(ityp)
if isym == nil {
sym.addType(ivar, ityp)
}
}
}
func (sym *symtab) addType(obj types.Object, t types.Type) {
fn := sym.typename(t, nil)
n := sym.typename(t, sym.pkg)
var pkg *types.Package
if obj != nil {
pkg = obj.Pkg()
}
if pkg == nil {
pkg = sym.pkg
}
id := n
if pkg != nil {
id = pkg.Name() + "_" + n
}
kind := skType
switch typ := t.(type) {
case *types.Basic:
kind |= skBasic
styp := sym.symtype(typ)
if styp == nil {
panic(fmt.Errorf("builtin type not already known [%s]!", n))
}
case *types.Array:
sym.addArrayType(pkg, obj, t, kind, id, n)
case *types.Slice:
sym.addSliceType(pkg, obj, t, kind, id, n)
case *types.Signature:
sym.addSignatureType(pkg, obj, t, kind, id, n)
case *types.Named:
kind |= skNamed
switch typ.Underlying().(type) {
case *types.Struct:
sym.addStructType(pkg, obj, t, kind, id, n)
case *types.Basic:
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind | skBasic,
id: id,
goname: n,
cgoname: "cgo_type_" + id,
cpyname: "cpy_type_" + id,
pysig: "object",
go2py: "cgopy_cnv_go2py_" + id,
py2go: "cgopy_cnv_py2go_" + id,
}
case *types.Array:
sym.addArrayType(pkg, obj, t, kind, id, n)
case *types.Slice:
sym.addSliceType(pkg, obj, t, kind, id, n)
case *types.Signature:
sym.addSignatureType(pkg, obj, t, kind, id, n)
case *types.Pointer:
sym.addPointerType(pkg, obj, t, kind, id, n)
case *types.Interface:
sym.addInterfaceType(pkg, obj, t, kind, id, n)
default:
panic(fmt.Errorf("unhandled named-type: [%T]\n%#v\n", obj, t))
}
// add methods
for i := 0; i < typ.NumMethods(); i++ {
m := typ.Method(i)
if !m.Exported() {
continue
}
if true {
mid := id + "_" + m.Name()
mname := m.Name()
sym.addMethod(pkg, m, m.Type(), skFunc, mid, mname)
}
}
case *types.Pointer:
sym.addPointerType(pkg, obj, t, kind, id, n)
case *types.Map:
sym.addMapType(pkg, obj, t, kind, id, n)
default:
panic(fmt.Errorf("unhandled obj [%T]\ntype [%#v]", obj, t))
}
}
func (sym *symtab) addArrayType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Array)
kind |= skArray
enam := sym.typename(typ.Elem(), nil)
elt := sym.sym(enam)
if elt == nil || elt.goname == "" {
eltname := sym.typename(typ.Elem(), pkg)
eobj := sym.pkg.Scope().Lookup(eltname)
if eobj == nil {
panic(fmt.Errorf("could not look-up %q!\n", enam))
}
sym.addSymbol(eobj)
elt = sym.sym(enam)
if elt == nil {
panic(fmt.Errorf(
"gopy: could not retrieve array-elt symbol for %q",
enam,
))
}
}
id = n
if strings.Contains(id, "[") {
strings.Replace(id, "[", "ArrayOf_", 1)
strings.Replace(id, "]", "_", 1)
}
if strings.Contains(id, "[]") {
strings.Replace(id, "[]", "SliceOf_", -1)
}
if strings.Contains(id, "[") {
strings.Replace(id, "[", "MapOf_", -1)
strings.Replace(id, "]", "_", -1)
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle", // handles
cpyname: PyHandle,
pysig: "[]" + elt.pysig,
go2py: "handleFmPtr_" + id,
py2go: "ptrFmHandle_" + id,
}
}
func (sym *symtab) addMapType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Map)
kind |= skMap
enam := sym.typename(typ.Elem(), nil)
elt := sym.sym(enam)
if elt == nil || elt.goname == "" {
eltname := sym.typename(typ.Elem(), pkg)
eobj := sym.pkg.Scope().Lookup(eltname)
if eobj == nil {
panic(fmt.Errorf("could not look-up %q!\n", enam))
}
sym.addSymbol(eobj)
elt = sym.sym(enam)
if elt == nil {
panic(fmt.Errorf(
"gopy: could not retrieve map-elt symbol for %q",
enam,
))
}
}
id = n
if strings.Contains(id, "[") {
strings.Replace(id, "[", "MapOf_", 1)
strings.Replace(id, "]", "_", 1)
}
if strings.Contains(id, "[]") {
strings.Replace(id, "[]", "SliceOf_", -1)
}
if strings.Contains(id, "[") {
strings.Replace(id, "[", "MapOf_", -1)
strings.Replace(id, "]", "_", -1)
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle",
cpyname: PyHandle,
pysig: "object",
go2py: "handleFmPtr_" + id,
py2go: "ptrFmHandle_" + id,
}
}
func (sym *symtab) addSliceType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Slice)
kind |= skSlice
enam := sym.typename(typ.Elem(), nil)
elt := sym.sym(enam)
if elt == nil || elt.goname == "" {
eltname := sym.typename(typ.Elem(), pkg)
eobj := sym.pkg.Scope().Lookup(eltname)
if eobj == nil {
panic(fmt.Errorf("could not look-up %q!\n", enam))
}
sym.addSymbol(eobj)
elt = sym.sym(enam)
if elt == nil {
panic(fmt.Errorf(
"gopy: could not retrieve slice-elt symbol for %q",
enam,
))
}
}
id = n
if strings.Contains(id, "[]") {
strings.Replace(id, "[]", "SliceOf_", -1)
}
if strings.Contains(id, "[") {
strings.Replace(id, "[", "MapOf_", -1)
strings.Replace(id, "]", "_", -1)
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle",
cpyname: PyHandle,
pysig: "[]" + elt.pysig,
go2py: "handleFmPtr_" + id,
py2go: "ptrFmHandle_" + id,
}
}
func (sym *symtab) addStructType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Struct)
kind |= skStruct
for i := 0; i < typ.NumFields(); i++ {
if isPrivate(typ.Field(i).Name()) {
continue
}
ftyp := typ.Field(i).Type()
fsym := sym.symtype(ftyp)
if fsym == nil {
sym.addType(typ.Field(i), ftyp)
fsym = sym.symtype(ftyp)
if fsym == nil {
panic(fmt.Errorf(
"gopy: could not add type [%s]",
ftyp.String(),
))
}
}
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle",
cpyname: PyHandle,
pysig: "object",
go2py: "handleFmPtr_" + n,
py2go: "ptrFmHandle_" + n,
}
}
func (sym *symtab) addSignatureType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
//typ := t.(*types.Signature)
kind |= skSignature
if (kind & skNamed) == 0 {
id = hash(id)
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle",
cpyname: PyHandle,
pysig: "callable",
go2py: "?",
py2go: "?",
}
}
func (sym *symtab) addMethod(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := types.ObjectString(obj, nil)
kind |= skFunc
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: fn + "_" + n,
cpyname: fn + "_" + n,
}
sig := t.Underlying().(*types.Signature)
sym.processTuple(sig.Results())
sym.processTuple(sig.Params())
}
func (sym *symtab) addPointerType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Pointer)
etyp := typ.Elem()
esym := sym.symtype(etyp)
if esym == nil {
sym.addType(obj, etyp)
esym = sym.symtype(etyp)
if esym == nil {
panic(fmt.Errorf(
"gopy: could not retrieve symbol for %q",
sym.typename(etyp, nil),
))
}
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: esym.kind | skPointer,
id: id,
goname: n,
cgoname: "CGoHandle", // handles
cpyname: PyHandle,
pysig: "object",
go2py: "handleFmPtr_" + n[1:] + "_Ptr",
py2go: "ptrFmHandle_" + n[1:] + "_Ptr",
}
}
func (sym *symtab) addInterfaceType(pkg *types.Package, obj types.Object, t types.Type, kind symkind, id, n string) {
fn := sym.typename(t, nil)
typ := t.Underlying().(*types.Interface)
kind |= skInterface
// special handling of 'error'
if isErrorType(typ) {
return
}
sym.syms[fn] = &symbol{
gopkg: pkg,
goobj: obj,
gotyp: t,
kind: kind,
id: id,
goname: n,
cgoname: "CGoHandle",
cpyname: PyHandle,
pysig: "object",
go2py: "handleFmPtr_" + n,
py2go: "ptrFmHandle_" + n,
}
}
func (sym *symtab) print() {
fmt.Printf("\n\n%s\n", strings.Repeat("=", 80))
for _, n := range sym.names() {
fmt.Printf("%q (kind=%v)\n", n, sym.syms[n].kind)
}
fmt.Printf("%s\n", strings.Repeat("=", 80))
}
func init() {
look := types.Universe.Lookup
syms := map[string]*symbol{
"bool": {
gopkg: look("bool").Pkg(),
goobj: look("bool"),
gotyp: look("bool").Type(),
kind: skType | skBasic,
goname: "bool",
cgoname: "C.char",
cpyname: "uint8_t",
pysig: "bool",
go2py: "boolGoToPy",
py2go: "boolPyToGo",
zval: "false",
},
"byte": {
gopkg: look("byte").Pkg(),
goobj: look("byte"),
gotyp: look("byte").Type(),
kind: skType | skBasic,
goname: "byte",
cpyname: "uint8_t",
cgoname: "C.char",
pysig: "int", // FIXME(sbinet) py2/py3
go2py: "C.char",
py2go: "byte",
zval: "0",
},
"int": {
gopkg: look("int").Pkg(),
goobj: look("int"),
gotyp: look("int").Type(),
kind: skType | skBasic,
goname: "int",
cpyname: "int",
cgoname: "C.long", // see below for 64 bit version
pysig: "int",
go2py: "C.long",
py2go: "int",
zval: "0",
},
"int8": {
gopkg: look("int8").Pkg(),
goobj: look("int8"),
gotyp: look("int8").Type(),
kind: skType | skBasic,
goname: "int8",
cpyname: "int8_t",
cgoname: "C.char",
pysig: "int",
go2py: "C.char",
py2go: "int8",
zval: "0",
},
"int16": {
gopkg: look("int16").Pkg(),
goobj: look("int16"),
gotyp: look("int16").Type(),
kind: skType | skBasic,
goname: "int16",
cpyname: "int16_t",
cgoname: "C.short",
pysig: "int",
go2py: "C.short",
py2go: "int16",
zval: "0",
},
"int32": {
gopkg: look("int32").Pkg(),
goobj: look("int32"),
gotyp: look("int32").Type(),
kind: skType | skBasic,
goname: "int32",
cpyname: "int32_t",
cgoname: "C.long",
pysig: "int",
go2py: "C.long",
py2go: "int32",
zval: "0",
},
"int64": {
gopkg: look("int64").Pkg(),
goobj: look("int64"),
gotyp: look("int64").Type(),
kind: skType | skBasic,
goname: "int64",
cpyname: "int64_t",
cgoname: "C.longlong",
pysig: "long",
go2py: "C.longlong",
py2go: "int64",
zval: "0",
},
"uint": {
gopkg: look("uint").Pkg(),
goobj: look("uint"),
gotyp: look("uint").Type(),
kind: skType | skBasic,
goname: "uint",
cpyname: "unsigned int",
cgoname: "C.uint",
pysig: "int",
go2py: "C.uint",
py2go: "uint",
zval: "0",
},
"uint8": {
gopkg: look("uint8").Pkg(),
goobj: look("uint8"),
gotyp: look("uint8").Type(),
kind: skType | skBasic,
goname: "uint8",
cpyname: "uint8_t",
cgoname: "C.uchar",
pysig: "int",
go2py: "C.uchar",
py2go: "uint8",
zval: "0",
},
"uint16": {
gopkg: look("uint16").Pkg(),
goobj: look("uint16"),
gotyp: look("uint16").Type(),
kind: skType | skBasic,
goname: "uint16",
cpyname: "uint16_t",
cgoname: "C.ushort",
pysig: "int",
go2py: "C.ushort",
py2go: "uint16",
zval: "0",
},
"uint32": {
gopkg: look("uint32").Pkg(),
goobj: look("uint32"),
gotyp: look("uint32").Type(),
kind: skType | skBasic,
goname: "uint32",
cpyname: "uint32_t",
cgoname: "C.ulong",
pysig: "long",
go2py: "C.ulong",
py2go: "uint32",
zval: "0",
},
"uint64": {
gopkg: look("uint64").Pkg(),
goobj: look("uint64"),
gotyp: look("uint64").Type(),
kind: skType | skBasic,
goname: "uint64",
cpyname: "uint64_t",
cgoname: "C.ulonglong",
pysig: "long",
go2py: "C.ulonglong",
py2go: "uint64",
zval: "0",
},
"float32": {
gopkg: look("float32").Pkg(),
goobj: look("float32"),
gotyp: look("float32").Type(),
kind: skType | skBasic,
goname: "float32",
cpyname: "float",
cgoname: "C.float",
pysig: "float",
go2py: "C.float",
py2go: "float32",
zval: "0",
},
"float64": {
gopkg: look("float64").Pkg(),
goobj: look("float64"),
gotyp: look("float64").Type(),
kind: skType | skBasic,
goname: "float64",
cpyname: "double",
cgoname: "C.double",
pysig: "float",
go2py: "C.double",
py2go: "float64",
zval: "0",
},
"complex64": {
gopkg: look("complex64").Pkg(),
goobj: look("complex64"),
gotyp: look("complex64").Type(),
kind: skType | skBasic,
goname: "complex64",
cpyname: "float complex",
cgoname: "GoComplex64",
pysig: "complex",
go2py: "cgopy_cnv_go2py_complex64",
py2go: "cgopy_cnv_py2go_complex64",
zval: "0",
},
"complex128": {
gopkg: look("complex128").Pkg(),
goobj: look("complex128"),
gotyp: look("complex128").Type(),
kind: skType | skBasic,
goname: "complex128",
cpyname: "double complex",
cgoname: "GoComplex128",
pysig: "complex",
go2py: "cgopy_cnv_go2py_complex128",
py2go: "cgopy_cnv_py2go_complex128",
zval: "0",
},
"string": {
gopkg: look("string").Pkg(),
goobj: look("string"),
gotyp: look("string").Type(),
kind: skType | skBasic,
goname: "string",
cpyname: "char*",
cgoname: "*C.char",
pysig: "str",
go2py: "C.CString",
py2go: "C.GoString",
zval: `""`,
},
"rune": { // FIXME(sbinet) py2/py3
gopkg: look("rune").Pkg(),
goobj: look("rune"),
gotyp: look("rune").Type(),
kind: skType | skBasic,
goname: "rune",
cpyname: "GoRune",
cgoname: "C.long",
pysig: "str",
go2py: "C.long",
py2go: "rune",
zval: "0",
},
"error": {
gopkg: look("error").Pkg(),
goobj: look("error"),
gotyp: look("error").Type(),
kind: skType | skInterface,
goname: "error",
cpyname: "char*",
cgoname: "*C.char",
pysig: "str",
go2py: "C.CString",
py2go: "C.GoString",
zval: `""`,
},
}
if reflect.TypeOf(int(0)).Size() == 8 {
syms["int"] = &symbol{
gopkg: look("int").Pkg(),
goobj: look("int"),
gotyp: look("int").Type(),
kind: skType | skBasic,
goname: "int",
cpyname: "int64_t",
cgoname: "C.longlong",
pysig: "int",
go2py: "C.longlong",
py2go: "int",
zval: "0",
}
syms["uint"] = &symbol{
gopkg: look("uint").Pkg(),
goobj: look("uint"),
gotyp: look("uint").Type(),
kind: skType | skBasic,
goname: "uint",
cpyname: "uint64_t",
cgoname: "C.ulonglong",
pysig: "int",
go2py: "C.ulonglong",
py2go: "uint",
zval: "0",
}
}
for _, o := range []struct {
kind types.BasicKind
tname string
uname string
}{
{types.UntypedBool, "bool", "bool"},
{types.UntypedInt, "int", "int"},
{types.UntypedRune, "rune", "rune"},
{types.UntypedFloat, "float64", "float"},
{types.UntypedComplex, "complex128", "complex"},
{types.UntypedString, "string", "string"},
//FIXME(sbinet): what should be the python equivalent?
//{types.UntypedNil, "nil", "nil"},
} {
sym := *syms[o.tname]
n := "untyped " + o.uname
syms[n] = &sym
}
universe = &symtab{
pkg: nil,
syms: syms,
parent: nil,
}
}