Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 26 additions & 19 deletions _xtool/pydump/pydump.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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) {
Comment thread
toaction marked this conversation as resolved.
// 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,

@MeteorsLiu MeteorsLiu Oct 11, 2025

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as i'm concerned, the usage of signature source here, is only to indicate to remove first param of functions which are from PyDoc, because of PyDoc convention.

In conclusion, the only usage of signature source is to make some one know it's from PyDoc, so then they can remove the first param.

Hence, why not handle it here? It seems that exporting signature source is unnecessary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meanwhile, I also have a suggestion: the current architecture extracts all signature strings first, then parses these strings during the pygen phase to obtain structured data before generating code. I think this step should also be moved forward to the pydump stage, so that pygen only receives the processed structured data and can focus solely on Go code generation.

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())
Expand All @@ -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
}
Comment thread
toaction marked this conversation as resolved.
sym.Sig = *sig
modInstance.Functions = append(modInstance.Functions, sym)
}
// TODO: variables, classes, etc.
Expand Down
26 changes: 22 additions & 4 deletions symbol/symbol.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
package symbol
Comment thread
toaction marked this conversation as resolved.

// 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 {
Expand Down
6 changes: 1 addition & 5 deletions tool/pygen/genfunc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading