Eliminate unnecessary code from wrap/main.go. Include full attributes

in return types of C functions to reduce compiler warnings.
This commit is contained in:
Greg 2019-04-26 15:08:44 -04:00
parent b93ba4c01f
commit ead1623d4b
2 changed files with 63 additions and 313 deletions

View File

@ -109,20 +109,37 @@ func _goType(ct string) string {
func (t *Type) CType() string { func (t *Type) CType() string {
return t._CType(false)
}
func (t *Type) CTypeAttrib() string {
return t._CType(true)
}
func (t *Type) _CType(attrib bool) string {
if t.ctype != "" { // cache if t.ctype != "" { // cache
return t.ctype return t.ctype
} }
ct := t.Node.CtypeSimplified() var ct string
if attrib {
ct = t.Node.Ctype()
} else {
ct = t.Node.CtypeSimplified()
}
ct = strings.ReplaceAll(ct,"instancename",t.Class) ct = strings.ReplaceAll(ct,"instancename",t.Class)
ct = strings.ReplaceAll(ct,"instancetype",t.Class + " *") ct = strings.ReplaceAll(ct,"instancetype",t.Class + " *")
if len(ct) > 1 && ct[:2] == "id" { if len(ct) > 1 && ct[:2] == "id" {
ct = "NSObject *" + ct[2:] ct = "NSObject *" + ct[2:]
} }
if len(ct) > 11 { if len(ct) > 11 {
if ct[:12] == "instancename" { ct = t.Class } if ct[:12] == "instancename" { ct = t.Class + ct[12:] }
if ct[:12] == "instancetype" { ct = t.Class + " *" } if ct[:12] == "instancetype" { ct = t.Class + ct[12:] + " *" }
}
if attrib {
t._CType(false)
} else {
t.ctype = ct
} }
t.ctype = ct
return ct return ct
} }

View File

@ -2,7 +2,6 @@ package wrap
import ( import (
"fmt" "fmt"
//"reflect"
"strings" "strings"
"gitlab.wow.st/gmp/clast/ast" "gitlab.wow.st/gmp/clast/ast"
@ -13,148 +12,14 @@ var (
Debug = false Debug = false
) )
type cStruct struct {
goName, cName string
}
type Wrapper struct { type Wrapper struct {
Interfaces map[string]Interface Interfaces map[string]Interface
Tps map[string]*types.Node
Types map[string]string
gtMap map[string]string
ctMap map[string]*types.Node // map from go type as a string.
goStructTypes map[string]cStruct // map from gotype to struct descr.
goInterfaceTypes []string
cCode strings.Builder // put cGo code here cCode strings.Builder // put cGo code here
goTypes strings.Builder // put Go type declarations here goTypes strings.Builder // put Go type declarations here
goCode strings.Builder // put Go code here goCode strings.Builder // put Go code here
goHelpers strings.Builder // put Go helper functions here goHelpers strings.Builder // put Go helper functions here
Processed map[string]bool Processed map[string]bool
Processed2 map[string]bool
}
var gobuiltinTypes map[string]bool = map[string]bool{
"byte": true,
"int": true,
"float64": true,
}
// translate C builtin types to CGo
var builtinTypes map[string]string = map[string]string{
"char": "C.char",
"signed char": "C.schar",
"unsigned char": "C.uchar",
"short": "C.short",
"unsigned short": "C.ushort",
"int": "C.int",
"unsigned int": "C.uint",
"long": "C.long",
"unsigned long": "C.ulong",
"long long": "C.longlong",
"unsigned long long": "C.ulonglong",
"float": "C.float",
"double": "C.double",
"complex float": "C.complexfloat",
"complex double": "C.complexdouble",
}
//AddType registers a type that needs a Go wrapper struct
func (w *Wrapper) AddType(t, class string) {
//fmt.Printf("Type: %s\n",t)
if _,ok := builtinTypes[t]; ok {
return
}
nt := w.goType(t,class)
if Debug {
fmt.Printf("AddType(): (%s) -> %s\n",t,nt)
}
if nt == "" {
return
}
if _,ok := w.Interfaces[nt]; !ok { // not an interface
return
}
}
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)
if err != nil {
//fmt.Printf("Cannot parse type %s\n",t)
return ""
}
if n.HasFunc() {
//fmt.Printf("Function types not supported (%s)\n",t)
return ""
}
ct := n.CtypeSimplified()
ret := ""
if nt, ok := w.gtMap[ct]; ok { // we already know this type
return nt
}
if x := n.PointsTo(); x != nil {
pt := x.CtypeSimplified()
// if _,ok := w.Interfaces[pt]; ok {
// // pointer to Objective-C interface, stop here
// //fmt.Printf("goType(): %s -> %s\n",t,pt)
// w.gtMap[ct] = pt
// w.goInterfaceTypes = append(w.goInterfaceTypes,pt)
// return pt
// }
// pt = x.BaseType().CtypeSimplified()
// if _,ok := w.Interfaces[pt]; ok {
// // ultimately points to an interface, so need a wrapper
// w.AddType(pt,class)
// ret = w.goType(pt,class) + "Ptr"
// //fmt.Printf("goType(): %s -> %s\n",t,ret)
// w.gtMap[ct] = ret
// return ret
// }
// pointer to non-interface type
ret = "*" + w.goType(pt,class)
w.gtMap[ct] = ret
w.ctMap[ret] = n
return ret
}
if x := n.ArrayOf(); x != nil {
pt := x.CtypeSimplified()
w.AddType(pt,class)
ret = "[]" + w.goType(pt,class)
//fmt.Printf("goType(): %s -> %s\n",t,ret)
w.gtMap[ct] = ret
w.ctMap[ret] = n
return ret
}
if bt,ok := builtinTypes[ct]; ok {
ct = bt
}
if _,ok := w.Interfaces[ct]; ok {
// pointer to Objective-C interface, stop here
//fmt.Printf("goType(): %s -> %s\n",t,pt)
w.gtMap[ct] = ct
w.goInterfaceTypes = append(w.goInterfaceTypes,ct)
w.ctMap[ct] = n
w.Types[ct] = t
return ct
}
if n.IsStruct() {
gt := strings.Title(ct)
gt = strings.ReplaceAll(gt, " ", "")
w.gtMap[ct] = gt
w.goStructTypes[gt] = cStruct{ goName: gt, cName: ct }
//fmt.Printf("goType(): %s -> %s\n",t,gt)
w.ctMap[gt] = n
return gt
}
//fmt.Printf("goType(): %s -> %s\n",t,ct)
w.gtMap[ct] = ct
w.ctMap[ct] = n
return ct
} }
func NewWrapper(debug bool) *Wrapper { func NewWrapper(debug bool) *Wrapper {
@ -162,53 +27,42 @@ func NewWrapper(debug bool) *Wrapper {
if Debug { fmt.Println("// Debug mode") } if Debug { fmt.Println("// Debug mode") }
return &Wrapper{ return &Wrapper{
Interfaces: map[string]Interface{}, Interfaces: map[string]Interface{},
Types: map[string]string{},
gtMap: map[string]string{},
ctMap: map[string]*types.Node{},
goStructTypes: map[string]cStruct{},
Processed: map[string]bool{}, Processed: map[string]bool{},
Processed2: map[string]bool{},
} }
} }
type Property struct { type Property struct {
Name, Type, Attr string Name, Attr string
Tp *types.Type Type *types.Type
} }
type Parameter struct { type Parameter struct {
Pname, Vname, Type string Pname, Vname string
Tp *types.Type Type *types.Type
} }
type Method struct { type Method struct {
Name, Type, Class string Name, Class string
Tp *types.Type Type *types.Type
ClassMethod bool ClassMethod bool
Parameters []Parameter Parameters []Parameter
} }
//isVoid() returns true if the method has no return value.
func (m Method) isVoid() bool { func (m Method) isVoid() bool {
return m.Type == "void" return m.Type.CType() == "void"
} }
//hasFunctionParam() returns true if a method has a function as a parameter. //hasFunctionParam() returns true if a method has a function as a parameter.
func (m Method) hasFunctionParam() bool { func (m Method) hasFunctionParam() bool {
for _,p := range m.Parameters { for _,p := range m.Parameters {
if p.Tp.Node.IsFunction() { if p.Type.Node.IsFunction() {
return true return true
} }
} }
return false return false
} }
func (w Wrapper) isObject(tp string) bool { // takes a goType
if _,ok := w.Interfaces[tp]; ok {
return true
}
return false
}
func (w Wrapper) cparamlist(m Method) string { func (w Wrapper) cparamlist(m Method) string {
ret := make([]string,0) ret := make([]string,0)
if !m.ClassMethod { if !m.ClassMethod {
@ -216,10 +70,10 @@ func (w Wrapper) cparamlist(m Method) string {
} }
for _,p := range m.Parameters { for _,p := range m.Parameters {
var tp string var tp string
if p.Tp.Node.IsPointer() { if p.Type.Node.IsPointer() {
tp = "void*" tp = "void*"
} else { } else {
tp = p.Tp.CType() tp = p.Type.CType()
} }
ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname)) ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname))
} }
@ -262,7 +116,7 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
gname = gname + "_" gname = gname + "_"
} }
ns = append(ns,gname) ns = append(ns,gname)
tps = append(tps,p.Tp) tps = append(tps,p.Type)
} }
ret := []string{} ret := []string{}
i := 0 i := 0
@ -277,78 +131,13 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
return ns, tps, strings.Join(ret,", ") return ns, tps, strings.Join(ret,", ")
} }
func (w Wrapper) goparamlist(m Method) (string,[]string,bool) {
ret := []string{}
tps := []string{}
for _,p := range m.Parameters {
gname := p.Vname
w.AddType(p.Type,m.Class)
tp := w.goType(p.Type,m.Class)
if tp == "" {
return "UNSUPPORTED TYPE", []string{},false
}
if w.isObject(tp) {
tp = "*" + tp
}
if goreserved[gname] {
gname = gname + "_"
}
tps = append(tps,tp)
ret = append(ret,fmt.Sprintf("%s %s",gname,tp))
}
return strings.Join(ret,", "),tps,true
}
func (w Wrapper) goparamnames(m Method) string {
ret := make([]string,0)
if !m.ClassMethod {
ret = append(ret,"o.ptr")
}
for _,p := range m.Parameters {
gname := p.Vname
if goreserved[gname] {
gname = gname + "_"
}
gt := w.goType(p.Type,m.Class)
if gt == "" {
return "UNSUPPORTED TYPE " + p.Type
}
if w.isObject(gt) {
gname = gname + ".ptr"
} else {
n := w.ctMap[gt]
star := ""
for pt := n.PointsTo(); pt != nil; pt = pt.PointsTo() {
star = star + "*"
}
ct := n.BaseType().CtypeSimplified()
if n.IsStruct() {
ct = strings.ReplaceAll(ct,"struct ","")
ct = "struct_" + ct
}
if gt[0] == '*' { // wrap pointers in unsafe.Pointer()
gname = "unsafe.Pointer(" + gname + ")"
}
gname = "(" + star + "C." + ct + ")(" + gname + ")"
}
ret = append(ret,gname)
}
return strings.Join(ret, ", ")
}
type Interface struct { type Interface struct {
Name, Super string Name string
Properties map[string]Property Properties map[string]Property
Methods map[string]Method Methods map[string]Method
} }
func (i Interface) IsRoot() bool {
if i.Super == "" || i.Super == i.Name {
return true
}
return false
}
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) { func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
//fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name) //fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name)
w.add(n.Name, n.Children()) w.add(n.Name, n.Children())
@ -375,7 +164,6 @@ 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) // need this?
} }
tp := types.NewTypeFromString(name,name) tp := types.NewTypeFromString(name,name)
types.Wrap(tp.GoType()) types.Wrap(tp.GoType())
@ -386,26 +174,22 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
//fmt.Printf("ObjCPropertyDecl: %s\n",x.Name) //fmt.Printf("ObjCPropertyDecl: %s\n",x.Name)
p := Property{ p := Property{
Name: x.Name, Name: x.Name,
Type: x.Type, Type: types.NewTypeFromString(x.Type,name),
Tp: types.NewTypeFromString(x.Type,name),
} }
//_,avail = w.GetParms(x,name) // TODO //_,avail = w.GetParms(x,name) // TODO
//if avail { //if avail {
// w.AddType(x.Type,name)
i.Properties[p.Name] = p i.Properties[p.Name] = p
//} //}
case *ast.ObjCMethodDecl: case *ast.ObjCMethodDecl:
//fmt.Printf("ObjCMethodDecl: %s\n",x.Name) //fmt.Printf("ObjCMethodDecl: %s\n",x.Name)
m := Method{ m := Method{
Name: x.Name, Name: x.Name,
Type: x.Type, Type: types.NewTypeFromString(x.Type,name),
Tp: types.NewTypeFromString(x.Type,name),
Class: name, Class: name,
ClassMethod: x.ClassMethod, ClassMethod: x.ClassMethod,
} }
m.Parameters, avail = w.GetParms(x,name) m.Parameters, avail = w.GetParms(x,name)
if avail { if avail {
// w.AddType(x.Type,name)
i.Methods[m.Name] = m i.Methods[m.Name] = m
} }
case *ast.ObjCProtocol: case *ast.ObjCProtocol:
@ -413,7 +197,6 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
case *ast.ObjCInterface: case *ast.ObjCInterface:
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
types.SetSuper(name,x.Name) types.SetSuper(name,x.Name)
} }
case *ast.Unknown: case *ast.Unknown:
@ -444,8 +227,7 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
p := Parameter{ p := Parameter{
Pname: n.Parameters[j], Pname: n.Parameters[j],
Vname: x.Name, Vname: x.Name,
Type: x.Type, Type: types.NewTypeFromString(x.Type,class),
Tp: types.NewTypeFromString(x.Type,class),
} }
ret = append(ret,p) ret = append(ret,p)
j++ j++
@ -487,24 +269,24 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
} }
// new version of ProcessType // new version of ProcessType
func (w *Wrapper) pt2(tps ...*types.Type) { func (w *Wrapper) processTypes(tps []*types.Type) {
switch len(tps) { switch len(tps) {
case 0: case 0:
return return
case 1: case 1:
w._pt2(tps[0]) w.processType(tps[0])
default: default:
for _,tp := range tps { for _,tp := range tps {
w.pt2(tp) w.processType(tp)
} }
return return
} }
} }
func (w *Wrapper) _pt2(tp *types.Type) { func (w *Wrapper) processType(tp *types.Type) {
bt := tp.BaseType() bt := tp.BaseType()
if w.Processed2[bt.GoType()] { return } if w.Processed[bt.GoType()] { return }
w.Processed2[bt.GoType()] = true w.Processed[bt.GoType()] = true
if bt.Node.IsFunction() { if bt.Node.IsFunction() {
return return
} }
@ -516,7 +298,7 @@ func (w *Wrapper) _pt2(tp *types.Type) {
if super != "" { if super != "" {
types.Wrap(super) types.Wrap(super)
pt := types.NewTypeFromString(super + "*","") pt := types.NewTypeFromString(super + "*","")
w._pt2(pt) w.processType(pt)
} }
} }
@ -536,60 +318,6 @@ func (c *Char) String() string {
`) `)
} }
func (w *Wrapper) ProcessType(gotype string) {
if gotype == "" {
return
}
if gotype[0] == '*' {
gotype = gotype[1:]
}
if w.Processed[gotype] {
return
}
w.Processed[gotype] = true
if _,ok := gobuiltinTypes[gotype]; ok {
return
}
ctype := w.Types[gotype]
if _,ok := builtinTypes[ctype]; ok {
return
}
if Debug {
fmt.Printf("Processing %s (%s)\n",gotype,ctype)
}
if i,ok := w.Interfaces[gotype]; ok {
if Debug {
fmt.Printf("Have interface for %s. super = %s\n",gotype,i.Super)
}
if i.Name != i.Super {
w.ProcessType(i.Super)
}
var fields string
// if there is an Interface known for this type, decide if it is the
// root object and if so give it a pointer element:
if i.IsRoot() {
fields = "ptr unsafe.Pointer"
} else {
fields = i.Super // embed superclass
}
w.goTypes.WriteString(fmt.Sprintf(`
// %s
type %s struct { %s }
`,ctype, gotype, fields))
}
if s,ok := w.goStructTypes[gotype]; ok {
ct := strings.ReplaceAll(s.cName," ","_")
w.goTypes.WriteString(fmt.Sprintf(`
type %s %s
`,s.goName,"C." + ct))
}
}
func (w *Wrapper) ProcessTypes(tps []string) {
for _,tp := range tps {
w.ProcessType(tp)
}
}
func (w *Wrapper) Wrap(toproc []string) { func (w *Wrapper) Wrap(toproc []string) {
@ -604,13 +332,14 @@ func (w *Wrapper) Wrap(toproc []string) {
for _,iface := range toproc { for _,iface := range toproc {
pInterfaces[iface] = w.Interfaces[iface] pInterfaces[iface] = w.Interfaces[iface]
} }
//FIXME: sort pInterfaces
for iname,i := range pInterfaces { for iname,i := range pInterfaces {
if Debug { if Debug {
fmt.Printf("Interface %s: %d properties, %d methods\n", fmt.Printf("Interface %s: %d properties, %d methods\n",
iname, len(i.Properties), len(i.Methods)) iname, len(i.Properties), len(i.Methods))
} }
w.goCode.WriteString(fmt.Sprintf(` /*w.goCode.WriteString(fmt.Sprintf(`
func New%s() *%s { func New%s() *%s {
ret := &%s{} ret := &%s{}
ret.ptr = unsafe.Pointer(C.New%s()) ret.ptr = unsafe.Pointer(C.New%s())
@ -624,42 +353,46 @@ func New%s() *%s {
New%s() { New%s() {
return [%s alloc]; return [%s alloc];
} }
`, i.Name, i.Name, i.Name)) `, i.Name, i.Name, i.Name))*/
//FIXME: sort properties
for _,p := range i.Properties { for _,p := range i.Properties {
if Debug { if Debug {
fmt.Printf(" property: %s (%s)\n", p.Name, p.Type) fmt.Printf(" property: %s (%s)\n", p.Name, p.Type.CType())
} }
w.AddType(p.Type,i.Name)
} }
//FIXME: sort methods
for _,m := range i.Methods { for _,m := range i.Methods {
if Debug { if Debug {
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type) fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
} }
if m.Tp.Node.IsFunction() { if m.Type.Node.IsFunction() {
continue continue
} }
if m.hasFunctionParam() { if m.hasFunctionParam() {
continue continue
} }
gname := strings.Title(m.Name) gname := strings.Title(m.Name)
if m.ClassMethod {
gname = i.Name + gname
} else {
gname = "(o *" + i.Name + ") " + gname
}
cname := i.Name + "_" + m.Name cname := i.Name + "_" + m.Name
w.AddType(m.Type,i.Name) cmtype := m.Type.CTypeAttrib()
//cmtype := w.ctMap[w.goType(m.Type,i.Name)].CtypeSimplified()
cmtype := m.Tp.CType()
ns,tps,gplist := m.gpntp() ns,tps,gplist := m.gpntp()
w.pt2(tps...) w.processTypes(tps)
w.pt2(m.Tp) w.processType(m.Type)
grtype := m.Tp.GoType() grtype := m.Type.GoType()
if grtype == "Void" { if grtype == "Void" {
grtype = "" grtype = ""
} }
w.goCode.WriteString(fmt.Sprintf(` w.goCode.WriteString(fmt.Sprintf(`
func (o *%s) %s(%s) %s { func %s(%s) %s {
`,i.Name,gname,gplist,grtype)) `,gname,gplist,grtype))
w.goCode.WriteString( w.goCode.WriteString(
types.GoToC(cname,ns,m.Tp,tps) + "}\n\n") types.GoToC(cname,ns,m.Type,tps) + "}\n\n")
cret := "" cret := ""
if !m.isVoid() { if !m.isVoid() {