Create GoString helper methods for anything that has a "WithString"
method. Multiple bug fixes in type system, fixed parsing of id, instancename and instancetype, allow NullableAnnotations after generic lists (e.g. "id<ObjectType> _Nullable"). Helper function to identify types that are function pointers.
This commit is contained in:
parent
8ea3d57cf0
commit
eced251710
|
@ -11,7 +11,8 @@ func main() {
|
||||||
fmt.Println("LE capable:",cd.IsLECapableHardware())
|
fmt.Println("LE capable:",cd.IsLECapableHardware())
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
fmt.Println("LE capable:",cd.IsLECapableHardware())
|
fmt.Println("LE capable:",cd.IsLECapableHardware())
|
||||||
uuid := ble.CBUUIDWithString(ble.NSStringWithUTF8String(ble.CharFromString("180d")))
|
uuid := ble.CBUUIDWithGoString("180d")
|
||||||
cd.ScanFor(uuid)
|
cd.ScanFor(uuid)
|
||||||
time.Sleep(time.Second * 15)
|
|
||||||
|
select { }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
n1 := ns.NSStringWithUTF8String(ns.CharFromString("hi there"))
|
n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there"))
|
||||||
c1 := n1.CapitalizedString()
|
c1 := n1.CapitalizedString()
|
||||||
gs := c1.UTF8String().String()
|
gs := c1.UTF8String().String()
|
||||||
fmt.Println(gs)
|
fmt.Println(gs)
|
||||||
n2 := ns.NSStringWithUTF8String(ns.CharFromString("hi world"))
|
n2 := ns.NSStringWithGoString("hi world")
|
||||||
n3 := ns.NSStringWithUTF8String(ns.CharFromString("ok bye"))
|
n3 := ns.NSStringWithGoString("ok bye")
|
||||||
a := ns.NSMutableArrayWithObjects(n1,n2,n3)
|
a := ns.NSMutableArrayWithObjects(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))
|
||||||
|
|
|
@ -22,6 +22,6 @@ Functions = [
|
||||||
Enums = [
|
Enums = [
|
||||||
"CF.*",
|
"CF.*",
|
||||||
]
|
]
|
||||||
SysImports = [ "Foundation/Foundation.h" ]
|
Frameworks = [ "Foundation" ]
|
||||||
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
||||||
VaArgs = 32
|
VaArgs = 32
|
||||||
|
|
|
@ -2,3 +2,4 @@ Package = "ClassOne"
|
||||||
InputFiles = [ "ClassOne/simple.h" ]
|
InputFiles = [ "ClassOne/simple.h" ]
|
||||||
Classes = [ "ClassOne","ClassTwo" ]
|
Classes = [ "ClassOne","ClassTwo" ]
|
||||||
Imports = [ "simple.h" ]
|
Imports = [ "simple.h" ]
|
||||||
|
Frameworks = [ "Foundation" ]
|
||||||
|
|
7
main.go
7
main.go
|
@ -149,7 +149,6 @@ func matches(x string, rs []string) bool {
|
||||||
|
|
||||||
// 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)
|
|
||||||
for _, in := range Config.InputFiles {
|
for _, in := range Config.InputFiles {
|
||||||
_, err := os.Stat(in)
|
_, err := os.Stat(in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -159,10 +158,11 @@ func Start() (err error) {
|
||||||
|
|
||||||
// 2. Preprocess NOT DONE
|
// 2. Preprocess NOT DONE
|
||||||
|
|
||||||
// 3. Generate JSON from AST
|
// 3. Generate AST
|
||||||
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
||||||
"-fsyntax-only","-fno-color-diagnostics"}
|
"-fsyntax-only","-fno-color-diagnostics"}
|
||||||
cargs = append(cargs,Config.InputFiles...)
|
cargs = append(cargs,Config.InputFiles...)
|
||||||
|
fmt.Printf("Generating AST\n")
|
||||||
astPP, err := exec.Command("clang",cargs...).Output()
|
astPP, err := exec.Command("clang",cargs...).Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// If clang fails it still prints out the AST, so we have to run it
|
// If clang fails it still prints out the AST, so we have to run it
|
||||||
|
@ -175,9 +175,11 @@ func Start() (err error) {
|
||||||
lines := readAST(astPP)
|
lines := readAST(astPP)
|
||||||
|
|
||||||
// Converting to nodes
|
// Converting to nodes
|
||||||
|
fmt.Printf("Building nodes\n")
|
||||||
nodes := convertLinesToNodesParallel(lines)
|
nodes := convertLinesToNodesParallel(lines)
|
||||||
|
|
||||||
// build tree
|
// build tree
|
||||||
|
fmt.Printf("Assembling tree\n")
|
||||||
tree := buildTree(nodes, 0)
|
tree := buildTree(nodes, 0)
|
||||||
w := wrap.NewWrapper(Debug)
|
w := wrap.NewWrapper(Debug)
|
||||||
w.Package = Config.Package
|
w.Package = Config.Package
|
||||||
|
@ -190,6 +192,7 @@ func Start() (err error) {
|
||||||
}
|
}
|
||||||
w.VaArgs = Config.VaArgs
|
w.VaArgs = Config.VaArgs
|
||||||
for _, u := range tree {
|
for _, u := range tree {
|
||||||
|
fmt.Printf("--processing translation unit\n")
|
||||||
for _, n := range(u.Children()) {
|
for _, n := range(u.Children()) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
case *ast.ObjCInterfaceDecl:
|
case *ast.ObjCInterfaceDecl:
|
||||||
|
|
|
@ -50,7 +50,7 @@ func init() {
|
||||||
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_id = regexp.MustCompile(`\bid\b`)
|
||||||
r_instancename = regexp.MustCompile(`\binstancename\b`)
|
r_instancename = regexp.MustCompile(`\binstancename\b`)
|
||||||
r_instancetype = regexp.MustCompile(`\binstancetype\b`)
|
r_instancetype = regexp.MustCompile(`\binstancetype\b`)
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,6 @@ func NewType(n *Node, c string) *Type {
|
||||||
return &Type{
|
return &Type{
|
||||||
Node: n2,
|
Node: n2,
|
||||||
Class: c,
|
Class: c,
|
||||||
//ctype: "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,19 +124,16 @@ func NewTypeFromString(t,c string) *Type {
|
||||||
//fmt.Printf("t/c: %s/%s\n",t,c)
|
//fmt.Printf("t/c: %s/%s\n",t,c)
|
||||||
n,err := Parse(t)
|
n,err := Parse(t)
|
||||||
//fmt.Printf("%p %s",n,n.String())
|
//fmt.Printf("%p %s",n,n.String())
|
||||||
if n.IsId() {
|
|
||||||
n,err = Parse("NSObject*")
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &Type{}
|
return &Type{}
|
||||||
}
|
}
|
||||||
if n2,ok := clean(n, c); ok {
|
if n2,ok := clean(n, c); ok {
|
||||||
|
//found type parameters, re-parse
|
||||||
return NewTypeFromString(n2.Ctype(),c)
|
return NewTypeFromString(n2.Ctype(),c)
|
||||||
}
|
}
|
||||||
return &Type{
|
return &Type{
|
||||||
Node: n,
|
Node: n,
|
||||||
Class: c,
|
Class: c,
|
||||||
//ctype: "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,9 +215,9 @@ func (t *Type) _CType(attrib bool) string {
|
||||||
//fmt.Println("nil sent to _CType()")
|
//fmt.Println("nil sent to _CType()")
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if !attrib && t.ctype != "" { // cache
|
//if !attrib && t.ctype != "" { // cache
|
||||||
return t.ctype
|
// return t.ctype
|
||||||
}
|
//}
|
||||||
var ct string
|
var ct string
|
||||||
if attrib {
|
if attrib {
|
||||||
ignore := map[string]bool { "GenericList": true }
|
ignore := map[string]bool { "GenericList": true }
|
||||||
|
@ -296,6 +292,19 @@ func (o *Id) %s() *%s { return (*%s)(unsafe.Pointer(o)) }
|
||||||
`,t.Node.Ctype(),t.BaseType().GoType(),gt,super,gt,gt,gt,gt)
|
`,t.Node.Ctype(),t.BaseType().GoType(),gt,super,gt,gt,gt,gt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Type) IsFunctionPtr() bool {
|
||||||
|
if t == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if td := t.Typedef(); td != nil {
|
||||||
|
return td.IsFunctionPtr()
|
||||||
|
}
|
||||||
|
for pt := t.PointsTo(); pt != nil; pt = pt.PointsTo() {
|
||||||
|
return pt.IsFunction()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Type) IsFunction() bool {
|
func (t *Type) IsFunction() bool {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
fmt.Println("nil sent to IsFunction()")
|
fmt.Println("nil sent to IsFunction()")
|
||||||
|
|
|
@ -81,21 +81,31 @@ digit:
|
||||||
[0-9]
|
[0-9]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import (
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
var TypeName func(s string, n *Node) (string, *Node)
|
var TypeName func(s string, n *Node) (string, *Node)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
instancename := regexp.MustCompile("instancename")
|
||||||
|
instancetype := regexp.MustCompile("instancetype")
|
||||||
|
cacheable := func(s string) bool {
|
||||||
|
return !instancetype.MatchString(s) && !instancename.MatchString(s)
|
||||||
|
}
|
||||||
|
|
||||||
cache := map[string]*Node{}
|
cache := map[string]*Node{}
|
||||||
TypeName = func(s string, n *Node) (string, *Node) {
|
TypeName = func(s string, n *Node) (string, *Node) {
|
||||||
if n2,ok := cache[s]; ok {
|
if n2,ok := cache[s]; ok {
|
||||||
return "",n2
|
return "",n2
|
||||||
}
|
}
|
||||||
s2,n2 := _TypeName(s,n)
|
s2,n2 := _TypeName(s,n)
|
||||||
if s2 == "" {
|
if s2 == "" && cacheable(s) {
|
||||||
cache[s] = n2
|
cache[s] = n2
|
||||||
}
|
}
|
||||||
return s2,n2
|
return s2,n2
|
||||||
}
|
}
|
||||||
TypeName = _TypeName
|
//TypeName = _TypeName
|
||||||
}
|
}
|
||||||
|
|
||||||
func _TypeName(s string, n *Node) (string, *Node) {
|
func _TypeName(s string, n *Node) (string, *Node) {
|
||||||
|
@ -318,10 +328,10 @@ func BareTypedefName(s string, n *Node) (string, *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TypedefName(s string, n *Node) (string, *Node) {
|
func TypedefName(s string, n *Node) (string, *Node) {
|
||||||
return OneOf(
|
return Seq(
|
||||||
Seq(BareTypedefName, AngBracketed(GenericList)),
|
|
||||||
Seq(BareTypedefName, NullableAnnotation),
|
|
||||||
BareTypedefName,
|
BareTypedefName,
|
||||||
|
Opt(AngBracketed(GenericList)),
|
||||||
|
Opt(NullableAnnotation),
|
||||||
)(s,n)
|
)(s,n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ func (n *Node) stripAbstract(k string) *Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ret := NewNode(n.Kind)
|
ret := NewNode(n.Kind)
|
||||||
cs := n.Children[:]
|
cs := append([]*Node{},n.Children...)
|
||||||
|
|
||||||
dbg("stripAbstract(): i = %d\n",i)
|
dbg("stripAbstract(): i = %d\n",i)
|
||||||
//Scan backwords skipping TypeQualifier and NullableAnnotation tags
|
//Scan backwords skipping TypeQualifier and NullableAnnotation tags
|
||||||
|
@ -97,7 +97,10 @@ 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.IsInstancetype() || n.PointsTo() != nil
|
if pt := n.PointsTo(); pt != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return n.IsInstancetype() || n.IsId()
|
||||||
}
|
}
|
||||||
|
|
||||||
//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
|
||||||
|
@ -124,6 +127,9 @@ func (n *Node) IsFunction() bool {
|
||||||
if n == nil || len(n.Children) < 1 {
|
if n == nil || len(n.Children) < 1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if pt := n.PointsTo(); pt != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return n.Children[len(n.Children)-1].Kind == "Function"
|
return n.Children[len(n.Children)-1].Kind == "Function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +146,8 @@ 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" &&
|
return !n.IsFunction() &&
|
||||||
|
n.Children[0].Kind == "TypedefName" &&
|
||||||
n.Children[0].Content == "id"
|
n.Children[0].Content == "id"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
55
wrap/main.go
55
wrap/main.go
|
@ -113,7 +113,7 @@ func (m Method) isVoid() bool {
|
||||||
//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.Type.IsFunction() {
|
if p.Type.IsFunction() || p.Type.IsFunctionPtr() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,7 +521,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
if gt == "NSEnumerator" {
|
if gt == "NSEnumerator" {
|
||||||
w.EnumeratorHelpers()
|
w.EnumeratorHelpers()
|
||||||
}
|
}
|
||||||
if bt.IsFunction() {
|
if bt.IsFunction() || bt.IsFunctionPtr() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
super := types.Super(gt)
|
super := types.Super(gt)
|
||||||
|
@ -535,7 +535,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
||||||
|
|
||||||
func (w *Wrapper) CharHelpers() {
|
func (w *Wrapper) CharHelpers() {
|
||||||
w.goHelpers.WriteString(`
|
w.goHelpers.WriteString(`
|
||||||
func CharFromString(s string) *Char {
|
func CharWithGoString(s string) *Char {
|
||||||
return (*Char)(unsafe.Pointer(C.CString(s)))
|
return (*Char)(unsafe.Pointer(C.CString(s)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +555,8 @@ func (e *NSEnumerator) ForIn(f func(*Id) bool) {
|
||||||
for o := e.NextObject(); o != nil; o = e.NextObject() {
|
for o := e.NextObject(); o != nil; o = e.NextObject() {
|
||||||
if !f(o) { break }
|
if !f(o) { break }
|
||||||
}
|
}
|
||||||
}`)
|
}
|
||||||
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Wrapper) ProcessMethod(m *Method) {
|
func (w *Wrapper) ProcessMethod(m *Method) {
|
||||||
|
@ -570,13 +571,12 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
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.Type.IsFunction() || m.hasFunctionParam() {
|
if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
gname := strings.Title(m.Name)
|
gname := strings.Title(m.Name)
|
||||||
switch {
|
switch {
|
||||||
case !m.ClassMethod:
|
case !m.ClassMethod:
|
||||||
gname = "(o *" + m.GoClass + ") " + gname
|
|
||||||
case m.Type.GoType() != "*" + m.GoClass:
|
case m.Type.GoType() != "*" + m.GoClass:
|
||||||
gname = m.GoClass + gname
|
gname = m.GoClass + gname
|
||||||
default:
|
default:
|
||||||
|
@ -592,6 +592,10 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
gname = m.GoClass + gname[lens1-i:]
|
gname = m.GoClass + gname[lens1-i:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
receiver := ""
|
||||||
|
if !m.ClassMethod {
|
||||||
|
receiver = "(o *" + m.GoClass + ") "
|
||||||
|
}
|
||||||
cname := m.Name
|
cname := m.Name
|
||||||
if m.Class != "" {
|
if m.Class != "" {
|
||||||
cname = m.Class + "_" + cname
|
cname = m.Class + "_" + cname
|
||||||
|
@ -611,8 +615,8 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
||||||
}
|
}
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
//%s
|
//%s
|
||||||
func %s(%s) %s {
|
func %s%s(%s) %s {
|
||||||
`,m.Type.CType(),gname,gplist,grtype))
|
`,m.Type.CType(),receiver,gname,gplist,grtype))
|
||||||
lparm := len(tps)-1
|
lparm := len(tps)-1
|
||||||
if len(tps) > 0 && tps[lparm].Variadic {
|
if len(tps) > 0 && tps[lparm].Variadic {
|
||||||
vn := ns[lparm]
|
vn := ns[lparm]
|
||||||
|
@ -659,7 +663,42 @@ func %s(%s) %s {
|
||||||
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
||||||
}`, cret, cobj, w.objcparamlist(m)))
|
}`, cret, cobj, w.objcparamlist(m)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create GoString helper method
|
||||||
|
if ok,_ := regexp.MatchString("WithString$",m.Name); ok {
|
||||||
|
//fmt.Printf("--%s\n",gname)
|
||||||
|
gname2 := gname[:len(gname)-6] + "GoString"
|
||||||
|
gps := []string{}
|
||||||
|
i := 0
|
||||||
|
if !m.ClassMethod { i = 1 }
|
||||||
|
for ; i < len(ns); i++ {
|
||||||
|
gt := tps[i].GoType()
|
||||||
|
//fmt.Printf(" %s\n",gt)
|
||||||
|
ns2 := ns[i]
|
||||||
|
if gt == "*NSString" {
|
||||||
|
gt = "string"
|
||||||
|
ns[i] = gStringToNsstring(ns[i])
|
||||||
|
}
|
||||||
|
gps = append(gps,ns2 + " " + gt)
|
||||||
|
}
|
||||||
|
gplist = strings.Join(gps,", ")
|
||||||
|
obj := ""
|
||||||
|
if !m.ClassMethod {
|
||||||
|
obj = "o."
|
||||||
|
ns = ns[1:]
|
||||||
|
}
|
||||||
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
|
func %s%s(%s) %s {
|
||||||
|
return %s%s(%s)
|
||||||
}
|
}
|
||||||
|
`,receiver,gname2,gplist,grtype,obj,gname,strings.Join(ns,", ")))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func gStringToNsstring(s string) string {
|
||||||
|
return fmt.Sprintf("NSStringWithUTF8String(CharWithGoString(%s))",s)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func (w *Wrapper) ProcessEnum(e *Enum) {
|
func (w *Wrapper) ProcessEnum(e *Enum) {
|
||||||
gtp := ""
|
gtp := ""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user