Handle Objective-C methods with variadic arguments.
This commit is contained in:
parent
57232548fa
commit
d78e055008
|
@ -298,10 +298,10 @@ func Parse(fullline string) Node {
|
||||||
return parseWeakAttr(line)
|
return parseWeakAttr(line)
|
||||||
case "WhileStmt":
|
case "WhileStmt":
|
||||||
return parseWhileStmt(line)
|
return parseWhileStmt(line)
|
||||||
|
case "...":
|
||||||
|
return parseVariadic(line)
|
||||||
case "NullStmt":
|
case "NullStmt":
|
||||||
return nil
|
return nil
|
||||||
case "...": // FIXME for variadic functions
|
|
||||||
return nil
|
|
||||||
default:
|
default:
|
||||||
return parseUnknown(nodeName,line)
|
return parseUnknown(nodeName,line)
|
||||||
}
|
}
|
||||||
|
|
35
ast/variadic.go
Normal file
35
ast/variadic.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
// Variadic node indicates an ellipsis (...) in the Clang AST.
|
||||||
|
type Variadic struct {
|
||||||
|
ChildNodes []Node
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseVariadic(line string) *Variadic {
|
||||||
|
return &Variadic{
|
||||||
|
ChildNodes: []Node{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChild adds a new child node. Child nodes can then be accessed with the
|
||||||
|
// Children attribute.
|
||||||
|
func (n *Variadic) 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 *Variadic) Address() Address {
|
||||||
|
return Address(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 *Variadic) Children() []Node {
|
||||||
|
return n.ChildNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position returns the position in the original source code.
|
||||||
|
func (n *Variadic) Position() Position {
|
||||||
|
return Position{}
|
||||||
|
}
|
|
@ -11,6 +11,8 @@ func main() {
|
||||||
c1 := n1.CapitalizedString()
|
c1 := n1.CapitalizedString()
|
||||||
gs := c1.UTF8String().String()
|
gs := c1.UTF8String().String()
|
||||||
fmt.Println(gs)
|
fmt.Println(gs)
|
||||||
a := ns.ArrayWithObjects(n1)
|
n2 := ns.StringWithUTF8String(ns.CharFromString("hi world"))
|
||||||
_ = a
|
n3 := ns.StringWithUTF8String(ns.CharFromString("ok bye"))
|
||||||
|
a := ns.ArrayWithObjects(n1,n2,n3)
|
||||||
|
fmt.Println("Length(a) = ",a.Count())
|
||||||
}
|
}
|
||||||
|
|
4
main.go
4
main.go
|
@ -22,6 +22,7 @@ type conf struct {
|
||||||
Imports []string
|
Imports []string
|
||||||
SysImports []string
|
SysImports []string
|
||||||
Pragma []string
|
Pragma []string
|
||||||
|
VaArgs int
|
||||||
}
|
}
|
||||||
|
|
||||||
var Config conf
|
var Config conf
|
||||||
|
@ -171,6 +172,9 @@ func Start() (err error) {
|
||||||
w.Import(Config.Imports)
|
w.Import(Config.Imports)
|
||||||
w.SysImport(Config.SysImports)
|
w.SysImport(Config.SysImports)
|
||||||
w.Pragma(Config.Pragma)
|
w.Pragma(Config.Pragma)
|
||||||
|
if Config.VaArgs == 0 {
|
||||||
|
w.VaArgs = 16
|
||||||
|
}
|
||||||
for _, u := range tree {
|
for _, u := range tree {
|
||||||
for _, n := range(u.Children()) {
|
for _, n := range(u.Children()) {
|
||||||
switch x := n.(type) {
|
switch x := n.(type) {
|
||||||
|
|
|
@ -66,6 +66,7 @@ type Type struct {
|
||||||
Node *Node
|
Node *Node
|
||||||
Class string
|
Class string
|
||||||
ctype string
|
ctype string
|
||||||
|
Variadic bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewType(n *Node, c string) *Type {
|
func NewType(n *Node, c string) *Type {
|
||||||
|
@ -292,12 +293,15 @@ func GoToC(name string, pnames []string, rtype *Type, ptypes []*Type) string {
|
||||||
for i := 0; i < len(pnames); i++ {
|
for i := 0; i < len(pnames); i++ {
|
||||||
pn,pt := pnames[i],ptypes[i]
|
pn,pt := pnames[i],ptypes[i]
|
||||||
p := pn
|
p := pn
|
||||||
if shouldWrap(pt.GoType()) || isGoInterface(pt.GoType()) {
|
if (shouldWrap(pt.GoType()) || isGoInterface(pt.GoType())) && !pt.Variadic {
|
||||||
p = pn + ".Ptr()"
|
p = pn + ".Ptr()"
|
||||||
} else {
|
} else {
|
||||||
if pt.Node.IsPointer() {
|
switch {
|
||||||
|
case pt.Variadic:
|
||||||
|
p = "unsafe.Pointer(&" + p + ")"
|
||||||
|
case pt.Node.IsPointer():
|
||||||
p = "unsafe.Pointer(" + pn + ")"
|
p = "unsafe.Pointer(" + pn + ")"
|
||||||
} else {
|
default:
|
||||||
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
p = "(" + pt.CGoType() + ")(" + pn + ")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
44
wrap/main.go
44
wrap/main.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.wow.st/gmp/nswrap/ast"
|
"gitlab.wow.st/gmp/nswrap/ast"
|
||||||
|
@ -23,6 +24,7 @@ type Wrapper struct {
|
||||||
goCode strings.Builder // put Go code here
|
goCode strings.Builder // put Go code here
|
||||||
goHelpers strings.Builder // put Go helper functions here
|
goHelpers strings.Builder // put Go helper functions here
|
||||||
Processed map[string]bool
|
Processed map[string]bool
|
||||||
|
VaArgs int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWrapper(debug bool) *Wrapper {
|
func NewWrapper(debug bool) *Wrapper {
|
||||||
|
@ -31,6 +33,7 @@ func NewWrapper(debug bool) *Wrapper {
|
||||||
ret := &Wrapper{
|
ret := &Wrapper{
|
||||||
Interfaces: map[string]Interface{},
|
Interfaces: map[string]Interface{},
|
||||||
Processed: map[string]bool{},
|
Processed: map[string]bool{},
|
||||||
|
VaArgs: 16,
|
||||||
}
|
}
|
||||||
ret.cCode.WriteString(`/*
|
ret.cCode.WriteString(`/*
|
||||||
#cgo CFLAGS: -x objective-c
|
#cgo CFLAGS: -x objective-c
|
||||||
|
@ -102,7 +105,7 @@ func (w Wrapper) cparamlist(m Method) string {
|
||||||
}
|
}
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
var tp string
|
var tp string
|
||||||
if p.Type.Node.IsPointer() {
|
if p.Type.Node.IsPointer() || p.Type.Variadic {
|
||||||
tp = "void*"
|
tp = "void*"
|
||||||
} else {
|
} else {
|
||||||
tp = p.Type.CType()
|
tp = p.Type.CType()
|
||||||
|
@ -119,13 +122,22 @@ func (w Wrapper) objcparamlist(m Method) string {
|
||||||
first := true
|
first := true
|
||||||
ret := []string{}
|
ret := []string{}
|
||||||
for _,p := range m.Parameters {
|
for _,p := range m.Parameters {
|
||||||
if first {
|
if first && !p.Type.Variadic {
|
||||||
ret = append(ret,m.Name + ":" + p.Vname)
|
ret = append(ret,m.Name + ":" + p.Vname)
|
||||||
first = false
|
first = false
|
||||||
|
} else {
|
||||||
|
if p.Type.Variadic {
|
||||||
|
str := []string{m.Name + ":arr[0]"}
|
||||||
|
for i := 1; i < w.VaArgs; i++ {
|
||||||
|
str = append(str,"arr["+strconv.Itoa(i)+"]")
|
||||||
|
}
|
||||||
|
str = append(str,"nil")
|
||||||
|
ret = append(ret, strings.Join(str,", "))
|
||||||
} else {
|
} else {
|
||||||
ret = append(ret, p.Pname + ":" + p.Vname)
|
ret = append(ret, p.Pname + ":" + p.Vname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return strings.Join(ret," ")
|
return strings.Join(ret," ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,6 +170,10 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
|
||||||
if gt == "*Void" {
|
if gt == "*Void" {
|
||||||
gt = "unsafe.Pointer"
|
gt = "unsafe.Pointer"
|
||||||
}
|
}
|
||||||
|
if tps[i].Variadic {
|
||||||
|
gt = "..." + gt
|
||||||
|
ns[i] = ns[i] + "s"
|
||||||
|
}
|
||||||
ret = append(ret,ns[i] + " " + gt)
|
ret = append(ret,ns[i] + " " + gt)
|
||||||
}
|
}
|
||||||
return ns, tps, strings.Join(ret,", ")
|
return ns, tps, strings.Join(ret,", ")
|
||||||
|
@ -266,6 +282,8 @@ func (w *Wrapper) GetParms(n *ast.ObjCMethodDecl,class string) ([]Parameter,bool
|
||||||
}
|
}
|
||||||
ret = append(ret,p)
|
ret = append(ret,p)
|
||||||
j++
|
j++
|
||||||
|
case *ast.Variadic:
|
||||||
|
ret[j-1].Type.Variadic = true
|
||||||
case *ast.AvailabilityAttr:
|
case *ast.AvailabilityAttr:
|
||||||
avail = append(avail,
|
avail = append(avail,
|
||||||
AvailAttr{
|
AvailAttr{
|
||||||
|
@ -432,6 +450,18 @@ New%s() {
|
||||||
w.goCode.WriteString(fmt.Sprintf(`
|
w.goCode.WriteString(fmt.Sprintf(`
|
||||||
func %s(%s) %s {
|
func %s(%s) %s {
|
||||||
`,gname,gplist,grtype))
|
`,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(
|
w.goCode.WriteString(
|
||||||
types.GoToC(cname,ns,m.Type,tps) + "}\n\n")
|
types.GoToC(cname,ns,m.Type,tps) + "}\n\n")
|
||||||
|
|
||||||
|
@ -448,8 +478,14 @@ func %s(%s) %s {
|
||||||
w.cCode.WriteString(fmt.Sprintf(`
|
w.cCode.WriteString(fmt.Sprintf(`
|
||||||
%s
|
%s
|
||||||
%s(%s) {
|
%s(%s) {
|
||||||
%s[%s %s];
|
`, cmtype, cname, w.cparamlist(m)))
|
||||||
}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
of.WriteString("package " + w.Package + "\n\n")
|
of.WriteString("package " + w.Package + "\n\n")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user