2015-07-24 14:16:31 +00:00
|
|
|
// 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"
|
|
|
|
|
|
|
|
"golang.org/x/tools/go/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Var struct {
|
2015-08-04 13:51:41 +00:00
|
|
|
//pkg *Package
|
|
|
|
sym *symbol // symbol associated with var's type
|
|
|
|
id string
|
|
|
|
doc string
|
|
|
|
name string
|
|
|
|
//typ types.Type
|
|
|
|
//dtype typedesc
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-28 14:00:18 +00:00
|
|
|
func (v *Var) Name() string {
|
|
|
|
return v.name
|
|
|
|
}
|
|
|
|
|
2015-07-29 09:44:06 +00:00
|
|
|
func newVar(p *Package, typ types.Type, objname, name, doc string) *Var {
|
2015-08-04 13:51:41 +00:00
|
|
|
sym := p.syms.symtype(typ)
|
|
|
|
if sym == nil {
|
|
|
|
panic(fmt.Errorf("could not find symbol for type [%s]!", typ.String()))
|
|
|
|
}
|
2015-07-28 14:00:18 +00:00
|
|
|
return &Var{
|
2015-08-04 13:51:41 +00:00
|
|
|
//pkg: p,
|
|
|
|
sym: sym,
|
|
|
|
id: p.Name() + "_" + objname,
|
|
|
|
doc: doc,
|
|
|
|
name: name,
|
|
|
|
//typ: typ,
|
|
|
|
//dtype: getTypedesc(typ),
|
2015-07-28 14:00:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newVarsFrom(p *Package, tuple *types.Tuple) []*Var {
|
2015-07-24 14:16:31 +00:00
|
|
|
vars := make([]*Var, 0, tuple.Len())
|
|
|
|
for i := 0; i < tuple.Len(); i++ {
|
2015-07-28 14:00:18 +00:00
|
|
|
vars = append(vars, newVarFrom(p, tuple.At(i)))
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
return vars
|
|
|
|
}
|
|
|
|
|
2015-07-28 14:00:18 +00:00
|
|
|
func newVarFrom(p *Package, v *types.Var) *Var {
|
2015-07-29 09:44:06 +00:00
|
|
|
return newVar(p, v.Type(), v.Name(), v.Name(), p.getDoc("", v))
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-31 16:01:49 +00:00
|
|
|
func getTypeString(t types.Type) string {
|
|
|
|
return types.TypeString(t, func(*types.Package) string { return " " })
|
|
|
|
}
|
|
|
|
|
2015-07-24 14:16:31 +00:00
|
|
|
func getTypedesc(t types.Type) typedesc {
|
|
|
|
switch typ := t.(type) {
|
|
|
|
case *types.Basic:
|
|
|
|
dtype, ok := typedescr[typ.Kind()]
|
|
|
|
if ok {
|
|
|
|
return dtype
|
|
|
|
}
|
|
|
|
case *types.Named:
|
|
|
|
switch typ.Underlying().(type) {
|
|
|
|
case *types.Struct:
|
2015-07-28 08:05:13 +00:00
|
|
|
obj := typ.Obj()
|
|
|
|
pkgname := obj.Pkg().Name()
|
|
|
|
id := pkgname + "_" + obj.Name()
|
2015-07-24 14:16:31 +00:00
|
|
|
return typedesc{
|
2015-08-04 13:51:41 +00:00
|
|
|
ctype: "cpy_" + id,
|
|
|
|
cgotype: "cgo_" + id,
|
2015-07-31 14:51:30 +00:00
|
|
|
pyfmt: "O&",
|
|
|
|
c2py: "cgopy_cnv_c2py_" + id,
|
|
|
|
py2c: "cgopy_cnv_py2c_" + id,
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
2015-07-29 12:15:11 +00:00
|
|
|
case *types.Interface:
|
2015-07-31 14:51:30 +00:00
|
|
|
obj := typ.Obj()
|
|
|
|
id := obj.Name()
|
|
|
|
if obj.Pkg() != nil {
|
|
|
|
id = obj.Pkg().Name() + "_" + id
|
|
|
|
}
|
2015-07-29 12:15:11 +00:00
|
|
|
return typedesc{
|
|
|
|
ctype: "GoInterface",
|
|
|
|
cgotype: "GoInterface",
|
2015-07-31 14:51:30 +00:00
|
|
|
pyfmt: "O&",
|
|
|
|
c2py: "cgopy_cnv_c2py_" + id,
|
|
|
|
py2c: "cgopy_cnv_py2c_" + id,
|
2015-07-29 12:15:11 +00:00
|
|
|
}
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unhandled type: %#v", typ))
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
2015-07-31 16:01:49 +00:00
|
|
|
case *types.Array:
|
|
|
|
id := fmt.Sprintf("_array_%d_%s", typ.Len(), getTypeString(typ.Elem()))
|
|
|
|
return typedesc{
|
2015-08-04 13:51:41 +00:00
|
|
|
ctype: "cpy_" + id,
|
|
|
|
cgotype: "cgo_" + id,
|
2015-07-31 16:01:49 +00:00
|
|
|
pyfmt: "O&",
|
|
|
|
c2py: "cgopy_cnv_c2py_" + id,
|
|
|
|
py2c: "cgopy_cnv_py2c_" + id,
|
|
|
|
}
|
|
|
|
|
2015-07-24 14:16:31 +00:00
|
|
|
case *types.Pointer:
|
|
|
|
elem := typ.Elem()
|
|
|
|
return getTypedesc(elem)
|
2015-07-30 14:05:45 +00:00
|
|
|
|
|
|
|
case *types.Signature:
|
|
|
|
return typedesc{
|
|
|
|
ctype: "GoFunction",
|
|
|
|
cgotype: "GoFunction",
|
|
|
|
pyfmt: "?",
|
|
|
|
}
|
|
|
|
|
|
|
|
case *types.Slice:
|
|
|
|
return typedesc{
|
|
|
|
ctype: "GoSlice",
|
|
|
|
cgotype: "GoSlice",
|
|
|
|
pyfmt: "?",
|
|
|
|
}
|
|
|
|
|
2015-07-24 14:16:31 +00:00
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unhandled type: %#v\n", typ))
|
|
|
|
}
|
|
|
|
return typedesc{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) GoType() types.Type {
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.goobj.Type()
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) CType() string {
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.cpyname
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) CGoType() string {
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.cgoname
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) PyCode() string {
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.pyfmt
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) isGoString() bool {
|
|
|
|
switch typ := v.GoType().(type) {
|
|
|
|
case *types.Basic:
|
|
|
|
return typ.Kind() == types.String
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) genDecl(g *printer) {
|
2015-07-28 14:00:18 +00:00
|
|
|
g.Printf("%[1]s c_%[2]s;\n", v.CGoType(), v.Name())
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-28 08:04:36 +00:00
|
|
|
func (v *Var) genRecvDecl(g *printer) {
|
2015-07-28 14:00:18 +00:00
|
|
|
g.Printf("%[1]s c_%[2]s;\n", v.CGoType(), v.Name())
|
2015-07-28 08:04:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) genRecvImpl(g *printer) {
|
2015-08-04 13:51:41 +00:00
|
|
|
n := v.sym.cpyname
|
|
|
|
g.Printf("c_%[1]s = ((%[2]s*)self)->cgopy;\n", v.Name(), n)
|
2015-07-28 08:04:36 +00:00
|
|
|
}
|
|
|
|
|
2015-07-24 14:16:31 +00:00
|
|
|
func (v *Var) genRetDecl(g *printer) {
|
2015-08-04 13:51:41 +00:00
|
|
|
g.Printf("%[1]s c_gopy_ret;\n", v.sym.cgoname)
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
2015-07-31 14:51:30 +00:00
|
|
|
func (v *Var) getArgParse() (string, []string) {
|
|
|
|
addrs := make([]string, 0, 1)
|
2015-08-04 13:51:41 +00:00
|
|
|
cnv := v.sym.hasConverter()
|
2015-07-31 14:51:30 +00:00
|
|
|
if cnv {
|
2015-08-04 13:51:41 +00:00
|
|
|
addrs = append(addrs, v.sym.py2c)
|
2015-07-31 14:51:30 +00:00
|
|
|
}
|
2015-07-28 14:00:18 +00:00
|
|
|
addr := "&c_" + v.Name()
|
2015-07-31 14:51:30 +00:00
|
|
|
addrs = append(addrs, addr)
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.pyfmt, addrs
|
2015-07-31 14:51:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) getArgBuildValue() (string, []string) {
|
|
|
|
args := make([]string, 0, 1)
|
2015-08-04 13:51:41 +00:00
|
|
|
cnv := v.sym.hasConverter()
|
2015-07-31 14:51:30 +00:00
|
|
|
if cnv {
|
2015-08-04 13:51:41 +00:00
|
|
|
args = append(args, ""+v.sym.c2py)
|
2015-07-31 14:51:30 +00:00
|
|
|
}
|
|
|
|
arg := "c_" + v.Name()
|
|
|
|
if cnv {
|
|
|
|
arg = "&" + arg
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
2015-07-31 14:51:30 +00:00
|
|
|
args = append(args, arg)
|
|
|
|
|
2015-08-04 13:51:41 +00:00
|
|
|
return v.sym.pyfmt, args
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) genFuncPreamble(g *printer) {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) getFuncArg() string {
|
2015-07-28 14:00:18 +00:00
|
|
|
return "c_" + v.Name()
|
2015-07-24 14:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (v *Var) needWrap() bool {
|
|
|
|
typ := v.GoType()
|
|
|
|
return needWrapType(typ)
|
|
|
|
}
|