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
|
||||
}
|
||||
|
||||
// parseTypeString converts a string like
|
||||
// parseTypeString converts a function/method type string such as
|
||||
// - `QString (const char *, const char *, int)`
|
||||
// - `void (const QKeySequence \u0026)`
|
||||
// into its (A) return type and (B) separate parameter types.
|
||||
|
@ -7,10 +7,12 @@ import (
|
||||
|
||||
var (
|
||||
KnownClassnames map[string]struct{} // Entries of the form QFoo::Bar if it is an inner class
|
||||
KnownTypedefs map[string]CppTypedef
|
||||
)
|
||||
|
||||
func init() {
|
||||
KnownClassnames = make(map[string]struct{})
|
||||
KnownTypedefs = make(map[string]CppTypedef)
|
||||
}
|
||||
|
||||
type CppParameter struct {
|
||||
@ -23,6 +25,20 @@ type CppParameter struct {
|
||||
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 {
|
||||
if p.TypeAlias != "" {
|
||||
return p.TypeAlias
|
||||
@ -221,7 +237,7 @@ type CppClass struct {
|
||||
|
||||
type CppTypedef struct {
|
||||
Alias string
|
||||
UnderlyingType string
|
||||
UnderlyingType CppParameter
|
||||
}
|
||||
|
||||
type CppParsedHeader struct {
|
||||
|
@ -141,6 +141,10 @@ func main() {
|
||||
for _, c := range parsed.Classes {
|
||||
KnownClassnames[c.ClassName] = struct{}{}
|
||||
}
|
||||
for _, td := range parsed.Typedefs {
|
||||
KnownTypedefs[td.Alias] = td // copy
|
||||
}
|
||||
|
||||
processHeaders = append(processHeaders, parsed)
|
||||
}
|
||||
|
||||
@ -151,6 +155,10 @@ func main() {
|
||||
for _, parsed := range processHeaders {
|
||||
|
||||
log.Printf("Processing %q...", parsed.Filename)
|
||||
|
||||
// More AST transforms on our IL
|
||||
astTransformTypedefs(parsed)
|
||||
|
||||
{
|
||||
// Save the IL file for debug inspection
|
||||
jb, err := json.MarshalIndent(parsed, "", "\t")
|
||||
|
@ -23,9 +23,14 @@ func takeChildren(c *CppClass) []CppClass {
|
||||
func astTransformChildClasses(parsed *CppParsedHeader) {
|
||||
var taken []CppClass
|
||||
|
||||
for i, _ := range parsed.Classes {
|
||||
for i, c := range parsed.Classes {
|
||||
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...)
|
||||
|
||||
}
|
||||
|
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