One test case of variadic functions now passing. More to clear.

This commit is contained in:
Nishant Sharma 2022-06-06 11:20:23 +05:30
parent fcad870bd8
commit ece09eda60
6 changed files with 106 additions and 42 deletions

View File

@ -0,0 +1,15 @@
# Copyright 2018 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.
import variadic, go
varResult = variadic.VariFunc(1,2,3,4,5)
print("Variadic 1+2+3+4+5 = %d" % varResult)
nonvarResult = variadic.NonVariFunc(1, go.Slice_int([2,3,4]),5)
print("NonVariadic 1+[2+3+4]+5 = %d" % nonvarResult)
if isinstance(varResult, int):
print("Type OK")
else:
print("Type Not OK")

View File

@ -0,0 +1,19 @@
package variadic
func VariFunc(vargs ...int) int{
total := 0
for _, num := range vargs {
total += num
}
return total
}
func NonVariFunc(arg1 int, arg2 []int, arg3 int) int{
total := arg1
for _, num := range arg2 {
total += num
}
total += arg3
return total
}

View File

@ -87,18 +87,22 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
return false
}
anm := pySafeArg(arg.Name(), i)
if ifchandle && arg.sym.goname == "interface{}" {
goArgs = append(goArgs, fmt.Sprintf("%s %s", anm, CGoHandle))
pyArgs = append(pyArgs, fmt.Sprintf("param('%s', '%s')", PyHandle, anm))
} else {
goArgs = append(goArgs, fmt.Sprintf("%s %s", anm, sarg.cgoname))
if sarg.cpyname == "PyObject*" {
pyArgs = append(pyArgs, fmt.Sprintf("param('%s', '%s', transfer_ownership=False)", sarg.cpyname, anm))
pyArgs = append(pyArgs, fmt.Sprintf("param('%s', '%s%s', transfer_ownership=False)", sarg.cpyname, anm))
} else {
pyArgs = append(pyArgs, fmt.Sprintf("param('%s', '%s')", sarg.cpyname, anm))
}
}
wpArgs = append(wpArgs, anm)
if i!=nargs-1 || !fsym.isVariadic {
wpArgs = append(wpArgs, anm)
}
}
// support for optional arg to run in a separate go routine -- only if no return val
@ -108,6 +112,11 @@ func (g *pyGen) genFuncSig(sym *symbol, fsym *Func) bool {
wpArgs = append(wpArgs, "goRun=False")
}
// To support variadic args, we add *args at the end.
if fsym.isVariadic {
wpArgs = append(wpArgs, "*args")
}
// When building the pybindgen builder code, we start with
// a function that adds function calls with exception checking.
// But given specific return types, we may want to add more
@ -276,25 +285,6 @@ if __err != nil {
g.gofile.Printf("var __err error\n")
}
// pywrap output
mnm := fsym.ID()
if isMethod {
mnm = sym.id + "_" + fsym.GoName()
}
rvHasHandle := false
if nres > 0 {
ret := res[0]
if !rvIsErr && ret.sym.hasHandle() {
rvHasHandle = true
cvnm := ret.sym.pyPkgId(g.pkg.pkg)
g.pywrap.Printf("return %s(handle=_%s.%s(", cvnm, pkgname, mnm)
} else {
g.pywrap.Printf("return _%s.%s(", pkgname, mnm)
}
} else {
g.pywrap.Printf("_%s.%s(", pkgname, mnm)
}
callArgs := []string{}
wrapArgs := []string{}
if isMethod {
@ -313,6 +303,9 @@ if __err != nil {
default:
na = anm
}
if i == len(args) - 1 && fsym.isVariadic {
na = na + "..."
}
callArgs = append(callArgs, na)
switch {
case arg.sym.goname == "interface{}":
@ -326,6 +319,30 @@ if __err != nil {
default:
wrapArgs = append(wrapArgs, anm)
}
// To support variadic args, we add *args at the end.
if fsym.isVariadic && i == len(args)-1 {
g.pywrap.Printf("%s = go.Slice_int(args)\n", anm)
}
}
// pywrap output
mnm := fsym.ID()
if isMethod {
mnm = sym.id + "_" + fsym.GoName()
}
rvHasHandle := false
if nres > 0 {
ret := res[0]
if !rvIsErr && ret.sym.hasHandle() {
rvHasHandle = true
cvnm := ret.sym.pyPkgId(g.pkg.pkg)
g.pywrap.Printf("return %s(handle=_%s.%s(", cvnm, pkgname, mnm)
} else {
g.pywrap.Printf("return _%s.%s(", pkgname, mnm)
}
} else {
g.pywrap.Printf("_%s.%s(", pkgname, mnm)
}
hasRetCvt := false

View File

@ -153,11 +153,6 @@ func isPyCompatField(f *types.Var) (*symbol, error) {
func isPyCompatFunc(sig *types.Signature) (ret types.Type, haserr, hasfun bool, err error) {
res := sig.Results()
if sig.Variadic() {
err = fmt.Errorf("gopy: not yet supporting variadic functions: %s", sig.String())
return
}
switch res.Len() {
case 2:
if !isErrorType(res.At(1).Type()) {

View File

@ -367,12 +367,13 @@ type Func struct {
obj types.Object
name string
id string
doc string
ret types.Type // return type, if any
err bool // true if original go func has comma-error
ctor bool // true if this is a newXXX function
hasfun bool // true if this function has a function argument
id string
doc string
ret types.Type // return type, if any
err bool // true if original go func has comma-error
ctor bool // true if this is a newXXX function
hasfun bool // true if this function has a function argument
isVariadic bool // True, if this is a variadic function.
}
func newFuncFrom(p *Package, parent string, obj types.Object, sig *types.Signature) (*Func, error) {
@ -392,16 +393,17 @@ func newFuncFrom(p *Package, parent string, obj types.Object, sig *types.Signatu
}
return &Func{
obj: obj,
pkg: p,
sig: sv,
typ: obj.Type(),
name: obj.Name(),
id: id,
doc: p.getDoc(parent, obj),
ret: ret,
err: haserr,
hasfun: hasfun,
obj: obj,
pkg: p,
sig: sv,
typ: obj.Type(),
name: obj.Name(),
id: id,
doc: p.getDoc(parent, obj),
ret: ret,
err: haserr,
hasfun: hasfun,
isVariadic: sig.Variadic(),
}, nil
// TODO: could optimize by generating code once for each type of callback

View File

@ -48,6 +48,7 @@ var (
"_examples/gopygc": []string{"py2", "py3"},
"_examples/cstrings": []string{"py2", "py3"},
"_examples/pkgconflict": []string{"py2", "py3"},
"_examples/variadic": []string{"py3"},
}
testEnvironment = os.Environ()
@ -811,6 +812,21 @@ func TestPkgConflict(t *testing.T) {
// })
// }
func TestBindVariadic(t *testing.T) {
// t.Parallel()
path := "_examples/variadic"
testPkg(t, pkg{
path: path,
lang: features[path],
cmd: "build",
extras: nil,
want: []byte(`Variadic 1+2+3+4+5 = 15
NonVariadic 1+[2+3+4]+5 = 15
Type OK
`),
})
}
// Generate / verify SUPPORT_MATRIX.md from features map.
func TestCheckSupportMatrix(t *testing.T) {
var buf bytes.Buffer