Better handling of multiple classes and input files. Handle
Objective C type parameter declarations. Check Typedefs when determining if a Type is a pointer or a function.
This commit is contained in:
parent
6135381cc7
commit
977a09e77e
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,6 +1,8 @@
|
|||
clast
|
||||
ast.txt
|
||||
*.ast
|
||||
simple
|
||||
complex
|
||||
program
|
||||
examples/foundation/foundation
|
||||
examples/foundation/ns
|
||||
examples/simple/simple
|
||||
examples/simple/simple/ClassOne
|
||||
|
|
|
@ -212,6 +212,8 @@ func Parse(fullline string) Node {
|
|||
return parseObjCProtocol(line)
|
||||
case "ObjCPropertyDecl":
|
||||
return parseObjCPropertyDecl(line)
|
||||
case "ObjCTypeParamDecl":
|
||||
return parseObjCTypeParamDecl(line)
|
||||
case "OffsetOfExpr":
|
||||
return parseOffsetOfExpr(line)
|
||||
case "PackedAttr":
|
||||
|
|
80
ast/objc_type_param_decl.go
Normal file
80
ast/objc_type_param_decl.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package ast
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ObjCTypeParamDecl is node represents a parameter of variable declaration.
|
||||
type ObjCTypeParamDecl struct {
|
||||
Addr Address
|
||||
Pos Position
|
||||
Position2 string
|
||||
Name string
|
||||
Type string
|
||||
Type2 string
|
||||
IsReferenced bool
|
||||
IsCovariant bool
|
||||
IsBounded bool
|
||||
ChildNodes []Node
|
||||
}
|
||||
|
||||
func parseObjCTypeParamDecl(line string) *ObjCTypeParamDecl {
|
||||
groups := groupsFromRegex(
|
||||
`<(?P<position>.*)>
|
||||
(?P<position2> [^ ]+:[\d:]+)?
|
||||
(?P<referenced> referenced)?
|
||||
(?P<name> \w+)?
|
||||
(?P<covariant> covariant)?
|
||||
(?P<bounded> bounded)?
|
||||
'(?P<type>.*?)'
|
||||
(?P<type2>:'.*?')?
|
||||
`,
|
||||
line,
|
||||
)
|
||||
|
||||
type2 := groups["type2"]
|
||||
if type2 != "" {
|
||||
type2 = type2[2 : len(type2)-1]
|
||||
}
|
||||
|
||||
if strings.Index(groups["position"], "<invalid sloc>") > -1 {
|
||||
groups["position"] = "<invalid sloc>"
|
||||
groups["position2"] = "<invalid sloc>"
|
||||
}
|
||||
|
||||
return &ObjCTypeParamDecl{
|
||||
Addr: ParseAddress(groups["address"]),
|
||||
Pos: NewPositionFromString(groups["position"]),
|
||||
Position2: strings.TrimSpace(groups["position2"]),
|
||||
Name: strings.TrimSpace(groups["name"]),
|
||||
Type: groups["type"],
|
||||
Type2: type2,
|
||||
IsReferenced: len(groups["referenced"]) > 0,
|
||||
IsCovariant: len(groups["covariant"]) > 0,
|
||||
IsBounded : len(groups["bounded"]) > 0,
|
||||
ChildNodes: []Node{},
|
||||
}
|
||||
}
|
||||
|
||||
// AddChild adds a new child node. Child nodes can then be accessed with the
|
||||
// Children attribute.
|
||||
func (n *ObjCTypeParamDecl) 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 *ObjCTypeParamDecl) 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 *ObjCTypeParamDecl) Children() []Node {
|
||||
return n.ChildNodes
|
||||
}
|
||||
|
||||
// Position returns the position in the original source code.
|
||||
func (n *ObjCTypeParamDecl) Position() Position {
|
||||
return n.Pos
|
||||
}
|
18
examples/foundation/main.go
Normal file
18
examples/foundation/main.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitlab.wow.st/gmp/nswrap/examples/foundation/ns"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("Started")
|
||||
n := ns.StringWithUTF8String(ns.CharFromString("hi there"))
|
||||
c := n.CapitalizedString()
|
||||
gstring := c.UTF8String().String()
|
||||
fmt.Println(gstring)
|
||||
fmt.Println("ok")
|
||||
}
|
||||
|
10
examples/foundation/nswrap.toml
Normal file
10
examples/foundation/nswrap.toml
Normal file
|
@ -0,0 +1,10 @@
|
|||
InputFiles = [
|
||||
"/System/Library/Frameworks/Foundation.framework/Headers/NSDictionary.h",
|
||||
"/System/Library/Frameworks/Foundation.framework/Headers/NSString.h",
|
||||
]
|
||||
Classes = [
|
||||
"NSString",
|
||||
"NSDictionary",
|
||||
]
|
||||
SysImports = [ "Foundation/Foundation.h" ]
|
||||
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
103
examples/simple/ClassOne/main.go
Normal file
103
examples/simple/ClassOne/main.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package ClassOne
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -x objective-c
|
||||
#cgo LDFLAGS: -framework Foundation
|
||||
|
||||
#import "simple.h"
|
||||
|
||||
ClassOne*
|
||||
NewClassOne() {
|
||||
return [ClassOne alloc];
|
||||
}
|
||||
|
||||
int
|
||||
ClassOne_geti1(void* obj) {
|
||||
return [(id)obj geti1];
|
||||
}
|
||||
int*
|
||||
ClassOne_getp1(void* obj) {
|
||||
return [(id)obj getp1];
|
||||
}
|
||||
int
|
||||
ClassOne_hi1(void* obj, struct stru in) {
|
||||
return [(id)obj hi1:in];
|
||||
}
|
||||
int
|
||||
ClassOne_hi2(void* obj, void* in) {
|
||||
return [(id)obj hi2:in];
|
||||
}
|
||||
struct stru
|
||||
ClassOne_nstru1(void* obj) {
|
||||
return [(id)obj nstru1];
|
||||
}
|
||||
struct stru*
|
||||
ClassOne_nstru2(void* obj) {
|
||||
return [(id)obj nstru2];
|
||||
}
|
||||
ClassOne*
|
||||
ClassOne_init(void* obj) {
|
||||
return [(id)obj init];
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
//ClassOne*
|
||||
type ClassOne struct { NSObject }
|
||||
|
||||
//NSObject*
|
||||
type NSObject struct { ptr unsafe.Pointer }
|
||||
|
||||
//int
|
||||
type Int C.int
|
||||
|
||||
//struct stru
|
||||
type Stru C.struct_stru
|
||||
|
||||
func NewClassOne() *ClassOne {
|
||||
ret := &ClassOne{}
|
||||
ret.ptr = unsafe.Pointer(C.NewClassOne())
|
||||
//ret = ret.Init()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (o *ClassOne) Geti1() Int {
|
||||
return (Int)(C.ClassOne_geti1(o.ptr))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Getp1() *Int {
|
||||
return (*Int)(unsafe.Pointer(C.ClassOne_getp1(o.ptr)))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Hi1(in Stru) Int {
|
||||
return (Int)(C.ClassOne_hi1(o.ptr, (C.struct_stru)(in)))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Hi2(in *Stru) Int {
|
||||
return (Int)(C.ClassOne_hi2(o.ptr, unsafe.Pointer(in)))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Nstru1() Stru {
|
||||
return (Stru)(C.ClassOne_nstru1(o.ptr))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Nstru2() *Stru {
|
||||
return (*Stru)(unsafe.Pointer(C.ClassOne_nstru2(o.ptr)))
|
||||
}
|
||||
|
||||
|
||||
func (o *ClassOne) Init() *ClassOne {
|
||||
ret := &ClassOne{}
|
||||
ret.ptr = unsafe.Pointer(C.ClassOne_init(o.ptr))
|
||||
return ret
|
||||
}
|
||||
|
22
examples/simple/ClassOne/simple.h
Normal file
22
examples/simple/ClassOne/simple.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
struct stru {int a,b;};
|
||||
|
||||
@interface ClassOne : NSObject
|
||||
{
|
||||
int i1;
|
||||
int *p1;
|
||||
int a1[2];
|
||||
int (*f)();
|
||||
}
|
||||
|
||||
- (ClassOne*) init;
|
||||
- (int) geti1;
|
||||
- (int *) getp1;
|
||||
- (int (*)()) getf1;
|
||||
- (int) hi1:(struct stru)in;
|
||||
- (int) hi2:(struct stru*)in;
|
||||
- (struct stru) nstru1;
|
||||
- (struct stru*) nstru2;
|
||||
@end
|
||||
|
59
examples/simple/ClassOne/simple.m
Normal file
59
examples/simple/ClassOne/simple.m
Normal file
|
@ -0,0 +1,59 @@
|
|||
#import "simple.h"
|
||||
|
||||
@implementation ClassOne
|
||||
|
||||
- (ClassOne*) init
|
||||
{
|
||||
ClassOne *ret;
|
||||
ret = [ClassOne alloc];
|
||||
ret->i1 = 12;
|
||||
ret->p1 = malloc(sizeof(int));
|
||||
*ret->p1 = 16;
|
||||
ret->a1[0] = 4;
|
||||
ret ->a1[1] = 5;
|
||||
return ret;
|
||||
}
|
||||
|
||||
- (int) geti1
|
||||
{
|
||||
return i1;
|
||||
}
|
||||
|
||||
- (int *) getp1
|
||||
{
|
||||
return p1;
|
||||
}
|
||||
|
||||
- (int (*)()) getf1
|
||||
{
|
||||
return f;
|
||||
}
|
||||
|
||||
- (int) hi1:(struct stru)in
|
||||
{
|
||||
return in.a;
|
||||
}
|
||||
|
||||
- (int) hi2:(struct stru*)in
|
||||
{
|
||||
return in->a;
|
||||
}
|
||||
|
||||
- (struct stru) nstru1
|
||||
{
|
||||
struct stru ret;
|
||||
ret.a = 7;
|
||||
ret.b = 8;
|
||||
return ret;
|
||||
}
|
||||
- (struct stru*) nstru2
|
||||
{
|
||||
struct stru* ret;
|
||||
ret = malloc(sizeof(struct stru));
|
||||
ret->a = 9;
|
||||
ret->b = 10;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@end
|
||||
|
21
examples/simple/main.go
Normal file
21
examples/simple/main.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitlab.wow.st/gmp/nswrap/examples/simple/ClassOne"
|
||||
)
|
||||
|
||||
func main() {
|
||||
o := ClassOne.NewClassOne().Init()
|
||||
fmt.Println("i1 = ",o.Geti1())
|
||||
fmt.Println("p1 = ",o.Getp1())
|
||||
p1 := o.Getp1()
|
||||
fmt.Println("*p1 = ", *p1)
|
||||
*p1 = 17
|
||||
fmt.Println("*p1 = ", *o.Getp1())
|
||||
ns := o.Nstru1()
|
||||
np := o.Nstru2()
|
||||
fmt.Println(o.Hi1(ns))
|
||||
fmt.Println(o.Hi2(np))
|
||||
}
|
||||
|
4
examples/simple/nswrap.toml
Normal file
4
examples/simple/nswrap.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
Package = "ClassOne"
|
||||
InputFiles = [ "ClassOne/simple.h" ]
|
||||
Classes = [ "ClassOne" ]
|
||||
Imports = [ "simple.h" ]
|
25
main.go
25
main.go
|
@ -9,12 +9,14 @@ import (
|
|||
|
||||
"github.com/BurntSushi/toml"
|
||||
"gitlab.wow.st/gmp/nswrap/ast"
|
||||
"gitlab.wow.st/gmp/nswrap/types"
|
||||
"gitlab.wow.st/gmp/nswrap/wrap"
|
||||
)
|
||||
|
||||
var Debug = false
|
||||
|
||||
type conf struct {
|
||||
Package string
|
||||
InputFiles []string
|
||||
Classes []string
|
||||
Imports []string
|
||||
|
@ -163,17 +165,22 @@ func Start() (err error) {
|
|||
|
||||
// build tree
|
||||
tree := buildTree(nodes, 0)
|
||||
unit := tree[0]
|
||||
//unit := tree[0]
|
||||
w := wrap.NewWrapper(Debug)
|
||||
w.Package = Config.Package
|
||||
w.Import(Config.Imports)
|
||||
w.SysImport(Config.SysImports)
|
||||
w.Pragma(Config.Pragma)
|
||||
for _, n := range(unit.Children()) {
|
||||
switch x := n.(type) {
|
||||
case *ast.ObjCInterfaceDecl:
|
||||
w.AddInterface(x)
|
||||
case *ast.ObjCCategoryDecl:
|
||||
w.AddCategory(x)
|
||||
for _, u := range tree {
|
||||
for _, n := range(u.Children()) {
|
||||
switch x := n.(type) {
|
||||
case *ast.ObjCInterfaceDecl:
|
||||
w.AddInterface(x)
|
||||
case *ast.ObjCCategoryDecl:
|
||||
w.AddCategory(x)
|
||||
case *ast.TypedefDecl:
|
||||
types.AddTypedef(x.Name,x.Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
w.Wrap(Config.Classes)
|
||||
|
@ -181,8 +188,8 @@ func Start() (err error) {
|
|||
}
|
||||
|
||||
func main() {
|
||||
if _, err := toml.DecodeFile("conf.toml",&Config); err != nil {
|
||||
fmt.Printf("Cannot open config file conf.toml.\n")
|
||||
if _, err := toml.DecodeFile("nswrap.toml",&Config); err != nil {
|
||||
fmt.Printf("Cannot open config file nswrap.toml.\n")
|
||||
os.Exit(-1)
|
||||
}
|
||||
if err := Start(); err != nil {
|
||||
|
|
|
@ -102,11 +102,6 @@ func NodeNamed(k string, p Parser) Parser {
|
|||
|
||||
// Combinators
|
||||
|
||||
//Id is the identity parser
|
||||
func Id(s string, n *Node) (string, *Node) {
|
||||
return s,n
|
||||
}
|
||||
|
||||
//Opt optionally runs a Parser, returning the input node if it fails
|
||||
func Opt(p Parser) Parser {
|
||||
return func(s string, n *Node) (string, *Node) {
|
||||
|
|
|
@ -12,6 +12,12 @@ var super map[string]string
|
|||
//go struct.
|
||||
var wrapped map[string]bool
|
||||
|
||||
//TypeParameters maps, for each class, a TypedefName to a type, representing
|
||||
//the Objective-C type parameters for that class
|
||||
var TypeParameters map[string]map[string]string
|
||||
|
||||
var Typedefs map[string]*Type
|
||||
|
||||
func Super(c string) string {
|
||||
if super == nil {
|
||||
super = make(map[string]string)
|
||||
|
@ -26,6 +32,23 @@ func SetSuper(c, p string) {
|
|||
super[c] = p
|
||||
}
|
||||
|
||||
func SetTypeParam(c, n, t string) {
|
||||
if TypeParameters == nil {
|
||||
TypeParameters = make(map[string]map[string]string)
|
||||
}
|
||||
if TypeParameters[c] == nil {
|
||||
TypeParameters[c] = make(map[string]string)
|
||||
}
|
||||
TypeParameters[c][n] = t
|
||||
}
|
||||
|
||||
func AddTypedef(n,t string) {
|
||||
if Typedefs == nil {
|
||||
Typedefs = make(map[string]*Type)
|
||||
}
|
||||
Typedefs[n] = NewTypeFromString(t,"")
|
||||
}
|
||||
|
||||
type Type struct {
|
||||
Node *Node
|
||||
Class string
|
||||
|
@ -42,12 +65,22 @@ func NewType(n *Node, c string) *Type {
|
|||
|
||||
func NewTypeFromString(t,c string) *Type {
|
||||
n,err := Parse(t)
|
||||
if n.CtypeSimplified() == "id" {
|
||||
if n.IsId() {
|
||||
//if n.CtypeSimplified() == "id" {
|
||||
n,err = Parse("NSObject*")
|
||||
}
|
||||
if err != nil {
|
||||
return &Type{}
|
||||
}
|
||||
if TypeParameters[c] != nil {
|
||||
recur := false
|
||||
for k,v := range TypeParameters[c] {
|
||||
recur = n.renameTypedefs(k,v)
|
||||
}
|
||||
if recur {
|
||||
return NewTypeFromString(n.Ctype(),c)
|
||||
}
|
||||
}
|
||||
return &Type{
|
||||
Node: n,
|
||||
Class: c,
|
||||
|
@ -117,19 +150,21 @@ func (t *Type) CTypeAttrib() string {
|
|||
}
|
||||
|
||||
func (t *Type) _CType(attrib bool) string {
|
||||
//if !attrib && c.ctype != "" ... FIXME?
|
||||
if t.ctype != "" { // cache
|
||||
return t.ctype
|
||||
}
|
||||
var ct string
|
||||
if attrib {
|
||||
ct = t.Node.Ctype()
|
||||
ignore := map[string]bool { "GenericList": true }
|
||||
ct = t.Node._Ctype(ignore)
|
||||
} else {
|
||||
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:]
|
||||
ct = "NSObject*" + ct[2:]
|
||||
}
|
||||
if len(ct) > 11 {
|
||||
if ct[:12] == "instancename" { ct = t.Class + ct[12:] }
|
||||
|
@ -148,14 +183,18 @@ func (t *Type) GoTypeDecl() string {
|
|||
return t.GoInterfaceDecl()
|
||||
}
|
||||
tp := t.BaseType()
|
||||
if tp.Node.IsId() {
|
||||
return ""
|
||||
}
|
||||
gt := tp.GoType()
|
||||
switch gt {
|
||||
case "", "Void":
|
||||
return ""
|
||||
default:
|
||||
return fmt.Sprintf(`
|
||||
//%s
|
||||
type %s %s
|
||||
`,gt,tp.CGoType())
|
||||
`,t.Node.CtypeSimplified(),gt,tp.CGoType())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,12 +209,27 @@ func (t *Type) GoInterfaceDecl() string {
|
|||
super = "ptr unsafe.Pointer"
|
||||
}
|
||||
return fmt.Sprintf(`
|
||||
//%s
|
||||
%stype %s struct { %s }
|
||||
`,x,gt,super)
|
||||
`,t.CTypeAttrib(),x,gt,super)
|
||||
}
|
||||
|
||||
func (t *Type) IsFunction() bool {
|
||||
if td,ok := Typedefs[t.BaseType().CType()]; ok {
|
||||
return td.IsFunction()
|
||||
}
|
||||
return t.Node.IsFunction()
|
||||
}
|
||||
|
||||
func (t *Type) IsPointer() bool {
|
||||
if td,ok := Typedefs[t.BaseType().CType()]; ok {
|
||||
return td.IsPointer()
|
||||
}
|
||||
return t.Node.IsPointer()
|
||||
}
|
||||
|
||||
func (t *Type) CToGo(cval string) string { // cast C value to CGo
|
||||
if t.Node.IsPointer() {
|
||||
if t.IsPointer() {
|
||||
cval = "unsafe.Pointer(" + cval + ")"
|
||||
}
|
||||
return fmt.Sprintf("(%s)(%s)",t.GoType(),cval)
|
||||
|
|
|
@ -30,6 +30,7 @@ func AbstractDeclarator(s string, n *Node) (string, *Node) {
|
|||
Opt(Pointer),
|
||||
OneOrMore(DirectAbstractDeclarator)),
|
||||
Pointer,
|
||||
Id,
|
||||
Block,
|
||||
)(s,n)
|
||||
}
|
||||
|
@ -136,6 +137,14 @@ func NullableAnnotation(s string, n *Node) (string, *Node) {
|
|||
))(s,n)
|
||||
}
|
||||
|
||||
func Id(s string, n *Node) (string, *Node) {
|
||||
return Seq(
|
||||
NodeNamed("Id",Lit("id")),
|
||||
Opt(TypeQualifierList),
|
||||
Opt(NullableAnnotation),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
func Pointer(s string, n *Node) (string, *Node) {
|
||||
return Seq(
|
||||
NodeNamed("Pointer",Lit("*")),
|
||||
|
|
|
@ -96,7 +96,7 @@ func (n *Node) PointsTo() *Node {
|
|||
|
||||
//IsPointer returns true if the node is a pointer
|
||||
func (n *Node) IsPointer() bool {
|
||||
return n.PointsTo() != nil
|
||||
return n.IsId() || n.PointsTo() != nil
|
||||
}
|
||||
|
||||
//ArrayOf, when called on an array node returns a node describing the type
|
||||
|
@ -126,6 +126,13 @@ func (n *Node) IsFunction() bool {
|
|||
return n.Children[len(n.Children)-1].Kind == "Function"
|
||||
}
|
||||
|
||||
func (n *Node) IsId() bool {
|
||||
if n == nil || len(n.Children) < 1 {
|
||||
return false
|
||||
}
|
||||
return n.Children[0].Kind == "TypedefName" && n.Children[0].Content == "id"
|
||||
}
|
||||
|
||||
//BaseType strips off all layers of pointer indirection
|
||||
func (n *Node) BaseType() *Node {
|
||||
if n == nil {
|
||||
|
|
|
@ -67,6 +67,24 @@ func (n *Node) AddChild(c *Node) *Node {
|
|||
return n
|
||||
}
|
||||
|
||||
//returns true if anything gets renamed
|
||||
func (n *Node) renameTypedefs(a,b string) (ret bool) {
|
||||
ret = false
|
||||
if n == nil { return }
|
||||
for i,c := range n.Children {
|
||||
if c.Kind == "TypedefName" && c.Content == a {
|
||||
ret = true
|
||||
n.Children[i] = NewNode("TypedefName", b)
|
||||
n.Children[i].Children = c.Children
|
||||
}
|
||||
if len(c.Children) > 0 {
|
||||
ret2 := c.renameTypedefs(a,b)
|
||||
ret = ret || ret2
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (n *Node) CtypeSimplified() string {
|
||||
ignore := map[string]bool{
|
||||
"NullableAnnotation": true,
|
||||
|
|
51
wrap/main.go
51
wrap/main.go
|
@ -2,6 +2,8 @@ package wrap
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"gitlab.wow.st/gmp/nswrap/ast"
|
||||
|
@ -13,6 +15,7 @@ var (
|
|||
)
|
||||
|
||||
type Wrapper struct {
|
||||
Package string
|
||||
Interfaces map[string]Interface
|
||||
|
||||
cCode strings.Builder // put cGo code here
|
||||
|
@ -81,7 +84,7 @@ func (m Method) isVoid() bool {
|
|||
//hasFunctionParam() returns true if a method has a function as a parameter.
|
||||
func (m Method) hasFunctionParam() bool {
|
||||
for _,p := range m.Parameters {
|
||||
if p.Type.Node.IsFunction() {
|
||||
if p.Type.IsFunction() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +227,9 @@ func (w *Wrapper) add(name string, ns []ast.Node) {
|
|||
//fmt.Printf("ast.ObjCInterface: %s inherits from %s\n",name,x.Name)
|
||||
types.SetSuper(name,x.Name)
|
||||
}
|
||||
case *ast.ObjCTypeParamDecl:
|
||||
//fmt.Printf("ObjCTypeParamDecl: %s = %s\n",x.Name,x.Type)
|
||||
types.SetTypeParam(name,x.Name,x.Type)
|
||||
case *ast.Unknown:
|
||||
//fmt.Printf("(*ast.Unkonwn %s: %s)\n",x.Name,x.Content)
|
||||
default:
|
||||
|
@ -312,7 +318,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
|||
bt := tp.BaseType()
|
||||
if w.Processed[bt.GoType()] { return }
|
||||
w.Processed[bt.GoType()] = true
|
||||
if bt.Node.IsFunction() {
|
||||
if bt.IsFunction() {
|
||||
return
|
||||
}
|
||||
w.goTypes.WriteString(tp.GoTypeDecl())
|
||||
|
@ -345,17 +351,26 @@ func (c *Char) String() string {
|
|||
|
||||
|
||||
func (w *Wrapper) Wrap(toproc []string) {
|
||||
|
||||
if w.Package == "" { w.Package = "ns" }
|
||||
err := os.MkdirAll(w.Package,0755)
|
||||
if err != nil {
|
||||
fmt.Printf("Error creating directory '%s'\n%s\n",w.Package,err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
of,err := os.Create(path.Join(w.Package,"main.go"))
|
||||
if err != nil {
|
||||
fmt.Printf("Error opening file %s\n%s\n",path.Join(w.Package,"main.go"),err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
fmt.Printf("Writing output to %s\n",path.Join(w.Package,"main.go"))
|
||||
pInterfaces := map[string]Interface{}
|
||||
for _,iface := range toproc {
|
||||
pInterfaces[iface] = w.Interfaces[iface]
|
||||
}
|
||||
//FIXME: sort pInterfaces
|
||||
for iname,i := range pInterfaces {
|
||||
if Debug {
|
||||
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
||||
iname, len(i.Properties), len(i.Methods))
|
||||
}
|
||||
for _,i := range pInterfaces {
|
||||
fmt.Printf("Interface %s: %d properties, %d methods\n",
|
||||
i.Name, len(i.Properties), len(i.Methods))
|
||||
|
||||
w.goCode.WriteString(fmt.Sprintf(`
|
||||
func New%s() *%s {
|
||||
|
@ -384,16 +399,14 @@ New%s() {
|
|||
if Debug {
|
||||
fmt.Printf(" method: %s (%s)\n", m.Name, m.Type)
|
||||
}
|
||||
if m.Type.Node.IsFunction() {
|
||||
if m.Type.IsFunction() {
|
||||
continue
|
||||
}
|
||||
if m.hasFunctionParam() {
|
||||
continue
|
||||
}
|
||||
gname := strings.Title(m.Name)
|
||||
if m.ClassMethod {
|
||||
gname = i.Name + gname
|
||||
} else {
|
||||
if !m.ClassMethod {
|
||||
gname = "(o *" + i.Name + ") " + gname
|
||||
}
|
||||
cname := i.Name + "_" + m.Name
|
||||
|
@ -429,10 +442,9 @@ func %s(%s) %s {
|
|||
}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(m)))
|
||||
}
|
||||
}
|
||||
fmt.Println(`package main
|
||||
`)
|
||||
fmt.Println(w.cCode.String())
|
||||
fmt.Println(`
|
||||
of.WriteString("package " + w.Package + "\n\n")
|
||||
of.WriteString(w.cCode.String())
|
||||
of.WriteString(`
|
||||
*/
|
||||
import "C"
|
||||
|
||||
|
@ -440,7 +452,8 @@ import (
|
|||
"unsafe"
|
||||
)
|
||||
`)
|
||||
fmt.Println(w.goTypes.String())
|
||||
fmt.Println(w.goHelpers.String())
|
||||
fmt.Println(w.goCode.String())
|
||||
of.WriteString(w.goTypes.String())
|
||||
of.WriteString(w.goHelpers.String())
|
||||
of.WriteString(w.goCode.String())
|
||||
of.Close()
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user