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)
|
||||
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
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()
|
||||
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())
|
||||
}
|
||||
|
|
4
main.go
4
main.go
|
@ -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) {
|
||||
|
|
|
@ -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 + ")"
|
||||
}
|
||||
}
|
||||
|
|
46
wrap/main.go
46
wrap/main.go
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue
Block a user