diff --git a/ssa/package.go b/ssa/package.go index e90426d5c3..6692844160 100644 --- a/ssa/package.go +++ b/ssa/package.go @@ -181,6 +181,7 @@ type aProgram struct { callNoArgs *types.Signature callOneArg *types.Signature callFOArgs *types.Signature + callArgs *types.Signature loadPyModS *types.Signature getAttrStr *types.Signature pyUniStr *types.Signature diff --git a/ssa/python.go b/ssa/python.go index e6718181f0..db8de0c9fb 100644 --- a/ssa/python.go +++ b/ssa/python.go @@ -76,6 +76,14 @@ func (p Package) pyFunc(fullName string, sig *types.Signature) Expr { return p.NewFunc(fullName, sig, InC).Expr } +func (p Package) pyGoFunc(fnName string) Expr { + p.NeedPyInit = true + fn := p.Prog.python().Scope().Lookup(fnName).(*types.Func) + name := FullName(fn.Pkg(), fnName) + sig := fn.Type().(*types.Signature) + return p.NewFunc(name, sig, InGo).Expr +} + func (p Program) paramObjPtr() *types.Var { if p.paramObjPtr_ == nil { objPtr := p.PyObjectPtr().raw.Type @@ -126,7 +134,6 @@ func (p Program) tyCallFunctionObjArgs() *types.Signature { return p.callFOArgs } -/* // func(*Object, *Object, *Object) *Object func (p Program) tyCall() *types.Signature { if p.callArgs == nil { @@ -137,7 +144,6 @@ func (p Program) tyCall() *types.Signature { } return p.callArgs } -*/ // func(*Object, uintptr, *Object) cint func (p Program) tyListSetItem() *types.Signature { @@ -342,6 +348,10 @@ func (b Builder) PyLoadModSyms(modName string, objs ...PyObjRef) Expr { return b.Call(fnLoad, args...) } +const ( + pyKwargs = "github.com/goplus/lib/py.Kwargs" +) + func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { prog := b.Prog pkg := b.Pkg @@ -360,6 +370,16 @@ func (b Builder) pyCall(fn Expr, args []Expr) (ret Expr) { } fallthrough default: + if sig.Variadic() { + if params := sig.Params(); params.At(params.Len()-1).Name() == NameValist && + len(args) >= params.Len() && args[len(args)-1].Type.RawType().String() == pyKwargs { + kwargs := b.Call(b.Pkg.pyGoFunc("KwargsToDict"), args[len(args)-1]) + call := pkg.pyFunc("PyObject_Call", prog.tyCall()) + ret = b.Call(call, fn, b.PyTuple(args[:len(args)-1]...), kwargs) + return + } + } + call := pkg.pyFunc("PyObject_CallFunctionObjArgs", prog.tyCallFunctionObjArgs()) n = len(args) callargs := make([]Expr, n+2)