llpyg: ready to test
This commit is contained in:
@@ -46,7 +46,7 @@ func main() {
|
|||||||
sym.SetItem(c.Str("type"), cjson.String(val.Type().Name().CStr()))
|
sym.SetItem(c.Str("type"), cjson.String(val.Type().Name().CStr()))
|
||||||
sym.SetItem(c.Str("name"), cjson.String(key.CStr()))
|
sym.SetItem(c.Str("name"), cjson.String(key.CStr()))
|
||||||
sym.SetItem(c.Str("doc"), cjson.String(doc.CStr()))
|
sym.SetItem(c.Str("doc"), cjson.String(doc.CStr()))
|
||||||
if val.Callable() != 0 && false {
|
if val.Callable() != 0 {
|
||||||
sig := inspect.Signature(val)
|
sig := inspect.Signature(val)
|
||||||
sym.SetItem(c.Str("sig"), cjson.String(sig.Str().CStr()))
|
sym.SetItem(c.Str("sig"), cjson.String(sig.Str().CStr()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,25 +17,128 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/types"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/goplus/gogen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type symbol struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Doc string `json:"doc"`
|
||||||
|
Sig string `json:"sig"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type module struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Items []*symbol `json:"items"`
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Fprintln(os.Stderr, "Usage: llpyg <pythonLibPath> [destDir]")
|
fmt.Fprintln(os.Stderr, "Usage: llpyg <pythonLibPath>")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pyLib := os.Args[1]
|
pyLib := os.Args[1]
|
||||||
destDir := "."
|
|
||||||
if len(os.Args) > 2 {
|
|
||||||
destDir = os.Args[2]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var out bytes.Buffer
|
||||||
pydump := exec.Command("pydump", pyLib)
|
pydump := exec.Command("pydump", pyLib)
|
||||||
pydump.Stdout = os.Stdout
|
pydump.Stdout = &out
|
||||||
pydump.Run()
|
pydump.Run()
|
||||||
|
|
||||||
_ = destDir
|
var mod module
|
||||||
|
json.Unmarshal(out.Bytes(), &mod)
|
||||||
|
|
||||||
|
pkg := gogen.NewPackage("", mod.Name, nil)
|
||||||
|
pkg.Import("unsafe").MarkForceUsed(pkg) // import _ "unsafe"
|
||||||
|
py := pkg.Import("github.com/goplus/llgo/py") // import "github.com/goplus/llgo/py"
|
||||||
|
|
||||||
|
obj := py.Ref("Object").(*types.TypeName).Type().(*types.Named)
|
||||||
|
objPtr := types.NewPointer(obj)
|
||||||
|
ret := types.NewTuple(pkg.NewParam(0, "", objPtr))
|
||||||
|
|
||||||
|
ctx := &context{pkg, obj, objPtr, ret, py}
|
||||||
|
for _, sym := range mod.Items {
|
||||||
|
switch sym.Type {
|
||||||
|
case "builtin_function_or_method", "function":
|
||||||
|
ctx.genFunc(pkg, sym)
|
||||||
|
case "str", "float", "bool", "type", "dict", "list", "module", "int", "set": // skip
|
||||||
|
default:
|
||||||
|
t := sym.Type
|
||||||
|
if len(t) > 0 && (t[0] >= 'a' && t[0] <= 'z') {
|
||||||
|
log.Panicln("unsupport type:", sym.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg.WriteTo(os.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
type context struct {
|
||||||
|
pkg *gogen.Package
|
||||||
|
obj *types.Named
|
||||||
|
objPtr *types.Pointer
|
||||||
|
ret *types.Tuple
|
||||||
|
py gogen.PkgRef
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *context) genFunc(pkg *gogen.Package, sym *symbol) {
|
||||||
|
name := sym.Name
|
||||||
|
if len(name) == 0 || name[0] == '_' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
params, variadic, skip := ctx.genParams(pkg, sym.Sig)
|
||||||
|
if skip {
|
||||||
|
// TODO(xsw): don't skip any func
|
||||||
|
log.Println("skip func:", name, sym.Sig)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if c := name[0]; c >= 'a' && c <= 'z' {
|
||||||
|
name = string(c+'A'-'a') + name[1:]
|
||||||
|
}
|
||||||
|
fn := pkg.NewFunc(nil, name, params, ctx.ret, variadic)
|
||||||
|
fn.SetComments(pkg, ctx.genComment(sym.Doc))
|
||||||
|
fn.BodyStart(pkg).End()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *context) genParams(pkg *gogen.Package, sig string) (*types.Tuple, bool, bool) {
|
||||||
|
if sig == "<NULL>" {
|
||||||
|
return nil, false, true
|
||||||
|
}
|
||||||
|
sig = strings.TrimSuffix(strings.TrimPrefix(sig, "("), ")")
|
||||||
|
parts := strings.Split(sig, ",")
|
||||||
|
n := len(parts)
|
||||||
|
if last := strings.TrimSpace(parts[n-1]); last == "/" {
|
||||||
|
n--
|
||||||
|
}
|
||||||
|
objPtr := ctx.objPtr
|
||||||
|
list := make([]*types.Var, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
part := strings.TrimSpace(parts[i])
|
||||||
|
if strings.HasPrefix(part, "*") {
|
||||||
|
if len(part) > 1 && part[1] == '*' || i != n-1 {
|
||||||
|
return nil, false, true
|
||||||
|
}
|
||||||
|
list[i] = pkg.NewParam(0, part[1:], types.NewSlice(objPtr))
|
||||||
|
return types.NewTuple(list...), true, false
|
||||||
|
}
|
||||||
|
list[i] = pkg.NewParam(0, part, objPtr)
|
||||||
|
}
|
||||||
|
return types.NewTuple(list...), false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *context) genComment(doc string) *ast.CommentGroup {
|
||||||
|
lines := strings.Split(doc, "\n")
|
||||||
|
list := make([]*ast.Comment, len(lines))
|
||||||
|
for i, line := range lines {
|
||||||
|
list[i] = &ast.Comment{Text: "// " + line}
|
||||||
|
}
|
||||||
|
return &ast.CommentGroup{List: list}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user