Handle functions identified by regexp in nswrap.toml config
file. Handle inherited class methods.
This commit is contained in:
parent
380fee39bf
commit
be92b200ad
|
@ -8,14 +8,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
n1 := ns.StringWithUTF8String(ns.CharFromString("hi there"))
|
n1 := ns.NSStringStringWithUTF8String(ns.CharFromString("hi there"))
|
||||||
c1 := n1.CapitalizedString()
|
c1 := n1.CapitalizedString()
|
||||||
gs := c1.UTF8String().String()
|
gs := c1.UTF8String().String()
|
||||||
fmt.Println(gs)
|
fmt.Println(gs)
|
||||||
n2 := ns.StringWithUTF8String(ns.CharFromString("hi world"))
|
n2 := ns.NSStringStringWithUTF8String(ns.CharFromString("hi world"))
|
||||||
n3 := ns.StringWithUTF8String(ns.CharFromString("ok bye"))
|
n3 := ns.NSStringStringWithUTF8String(ns.CharFromString("ok bye"))
|
||||||
a := ns.ArrayWithObjects(n1,n2,n3)
|
a := ns.NSMutableArrayArrayWithObjects(n1,n2,n3)
|
||||||
fmt.Println("Length(a) = ",a.Count())
|
fmt.Println("Length(a) = ",a.Count())
|
||||||
fmt.Println("is n2 in a?",a.ContainsObject(n2))
|
fmt.Println("is n2 in a?",a.ContainsObject(n2))
|
||||||
fmt.Println("is c1 in a?",a.ContainsObject(c1))
|
fmt.Println("is c1 in a?",a.ContainsObject(c1))
|
||||||
|
n4 := n2.SubstringFromIndex(3)
|
||||||
|
n5 := n3.SubstringToIndex(4)
|
||||||
|
a.AddObject(n4)
|
||||||
|
a.AddObject(n5)
|
||||||
|
fmt.Println("Length(a) = ",a.Count())
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ InputFiles = [
|
||||||
]
|
]
|
||||||
Classes = [
|
Classes = [
|
||||||
"NSArray",
|
"NSArray",
|
||||||
|
"NSMutableArray",
|
||||||
"NSDictionary",
|
"NSDictionary",
|
||||||
"NSSet",
|
"NSSet",
|
||||||
"NSDate",
|
"NSDate",
|
||||||
|
@ -14,6 +15,9 @@ Classes = [
|
||||||
"NSScanner",
|
"NSScanner",
|
||||||
"NSFileManager",
|
"NSFileManager",
|
||||||
]
|
]
|
||||||
|
Functions = [
|
||||||
|
"NSMakeRange",
|
||||||
|
]
|
||||||
SysImports = [ "Foundation/Foundation.h" ]
|
SysImports = [ "Foundation/Foundation.h" ]
|
||||||
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
||||||
VaArgs = 32
|
VaArgs = 32
|
||||||
|
|
15
main.go
15
main.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ type conf struct {
|
||||||
Package string
|
Package string
|
||||||
InputFiles []string
|
InputFiles []string
|
||||||
Classes []string
|
Classes []string
|
||||||
|
Functions []string
|
||||||
Imports []string
|
Imports []string
|
||||||
SysImports []string
|
SysImports []string
|
||||||
Pragma []string
|
Pragma []string
|
||||||
|
@ -134,6 +136,15 @@ func buildTree(nodes []treeNode, depth int) []ast.Node {
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func matches(x string, rs []string) bool {
|
||||||
|
for _,r := range rs {
|
||||||
|
if m, _ := regexp.MatchString("^" + r + "$",x); m {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Start begins transpiling an input file.
|
// Start begins transpiling an input file.
|
||||||
func Start() (err error) {
|
func Start() (err error) {
|
||||||
// 1. Compile it first (checking for errors)
|
// 1. Compile it first (checking for errors)
|
||||||
|
@ -185,6 +196,10 @@ func Start() (err error) {
|
||||||
w.AddCategory(x)
|
w.AddCategory(x)
|
||||||
case *ast.TypedefDecl:
|
case *ast.TypedefDecl:
|
||||||
types.AddTypedef(x.Name,x.Type)
|
types.AddTypedef(x.Name,x.Type)
|
||||||
|
case *ast.FunctionDecl:
|
||||||
|
if matches(x.Name,Config.Functions) {
|
||||||
|
w.AddFunction(x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,12 +37,22 @@ func (t *Type) Typedef() *Type {
|
||||||
return typedefs[t.CType()]
|
return typedefs[t.CType()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
r_id *regexp.Regexp
|
||||||
|
r_instancename *regexp.Regexp
|
||||||
|
r_instancetype *regexp.Regexp
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
super = make(map[string]string)
|
super = make(map[string]string)
|
||||||
wrapped = make(map[string]bool)
|
wrapped = make(map[string]bool)
|
||||||
goInterfaces = make(map[string]bool)
|
goInterfaces = make(map[string]bool)
|
||||||
TypeParameters = make(map[string]map[string]string)
|
TypeParameters = make(map[string]map[string]string)
|
||||||
typedefs = make(map[string]*Type)
|
typedefs = make(map[string]*Type)
|
||||||
|
|
||||||
|
r_id = regexp.MustCompile("\bid\b")
|
||||||
|
r_instancename = regexp.MustCompile(`\binstancename\b`)
|
||||||
|
r_instancetype = regexp.MustCompile(`\binstancetype\b`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Super(c string) string {
|
func Super(c string) string {
|
||||||
|
@ -71,6 +82,14 @@ type Type struct {
|
||||||
Variadic bool
|
Variadic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Type) CloneToClass(c string) *Type {
|
||||||
|
return &Type{
|
||||||
|
Node: t.Node,
|
||||||
|
Class: c,
|
||||||
|
Variadic: t.Variadic,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func clean(n *Node,c string) (*Node,bool) {
|
func clean(n *Node,c string) (*Node,bool) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return nil,false
|
return nil,false
|
||||||
|
@ -84,8 +103,8 @@ func clean(n *Node,c string) (*Node,bool) {
|
||||||
recur = ret.renameTypedefs(k,v)
|
recur = ret.renameTypedefs(k,v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recur = recur || ret.renameTypedefs("instancename",c)
|
// recur = recur || ret.renameTypedefs("instancename",c)
|
||||||
recur = recur || ret.renameTypedefs("instancetype",c + "*")
|
// recur = recur || ret.renameTypedefs("instancetype",c + "*")
|
||||||
if recur {
|
if recur {
|
||||||
clean(n, c)
|
clean(n, c)
|
||||||
return ret,true
|
return ret,true
|
||||||
|
@ -127,7 +146,14 @@ func (t *Type) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) PointsTo() *Type {
|
func (t *Type) PointsTo() *Type {
|
||||||
return NewType(t.Node.PointsTo(), t.Class)
|
if td := t.Typedef(); td != nil {
|
||||||
|
return td.PointsTo()
|
||||||
|
}
|
||||||
|
if pt := t.Node.PointsTo(); pt != nil {
|
||||||
|
return NewType(t.Node.PointsTo(), t.Class)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Wrap(s string) {
|
func Wrap(s string) {
|
||||||
|
@ -136,6 +162,9 @@ func Wrap(s string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) BaseType() *Type {
|
func (t *Type) BaseType() *Type {
|
||||||
|
if t == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
ret := NewType(
|
ret := NewType(
|
||||||
t.Node.BaseType(),
|
t.Node.BaseType(),
|
||||||
t.Class,
|
t.Class,
|
||||||
|
@ -172,10 +201,12 @@ func _goType(ct string) string {
|
||||||
if len(ct) > 0 && ct[0] == '*' && isGoInterface(ct[1:]) {
|
if len(ct) > 0 && ct[0] == '*' && isGoInterface(ct[1:]) {
|
||||||
return ct[1:]
|
return ct[1:]
|
||||||
}
|
}
|
||||||
|
if ct == "Id" {
|
||||||
|
ct = "*Id"
|
||||||
|
}
|
||||||
return ct
|
return ct
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (t *Type) CType() string {
|
func (t *Type) CType() string {
|
||||||
return t._CType(false)
|
return t._CType(false)
|
||||||
}
|
}
|
||||||
|
@ -185,6 +216,10 @@ func (t *Type) CTypeAttrib() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) _CType(attrib bool) string {
|
func (t *Type) _CType(attrib bool) string {
|
||||||
|
if t == nil {
|
||||||
|
fmt.Println("nil sent to _CType()")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
//if !attrib && c.ctype != "" ... FIXME?
|
//if !attrib && c.ctype != "" ... FIXME?
|
||||||
if t.ctype != "" { // cache
|
if t.ctype != "" { // cache
|
||||||
return t.ctype
|
return t.ctype
|
||||||
|
@ -196,9 +231,9 @@ func (t *Type) _CType(attrib bool) string {
|
||||||
} else {
|
} else {
|
||||||
ct = t.Node.CtypeSimplified()
|
ct = t.Node.CtypeSimplified()
|
||||||
}
|
}
|
||||||
if len(ct) > 1 && ct[:2] == "id" {
|
ct = r_id.ReplaceAllString(ct,"NSObject*")
|
||||||
ct = "NSObject*" + ct[2:]
|
ct = r_instancename.ReplaceAllString(ct,t.Class)
|
||||||
}
|
ct = r_instancetype.ReplaceAllString(ct,t.Class + "*")
|
||||||
if attrib {
|
if attrib {
|
||||||
t._CType(false)
|
t._CType(false)
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,12 +296,23 @@ func (o *%s) Ptr() unsafe.Pointer { return unsafe.Pointer(o) }
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Type) IsFunction() bool {
|
func (t *Type) IsFunction() bool {
|
||||||
|
if t == nil {
|
||||||
|
fmt.Println("nil sent to IsFunction()")
|
||||||
|
return false
|
||||||
|
}
|
||||||
if td := t.Typedef(); td != nil {
|
if td := t.Typedef(); td != nil {
|
||||||
return td.IsFunction()
|
return td.IsFunction()
|
||||||
}
|
}
|
||||||
return t.Node.IsFunction()
|
return t.Node.IsFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Type) ReturnType() *Type {
|
||||||
|
if rt := t.Node.ReturnType(); rt != nil {
|
||||||
|
return NewType(rt,t.Class)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Type) IsPointer() bool {
|
func (t *Type) IsPointer() bool {
|
||||||
if td := t.Typedef(); td != nil {
|
if td := t.Typedef(); td != nil {
|
||||||
return td.IsPointer()
|
return td.IsPointer()
|
||||||
|
@ -283,6 +329,10 @@ func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
||||||
|
|
||||||
// Call a C function from Go with a given return type and parameter types
|
// 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 {
|
func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
|
if rtype == nil {
|
||||||
|
fmt.Println("nil sent to GoToC")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
var ret strings.Builder
|
var ret strings.Builder
|
||||||
rt := rtype.CType()
|
rt := rtype.CType()
|
||||||
if rt != "void" {
|
if rt != "void" {
|
||||||
|
@ -290,8 +340,8 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
if isGoInterface(rtgt) {
|
if isGoInterface(rtgt) {
|
||||||
rtgt = "*Id"
|
rtgt = "*Id"
|
||||||
}
|
}
|
||||||
ret.WriteString(" return (" + rtgt + ")(")
|
ret.WriteString("return (" + rtgt + ")(")
|
||||||
if rtype.Node.IsPointer() {
|
if rtype.IsPointer() {
|
||||||
ret.WriteString("unsafe.Pointer(")
|
ret.WriteString("unsafe.Pointer(")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +356,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
switch {
|
switch {
|
||||||
case pt.Variadic:
|
case pt.Variadic:
|
||||||
p = "unsafe.Pointer(&" + p + ")"
|
p = "unsafe.Pointer(&" + p + ")"
|
||||||
case pt.Node.IsPointer():
|
case pt.IsPointer():
|
||||||
p = "unsafe.Pointer(" + pn + ")"
|
p = "unsafe.Pointer(" + pn + ")"
|
||||||
default:
|
default:
|
||||||
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
||||||
|
@ -318,7 +368,7 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
if rt != "void" {
|
if rt != "void" {
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
if rtype.Node.IsPointer() {
|
if rtype.IsPointer() {
|
||||||
ret.WriteString(")")
|
ret.WriteString(")")
|
||||||
}
|
}
|
||||||
ret.WriteString("\n")
|
ret.WriteString("\n")
|
||||||
|
|
|
@ -110,7 +110,7 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
||||||
Opt(Pointer),
|
Opt(Pointer),
|
||||||
OneOrMore(DirectAbstractDeclarator)),
|
OneOrMore(DirectAbstractDeclarator)),
|
||||||
Pointer,
|
Pointer,
|
||||||
Id,
|
//Id,
|
||||||
Block,
|
Block,
|
||||||
)(s,n)
|
)(s,n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,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.IsId() || n.PointsTo() != nil
|
return n.IsId() || n.IsInstancetype() || 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
|
||||||
|
@ -127,11 +127,29 @@ func (n *Node) IsFunction() bool {
|
||||||
return n.Children[len(n.Children)-1].Kind == "Function"
|
return n.Children[len(n.Children)-1].Kind == "Function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Node) ReturnType() *Node {
|
||||||
|
if !n.IsFunction() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := NewNode(n.Kind)
|
||||||
|
ret.Children = n.Children[:len(n.Children)-1]
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Node) IsId() bool {
|
func (n *Node) IsId() bool {
|
||||||
if n == nil || len(n.Children) < 1 {
|
if n == nil || len(n.Children) < 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return n.Children[0].Kind == "TypedefName" && n.Children[0].Content == "id"
|
return n.Children[0].Kind == "TypedefName" &&
|
||||||
|
n.Children[0].Content == "id"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Node) IsInstancetype() bool {
|
||||||
|
if n == nil || len(n.Children) < 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return n.Children[0].Kind == "TypedefName" &&
|
||||||
|
n.Children[0].Content == "instancetype"
|
||||||
}
|
}
|
||||||
|
|
||||||
//BaseType strips off all layers of pointer indirection
|
//BaseType strips off all layers of pointer indirection
|
||||||
|
|
284
wrap/main.go
284
wrap/main.go
|
@ -17,7 +17,8 @@ var (
|
||||||
|
|
||||||
type Wrapper struct {
|
type Wrapper struct {
|
||||||
Package string
|
Package string
|
||||||
Interfaces map[string]Interface
|
Interfaces map[string]*Interface
|
||||||
|
Functions map[string]*Method
|
||||||
|
|
||||||
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
|
||||||
|
@ -31,7 +32,8 @@ func NewWrapper(debug bool) *Wrapper {
|
||||||
Debug = debug
|
Debug = debug
|
||||||
if Debug { fmt.Println("// Debug mode") }
|
if Debug { fmt.Println("// Debug mode") }
|
||||||
ret := &Wrapper{
|
ret := &Wrapper{
|
||||||
Interfaces: map[string]Interface{},
|
Interfaces: map[string]*Interface{},
|
||||||
|
Functions: map[string]*Method{},
|
||||||
Processed: map[string]bool{},
|
Processed: map[string]bool{},
|
||||||
VaArgs: 16,
|
VaArgs: 16,
|
||||||
}
|
}
|
||||||
|
@ -80,7 +82,7 @@ type Method struct {
|
||||||
Name, Class string
|
Name, Class string
|
||||||
Type *types.Type
|
Type *types.Type
|
||||||
ClassMethod bool
|
ClassMethod bool
|
||||||
Parameters []Parameter
|
Parameters []*Parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
//isVoid() returns true if the method has no return value.
|
//isVoid() returns true if the method has no return value.
|
||||||
|
@ -98,24 +100,26 @@ func (m Method) hasFunctionParam() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w Wrapper) cparamlist(m Method) string {
|
func (w Wrapper) cparamlist(m *Method) (string,string) {
|
||||||
|
ns := make([]string,0)
|
||||||
ret := make([]string,0)
|
ret := make([]string,0)
|
||||||
if !m.ClassMethod {
|
if !m.ClassMethod {
|
||||||
ret = append(ret,"void* obj")
|
ret = append(ret,"void* o")
|
||||||
}
|
}
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
var tp string
|
var tp string
|
||||||
if p.Type.Node.IsPointer() || p.Type.Variadic {
|
if p.Type.IsPointer() || p.Type.Variadic {
|
||||||
tp = "void*"
|
tp = "void*"
|
||||||
} else {
|
} else {
|
||||||
tp = p.Type.CType()
|
tp = p.Type.CType()
|
||||||
}
|
}
|
||||||
|
ns = append(ns,p.Vname)
|
||||||
ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname))
|
ret = append(ret,fmt.Sprintf("%s %s",tp,p.Vname))
|
||||||
}
|
}
|
||||||
return strings.Join(ret,", ")
|
return strings.Join(ns,", "),strings.Join(ret,", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w Wrapper) objcparamlist(m Method) string {
|
func (w Wrapper) objcparamlist(m *Method) string {
|
||||||
if len(m.Parameters) == 0 {
|
if len(m.Parameters) == 0 {
|
||||||
return m.Name
|
return m.Name
|
||||||
}
|
}
|
||||||
|
@ -182,8 +186,8 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
|
||||||
|
|
||||||
type Interface struct {
|
type Interface struct {
|
||||||
Name string
|
Name string
|
||||||
Properties map[string]Property
|
Properties map[string]*Property
|
||||||
Methods map[string]Method
|
Methods map[string]*Method
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
||||||
|
@ -203,14 +207,52 @@ func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) {
|
||||||
fmt.Printf("Not adding methods for %s: interface name not found in first child node of category defclaration\n",n.Name)
|
fmt.Printf("Not adding methods for %s: interface name not found in first child node of category defclaration\n",n.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) AddFunction(n *ast.FunctionDecl) {
|
||||||
|
//treat functions as class methods with no class
|
||||||
|
tp := types.NewTypeFromString(n.Type,"")
|
||||||
|
m := &Method{
|
||||||
|
Name: n.Name,
|
||||||
|
Type: tp.ReturnType(),
|
||||||
|
Class: "",
|
||||||
|
ClassMethod: true,
|
||||||
|
Parameters: []*Parameter{},
|
||||||
|
}
|
||||||
|
f := tp.Node.Children[len(tp.Node.Children)-1] // Function node
|
||||||
|
if f.Kind != "Function" {
|
||||||
|
//fmt.Printf("AddFunction(%s): not a function -- Node type is %s\n%s",n.Name,f.Kind,tp.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//fmt.Printf("FunctionDecl: %s (%s) %s\n",n.Type,m.Type.CType(),n.Name)
|
||||||
|
i := 0
|
||||||
|
for _,c := range n.Children() {
|
||||||
|
switch x := c.(type) {
|
||||||
|
case *ast.ParmVarDecl:
|
||||||
|
p := &Parameter{
|
||||||
|
Vname: x.Name,
|
||||||
|
Type: types.NewTypeFromString(x.Type,""),
|
||||||
|
}
|
||||||
|
m.Parameters = append(m.Parameters,p)
|
||||||
|
i++
|
||||||
|
//fmt.Printf(" %s\n",p.Type.CType())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i > 0 && len(f.Children) > i {
|
||||||
|
if e := f.Children[i]; len(e.Children) > 0 {
|
||||||
|
//fmt.Println(" Next parameter: ",e.Children[0].String())
|
||||||
|
m.Parameters[i-1].Type.Variadic = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.Functions[n.Name] = m
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Wrapper) add(name string, ns []ast.Node) {
|
func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
var i Interface
|
var i *Interface
|
||||||
var ok bool
|
var ok bool
|
||||||
if i,ok = w.Interfaces[name]; !ok {
|
if i,ok = w.Interfaces[name]; !ok {
|
||||||
i = Interface{
|
i = &Interface{
|
||||||
Name: name,
|
Name: name,
|
||||||
Properties: map[string]Property{},
|
Properties: map[string]*Property{},
|
||||||
Methods: map[string]Method{},
|
Methods: map[string]*Method{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tp := types.NewTypeFromString(name,name)
|
tp := types.NewTypeFromString(name,name)
|
||||||
|
@ -220,7 +262,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
case *ast.ObjCPropertyDecl:
|
case *ast.ObjCPropertyDecl:
|
||||||
//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: types.NewTypeFromString(x.Type,name),
|
Type: types.NewTypeFromString(x.Type,name),
|
||||||
}
|
}
|
||||||
|
@ -230,7 +272,7 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
//}
|
//}
|
||||||
case *ast.ObjCMethodDecl:
|
case *ast.ObjCMethodDecl:
|
||||||
//fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name)
|
//fmt.Printf("ObjCMethodDecl: %s (%s) %s\n",x.Type,name,x.Name)
|
||||||
m := Method{
|
m := &Method{
|
||||||
Name: x.Name,
|
Name: x.Name,
|
||||||
Type: types.NewTypeFromString(x.Type,name),
|
Type: types.NewTypeFromString(x.Type,name),
|
||||||
Class: name,
|
Class: name,
|
||||||
|
@ -257,6 +299,37 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
//fmt.Println(reflect.TypeOf(x))
|
//fmt.Println(reflect.TypeOf(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Add class methods from super class
|
||||||
|
var supmethods func(*Interface,string)
|
||||||
|
supmethods = func(i *Interface, s string) {
|
||||||
|
if sup,ok := w.Interfaces[s]; !ok {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
for _,m := range sup.Methods {
|
||||||
|
if !m.ClassMethod {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m2 := &Method{
|
||||||
|
Name: m.Name,
|
||||||
|
Class: i.Name,
|
||||||
|
Type: m.Type.CloneToClass(i.Name),
|
||||||
|
ClassMethod: true,
|
||||||
|
Parameters: []*Parameter{},
|
||||||
|
}
|
||||||
|
for _,p := range m.Parameters {
|
||||||
|
m2.Parameters = append(m2.Parameters,
|
||||||
|
&Parameter{
|
||||||
|
Pname: p.Pname,
|
||||||
|
Vname: p.Vname,
|
||||||
|
Type: p.Type.CloneToClass(i.Name),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
i.Methods[m.Name] = m2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
supmethods(i,types.Super(s))
|
||||||
|
}
|
||||||
|
supmethods(i,types.Super(i.Name))
|
||||||
//fmt.Println("Add interface ",i.Name)
|
//fmt.Println("Add interface ",i.Name)
|
||||||
w.Interfaces[i.Name] = i
|
w.Interfaces[i.Name] = i
|
||||||
}
|
}
|
||||||
|
@ -269,18 +342,28 @@ type AvailAttr struct {
|
||||||
//GetParms returns the parameters of a method declaration and a bool
|
//GetParms returns the parameters of a method declaration and a bool
|
||||||
//indicating whether the given method is available on MacOS and not
|
//indicating whether the given method is available on MacOS and not
|
||||||
//deprecated.
|
//deprecated.
|
||||||
func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool) {
|
func (w *Wrapper) GetParms(n ast.Node,class string) ([]*Parameter,bool) {
|
||||||
ret := make([]Parameter,0)
|
ret := make([]*Parameter,0)
|
||||||
avail := make([]AvailAttr,0)
|
avail := make([]AvailAttr,0)
|
||||||
|
var parms []string
|
||||||
|
switch x := n.(type) {
|
||||||
|
case *ast.ObjCMethodDecl:
|
||||||
|
parms = x.Parameters
|
||||||
|
case *ast.FunctionDecl:
|
||||||
|
default:
|
||||||
|
panic("GetParms called with wrong node type")
|
||||||
|
}
|
||||||
j := 0
|
j := 0
|
||||||
for _,c := range n.Children() {
|
for _,c := range n.Children() {
|
||||||
switch x := c.(type) {
|
switch x := c.(type) {
|
||||||
case *ast.ParmVarDecl:
|
case *ast.ParmVarDecl:
|
||||||
p := Parameter{
|
p := &Parameter{
|
||||||
Pname: n.Parameters[j],
|
|
||||||
Vname: x.Name,
|
Vname: x.Name,
|
||||||
Type: types.NewTypeFromString(x.Type,class),
|
Type: types.NewTypeFromString(x.Type,class),
|
||||||
}
|
}
|
||||||
|
if parms != nil {
|
||||||
|
p.Pname = parms[j]
|
||||||
|
}
|
||||||
ret = append(ret,p)
|
ret = append(ret,p)
|
||||||
j++
|
j++
|
||||||
case *ast.Variadic:
|
case *ast.Variadic:
|
||||||
|
@ -316,9 +399,9 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
// check that we found the right number of parameters
|
// check that we found the right number of parameters
|
||||||
if len(ret) != len(n.Parameters) {
|
//if len(ret) != len(n.Parameters) {
|
||||||
fmt.Printf("Error in method declaration %s: Wrong number of ParmVarDecl children: %d parameters but %d ParmVarDecl children\n",n.Name,len(n.Parameters),len(ret))
|
// fmt.Printf("Error in method declaration %s: Wrong number of ParmVarDecl children: %d parameters but %d ParmVarDecl children\n",n.Name,len(n.Parameters),len(ret))
|
||||||
}
|
//}
|
||||||
return ret, true
|
return ret, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,6 +461,91 @@ func (c *Char) String() string {
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) ProcessMethod(m *Method) {
|
||||||
|
w._processMethod(m,false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) ProcessFunction(m *Method) {
|
||||||
|
w._processMethod(m,true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
|
if Debug {
|
||||||
|
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
||||||
|
}
|
||||||
|
if m.Type.IsFunction() || m.hasFunctionParam() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
gname := strings.Title(m.Name)
|
||||||
|
if !m.ClassMethod {
|
||||||
|
gname = "(o *" + m.Class + ") " + gname
|
||||||
|
} else {
|
||||||
|
gname = m.Class + gname
|
||||||
|
}
|
||||||
|
cname := m.Name
|
||||||
|
if m.Class != "" {
|
||||||
|
cname = m.Class + "_" + cname
|
||||||
|
}
|
||||||
|
|
||||||
|
cmtype := m.Type.CTypeAttrib()
|
||||||
|
ns,tps,gplist := m.gpntp()
|
||||||
|
w.processTypes(tps)
|
||||||
|
w.processType(m.Type)
|
||||||
|
grtype := m.Type.GoType()
|
||||||
|
if grtype == "Void" {
|
||||||
|
grtype = ""
|
||||||
|
}
|
||||||
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
|
//%s
|
||||||
|
func %s(%s) %s {
|
||||||
|
`,m.Type.CType(),gname,gplist,grtype))
|
||||||
|
lparm := len(tps)-1
|
||||||
|
if len(tps) > 0 && tps[lparm].Variadic {
|
||||||
|
vn := ns[lparm]
|
||||||
|
vn = vn[:len(vn)-1]
|
||||||
|
ns[lparm] = vn
|
||||||
|
w.goCode.WriteString(fmt.Sprintf(
|
||||||
|
` var %s [%d]unsafe.Pointer
|
||||||
|
for i,o := range %ss {
|
||||||
|
%s[i] = o.Ptr()
|
||||||
|
}
|
||||||
|
`,vn,w.VaArgs,vn,vn))
|
||||||
|
}
|
||||||
|
w.goCode.WriteString(` ` +
|
||||||
|
types.GoToC(cname,ns,m.Type,tps) + "\n}\n\n")
|
||||||
|
|
||||||
|
cret := ""
|
||||||
|
if !m.isVoid() {
|
||||||
|
cret = "return "
|
||||||
|
}
|
||||||
|
var cobj string
|
||||||
|
if m.ClassMethod {
|
||||||
|
cobj = m.Class
|
||||||
|
} else {
|
||||||
|
cobj = "(id)o"
|
||||||
|
}
|
||||||
|
cns,cntps := w.cparamlist(m)
|
||||||
|
_ = cns
|
||||||
|
if fun {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.cCode.WriteString(fmt.Sprintf(`
|
||||||
|
%s
|
||||||
|
%s(%s) {
|
||||||
|
`, cmtype, cname, cntps))
|
||||||
|
if len(tps) > 0 && tps[lparm].Variadic {
|
||||||
|
w.cCode.WriteString(fmt.Sprintf(
|
||||||
|
` %s* arr = %s;
|
||||||
|
`, tps[lparm].CType(), ns[lparm]))
|
||||||
|
}
|
||||||
|
if fun {
|
||||||
|
w.cCode.WriteString(fmt.Sprintf(` %s%s(%s);
|
||||||
|
}`, cret, m.Name, cns))
|
||||||
|
} else {
|
||||||
|
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
||||||
|
}`, cret, cobj, w.objcparamlist(m)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Wrapper) Wrap(toproc []string) {
|
func (w *Wrapper) Wrap(toproc []string) {
|
||||||
if w.Package == "" { w.Package = "ns" }
|
if w.Package == "" { w.Package = "ns" }
|
||||||
|
@ -392,7 +560,7 @@ func (w *Wrapper) Wrap(toproc []string) {
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
fmt.Printf("Writing output to %s\n",path.Join(w.Package,"main.go"))
|
fmt.Printf("Writing output to %s\n",path.Join(w.Package,"main.go"))
|
||||||
pInterfaces := map[string]Interface{}
|
pInterfaces := map[string]*Interface{}
|
||||||
for _,iface := range toproc {
|
for _,iface := range toproc {
|
||||||
pInterfaces[iface] = w.Interfaces[iface]
|
pInterfaces[iface] = w.Interfaces[iface]
|
||||||
}
|
}
|
||||||
|
@ -422,71 +590,15 @@ New%s() {
|
||||||
}
|
}
|
||||||
//FIXME: sort methods
|
//FIXME: sort methods
|
||||||
for _,m := range i.Methods {
|
for _,m := range i.Methods {
|
||||||
if Debug {
|
w.ProcessMethod(m)
|
||||||
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
|
||||||
}
|
|
||||||
if m.Type.IsFunction() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if m.hasFunctionParam() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
gname := strings.Title(m.Name)
|
|
||||||
if !m.ClassMethod {
|
|
||||||
gname = "(o *" + i.Name + ") " + gname
|
|
||||||
}
|
|
||||||
cname := i.Name + "_" + m.Name
|
|
||||||
|
|
||||||
cmtype := m.Type.CTypeAttrib()
|
|
||||||
ns,tps,gplist := m.gpntp()
|
|
||||||
w.processTypes(tps)
|
|
||||||
w.processType(m.Type)
|
|
||||||
grtype := m.Type.GoType()
|
|
||||||
if grtype == "Void" {
|
|
||||||
grtype = ""
|
|
||||||
}
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
|
||||||
//%s
|
|
||||||
func %s(%s) %s {
|
|
||||||
`,m.Type.CType(),gname,gplist,grtype))
|
|
||||||
lparm := len(tps)-1
|
|
||||||
if len(tps) > 0 && tps[lparm].Variadic {
|
|
||||||
vn := ns[lparm]
|
|
||||||
vn = vn[:len(vn)-1]
|
|
||||||
ns[lparm] = vn
|
|
||||||
w.goCode.WriteString(fmt.Sprintf(
|
|
||||||
` var %s [%d]unsafe.Pointer
|
|
||||||
for i,o := range %ss {
|
|
||||||
%s[i] = o.Ptr()
|
|
||||||
}
|
|
||||||
`,vn,w.VaArgs,vn,vn))
|
|
||||||
}
|
|
||||||
w.goCode.WriteString(
|
|
||||||
types.GoToC(cname,ns,m.Type,tps) + "}\n\n")
|
|
||||||
|
|
||||||
cret := ""
|
|
||||||
if !m.isVoid() {
|
|
||||||
cret = "return "
|
|
||||||
}
|
|
||||||
var cobj string
|
|
||||||
if m.ClassMethod {
|
|
||||||
cobj = i.Name
|
|
||||||
} else {
|
|
||||||
cobj = "(id)obj"
|
|
||||||
}
|
|
||||||
w.cCode.WriteString(fmt.Sprintf(`
|
|
||||||
%s
|
|
||||||
%s(%s) {
|
|
||||||
`, cmtype, cname, w.cparamlist(m)))
|
|
||||||
if len(tps) > 0 && tps[lparm].Variadic {
|
|
||||||
w.cCode.WriteString(fmt.Sprintf(
|
|
||||||
` %s* arr = %s;
|
|
||||||
`, tps[lparm].CType(), ns[lparm]))
|
|
||||||
}
|
|
||||||
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
|
||||||
}`, cret, cobj, w.objcparamlist(m)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _,m := range w.Functions {
|
||||||
|
//fmt.Printf("Processing function %s %s\n",m.Type.CType(),m.Name)
|
||||||
|
w.ProcessFunction(m)
|
||||||
|
}
|
||||||
|
fmt.Printf("%d functions\n", len(w.Functions))
|
||||||
of.WriteString("package " + w.Package + "\n\n")
|
of.WriteString("package " + w.Package + "\n\n")
|
||||||
of.WriteString(w.cCode.String())
|
of.WriteString(w.cCode.String())
|
||||||
of.WriteString(`
|
of.WriteString(`
|
||||||
|
|
Loading…
Reference in New Issue
Block a user