diff --git a/_xtool/pydump/pydump.go b/_xtool/pydump/pydump.go index 7b8be43..9a45b4d 100644 --- a/_xtool/pydump/pydump.go +++ b/_xtool/pydump/pydump.go @@ -1,10 +1,11 @@ package main import ( - "os" + "encoding/json" "fmt" + "os" "strings" - "encoding/json" + "github.com/goplus/lib/c" "github.com/goplus/lib/py" "github.com/goplus/lib/py/inspect" @@ -38,55 +39,57 @@ func extractSignatureFromDoc(doc, funcName string) string { return strings.Join(fields, " ") } -func getSignature(val *py.Object, sym *symbol.Symbol) string { - // function, method, class, or implement __call__ +func getSignature(val *py.Object, sym *symbol.Symbol) (*symbol.Signature, error) { + // which implement __call__ if val.Callable() == 0 { - return "" + return nil, fmt.Errorf("not callable") } - // get signature from inspect + // inspect sigFromInspect := inspect.Signature(val) if sigFromInspect != nil { sig := c.GoString(sigFromInspect.Str().CStr()) - if sig != "(*args, **kwargs)" { - return sig - } + return &symbol.Signature{ + Source: symbol.SigSourceInspect, + Str: sig, + }, nil } - // get signature from doc + // doc sigFromDoc := extractSignatureFromDoc(sym.Doc, sym.Name) if sigFromDoc != "" { - return sigFromDoc + return &symbol.Signature{ + Source: symbol.SigSourceDoc, + Str: sigFromDoc, + }, nil } // Paradigms if pyFuncTypes[sym.Type] { - return "(*args, **kwargs)" + return &symbol.Signature{ + Source: symbol.SigSourceParadigm, + Str: "(*args, **kwargs)", + }, nil } - return "" + return nil, fmt.Errorf("failed to get signature") } // moduleName: Python module name func pydump(moduleName string) (*symbol.Module, error) { - // import module mod := py.ImportModule(c.AllocaCStr(moduleName)) if mod == nil { return nil, fmt.Errorf("failed to import module %s", moduleName) } - // get dict, python list Object keys := mod.ModuleGetDict().DictKeys() if keys == nil { return nil, fmt.Errorf("failed to get dict keys of %s", moduleName) } - // create module instance modInstance := &symbol.Module{ Name: moduleName, } - // get symbols for i, n := 0, keys.ListLen(); i < n; i++ { key := keys.ListItem(i) val := mod.GetAttr(key) if val == nil { continue } - // define symbol sym := &symbol.Symbol{} sym.Name = c.GoString(key.CStr()) sym.Type = c.GoString(val.Type().TypeName().CStr()) @@ -96,7 +99,11 @@ func pydump(moduleName string) (*symbol.Module, error) { } // functions if pyFuncTypes[sym.Type] { - sym.Sig = getSignature(val, sym) + sig, err := getSignature(val, sym) + if err != nil { + return nil, err + } + sym.Sig = *sig modInstance.Functions = append(modInstance.Functions, sym) } // TODO: variables, classes, etc. diff --git a/symbol/symbol.go b/symbol/symbol.go index e0e5d2b..ad40fe8 100644 --- a/symbol/symbol.go +++ b/symbol/symbol.go @@ -1,10 +1,28 @@ package symbol +// represents the origin of a function signature +type SigSource int + +const ( + // signature extracted from docstring + SigSourceDoc SigSource = iota + // signature from Python inspect module + SigSourceInspect + // generic fallback signature + SigSourceParadigm +) + +// represents a function signature with its source information +type Signature struct { + Str string `json:"str"` // The signature string + Source SigSource `json:"source"` // Where the signature was obtained +} + type Symbol struct { - Name string `json:"name"` - Type string `json:"type"` - Doc string `json:"doc"` - Sig string `json:"sig"` + Name string `json:"name"` + Type string `json:"type"` + Doc string `json:"doc"` + Sig Signature `json:"sig"` } type Module struct { diff --git a/tool/pygen/genfunc.go b/tool/pygen/genfunc.go index 9474b7d..40685ed 100644 --- a/tool/pygen/genfunc.go +++ b/tool/pygen/genfunc.go @@ -13,12 +13,8 @@ func (ctx *context) genFunc(pkg *gogen.Package, sym *symbol.Symbol) { if len(name) == 0 || name[0] == '_' { return } - if symSig == "" { // no signature - ctx.skips = append(ctx.skips, *sym) - return - } // signature - params, variadic := ctx.genParams(pkg, symSig) + params, variadic := ctx.genParams(pkg, symSig.Str) goName := ctx.genName(name, -1) sig := types.NewSignatureType(nil, nil, nil, params, ctx.ret, variadic) // ret: *py.Object fn := pkg.NewFuncDecl(token.NoPos, goName, sig)