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())
|
||||
time.Sleep(time.Second * 1)
|
||||
fmt.Println("LE capable:",cd.IsLECapableHardware())
|
||||
uuid := ble.CBUUIDWithString(ble.NSStringWithUTF8String(ble.CharFromString("180d")))
|
||||
uuid := ble.CBUUIDWithGoString("180d")
|
||||
cd.ScanFor(uuid)
|
||||
time.Sleep(time.Second * 15)
|
||||
|
||||
select { }
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
n1 := ns.NSStringWithUTF8String(ns.CharFromString("hi there"))
|
||||
n1 := ns.NSStringWithUTF8String(ns.CharWithGoString("hi there"))
|
||||
c1 := n1.CapitalizedString()
|
||||
gs := c1.UTF8String().String()
|
||||
fmt.Println(gs)
|
||||
n2 := ns.NSStringWithUTF8String(ns.CharFromString("hi world"))
|
||||
n3 := ns.NSStringWithUTF8String(ns.CharFromString("ok bye"))
|
||||
n2 := ns.NSStringWithGoString("hi world")
|
||||
n3 := ns.NSStringWithGoString("ok bye")
|
||||
a := ns.NSMutableArrayWithObjects(n1,n2,n3)
|
||||
fmt.Println("Length(a) = ",a.Count())
|
||||
fmt.Println("is n2 in a?",a.ContainsObject(n2))
|
||||
|
|
|
@ -22,6 +22,6 @@ Functions = [
|
|||
Enums = [
|
||||
"CF.*",
|
||||
]
|
||||
SysImports = [ "Foundation/Foundation.h" ]
|
||||
Frameworks = [ "Foundation" ]
|
||||
Pragma = [ 'clang diagnostic ignored "-Wformat-security"' ]
|
||||
VaArgs = 32
|
||||
|
|
|
@ -2,3 +2,4 @@ Package = "ClassOne"
|
|||
InputFiles = [ "ClassOne/simple.h" ]
|
||||
Classes = [ "ClassOne","ClassTwo" ]
|
||||
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.
|
||||
func Start() (err error) {
|
||||
// 1. Compile it first (checking for errors)
|
||||
for _, in := range Config.InputFiles {
|
||||
_, err := os.Stat(in)
|
||||
if err != nil {
|
||||
|
@ -159,10 +158,11 @@ func Start() (err error) {
|
|||
|
||||
// 2. Preprocess NOT DONE
|
||||
|
||||
// 3. Generate JSON from AST
|
||||
// 3. Generate AST
|
||||
cargs := []string{"-xobjective-c", "-Xclang", "-ast-dump",
|
||||
"-fsyntax-only","-fno-color-diagnostics"}
|
||||
cargs = append(cargs,Config.InputFiles...)
|
||||
fmt.Printf("Generating AST\n")
|
||||
astPP, err := exec.Command("clang",cargs...).Output()
|
||||
if err != nil {
|
||||
// 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)
|
||||
|
||||
// Converting to nodes
|
||||
fmt.Printf("Building nodes\n")
|
||||
nodes := convertLinesToNodesParallel(lines)
|
||||
|
||||
// build tree
|
||||
fmt.Printf("Assembling tree\n")
|
||||
tree := buildTree(nodes, 0)
|
||||
w := wrap.NewWrapper(Debug)
|
||||
w.Package = Config.Package
|
||||
|
@ -190,6 +192,7 @@ func Start() (err error) {
|
|||
}
|
||||
w.VaArgs = Config.VaArgs
|
||||
for _, u := range tree {
|
||||
fmt.Printf("--processing translation unit\n")
|
||||
for _, n := range(u.Children()) {
|
||||
switch x := n.(type) {
|
||||
case *ast.ObjCInterfaceDecl:
|
||||
|
|
|
@ -50,7 +50,7 @@ func init() {
|
|||
TypeParameters = make(map[string]map[string]string)
|
||||
typedefs = make(map[string]*Type)
|
||||
|
||||
r_id = regexp.MustCompile("\bid\b")
|
||||
r_id = regexp.MustCompile(`\bid\b`)
|
||||
r_instancename = regexp.MustCompile(`\binstancename\b`)
|
||||
r_instancetype = regexp.MustCompile(`\binstancetype\b`)
|
||||
}
|
||||
|
@ -117,7 +117,6 @@ func NewType(n *Node, c string) *Type {
|
|||
return &Type{
|
||||
Node: n2,
|
||||
Class: c,
|
||||
//ctype: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,19 +124,16 @@ func NewTypeFromString(t,c string) *Type {
|
|||
//fmt.Printf("t/c: %s/%s\n",t,c)
|
||||
n,err := Parse(t)
|
||||
//fmt.Printf("%p %s",n,n.String())
|
||||
if n.IsId() {
|
||||
n,err = Parse("NSObject*")
|
||||
}
|
||||
if err != nil {
|
||||
return &Type{}
|
||||
}
|
||||
if n2,ok := clean(n, c); ok {
|
||||
//found type parameters, re-parse
|
||||
return NewTypeFromString(n2.Ctype(),c)
|
||||
}
|
||||
return &Type{
|
||||
Node: n,
|
||||
Class: c,
|
||||
//ctype: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,9 +215,9 @@ func (t *Type) _CType(attrib bool) string {
|
|||
//fmt.Println("nil sent to _CType()")
|
||||
return ""
|
||||
}
|
||||
if !attrib && t.ctype != "" { // cache
|
||||
return t.ctype
|
||||
}
|
||||
//if !attrib && t.ctype != "" { // cache
|
||||
// return t.ctype
|
||||
//}
|
||||
var ct string
|
||||
if attrib {
|
||||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
if t == nil {
|
||||
fmt.Println("nil sent to IsFunction()")
|
||||
|
|
|
@ -81,21 +81,31 @@ digit:
|
|||
[0-9]
|
||||
*/
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var TypeName func(s string, n *Node) (string, *Node)
|
||||
|
||||
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{}
|
||||
TypeName = func(s string, n *Node) (string, *Node) {
|
||||
if n2,ok := cache[s]; ok {
|
||||
return "",n2
|
||||
}
|
||||
s2,n2 := _TypeName(s,n)
|
||||
if s2 == "" {
|
||||
if s2 == "" && cacheable(s) {
|
||||
cache[s] = n2
|
||||
}
|
||||
return s2,n2
|
||||
}
|
||||
TypeName = _TypeName
|
||||
//TypeName = _TypeName
|
||||
}
|
||||
|
||||
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) {
|
||||
return OneOf(
|
||||
Seq(BareTypedefName, AngBracketed(GenericList)),
|
||||
Seq(BareTypedefName, NullableAnnotation),
|
||||
return Seq(
|
||||
BareTypedefName,
|
||||
Opt(AngBracketed(GenericList)),
|
||||
Opt(NullableAnnotation),
|
||||
)(s,n)
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ func (n *Node) stripAbstract(k string) *Node {
|
|||
return nil
|
||||
}
|
||||
ret := NewNode(n.Kind)
|
||||
cs := n.Children[:]
|
||||
cs := append([]*Node{},n.Children...)
|
||||
|
||||
dbg("stripAbstract(): i = %d\n",i)
|
||||
//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
|
||||
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
|
||||
|
@ -124,6 +127,9 @@ func (n *Node) IsFunction() bool {
|
|||
if n == nil || len(n.Children) < 1 {
|
||||
return false
|
||||
}
|
||||
if pt := n.PointsTo(); pt != nil {
|
||||
return false
|
||||
}
|
||||
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 {
|
||||
return false
|
||||
}
|
||||
return n.Children[0].Kind == "TypedefName" &&
|
||||
return !n.IsFunction() &&
|
||||
n.Children[0].Kind == "TypedefName" &&
|
||||
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.
|
||||
func (m Method) hasFunctionParam() bool {
|
||||
for _,p := range m.Parameters {
|
||||
if p.Type.IsFunction() {
|
||||
if p.Type.IsFunction() || p.Type.IsFunctionPtr() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
|||
if gt == "NSEnumerator" {
|
||||
w.EnumeratorHelpers()
|
||||
}
|
||||
if bt.IsFunction() {
|
||||
if bt.IsFunction() || bt.IsFunctionPtr() {
|
||||
return
|
||||
}
|
||||
super := types.Super(gt)
|
||||
|
@ -535,7 +535,7 @@ func (w *Wrapper) processType(tp *types.Type) {
|
|||
|
||||
func (w *Wrapper) CharHelpers() {
|
||||
w.goHelpers.WriteString(`
|
||||
func CharFromString(s string) *Char {
|
||||
func CharWithGoString(s string) *Char {
|
||||
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() {
|
||||
if !f(o) { break }
|
||||
}
|
||||
}`)
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
func (w *Wrapper) ProcessMethod(m *Method) {
|
||||
|
@ -570,13 +571,12 @@ 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() {
|
||||
if m.Type.IsFunction() || m.Type.IsFunctionPtr() || m.hasFunctionParam() {
|
||||
return
|
||||
}
|
||||
gname := strings.Title(m.Name)
|
||||
switch {
|
||||
case !m.ClassMethod:
|
||||
gname = "(o *" + m.GoClass + ") " + gname
|
||||
case m.Type.GoType() != "*" + m.GoClass:
|
||||
gname = m.GoClass + gname
|
||||
default:
|
||||
|
@ -592,6 +592,10 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
|||
gname = m.GoClass + gname[lens1-i:]
|
||||
}
|
||||
}
|
||||
receiver := ""
|
||||
if !m.ClassMethod {
|
||||
receiver = "(o *" + m.GoClass + ") "
|
||||
}
|
||||
cname := m.Name
|
||||
if m.Class != "" {
|
||||
cname = m.Class + "_" + cname
|
||||
|
@ -611,8 +615,8 @@ func (w *Wrapper) _processMethod(m *Method,fun bool) {
|
|||
}
|
||||
w.goCode.WriteString(fmt.Sprintf(`
|
||||
//%s
|
||||
func %s(%s) %s {
|
||||
`,m.Type.CType(),gname,gplist,grtype))
|
||||
func %s%s(%s) %s {
|
||||
`,m.Type.CType(),receiver,gname,gplist,grtype))
|
||||
lparm := len(tps)-1
|
||||
if len(tps) > 0 && tps[lparm].Variadic {
|
||||
vn := ns[lparm]
|
||||
|
@ -659,7 +663,42 @@ func %s(%s) %s {
|
|||
w.cCode.WriteString(fmt.Sprintf(` %s[%s %s];
|
||||
}`, 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) {
|
||||
gtp := ""
|
||||
|
|
Loading…
Reference in New Issue
Block a user