Identify methods from interfaces and categories, determine their
parameter and return types.
This commit is contained in:
parent
6a9c5c2811
commit
bcb4a0680d
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,3 @@
|
||||||
clast
|
clast
|
||||||
ast.txt
|
ast.txt
|
||||||
|
*.ast
|
||||||
|
|
|
@ -186,6 +186,8 @@ func Parse(fullline string) Node {
|
||||||
return parseNonNullAttr(line)
|
return parseNonNullAttr(line)
|
||||||
case "NotTailCalledAttr":
|
case "NotTailCalledAttr":
|
||||||
return parseNotTailCalledAttr(line)
|
return parseNotTailCalledAttr(line)
|
||||||
|
case "ObjCCategoryDecl":
|
||||||
|
return parseObjCCategoryDecl(line)
|
||||||
case "ObjCInterface":
|
case "ObjCInterface":
|
||||||
return parseObjCInterface(line)
|
return parseObjCInterface(line)
|
||||||
case "ObjCInterfaceType":
|
case "ObjCInterfaceType":
|
||||||
|
@ -206,6 +208,8 @@ func Parse(fullline string) Node {
|
||||||
return parseObjCObjectPointerType(line)
|
return parseObjCObjectPointerType(line)
|
||||||
case "ObjCProtocol":
|
case "ObjCProtocol":
|
||||||
return parseObjCProtocol(line)
|
return parseObjCProtocol(line)
|
||||||
|
case "ObjCPropertyDecl":
|
||||||
|
return parseObjCPropertyDecl(line)
|
||||||
case "OffsetOfExpr":
|
case "OffsetOfExpr":
|
||||||
return parseOffsetOfExpr(line)
|
return parseOffsetOfExpr(line)
|
||||||
case "PackedAttr":
|
case "PackedAttr":
|
||||||
|
|
56
ast/objc_category_decl.go
Normal file
56
ast/objc_category_decl.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
import (
|
||||||
|
// "fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjCCategoryDecl is node represents a category declaration.
|
||||||
|
type ObjCCategoryDecl struct {
|
||||||
|
Addr Address
|
||||||
|
Pos Position
|
||||||
|
Position2 string
|
||||||
|
Name string
|
||||||
|
ChildNodes []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseObjCCategoryDecl(line string) *ObjCCategoryDecl {
|
||||||
|
groups := groupsFromRegex(
|
||||||
|
`(?:prev (?P<prev>0x[0-9a-f]+) )?
|
||||||
|
<(?P<position><invalid sloc>|.*)>
|
||||||
|
(?P<position2> <invalid sloc>| col:\d+| line:\d+:\d+)
|
||||||
|
(?P<name> \w+)?`,
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &ObjCCategoryDecl{
|
||||||
|
Addr: ParseAddress(groups["address"]),
|
||||||
|
Pos: NewPositionFromString(groups["position"]),
|
||||||
|
Position2: strings.TrimSpace(groups["position2"]),
|
||||||
|
Name: strings.TrimSpace(groups["name"]),
|
||||||
|
ChildNodes: []Node{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChild adds a new child node. Child nodes can then be accessed with the
|
||||||
|
// Children attribute.
|
||||||
|
func (n *ObjCCategoryDecl) AddChild(node Node) {
|
||||||
|
n.ChildNodes = append(n.ChildNodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address returns the numeric address of the node. See the documentation for
|
||||||
|
// the Address type for more information.
|
||||||
|
func (n *ObjCCategoryDecl) Address() Address {
|
||||||
|
return n.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children returns the child nodes. If this node does not have any children or
|
||||||
|
// this node does not support children it will always return an empty slice.
|
||||||
|
func (n *ObjCCategoryDecl) Children() []Node {
|
||||||
|
return n.ChildNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position returns the position in the original source code.
|
||||||
|
func (n *ObjCCategoryDecl) Position() Position {
|
||||||
|
return n.Pos
|
||||||
|
}
|
|
@ -3,19 +3,19 @@ package ast
|
||||||
// ObjCInterface is an Objective-C interface
|
// ObjCInterface is an Objective-C interface
|
||||||
type ObjCInterface struct {
|
type ObjCInterface struct {
|
||||||
Addr Address
|
Addr Address
|
||||||
Type string
|
Name string
|
||||||
ChildNodes []Node
|
ChildNodes []Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseObjCInterface(line string) *ObjCInterface {
|
func parseObjCInterface(line string) *ObjCInterface {
|
||||||
groups := groupsFromRegex(
|
groups := groupsFromRegex(
|
||||||
"'(?P<type>.*)'",
|
"'(?P<name>.*)'",
|
||||||
line,
|
line,
|
||||||
)
|
)
|
||||||
|
|
||||||
return &ObjCInterface{
|
return &ObjCInterface{
|
||||||
Addr: ParseAddress(groups["address"]),
|
Addr: ParseAddress(groups["address"]),
|
||||||
Type: groups["type"],
|
Name: groups["name"],
|
||||||
ChildNodes: []Node{},
|
ChildNodes: []Node{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@ type ObjCMethodDecl struct {
|
||||||
Implicit bool
|
Implicit bool
|
||||||
ClassMethod bool
|
ClassMethod bool
|
||||||
Name string
|
Name string
|
||||||
|
Parameters []string
|
||||||
Type string
|
Type string
|
||||||
|
Type2 string
|
||||||
Attr string
|
Attr string
|
||||||
ChildNodes []Node
|
ChildNodes []Node
|
||||||
}
|
}
|
||||||
|
@ -25,13 +27,17 @@ func parseObjCMethodDecl(line string) *ObjCMethodDecl {
|
||||||
(?P<implicit> implicit)?
|
(?P<implicit> implicit)?
|
||||||
(?P<methodtype> \+| \-)
|
(?P<methodtype> \+| \-)
|
||||||
(?P<names>.*?)
|
(?P<names>.*?)
|
||||||
(?P<type>'.*')
|
'(?P<type>[^']*?)'
|
||||||
|
(:'(?P<type2>.*?)')?
|
||||||
(?P<attr> .*)?`,
|
(?P<attr> .*)?`,
|
||||||
line,
|
line,
|
||||||
)
|
)
|
||||||
/*
|
names := strings.TrimSpace(groups["names"])
|
||||||
(?P<position2> <invalid sloc>| col:\d+| line:\d+:\d+)?
|
parts := strings.Split(strings.TrimSpace(groups["names"]),":")
|
||||||
*/
|
params := []string{}
|
||||||
|
if names[len(names)-1] == ':' {
|
||||||
|
params = parts[:len(parts)-1]
|
||||||
|
}
|
||||||
|
|
||||||
return &ObjCMethodDecl{
|
return &ObjCMethodDecl{
|
||||||
Addr: ParseAddress(groups["address"]),
|
Addr: ParseAddress(groups["address"]),
|
||||||
|
@ -39,9 +45,11 @@ func parseObjCMethodDecl(line string) *ObjCMethodDecl {
|
||||||
Position2: strings.TrimSpace(groups["position2"]),
|
Position2: strings.TrimSpace(groups["position2"]),
|
||||||
Implicit: len(groups["implicit"])>0,
|
Implicit: len(groups["implicit"])>0,
|
||||||
ClassMethod: groups["methodtype"] == " +",
|
ClassMethod: groups["methodtype"] == " +",
|
||||||
Name: groups["names"],
|
Name: parts[0],
|
||||||
Type: groups["type"],
|
Parameters: params,
|
||||||
Attr: groups["attr"],
|
Type: strings.TrimSpace(groups["type"]),
|
||||||
|
Type2: strings.TrimSpace(groups["type2"]),
|
||||||
|
Attr: strings.TrimSpace(groups["attr"]),
|
||||||
ChildNodes: []Node{},
|
ChildNodes: []Node{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
64
ast/objc_property_decl.go
Normal file
64
ast/objc_property_decl.go
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObjCPropertyDecl is node represents an Objective-C property declaration
|
||||||
|
type ObjCPropertyDecl struct {
|
||||||
|
Addr Address
|
||||||
|
Pos Position
|
||||||
|
Position2 string
|
||||||
|
Name string
|
||||||
|
Type string
|
||||||
|
Type2 string
|
||||||
|
Attr string
|
||||||
|
ChildNodes []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseObjCPropertyDecl(line string) *ObjCPropertyDecl {
|
||||||
|
groups := groupsFromRegex(
|
||||||
|
`(?:prev (?P<prev>0x[0-9a-f]+) )?
|
||||||
|
<(?P<position>.*<scratch space>.*?|.*<built-in>.*?|.*<invalid sloc>|.*?)>
|
||||||
|
(?P<position2> <invalid sloc>| col:\d+| line:\d+:\d+)?
|
||||||
|
(?P<name>.*?)
|
||||||
|
'(?P<type>[^']*?)'
|
||||||
|
(:'(?P<type2>.*?)')?
|
||||||
|
(?P<attr> .*)?`,
|
||||||
|
line,
|
||||||
|
)
|
||||||
|
|
||||||
|
return &ObjCPropertyDecl{
|
||||||
|
Addr: ParseAddress(groups["address"]),
|
||||||
|
Pos: NewPositionFromString(groups["position"]),
|
||||||
|
Position2: strings.TrimSpace(groups["position2"]),
|
||||||
|
Name: strings.TrimSpace(groups["name"]),
|
||||||
|
Type: strings.TrimSpace(groups["type"]),
|
||||||
|
Type2: strings.TrimSpace(groups["type2"]),
|
||||||
|
Attr: strings.TrimSpace(groups["attr"]),
|
||||||
|
ChildNodes: []Node{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChild adds a new child node. Child nodes can then be accessed with the
|
||||||
|
// Children attribute.
|
||||||
|
func (n *ObjCPropertyDecl) AddChild(node Node) {
|
||||||
|
n.ChildNodes = append(n.ChildNodes, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address returns the numeric address of the node. See the documentation for
|
||||||
|
// the Address type for more information.
|
||||||
|
func (n *ObjCPropertyDecl) Address() Address {
|
||||||
|
return n.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Children returns the child nodes. If this node does not have any children or
|
||||||
|
// this node does not support children it will always return an empty slice.
|
||||||
|
func (n *ObjCPropertyDecl) Children() []Node {
|
||||||
|
return n.ChildNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position returns the position in the original source code.
|
||||||
|
func (n *ObjCPropertyDecl) Position() Position {
|
||||||
|
return n.Pos
|
||||||
|
}
|
|
@ -3,19 +3,21 @@ package ast
|
||||||
// ObjCProtocol is an Objective-C protocol
|
// ObjCProtocol is an Objective-C protocol
|
||||||
type ObjCProtocol struct {
|
type ObjCProtocol struct {
|
||||||
Addr Address
|
Addr Address
|
||||||
Type string
|
Name string
|
||||||
|
Content string
|
||||||
ChildNodes []Node
|
ChildNodes []Node
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseObjCProtocol(line string) *ObjCProtocol {
|
func parseObjCProtocol(line string) *ObjCProtocol {
|
||||||
groups := groupsFromRegex(
|
groups := groupsFromRegex(
|
||||||
"'(?P<type>.*)'",
|
"'(?P<name>.*)'",
|
||||||
line,
|
line,
|
||||||
)
|
)
|
||||||
|
|
||||||
return &ObjCProtocol{
|
return &ObjCProtocol{
|
||||||
Addr: ParseAddress(groups["address"]),
|
Addr: ParseAddress(groups["address"]),
|
||||||
Type: groups["type"],
|
Name: groups["name"],
|
||||||
|
Content: groups["content"],
|
||||||
ChildNodes: []Node{},
|
ChildNodes: []Node{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
37
main.go
37
main.go
|
@ -207,11 +207,12 @@ func Start(args ProgramArgs) (err error) {
|
||||||
for _, n := range(unit.Children()) {
|
for _, n := range(unit.Children()) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
case *ast.ObjCInterfaceDecl:
|
case *ast.ObjCInterfaceDecl:
|
||||||
if x.Name == "CBPeripheral" {
|
w.AddInterface(x)
|
||||||
w.Wrap(x)
|
case *ast.ObjCCategoryDecl:
|
||||||
}
|
w.AddCategory(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
w.Wrap()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,17 +233,17 @@ func (i *inputDataFlags) Set(value string) error {
|
||||||
var clangFlags inputDataFlags
|
var clangFlags inputDataFlags
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
transpileCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
wrapCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
||||||
astCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
astCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
versionFlag = flag.Bool("v", false, "print the version and exit")
|
versionFlag = flag.Bool("v", false, "print the version and exit")
|
||||||
transpileCommand = flag.NewFlagSet("transpile", flag.ContinueOnError)
|
wrapCommand = flag.NewFlagSet("wrap", flag.ContinueOnError)
|
||||||
verboseFlag = transpileCommand.Bool("V", false, "print progress as comments")
|
verboseFlag = wrapCommand.Bool("V", false, "print progress as comments")
|
||||||
outputFlag = transpileCommand.String("o", "", "output Go generated code to the specified file")
|
outputFlag = wrapCommand.String("o", "", "output Go generated code to the specified file")
|
||||||
packageFlag = transpileCommand.String("p", "main", "set the name of the generated package")
|
packageFlag = wrapCommand.String("p", "main", "set the name of the generated package")
|
||||||
transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
|
wrapHelpFlag = wrapCommand.Bool("h", false, "print help information")
|
||||||
astCommand = flag.NewFlagSet("ast", flag.ContinueOnError)
|
astCommand = flag.NewFlagSet("ast", flag.ContinueOnError)
|
||||||
astHelpFlag = astCommand.Bool("h", false, "print help information")
|
astHelpFlag = astCommand.Bool("h", false, "print help information")
|
||||||
)
|
)
|
||||||
|
@ -259,8 +260,8 @@ func runCommand() int {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
|
usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
|
||||||
usage += "Commands:\n"
|
usage += "Commands:\n"
|
||||||
usage += " transpile\ttranspile an input C source file or files to Go\n"
|
usage += " wrap\twrap an Objective-C interface for Go\n"
|
||||||
usage += " ast\t\tprint AST before translated Go code\n\n"
|
usage += " ast\t\tprint AST\n\n"
|
||||||
|
|
||||||
usage += "Flags:\n"
|
usage += "Flags:\n"
|
||||||
fmt.Printf(usage, os.Args[0])
|
fmt.Printf(usage, os.Args[0])
|
||||||
|
@ -299,20 +300,20 @@ func runCommand() int {
|
||||||
args.ast = true
|
args.ast = true
|
||||||
args.inputFiles = astCommand.Args()
|
args.inputFiles = astCommand.Args()
|
||||||
args.clangFlags = clangFlags
|
args.clangFlags = clangFlags
|
||||||
case "transpile":
|
case "wrap":
|
||||||
err := transpileCommand.Parse(os.Args[2:])
|
err := wrapCommand.Parse(os.Args[2:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("transpile command cannot parse: %v", err)
|
fmt.Printf("wrap command cannot parse: %v", err)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if *transpileHelpFlag || transpileCommand.NArg() == 0 {
|
if *wrapHelpFlag || wrapCommand.NArg() == 0 {
|
||||||
fmt.Printf("Usage: %s transpile [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
|
fmt.Printf("Usage: %s wrap [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
|
||||||
transpileCommand.PrintDefaults()
|
wrapCommand.PrintDefaults()
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
args.inputFiles = transpileCommand.Args()
|
args.inputFiles = wrapCommand.Args()
|
||||||
args.outputFile = *outputFlag
|
args.outputFile = *outputFlag
|
||||||
args.packageName = *packageFlag
|
args.packageName = *packageFlag
|
||||||
args.verbose = *verboseFlag
|
args.verbose = *verboseFlag
|
||||||
|
|
213
wrap/main.go
213
wrap/main.go
|
@ -2,28 +2,219 @@ package wrap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
//"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"gitlab.wow.st/gmp/clast/ast"
|
"gitlab.wow.st/gmp/clast/ast"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Wrapper struct {
|
type Wrapper struct {
|
||||||
|
Interfaces map[string]Interface
|
||||||
|
Types map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) AddType(t string) {
|
||||||
|
// only for objects and pointers?
|
||||||
|
// strip off pointers, < > and blank space
|
||||||
|
nt := strings.ReplaceAll(t,"*","")
|
||||||
|
if len(nt) > 3 && nt[0:3] == "id<" {
|
||||||
|
nt = t[3:len(t)-1]
|
||||||
|
}
|
||||||
|
nt = strings.ReplaceAll(nt,"<","_")
|
||||||
|
nt = strings.ReplaceAll(nt,">","_")
|
||||||
|
if _,ok := builtinTypes[nt]; ok { // do not add builtin types
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(nt) > 5 && nt[0:5] == "enum " { // FIXME: deal with enums?
|
||||||
|
return
|
||||||
|
}
|
||||||
|
nt = strings.ReplaceAll(nt," ","")
|
||||||
|
if nt == "void" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Types[nt] = t
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWrapper() *Wrapper {
|
func NewWrapper() *Wrapper {
|
||||||
return &Wrapper{}
|
return &Wrapper{
|
||||||
|
Interfaces: map[string]Interface{},
|
||||||
|
Types: map[string]string{},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) Wrap(n *ast.ObjCInterfaceDecl) {
|
type Property struct {
|
||||||
fmt.Println("//generated by gitlab.wow.st/gmp/clast")
|
Name, Type, Type2, Attr string
|
||||||
for _,c := range n.Children() {
|
}
|
||||||
switch x := c.(type) {
|
|
||||||
case *ast.Unknown:
|
type Parameter struct {
|
||||||
fmt.Printf("%s: %s\n",x.Name,x.Content)
|
Name, Type, Type2 string
|
||||||
case *ast.ObjCMethodDecl:
|
}
|
||||||
fmt.Printf("*ast.ObjCMethodDecl: %s (%s %s)\n",x.Name,x.Type, x.Attr)
|
|
||||||
|
type Method struct {
|
||||||
|
Name, Type, Type2 string
|
||||||
|
Parameters map[string]Parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
type Interface struct {
|
||||||
|
Name string
|
||||||
|
Properties map[string]Property
|
||||||
|
Methods map[string]Method
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) AddInterface(n *ast.ObjCInterfaceDecl) {
|
||||||
|
//fmt.Printf("ast.ObjCInterfaceDecl: %s\n",n.Name)
|
||||||
|
w.add(n.Name, n.Children())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) AddCategory(n *ast.ObjCCategoryDecl) {
|
||||||
|
ns := n.Children()
|
||||||
|
switch x := ns[0].(type) {
|
||||||
|
case *ast.ObjCInterface:
|
||||||
|
w.add(x.Name, ns[1:])
|
||||||
default:
|
default:
|
||||||
fmt.Println(reflect.TypeOf(x))
|
fmt.Printf("Not adding methods for %s: interface name not found in first child node of category defclaration\n",n.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) add(name string, ns []ast.Node) {
|
||||||
|
var i Interface
|
||||||
|
var ok bool
|
||||||
|
if i,ok = w.Interfaces[name]; !ok {
|
||||||
|
i = Interface{
|
||||||
|
Name: name,
|
||||||
|
Properties: map[string]Property{},
|
||||||
|
Methods: map[string]Method{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _,c := range ns {
|
||||||
|
switch x := c.(type) {
|
||||||
|
case *ast.ObjCPropertyDecl:
|
||||||
|
p := Property{
|
||||||
|
Name: x.Name,
|
||||||
|
Type: x.Type,
|
||||||
|
Type2: x.Type2,
|
||||||
|
}
|
||||||
|
w.AddType(typeOrType2(x.Type,x.Type2))
|
||||||
|
i.Properties[p.Name] = p
|
||||||
|
case *ast.ObjCMethodDecl:
|
||||||
|
fmt.Printf("ObjcMethodDecl: %s\n",x.Name)
|
||||||
|
m := Method{
|
||||||
|
Name: x.Name,
|
||||||
|
Type: x.Type,
|
||||||
|
Type2: x.Type2,
|
||||||
|
}
|
||||||
|
w.AddType(typeOrType2(x.Type,x.Type2))
|
||||||
|
m.Parameters = w.GetParms(x)
|
||||||
|
i.Methods[m.Name] = m
|
||||||
|
case *ast.ObjCProtocol:
|
||||||
|
//fmt.Printf("ast.ObjCProtocol: %s\n",x.Name)
|
||||||
|
case *ast.ObjCInterface:
|
||||||
|
//fmt.Printf("ast.ObjCInterface: %s\n",x.Name)
|
||||||
|
case *ast.Unknown:
|
||||||
|
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
||||||
|
default:
|
||||||
|
//fmt.Println(reflect.TypeOf(x))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.Interfaces[i.Name] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl) map[string]Parameter {
|
||||||
|
ps := make([]Parameter,0)
|
||||||
|
avail := make([][]string,len(n.Children()))
|
||||||
|
var c ast.Node
|
||||||
|
i := -1
|
||||||
|
for i,c = range n.Children() {
|
||||||
|
switch x := c.(type) {
|
||||||
|
case *ast.ParmVarDecl:
|
||||||
|
i++
|
||||||
|
p := Parameter{
|
||||||
|
Type: x.Type,
|
||||||
|
Type2: x.Type2,
|
||||||
|
}
|
||||||
|
ps = append(ps,p)
|
||||||
|
avail = append(avail,[]string{})
|
||||||
|
case *ast.AvailabilityAttr:
|
||||||
|
avail[i] = append(avail[i],x.OS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isAvail := func(l []string) bool {
|
||||||
|
if len(l) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _,x := range l {
|
||||||
|
if x == "macos" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ret := make(map[string]Parameter)
|
||||||
|
j := 0
|
||||||
|
for i,p := range ps {
|
||||||
|
if isAvail(avail[i]) {
|
||||||
|
ret[n.Parameters[j]] = p
|
||||||
|
j++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _,p := range ret {
|
||||||
|
w.AddType(typeOrType2(p.Type,p.Type2))
|
||||||
|
}
|
||||||
|
if j != 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),i)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeOrType2(t1, t2 string) string {
|
||||||
|
if t2 != "" {
|
||||||
|
return t2
|
||||||
|
}
|
||||||
|
return t1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Wrapper) Wrap() {
|
||||||
|
//var cCode strings.Builder
|
||||||
|
var goCode strings.Builder
|
||||||
|
|
||||||
|
for k,t := range w.Types { // FIXME: SORT FIRST
|
||||||
|
w := fmt.Sprintf(`
|
||||||
|
// %s
|
||||||
|
type %s struct { ptr unsafe.Pointer }
|
||||||
|
`,t, k)
|
||||||
|
goCode.WriteString(w)
|
||||||
|
}
|
||||||
|
for k,v := range w.Interfaces {
|
||||||
|
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
||||||
|
k, len(v.Properties), len(v.Methods))
|
||||||
|
for _,y := range v.Properties {
|
||||||
|
fmt.Printf(" property: %s (%s)\n", y.Name, typeOrType2(y.Type,y.Type2))
|
||||||
|
}
|
||||||
|
for _,y := range v.Methods {
|
||||||
|
fmt.Printf(" method: %s (%s)\n", y.Name, typeOrType2(y.Type,y.Type2))
|
||||||
|
for _,z := range y.Parameters {
|
||||||
|
fmt.Printf(" %s:%s\n", z.Name, typeOrType2(z.Type,z.Type2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fmt.Println(goCode.String())
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user