Add type conversion functions to types package. Start moving the
wrapper to the new type system. Intermediate commit before I rip out the old stuff, not working yet.
This commit is contained in:
parent
885658b67b
commit
fb21881a8b
179
types/convert.go
Normal file
179
types/convert.go
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var super map[string]string
|
||||||
|
|
||||||
|
func Super(c string) string {
|
||||||
|
if super == nil {
|
||||||
|
super = make(map[string]string)
|
||||||
|
}
|
||||||
|
return super[c]
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetSuper(c, p string) {
|
||||||
|
if super == nil {
|
||||||
|
super = make(map[string]string)
|
||||||
|
}
|
||||||
|
super[c] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type struct {
|
||||||
|
Node *Node
|
||||||
|
Class string
|
||||||
|
ctype string
|
||||||
|
wrapped bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewType(n *Node, c string) *Type {
|
||||||
|
return &Type{
|
||||||
|
Node: n,
|
||||||
|
Class: c,
|
||||||
|
ctype: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTypeFromString(t,c string) *Type {
|
||||||
|
n,err := Parse(t)
|
||||||
|
if err != nil {
|
||||||
|
return &Type{}
|
||||||
|
}
|
||||||
|
return &Type{
|
||||||
|
Node: n,
|
||||||
|
Class: c,
|
||||||
|
ctype: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) String() string {
|
||||||
|
return t.Node.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) Wrap() *Type {
|
||||||
|
t.wrapped = true
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) BaseType() *Type {
|
||||||
|
ret := NewType(
|
||||||
|
t.Node.BaseType(),
|
||||||
|
t.Class,
|
||||||
|
)
|
||||||
|
if ret.CType() == ret.Class + " *" { // "instancename"
|
||||||
|
ret.ctype = ret.Class
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func swapstars(s string) string {
|
||||||
|
for i := len(s) - 1; i > 0 && s[i] == '*'; {
|
||||||
|
s = "*" + s[:i]
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) CGoType() string {
|
||||||
|
ct := swapstars("C." + t.CType())
|
||||||
|
ct = strings.ReplaceAll(ct," ","_")
|
||||||
|
return ct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) GoType() string {
|
||||||
|
ct := swapstars(t.CType())
|
||||||
|
ct = strings.Title(ct)
|
||||||
|
ct = strings.ReplaceAll(ct," ","")
|
||||||
|
ct = strings.ReplaceAll(ct,"Struct","")
|
||||||
|
return ct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) CType() string {
|
||||||
|
if t.ctype != "" { // cache
|
||||||
|
return t.ctype
|
||||||
|
}
|
||||||
|
ct := t.Node.CtypeSimplified()
|
||||||
|
ct = strings.ReplaceAll(ct,"instancename",t.Class)
|
||||||
|
ct = strings.ReplaceAll(ct,"instancetype",t.Class + " *")
|
||||||
|
if len(ct) > 1 && ct[:2] == "id" {
|
||||||
|
ct = "NSObject *" + ct[2:]
|
||||||
|
}
|
||||||
|
if len(ct) > 11 {
|
||||||
|
if ct[:12] == "instancename" { ct = t.Class }
|
||||||
|
if ct[:12] == "instancetype" { ct = t.Class + " *" }
|
||||||
|
}
|
||||||
|
t.ctype = ct
|
||||||
|
return ct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) GoTypeDecl() string {
|
||||||
|
if t.wrapped {
|
||||||
|
return t.GoInterfaceDecl()
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
type %s %s
|
||||||
|
`,t.GoType(),t.CGoType())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) GoInterfaceDecl() string {
|
||||||
|
super := Super(t.Class)
|
||||||
|
if super == "" {
|
||||||
|
super = "ptr unsafe.Pointer"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
type %s struct { %s }
|
||||||
|
`,t.GoType(), super)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
||||||
|
if t.Node.IsPointer() {
|
||||||
|
cval = "unsafe.Pointer(" + cval + ")"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("(%s)(%s)",t.GoType(),cval)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call a C function from Go with a given return type and parameter types
|
||||||
|
func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
|
var ret strings.Builder
|
||||||
|
rt := rtype.CType()
|
||||||
|
if rt != "void" {
|
||||||
|
if rtype.wrapped {
|
||||||
|
ret.WriteString("ret := &" + rtype.GoType()[1:] + "{}\n")
|
||||||
|
ret.WriteString("ret.ptr = unsafe.Pointer(")
|
||||||
|
} else {
|
||||||
|
ret.WriteString("return (" + rtype.GoType() + ")(")
|
||||||
|
if rtype.Node.IsPointer() {
|
||||||
|
ret.WriteString("unsafe.Pointer(")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret.WriteString("C." + name + "(")
|
||||||
|
parms := []string{}
|
||||||
|
for i := 0; i < len(pnames); i++ {
|
||||||
|
pn,pt := pnames[i],ptypes[i]
|
||||||
|
p := pn
|
||||||
|
if pt.wrapped {
|
||||||
|
p = pn + ".ptr"
|
||||||
|
} else {
|
||||||
|
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
||||||
|
}
|
||||||
|
parms = append(parms,p)
|
||||||
|
}
|
||||||
|
ret.WriteString(strings.Join(parms,", "))
|
||||||
|
ret.WriteString(")")
|
||||||
|
if rt != "void" {
|
||||||
|
if rtype.wrapped {
|
||||||
|
ret.WriteString(`)
|
||||||
|
return ret
|
||||||
|
`)
|
||||||
|
} else {
|
||||||
|
ret.WriteString(")")
|
||||||
|
if rtype.Node.IsPointer() {
|
||||||
|
ret.WriteString(")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret.String()
|
||||||
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ func (n *Node) PointsTo() *Node {
|
||||||
|
|
||||||
//IsPointer returns true if the node is a pointer
|
//IsPointer returns true if the node is a pointer
|
||||||
func (n *Node) IsPointer() bool {
|
func (n *Node) IsPointer() bool {
|
||||||
return n.PointsTo != nil
|
return n.PointsTo() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ArrayOf, when called on an array node returns a node describing the type
|
//ArrayOf, when called on an array node returns a node describing the type
|
||||||
|
|
|
@ -86,8 +86,8 @@ func (n *Node) _Ctype(ignore map[string]bool) string {
|
||||||
}
|
}
|
||||||
var ret strings.Builder
|
var ret strings.Builder
|
||||||
childStrings := func(n *Node) []string {
|
childStrings := func(n *Node) []string {
|
||||||
if n == nil { return []string{} }
|
|
||||||
ret := []string{}
|
ret := []string{}
|
||||||
|
if n == nil { return ret }
|
||||||
for _,c := range n.Children {
|
for _,c := range n.Children {
|
||||||
if x := c._Ctype(ignore); x != "" {
|
if x := c._Ctype(ignore); x != "" {
|
||||||
ret = append(ret, x)
|
ret = append(ret, x)
|
||||||
|
|
63
wrap/main.go
63
wrap/main.go
|
@ -19,6 +19,7 @@ type cStruct struct {
|
||||||
|
|
||||||
type Wrapper struct {
|
type Wrapper struct {
|
||||||
Interfaces map[string]Interface
|
Interfaces map[string]Interface
|
||||||
|
Tps map[string]*types.Node
|
||||||
Types map[string]string
|
Types map[string]string
|
||||||
gtMap map[string]string
|
gtMap map[string]string
|
||||||
ctMap map[string]*types.Node // map from go type as a string.
|
ctMap map[string]*types.Node // map from go type as a string.
|
||||||
|
@ -72,10 +73,14 @@ func (w *Wrapper) AddType(t, class string) {
|
||||||
if _,ok := w.Interfaces[nt]; !ok { // not an interface
|
if _,ok := w.Interfaces[nt]; !ok { // not an interface
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Types[nt] = t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) goType(t,class string) string {
|
func (w *Wrapper) goType(t,class string) string {
|
||||||
|
if len(t) > 1 && t[:2] == "id" { t = "NSObject *" }
|
||||||
|
if len(t) > 11 {
|
||||||
|
if t[:12] == "instancename" { t = class }
|
||||||
|
if t[:12] == "instancetype" { t = class + " *" }
|
||||||
|
}
|
||||||
n,err := types.Parse(t)
|
n,err := types.Parse(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//fmt.Printf("Cannot parse type %s\n",t)
|
//fmt.Printf("Cannot parse type %s\n",t)
|
||||||
|
@ -117,14 +122,12 @@ func (w *Wrapper) goType(t,class string) string {
|
||||||
if x := n.ArrayOf(); x != nil {
|
if x := n.ArrayOf(); x != nil {
|
||||||
pt := x.CtypeSimplified()
|
pt := x.CtypeSimplified()
|
||||||
w.AddType(pt,class)
|
w.AddType(pt,class)
|
||||||
ret = w.goType(pt,class) + "Arr"
|
ret = "[]" + w.goType(pt,class)
|
||||||
//fmt.Printf("goType(): %s -> %s\n",t,ret)
|
//fmt.Printf("goType(): %s -> %s\n",t,ret)
|
||||||
w.gtMap[ct] = ret
|
w.gtMap[ct] = ret
|
||||||
w.ctMap[ret] = n
|
w.ctMap[ret] = n
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
if ct == "id" { ct = "NSObject" }
|
|
||||||
if ct == "instancename" { ct = class }
|
|
||||||
if bt,ok := builtinTypes[ct]; ok {
|
if bt,ok := builtinTypes[ct]; ok {
|
||||||
ct = bt
|
ct = bt
|
||||||
}
|
}
|
||||||
|
@ -134,6 +137,7 @@ func (w *Wrapper) goType(t,class string) string {
|
||||||
w.gtMap[ct] = ct
|
w.gtMap[ct] = ct
|
||||||
w.goInterfaceTypes = append(w.goInterfaceTypes,ct)
|
w.goInterfaceTypes = append(w.goInterfaceTypes,ct)
|
||||||
w.ctMap[ct] = n
|
w.ctMap[ct] = n
|
||||||
|
w.Types[ct] = t
|
||||||
return ct
|
return ct
|
||||||
}
|
}
|
||||||
if n.IsStruct() {
|
if n.IsStruct() {
|
||||||
|
@ -183,14 +187,17 @@ func NewWrapper(debug bool) *Wrapper {
|
||||||
|
|
||||||
type Property struct {
|
type Property struct {
|
||||||
Name, Type, Attr string
|
Name, Type, Attr string
|
||||||
|
Tp *types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
type Parameter struct {
|
type Parameter struct {
|
||||||
Pname, Vname, Type string
|
Pname, Vname, Type string
|
||||||
|
Tp *types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
type Method struct {
|
type Method struct {
|
||||||
Name, Type, Class string
|
Name, Type, Class string
|
||||||
|
Tp *types.Type
|
||||||
ClassMethod bool
|
ClassMethod bool
|
||||||
Parameters []Parameter
|
Parameters []Parameter
|
||||||
}
|
}
|
||||||
|
@ -246,6 +253,20 @@ var goreserved map[string]bool = map[string]bool{
|
||||||
"range": true,
|
"range": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func gpntp(m Method) ([]string,[]*types.Type) {
|
||||||
|
ns := []string{}
|
||||||
|
tps := []*types.Type{}
|
||||||
|
for _,p := range m.Parameters {
|
||||||
|
gname := p.Vname
|
||||||
|
if goreserved[gname] {
|
||||||
|
gname = gname + "_"
|
||||||
|
}
|
||||||
|
ns = append(ns,gname)
|
||||||
|
tps = append(tps,p.Tp)
|
||||||
|
}
|
||||||
|
return ns,tps
|
||||||
|
}
|
||||||
|
|
||||||
func (w Wrapper) goparamlist(m Method) (string,[]string,bool) {
|
func (w Wrapper) goparamlist(m Method) (string,[]string,bool) {
|
||||||
ret := []string{}
|
ret := []string{}
|
||||||
tps := []string{}
|
tps := []string{}
|
||||||
|
@ -344,7 +365,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
Properties: map[string]Property{},
|
Properties: map[string]Property{},
|
||||||
Methods: map[string]Method{},
|
Methods: map[string]Method{},
|
||||||
}
|
}
|
||||||
w.AddType(name,name)
|
w.AddType(name,name) // need this?
|
||||||
}
|
}
|
||||||
var avail bool
|
var avail bool
|
||||||
for _,c := range ns {
|
for _,c := range ns {
|
||||||
|
@ -354,6 +375,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
p := Property{
|
p := Property{
|
||||||
Name: x.Name,
|
Name: x.Name,
|
||||||
Type: x.Type,
|
Type: x.Type,
|
||||||
|
Tp: types.NewTypeFromString(x.Type,name),
|
||||||
}
|
}
|
||||||
//_,avail = w.GetParms(x,name) // TODO
|
//_,avail = w.GetParms(x,name) // TODO
|
||||||
//if avail {
|
//if avail {
|
||||||
|
@ -365,6 +387,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
m := Method{
|
m := Method{
|
||||||
Name: x.Name,
|
Name: x.Name,
|
||||||
Type: x.Type,
|
Type: x.Type,
|
||||||
|
Tp: types.NewTypeFromString(x.Type,name),
|
||||||
Class: name,
|
Class: name,
|
||||||
ClassMethod: x.ClassMethod,
|
ClassMethod: x.ClassMethod,
|
||||||
}
|
}
|
||||||
|
@ -379,6 +402,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
if x.Super {
|
if x.Super {
|
||||||
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
||||||
i.Super = x.Name
|
i.Super = x.Name
|
||||||
|
types.SetSuper(name,x.Name)
|
||||||
}
|
}
|
||||||
case *ast.Unknown:
|
case *ast.Unknown:
|
||||||
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
||||||
|
@ -409,6 +433,7 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
|
||||||
Pname: n.Parameters[j],
|
Pname: n.Parameters[j],
|
||||||
Vname: x.Name,
|
Vname: x.Name,
|
||||||
Type: x.Type,
|
Type: x.Type,
|
||||||
|
Tp: types.NewTypeFromString(x.Name,class),
|
||||||
}
|
}
|
||||||
ret = append(ret,p)
|
ret = append(ret,p)
|
||||||
j++
|
j++
|
||||||
|
@ -456,6 +481,10 @@ func (w *Wrapper) ProcessType(gotype string) {
|
||||||
if gotype[0] == '*' {
|
if gotype[0] == '*' {
|
||||||
gotype = gotype[1:]
|
gotype = gotype[1:]
|
||||||
}
|
}
|
||||||
|
if w.Processed[gotype] {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Processed[gotype] = true
|
||||||
if _,ok := gobuiltinTypes[gotype]; ok {
|
if _,ok := gobuiltinTypes[gotype]; ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -466,9 +495,6 @@ func (w *Wrapper) ProcessType(gotype string) {
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("Processing %s (%s)\n",gotype,ctype)
|
fmt.Printf("Processing %s (%s)\n",gotype,ctype)
|
||||||
}
|
}
|
||||||
if w.Processed[gotype] {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if i,ok := w.Interfaces[gotype]; ok {
|
if i,ok := w.Interfaces[gotype]; ok {
|
||||||
if Debug {
|
if Debug {
|
||||||
fmt.Printf("Have interface for %s. super = %s\n",gotype,i.Super)
|
fmt.Printf("Have interface for %s. super = %s\n",gotype,i.Super)
|
||||||
|
@ -488,14 +514,12 @@ func (w *Wrapper) ProcessType(gotype string) {
|
||||||
// %s
|
// %s
|
||||||
type %s struct { %s }
|
type %s struct { %s }
|
||||||
`,ctype, gotype, fields))
|
`,ctype, gotype, fields))
|
||||||
w.Processed[gotype] = true
|
|
||||||
}
|
}
|
||||||
if s,ok := w.goStructTypes[gotype]; ok {
|
if s,ok := w.goStructTypes[gotype]; ok {
|
||||||
ct := strings.ReplaceAll(s.cName," ","_")
|
ct := strings.ReplaceAll(s.cName," ","_")
|
||||||
w.goTypes.WriteString(fmt.Sprintf(`
|
w.goTypes.WriteString(fmt.Sprintf(`
|
||||||
type %s %s
|
type %s %s
|
||||||
`,s.goName,"C." + ct))
|
`,s.goName,"C." + ct))
|
||||||
w.Processed[gotype] = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,8 +578,10 @@ New%s() {
|
||||||
|
|
||||||
grtype := ""
|
grtype := ""
|
||||||
grptr := ""
|
grptr := ""
|
||||||
|
_ = grptr
|
||||||
w.AddType(m.Type,i.Name)
|
w.AddType(m.Type,i.Name)
|
||||||
cmtype := cType(m.Type,i.Name)
|
//cmtype := cType(m.Type,i.Name)
|
||||||
|
cmtype := w.ctMap[w.goType(m.Type,i.Name)].CtypeSimplified()
|
||||||
if !m.isVoid() {
|
if !m.isVoid() {
|
||||||
grtype = w.goType(cmtype,i.Name)
|
grtype = w.goType(cmtype,i.Name)
|
||||||
if grtype == "" {
|
if grtype == "" {
|
||||||
|
@ -565,6 +591,8 @@ New%s() {
|
||||||
}
|
}
|
||||||
gcast := ""
|
gcast := ""
|
||||||
gcast2 := ""
|
gcast2 := ""
|
||||||
|
_ = gcast
|
||||||
|
_ = gcast2
|
||||||
if grtype != "" {
|
if grtype != "" {
|
||||||
if grtype[0] == '*' { // pointer return type
|
if grtype[0] == '*' { // pointer return type
|
||||||
if _,ok := w.Interfaces[grtype[1:]]; ok {
|
if _,ok := w.Interfaces[grtype[1:]]; ok {
|
||||||
|
@ -585,14 +613,23 @@ New%s() {
|
||||||
}
|
}
|
||||||
w.ProcessType(grtype)
|
w.ProcessType(grtype)
|
||||||
gplist, gptypes, ok := w.goparamlist(m)
|
gplist, gptypes, ok := w.goparamlist(m)
|
||||||
|
_ = gplist
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
w.ProcessTypes(gptypes)
|
w.ProcessTypes(gptypes)
|
||||||
|
ns,tps := gpntp(m)
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func (o *%s) %s(%s) %s%s {
|
func (o *%s) %s(%s) %s {
|
||||||
|
`,i.Name,gname,gplist,m.Tp.GoType()))
|
||||||
|
w.goCode.WriteString(types.GoToC(gname,ns,m.Tp,tps))
|
||||||
|
w.goCode.WriteString(`
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
/*w.goCode.WriteString(fmt.Sprintf(`
|
||||||
%sC.%s_%s(%s)%s
|
%sC.%s_%s(%s)%s
|
||||||
}`,i.Name, gname, gplist, grptr, grtype, gcast, i.Name, m.Name, w.goparamnames(m),gcast2))
|
}`,i.Name, gname, gplist, grptr, grtype, gcast, i.Name, m.Name, w.goparamnames(m),gcast2))*/
|
||||||
|
|
||||||
cret := ""
|
cret := ""
|
||||||
if !m.isVoid() {
|
if !m.isVoid() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user