Handle Objective-C methods with variadic arguments.

This commit is contained in:
Greg 2019-04-29 16:14:45 -04:00
parent 57232548fa
commit d78e055008
6 changed files with 93 additions and 12 deletions

View File

@ -298,10 +298,10 @@ func Parse(fullline string) Node {
return parseWeakAttr(line)
case "WhileStmt":
return parseWhileStmt(line)
case "...":
return parseVariadic(line)
case "NullStmt":
return nil
case "...": // FIXME for variadic functions
return nil
default:
return parseUnknown(nodeName,line)
}

35
ast/variadic.go Normal file
View 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{}
}

View File

@ -11,6 +11,8 @@ func main() {
c1 := n1.CapitalizedString()
gs := c1.UTF8String().String()
fmt.Println(gs)
a := ns.ArrayWithObjects(n1)
_ = a
n2 := ns.StringWithUTF8String(ns.CharFromString("hi world"))
n3 := ns.StringWithUTF8String(ns.CharFromString("ok bye"))
a := ns.ArrayWithObjects(n1,n2,n3)
fmt.Println("Length(a) = ",a.Count())
}

View File

@ -22,6 +22,7 @@ type conf struct {
Imports []string
SysImports []string
Pragma []string
VaArgs int
}
var Config conf
@ -171,6 +172,9 @@ func Start() (err error) {
w.Import(Config.Imports)
w.SysImport(Config.SysImports)
w.Pragma(Config.Pragma)
if Config.VaArgs == 0 {
w.VaArgs = 16
}
for _, u := range tree {
for _, n := range(u.Children()) {
switch x := n.(type) {

View File

@ -66,6 +66,7 @@ type Type struct {
Node *Node
Class string
ctype string
Variadic bool
}
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++ {
pn,pt := pnames[i],ptypes[i]
p := pn
if shouldWrap(pt.GoType()) || isGoInterface(pt.GoType()) {
if (shouldWrap(pt.GoType()) || isGoInterface(pt.GoType())) && !pt.Variadic {
p = pn + ".Ptr()"
} else {
if pt.Node.IsPointer() {
switch {
case pt.Variadic:
p = "unsafe.Pointer(&" + p + ")"
case pt.Node.IsPointer():
p = "unsafe.Pointer(" + pn + ")"
} else {
default:
p = "(" + pt.CGoType() + ")(" + pn + ")"
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path"
"strconv"
"strings"
"gitlab.wow.st/gmp/nswrap/ast"
@ -23,6 +24,7 @@ type Wrapper struct {
goCode strings.Builder // put Go code here
goHelpers strings.Builder // put Go helper functions here
Processed map[string]bool
VaArgs int
}
func NewWrapper(debug bool) *Wrapper {
@ -31,6 +33,7 @@ func NewWrapper(debug bool) *Wrapper {
ret := &Wrapper{
Interfaces: map[string]Interface{},
Processed: map[string]bool{},
VaArgs: 16,
}
ret.cCode.WriteString(`/*
#cgo CFLAGS: -x objective-c
@ -102,7 +105,7 @@ func (w Wrapper) cparamlist(m Method) string {
}
for _,p := range m.Parameters {
var tp string
if p.Type.Node.IsPointer() {
if p.Type.Node.IsPointer() || p.Type.Variadic {
tp = "void*"
} else {
tp = p.Type.CType()
@ -119,11 +122,20 @@ func (w Wrapper) objcparamlist(m Method) string {
first := true
ret := []string{}
for _,p := range m.Parameters {
if first {
if first && !p.Type.Variadic {
ret = append(ret,m.Name + ":" + p.Vname)
first = false
} else {
ret = append(ret, p.Pname + ":" + p.Vname)
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 {
ret = append(ret, p.Pname + ":" + p.Vname)
}
}
}
return strings.Join(ret," ")
@ -158,6 +170,10 @@ func (m *Method) gpntp() ([]string,[]*types.Type,string) {
if gt == "*Void" {
gt = "unsafe.Pointer"
}
if tps[i].Variadic {
gt = "..." + gt
ns[i] = ns[i] + "s"
}
ret = append(ret,ns[i] + " " + gt)
}
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)
j++
case *ast.Variadic:
ret[j-1].Type.Variadic = true
case *ast.AvailabilityAttr:
avail = append(avail,
AvailAttr{
@ -432,6 +450,18 @@ New%s() {
w.goCode.WriteString(fmt.Sprintf(`
func %s(%s) %s {
`,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(
types.GoToC(cname,ns,m.Type,tps) + "}\n\n")
@ -448,8 +478,14 @@ func %s(%s) %s {
w.cCode.WriteString(fmt.Sprintf(`
%s
%s(%s) {
%s[%s %s];
}`, cmtype, cname, w.cparamlist(m), cret, cobj, w.objcparamlist(m)))
`, cmtype, cname, w.cparamlist(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")