From 5af3cc6dfececeb97f0ca49ce09e49c0cf9febc6 Mon Sep 17 00:00:00 2001 From: mappu Date: Fri, 11 Apr 2025 22:32:22 +1200 Subject: [PATCH] genbindings: remember precise QList/QMap container types --- cmd/genbindings/config-allowlist.go | 4 ++-- cmd/genbindings/emitcabi.go | 26 +++++++++++++------------- cmd/genbindings/emitgo.go | 16 ++++++++-------- cmd/genbindings/intermediate.go | 16 ++++++++-------- cmd/genbindings/transformtypedefs.go | 18 ++++-------------- 5 files changed, 35 insertions(+), 45 deletions(-) diff --git a/cmd/genbindings/config-allowlist.go b/cmd/genbindings/config-allowlist.go index 0f5a62c1..ac5d2ff7 100644 --- a/cmd/genbindings/config-allowlist.go +++ b/cmd/genbindings/config-allowlist.go @@ -413,7 +413,7 @@ func AllowType(p CppParameter, isReturnType bool) error { return err } } - if t, ok := p.QListOf(); ok { + if t, _, ok := p.QListOf(); ok { if err := AllowType(t, isReturnType); err != nil { // e.g. QGradientStops is a QVector<> (OK) of QGradientStop (not OK) return err } @@ -424,7 +424,7 @@ func AllowType(p CppParameter, isReturnType bool) error { return ErrTooComplex } } - if kType, vType, ok := p.QMapOf(); ok { + if kType, vType, _, ok := p.QMapOf(); ok { if err := AllowType(kType, isReturnType); err != nil { return err } diff --git a/cmd/genbindings/emitcabi.go b/cmd/genbindings/emitcabi.go index 98b1921e..e7714aa8 100644 --- a/cmd/genbindings/emitcabi.go +++ b/cmd/genbindings/emitcabi.go @@ -82,13 +82,13 @@ func (p CppParameter) RenderTypeCabi() string { } else if p.ParameterType == "QByteArray" { return "struct miqt_string" - } else if inner, ok := p.QListOf(); ok { + } else if inner, _, ok := p.QListOf(); ok { return "struct miqt_array " + cppComment("of "+inner.RenderTypeCabi()) } else if inner, ok := p.QSetOf(); ok { return "struct miqt_array " + cppComment("set of "+inner.RenderTypeCabi()) - } else if inner1, inner2, ok := p.QMapOf(); ok { + } else if inner1, inner2, _, ok := p.QMapOf(); ok { return "struct miqt_map " + cppComment("of "+inner1.RenderTypeCabi()+" to "+inner2.RenderTypeCabi()) } else if inner1, inner2, ok := p.QPairOf(); ok { @@ -274,7 +274,7 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for preamble += indent + "QByteArray " + nameprefix + "_QByteArray(" + p.cParameterName() + ".data, " + p.cParameterName() + ".len);\n" return preamble, nameprefix + "_QByteArray" - } else if listType, ok := p.QListOf(); ok { + } else if listType, _, ok := p.QListOf(); ok { preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QList;\n" preamble += indent + nameprefix + "_QList.reserve(" + p.cParameterName() + ".len);\n" @@ -296,12 +296,12 @@ func emitCABI2CppForwarding(p CppParameter, indent string) (preamble string, for return preamble, nameprefix + "_QList" } - } else if kType, vType, ok := p.QMapOf(); ok { + } else if kType, vType, mapContainerType, ok := p.QMapOf(); ok { preamble += indent + p.GetQtCppType().ParameterType + " " + nameprefix + "_QMap;\n" // This container may be a QMap or a QHash // QHash supports .reserve(), but QMap doesn't - if strings.HasPrefix(p.ParameterType, "QHash<") { + if mapContainerType == "QHash" { preamble += indent + nameprefix + "_QMap.reserve(" + p.cParameterName() + ".len);\n" } @@ -461,7 +461,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string) afterCall += indent + assignExpression + namePrefix + "_ms;\n" return indent + shouldReturn + rvalue + ";\n" + afterCall - } else if t, ok := p.QListOf(); ok { + } else if t, _, ok := p.QListOf(); ok { // In some cases rvalue is a function call and the temporary // is necessary; in some cases it's a literal and the temporary is @@ -503,7 +503,7 @@ func emitAssignCppToCabi(assignExpression string, p CppParameter, rvalue string) afterCall += indent + assignExpression + "" + namePrefix + "_out;\n" return indent + shouldReturn + rvalue + ";\n" + afterCall - } else if kType, vType, ok := p.QMapOf(); ok { + } else if kType, vType, _, ok := p.QMapOf(); ok { // QMap shouldReturn = p.RenderTypeQtCpp() + " " + namePrefix + "_ret = " @@ -635,13 +635,13 @@ func getCabiZeroValue(p CppParameter) string { } else if p.ParameterType == "QString" || p.ParameterType == "QByteArray" { return "(struct miqt_string){}" - } else if _, ok := p.QListOf(); ok { + } else if _, _, ok := p.QListOf(); ok { return "(struct miqt_array){}" } else if _, ok := p.QSetOf(); ok { return "(struct miqt_array){}" - } else if _, _, ok := p.QMapOf(); ok { + } else if _, _, _, ok := p.QMapOf(); ok { return "(struct miqt_map){}" } else if _, _, ok := p.QPairOf(); ok { @@ -666,12 +666,12 @@ func getReferencedTypes(src *CppParsedHeader) []string { if p.QtClassType() { foundTypes[p.ParameterType] = struct{}{} } - if t, ok := p.QListOf(); ok { - foundTypes["QList"] = struct{}{} // FIXME or QVector? + if t, containerType, ok := p.QListOf(); ok { + foundTypes[containerType] = struct{}{} // QList / QVector maybeAddType(t) } - if kType, vType, ok := p.QMapOf(); ok { - foundTypes["QMap"] = struct{}{} // FIXME or QHash? + if kType, vType, containerType, ok := p.QMapOf(); ok { + foundTypes[containerType] = struct{}{} // QMap / QHash maybeAddType(kType) maybeAddType(vType) } diff --git a/cmd/genbindings/emitgo.go b/cmd/genbindings/emitgo.go index 57866b35..d69059f9 100644 --- a/cmd/genbindings/emitgo.go +++ b/cmd/genbindings/emitgo.go @@ -50,7 +50,7 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string { return "[]byte" } - if t, ok := p.QListOf(); ok { + if t, _, ok := p.QListOf(); ok { return "[]" + t.RenderTypeGo(gfs) } @@ -58,7 +58,7 @@ func (p CppParameter) RenderTypeGo(gfs *goFileState) string { return "map[" + t.RenderTypeGo(gfs) + "]struct{}" } - if t1, t2, ok := p.QMapOf(); ok { + if t1, t2, _, ok := p.QMapOf(); ok { return "map[" + t1.RenderTypeGo(gfs) + "]" + t2.RenderTypeGo(gfs) } @@ -196,7 +196,7 @@ func (p CppParameter) parameterTypeCgo() string { return "C.struct_miqt_string" } - if _, ok := p.QListOf(); ok { + if _, _, ok := p.QListOf(); ok { return "C.struct_miqt_array" } @@ -204,7 +204,7 @@ func (p CppParameter) parameterTypeCgo() string { return "C.struct_miqt_array" } - if _, _, ok := p.QMapOf(); ok { + if _, _, _, ok := p.QMapOf(); ok { return "C.struct_miqt_map" } @@ -359,7 +359,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble rvalue = nameprefix + "_alias" - } else if listType, ok := p.QListOf(); ok { + } else if listType, _, ok := p.QListOf(); ok { // QList // Go: convert T[] -> t* and len // CABI: create a real QList<> @@ -386,7 +386,7 @@ func (gfs *goFileState) emitParameterGo2CABIForwarding(p CppParameter) (preamble } else if _, ok := p.QSetOf(); ok { panic("QSet<> arguments are not yet implemented") // n.b. doesn't seem to exist in QtCore/QtGui/QtWidgets at all - } else if kType, vType, ok := p.QMapOf(); ok { + } else if kType, vType, _, ok := p.QMapOf(); ok { // QMap gfs.imports["unsafe"] = struct{}{} @@ -532,7 +532,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue afterword += assignExpr + namePrefix + "_ret" return shouldReturn + " " + rvalue + "\n" + afterword - } else if t, ok := rt.QListOf(); ok { + } else if t, _, ok := rt.QListOf(); ok { gfs.imports["unsafe"] = struct{}{} shouldReturn = "var " + namePrefix + "_ma C.struct_miqt_array = " @@ -565,7 +565,7 @@ func (gfs *goFileState) emitCabiToGo(assignExpr string, rt CppParameter, rvalue afterword += assignExpr + " " + namePrefix + "_ret\n" return shouldReturn + " " + rvalue + "\n" + afterword - } else if kType, vType, ok := rt.QMapOf(); ok { + } else if kType, vType, _, ok := rt.QMapOf(); ok { gfs.imports["unsafe"] = struct{}{} shouldReturn = "var " + namePrefix + "_mm C.struct_miqt_map = " diff --git a/cmd/genbindings/intermediate.go b/cmd/genbindings/intermediate.go index 6d8432d0..85073e26 100644 --- a/cmd/genbindings/intermediate.go +++ b/cmd/genbindings/intermediate.go @@ -112,23 +112,23 @@ func (p CppParameter) IsKnownEnum() bool { return ok } -func (p CppParameter) QListOf() (CppParameter, bool) { +func (p CppParameter) QListOf() (CppParameter, string, bool) { if strings.HasPrefix(p.ParameterType, "QList<") && strings.HasSuffix(p.ParameterType, `>`) { ret := parseSingleTypeString(p.ParameterType[6 : len(p.ParameterType)-1]) ret.ParameterName = p.ParameterName + "_lv" - return ret, true + return ret, "QList", true } if strings.HasPrefix(p.ParameterType, "QVector<") && strings.HasSuffix(p.ParameterType, `>`) { ret := parseSingleTypeString(p.ParameterType[8 : len(p.ParameterType)-1]) ret.ParameterName = p.ParameterName + "_vv" - return ret, true + return ret, "QVector", true } - return CppParameter{}, false + return CppParameter{}, "", false } -func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) { +func (p CppParameter) QMapOf() (CppParameter, CppParameter, string, bool) { // n.b. Need to block QMap::const_terator if strings.HasPrefix(p.ParameterType, `QMap<`) && strings.HasSuffix(p.ParameterType, `>`) { @@ -141,7 +141,7 @@ func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) { first.ParameterName = p.ParameterName + "_mapkey" second := parseSingleTypeString(interior[1]) second.ParameterName = p.ParameterName + "_mapval" - return first, second, true + return first, second, "QMap", true } if strings.HasPrefix(p.ParameterType, `QHash<`) && strings.HasSuffix(p.ParameterType, `>`) { @@ -154,10 +154,10 @@ func (p CppParameter) QMapOf() (CppParameter, CppParameter, bool) { first.ParameterName = p.ParameterName + "_hashkey" second := parseSingleTypeString(interior[1]) second.ParameterName = p.ParameterName + "_hashval" - return first, second, true + return first, second, "QHash", true } - return CppParameter{}, CppParameter{}, false + return CppParameter{}, CppParameter{}, "", false } func (p CppParameter) QPairOf() (CppParameter, CppParameter, bool) { diff --git a/cmd/genbindings/transformtypedefs.go b/cmd/genbindings/transformtypedefs.go index 97ecb794..03302295 100644 --- a/cmd/genbindings/transformtypedefs.go +++ b/cmd/genbindings/transformtypedefs.go @@ -1,9 +1,5 @@ package main -import ( - "strings" -) - func applyTypedefs(p CppParameter) CppParameter { for { @@ -14,36 +10,30 @@ func applyTypedefs(p CppParameter) CppParameter { p.ApplyTypedef(td.Typedef.UnderlyingType) } - if t, ok := p.QListOf(); ok { + if t, containerType, ok := p.QListOf(); ok { t2 := applyTypedefs(t) // recursive // Wipe out so that RenderTypeQtCpp() does not see it t2.QtCppOriginalType = nil - // QListOf returns for either QList< or QVector< - // Patch it up to the first < position and last character - bpos := strings.Index(p.ParameterType, `<`) - if p.QtCppOriginalType == nil { tmp := p // copy p.QtCppOriginalType = &tmp } - p.ParameterType = p.ParameterType[0:bpos] + `<` + t2.RenderTypeQtCpp() + `>` + p.ParameterType = containerType + `<` + t2.RenderTypeQtCpp() + `>` - } else if kType, vType, ok := p.QMapOf(); ok { + } else if kType, vType, containerType, ok := p.QMapOf(); ok { kType2 := applyTypedefs(kType) kType2.QtCppOriginalType = nil vType2 := applyTypedefs(vType) vType2.QtCppOriginalType = nil - bpos := strings.Index(p.ParameterType, `<`) - if p.QtCppOriginalType == nil { tmp := p // copy p.QtCppOriginalType = &tmp } - p.ParameterType = p.ParameterType[0:bpos] + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>` + p.ParameterType = containerType + `<` + kType2.RenderTypeQtCpp() + `, ` + vType2.RenderTypeQtCpp() + `>` } else if kType, vType, ok := p.QPairOf(); ok { kType2 := applyTypedefs(kType)