diff --git a/types/convert.go b/types/convert.go index 147ddcb..b222259 100644 --- a/types/convert.go +++ b/types/convert.go @@ -5,8 +5,13 @@ import ( "strings" ) +//super is a map recording which class is the parent of each other class var super map[string]string +//wrapped is a map recording whether a given GoType is to be "wrapped" in a +//go struct. +var wrapped map[string]bool + func Super(c string) string { if super == nil { super = make(map[string]string) @@ -25,7 +30,6 @@ type Type struct { Node *Node Class string ctype string - wrapped bool } func NewType(n *Node, c string) *Type { @@ -52,9 +56,12 @@ func (t *Type) String() string { return t.Node.String() } -func (t *Type) Wrap() *Type { - t.wrapped = true - return t +func (t *Type) Wrap() { + if wrapped == nil { + wrapped = make(map[string]bool) + } + // it is the pointers to this type that get wrapped + wrapped["*" + t.GoType()] = true } func (t *Type) BaseType() *Type { @@ -108,7 +115,8 @@ func (t *Type) CType() string { } func (t *Type) GoTypeDecl() string { - if t.wrapped { + if wrapped[t.GoType()] { + fmt.Printf("%s -> %s: %s is wrapped\n",t.GoType(),t.CGoType(),t.Class) return t.GoInterfaceDecl() } return fmt.Sprintf(` @@ -138,11 +146,11 @@ 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(") + if wrapped[rtype.GoType()] { + ret.WriteString(" ret := &" + rtype.GoType()[1:] + "{}\n") + ret.WriteString(" ret.ptr = unsafe.Pointer(") } else { - ret.WriteString("return (" + rtype.GoType() + ")(") + ret.WriteString(" return (" + rtype.GoType() + ")(") if rtype.Node.IsPointer() { ret.WriteString("unsafe.Pointer(") } @@ -153,7 +161,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string { for i := 0; i < len(pnames); i++ { pn,pt := pnames[i],ptypes[i] p := pn - if pt.wrapped { + if wrapped[pt.GoType()] { p = pn + ".ptr" } else { p = "(" + pt.CGoType() + ")(" + pn + ")" @@ -163,15 +171,16 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string { ret.WriteString(strings.Join(parms,", ")) ret.WriteString(")") if rt != "void" { - if rtype.wrapped { + if wrapped[rtype.GoType()] { ret.WriteString(`) -return ret + return ret `) } else { ret.WriteString(")") if rtype.Node.IsPointer() { ret.WriteString(")") } + ret.WriteString("\n") } } return ret.String() diff --git a/types/main.go b/types/main.go index 9b78642..33e5a0c 100644 --- a/types/main.go +++ b/types/main.go @@ -119,6 +119,13 @@ func (n *Node) IsStruct() bool { return n.Children[0].Kind == "Struct" } +func (n *Node) IsFunction() bool { + if n == nil || len(n.Children) < 1 { + return false + } + return n.Children[len(n.Children)-1].Kind == "Function" +} + //BaseType strips off all layers of pointer indirection func (n *Node) BaseType() *Node { if n == nil { diff --git a/wrap/main.go b/wrap/main.go index 4e9e517..dead150 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -30,6 +30,7 @@ type Wrapper struct { goTypes strings.Builder // put Go type declarations here goCode strings.Builder // put Go code here Processed map[string]bool + Processed2 map[string]bool } var gobuiltinTypes map[string]bool = map[string]bool{ @@ -155,23 +156,6 @@ func (w *Wrapper) goType(t,class string) string { return ct } -//FIXME: to be deleted -func cType(t, class string) string { - n, err := types.Parse(t) - if err != nil { - //fmt.Printf("Cannot parse type %s\n",t) - return "NOT IMPLEMENTED" - } - nt := n.CtypeSimplified() - if nt == "id" { - return "NSObject" - } - if nt == "instancetype" { - return class + " *" - } - return nt -} - func NewWrapper(debug bool) *Wrapper { Debug = debug if Debug { fmt.Println("// Debug mode") } @@ -182,6 +166,7 @@ func NewWrapper(debug bool) *Wrapper { ctMap: map[string]*types.Node{}, goStructTypes: map[string]cStruct{}, Processed: map[string]bool{}, + Processed2: map[string]bool{}, } } @@ -367,6 +352,8 @@ func (w *Wrapper) add(name string, ns []ast.Node) { } w.AddType(name,name) // need this? } + tp := types.NewTypeFromString(name,name) + tp.Wrap() var avail bool for _,c := range ns { switch x := c.(type) { @@ -433,7 +420,7 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool Pname: n.Parameters[j], Vname: x.Name, Type: x.Type, - Tp: types.NewTypeFromString(x.Name,class), + Tp: types.NewTypeFromString(x.Type,class), } ret = append(ret,p) j++ @@ -474,6 +461,30 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool return ret, true } +// new version of ProcessType +func (w *Wrapper) pt2(tps ...*types.Type) { + switch len(tps) { + case 0: + return + case 1: + break + default: + for _,tp := range tps { + w.pt2(tp) + } + return + } + tp := tps[0].BaseType() + if w.Processed2[tp.GoType()] { + return + } + w.Processed2[tp.GoType()] = true + if tp.Node.IsFunction() { + return + } + w.goTypes.WriteString(tp.GoTypeDecl()) +} + func (w *Wrapper) ProcessType(gotype string) { if gotype == "" { return @@ -574,62 +585,24 @@ New%s() { if Debug { fmt.Printf(" method: %s (%s)\n", m.Name, m.Type) } + if m.Tp.Node.IsFunction() { + continue + } gname := strings.Title(m.Name) + cname := i.Name + "_" + m.Name - grtype := "" - grptr := "" - _ = grptr w.AddType(m.Type,i.Name) - //cmtype := cType(m.Type,i.Name) - cmtype := w.ctMap[w.goType(m.Type,i.Name)].CtypeSimplified() - if !m.isVoid() { - grtype = w.goType(cmtype,i.Name) - if grtype == "" { - grtype = fmt.Sprintf("// goType(%s): NOT IMPLEMENTED\n",cmtype) - continue - } - } - gcast := "" - gcast2 := "" - _ = gcast - _ = gcast2 - if grtype != "" { - if grtype[0] == '*' { // pointer return type - if _,ok := w.Interfaces[grtype[1:]]; ok { - //grptr = "*" - gcast = "ret := &" + grtype[1:] + "{}\n ret.ptr = unsafe.Pointer(" - gcast2 = ")\n return ret" - } else { - gcast = "return (" + grtype + ")(unsafe.Pointer(" - gcast2 = "))" - } - } else { - gcast = fmt.Sprintf("return (%s)(",grtype) - gcast2 = ")" - } - } - if grtype == "id" { // can't return id - continue - } - w.ProcessType(grtype) - gplist, gptypes, ok := w.goparamlist(m) - _ = gplist - if !ok { - continue - } - w.ProcessTypes(gptypes) + //cmtype := w.ctMap[w.goType(m.Type,i.Name)].CtypeSimplified() + gplist,_,_ := w.goparamlist(m) + cmtype := m.Tp.CType() ns,tps := gpntp(m) + w.pt2(tps...) + w.pt2(m.Tp) w.goCode.WriteString(fmt.Sprintf(` 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 -}`,i.Name, gname, gplist, grptr, grtype, gcast, i.Name, m.Name, w.goparamnames(m),gcast2))*/ +`,i.Name,gname,gplist,m.Tp.GoType())) + w.goCode.WriteString( + types.GoToC(cname,ns,m.Tp,tps) + "}\n") cret := "" if !m.isVoid() { @@ -643,9 +616,9 @@ func (o *%s) %s(%s) %s { } w.cCode.WriteString(fmt.Sprintf(` %s -%s_%s(%s) { +%s(%s) { %s[%s %s]; -}`, cmtype, i.Name, m.Name, w.cparamlist(m), cret, cobj, w.objcparamlist(m))) +}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(m))) } } fmt.Println(`package main