mirror of
https://github.com/mappu/miqt.git
synced 2025-01-21 22:20:38 +00:00
genbindings: track all typedefs, apply in a fixup AST pass
This commit is contained in:
parent
85cf3b84d8
commit
0aa312c424
@ -548,7 +548,7 @@ func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseTypeString converts a string like
|
// parseTypeString converts a function/method type string such as
|
||||||
// - `QString (const char *, const char *, int)`
|
// - `QString (const char *, const char *, int)`
|
||||||
// - `void (const QKeySequence \u0026)`
|
// - `void (const QKeySequence \u0026)`
|
||||||
// into its (A) return type and (B) separate parameter types.
|
// into its (A) return type and (B) separate parameter types.
|
||||||
|
@ -7,10 +7,12 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
KnownClassnames map[string]struct{} // Entries of the form QFoo::Bar if it is an inner class
|
KnownClassnames map[string]struct{} // Entries of the form QFoo::Bar if it is an inner class
|
||||||
|
KnownTypedefs map[string]CppTypedef
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
KnownClassnames = make(map[string]struct{})
|
KnownClassnames = make(map[string]struct{})
|
||||||
|
KnownTypedefs = make(map[string]CppTypedef)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CppParameter struct {
|
type CppParameter struct {
|
||||||
@ -23,6 +25,20 @@ type CppParameter struct {
|
|||||||
Optional bool
|
Optional bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *CppParameter) AssignAlias(newType string) {
|
||||||
|
if p.TypeAlias == "" {
|
||||||
|
p.TypeAlias = p.ParameterType // Overwrite once only, at the earliest base type
|
||||||
|
}
|
||||||
|
p.ParameterType = newType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CppParameter) CopyWithAlias(alias CppParameter) CppParameter {
|
||||||
|
ret := *p // copy
|
||||||
|
ret.ParameterName = alias.ParameterName
|
||||||
|
ret.TypeAlias = alias.ParameterType
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func (p *CppParameter) UnderlyingType() string {
|
func (p *CppParameter) UnderlyingType() string {
|
||||||
if p.TypeAlias != "" {
|
if p.TypeAlias != "" {
|
||||||
return p.TypeAlias
|
return p.TypeAlias
|
||||||
@ -221,7 +237,7 @@ type CppClass struct {
|
|||||||
|
|
||||||
type CppTypedef struct {
|
type CppTypedef struct {
|
||||||
Alias string
|
Alias string
|
||||||
UnderlyingType string
|
UnderlyingType CppParameter
|
||||||
}
|
}
|
||||||
|
|
||||||
type CppParsedHeader struct {
|
type CppParsedHeader struct {
|
||||||
|
@ -141,6 +141,10 @@ func main() {
|
|||||||
for _, c := range parsed.Classes {
|
for _, c := range parsed.Classes {
|
||||||
KnownClassnames[c.ClassName] = struct{}{}
|
KnownClassnames[c.ClassName] = struct{}{}
|
||||||
}
|
}
|
||||||
|
for _, td := range parsed.Typedefs {
|
||||||
|
KnownTypedefs[td.Alias] = td // copy
|
||||||
|
}
|
||||||
|
|
||||||
processHeaders = append(processHeaders, parsed)
|
processHeaders = append(processHeaders, parsed)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,6 +155,10 @@ func main() {
|
|||||||
for _, parsed := range processHeaders {
|
for _, parsed := range processHeaders {
|
||||||
|
|
||||||
log.Printf("Processing %q...", parsed.Filename)
|
log.Printf("Processing %q...", parsed.Filename)
|
||||||
|
|
||||||
|
// More AST transforms on our IL
|
||||||
|
astTransformTypedefs(parsed)
|
||||||
|
|
||||||
{
|
{
|
||||||
// Save the IL file for debug inspection
|
// Save the IL file for debug inspection
|
||||||
jb, err := json.MarshalIndent(parsed, "", "\t")
|
jb, err := json.MarshalIndent(parsed, "", "\t")
|
||||||
|
@ -23,9 +23,14 @@ func takeChildren(c *CppClass) []CppClass {
|
|||||||
func astTransformChildClasses(parsed *CppParsedHeader) {
|
func astTransformChildClasses(parsed *CppParsedHeader) {
|
||||||
var taken []CppClass
|
var taken []CppClass
|
||||||
|
|
||||||
for i, _ := range parsed.Classes {
|
for i, c := range parsed.Classes {
|
||||||
taken = append(taken, takeChildren(&parsed.Classes[i])...)
|
taken = append(taken, takeChildren(&parsed.Classes[i])...)
|
||||||
|
|
||||||
|
// Also lift all child typedefs and enums
|
||||||
|
parsed.Typedefs = append(parsed.Typedefs, c.ChildTypedefs...)
|
||||||
|
parsed.Enums = append(parsed.Enums, c.ChildEnums...)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsed.Classes = append(parsed.Classes, taken...)
|
parsed.Classes = append(parsed.Classes, taken...)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
55
cmd/genbindings/transformtypedefs.go
Normal file
55
cmd/genbindings/transformtypedefs.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
func typedefUnderlyingOrInt(td CppTypedef) string {
|
||||||
|
if strings.HasPrefix(td.UnderlyingType.ParameterType, "QFlag<") {
|
||||||
|
return "int"
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasPrefix(td.UnderlyingType.ParameterType, "signed ") {
|
||||||
|
return td.UnderlyingType.ParameterType[7:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(td.UnderlyingType.ParameterType, "(*)") {
|
||||||
|
return "uintptr" // Function pointer, nonrepresentible
|
||||||
|
}
|
||||||
|
|
||||||
|
return td.UnderlyingType.ParameterType
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// astTransformTypedefs replaces the ParameterType with any known typedef value.
|
||||||
|
func astTransformTypedefs(parsed *CppParsedHeader) {
|
||||||
|
|
||||||
|
for i, c := range parsed.Classes {
|
||||||
|
|
||||||
|
for j, m := range c.Methods {
|
||||||
|
|
||||||
|
for k, p := range m.Parameters {
|
||||||
|
if td, ok := KnownTypedefs[p.ParameterType]; ok {
|
||||||
|
p = td.UnderlyingType.CopyWithAlias(p)
|
||||||
|
}
|
||||||
|
m.Parameters[k] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
if td, ok := KnownTypedefs[m.ReturnType.ParameterType]; ok {
|
||||||
|
m.ReturnType = td.UnderlyingType.CopyWithAlias(m.ReturnType)
|
||||||
|
//m.ReturnType.AssignAlias(typedefUnderlyingOrInt(td))
|
||||||
|
}
|
||||||
|
c.Methods[j] = m
|
||||||
|
}
|
||||||
|
|
||||||
|
for j, m := range c.Ctors {
|
||||||
|
|
||||||
|
for k, p := range m.Parameters {
|
||||||
|
if td, ok := KnownTypedefs[p.ParameterType]; ok {
|
||||||
|
p = td.UnderlyingType.CopyWithAlias(p) // .AssignAlias(typedefUnderlyingOrInt(td))
|
||||||
|
}
|
||||||
|
m.Parameters[k] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Ctors[j] = m
|
||||||
|
}
|
||||||
|
parsed.Classes[i] = c
|
||||||
|
}
|
||||||
|
}
|
45
cmd/genbindings/transformtypedefs_test.go
Normal file
45
cmd/genbindings/transformtypedefs_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTransformTypedefs(t *testing.T) {
|
||||||
|
// Test that the static typedefs are applied
|
||||||
|
|
||||||
|
makeTest := func(typeName string) CppParsedHeader {
|
||||||
|
return CppParsedHeader{
|
||||||
|
Classes: []CppClass{
|
||||||
|
|
||||||
|
CppClass{
|
||||||
|
ClassName: "QTestClass",
|
||||||
|
Ctors: []CppMethod{
|
||||||
|
|
||||||
|
CppMethod{
|
||||||
|
Parameters: []CppParameter{
|
||||||
|
CppParameter{
|
||||||
|
ParameterName: "foo",
|
||||||
|
ParameterType: typeName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
IsStatic: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// t.Logf("Existing typedefs: %#v\n", KnownTypedefs)
|
||||||
|
|
||||||
|
parsed := makeTest("WId")
|
||||||
|
|
||||||
|
astTransformTypedefs(&parsed)
|
||||||
|
|
||||||
|
got := parsed.Classes[0].Ctors[0].Parameters[0].ParameterType
|
||||||
|
expect := "uintptr_t"
|
||||||
|
if got != expect {
|
||||||
|
t.Errorf("Transform of WId got %q, expected %q", got, expect)
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user