mirror of
https://github.com/mappu/miqt.git
synced 2024-12-23 01:18:37 +00:00
genbindings: basic constructor support
This commit is contained in:
parent
545a819f81
commit
aaa9340808
@ -98,10 +98,26 @@ nextMethod:
|
|||||||
// Safe to ignore
|
// Safe to ignore
|
||||||
|
|
||||||
case "CXXConstructorDecl":
|
case "CXXConstructorDecl":
|
||||||
// panic("TODO")
|
|
||||||
|
|
||||||
|
var mm CppMethod
|
||||||
|
err := parseMethod(node, &mm)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, ErrTooComplex) {
|
||||||
|
log.Printf("Skipping method %q with complex type", mm.MethodName)
|
||||||
|
continue nextMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
// Real error
|
||||||
|
return CppClass{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ret.Ctors = append(ret.Ctors, mm)
|
||||||
|
|
||||||
case "CXXDestructorDecl":
|
case "CXXDestructorDecl":
|
||||||
// panic("TODO")
|
// We don't need to expose destructors in the binding beyond offering
|
||||||
|
// a regular delete function
|
||||||
|
|
||||||
case "CXXMethodDecl":
|
case "CXXMethodDecl":
|
||||||
if !visibility {
|
if !visibility {
|
||||||
@ -121,72 +137,15 @@ nextMethod:
|
|||||||
mm.MethodName = methodName[3:]
|
mm.MethodName = methodName[3:]
|
||||||
}
|
}
|
||||||
|
|
||||||
if typobj, ok := node["type"].(map[string]interface{}); ok {
|
err := parseMethod(node, &mm)
|
||||||
if qualType, ok := typobj["qualType"].(string); ok {
|
if err != nil {
|
||||||
// The qualType is the whole type of the method, including its parameter types
|
if errors.Is(err, ErrTooComplex) {
|
||||||
// If anything here is too complicated, skip the whole method
|
log.Printf("Skipping method %q with complex type", mm.MethodName)
|
||||||
|
continue nextMethod
|
||||||
var err error = nil
|
|
||||||
mm.ReturnType, mm.Parameters, err = parseTypeString(qualType)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, ErrTooComplex) {
|
|
||||||
log.Printf("Skipping method %q with complex type %q", mm.MethodName, qualType)
|
|
||||||
continue nextMethod
|
|
||||||
}
|
|
||||||
// Real error
|
|
||||||
return CppClass{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if methodInner, ok := node["inner"].([]interface{}); ok {
|
// Real error
|
||||||
paramCounter := 0
|
return CppClass{}, err
|
||||||
for _, methodObj := range methodInner {
|
|
||||||
methodObj, ok := methodObj.(map[string]interface{})
|
|
||||||
if !ok {
|
|
||||||
return CppClass{}, errors.New("inner[] element not an object")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch methodObj["kind"] {
|
|
||||||
case "ParmVarDecl":
|
|
||||||
// Parameter variable
|
|
||||||
parmName, _ := methodObj["name"].(string) // n.b. may be unnamed
|
|
||||||
if parmName == "" {
|
|
||||||
|
|
||||||
// Generate a default parameter name
|
|
||||||
// Super nice autogen names if this is a Q_PROPERTY setter:
|
|
||||||
if len(mm.Parameters) == 1 && strings.HasPrefix(mm.MethodName, "set") {
|
|
||||||
parmName = strings.ToLower(string(mm.MethodName[3])) + mm.MethodName[4:]
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Otherwise - default
|
|
||||||
parmName = fmt.Sprintf("param%d", paramCounter+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block reserved Go words, replace with generic parameters
|
|
||||||
if parmName == "default" || parmName == "const" || parmName == "func" {
|
|
||||||
parmName += "Val"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the name for the existing nth parameter
|
|
||||||
mm.Parameters[paramCounter].ParameterName = parmName
|
|
||||||
|
|
||||||
// If this parameter has any internal AST nodes of its
|
|
||||||
// own, assume it means it's an optional parameter
|
|
||||||
if _, ok := methodObj["inner"]; ok {
|
|
||||||
mm.Parameters[paramCounter].Optional = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next
|
|
||||||
paramCounter++
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Something else inside a declaration??
|
|
||||||
fmt.Printf("==> NOT IMPLEMENTED CXXMethodDecl->%q\n", kind)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Methods = append(ret.Methods, mm)
|
ret.Methods = append(ret.Methods, mm)
|
||||||
@ -201,6 +160,74 @@ nextMethod:
|
|||||||
|
|
||||||
var ErrTooComplex error = errors.New("Type declaration is too complex to parse")
|
var ErrTooComplex error = errors.New("Type declaration is too complex to parse")
|
||||||
|
|
||||||
|
func parseMethod(node map[string]interface{}, mm *CppMethod) error {
|
||||||
|
|
||||||
|
if typobj, ok := node["type"].(map[string]interface{}); ok {
|
||||||
|
if qualType, ok := typobj["qualType"].(string); ok {
|
||||||
|
// The qualType is the whole type of the method, including its parameter types
|
||||||
|
// If anything here is too complicated, skip the whole method
|
||||||
|
|
||||||
|
var err error = nil
|
||||||
|
mm.ReturnType, mm.Parameters, err = parseTypeString(qualType)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if methodInner, ok := node["inner"].([]interface{}); ok {
|
||||||
|
paramCounter := 0
|
||||||
|
for _, methodObj := range methodInner {
|
||||||
|
methodObj, ok := methodObj.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return errors.New("inner[] element not an object")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch methodObj["kind"] {
|
||||||
|
case "ParmVarDecl":
|
||||||
|
// Parameter variable
|
||||||
|
parmName, _ := methodObj["name"].(string) // n.b. may be unnamed
|
||||||
|
if parmName == "" {
|
||||||
|
|
||||||
|
// Generate a default parameter name
|
||||||
|
// Super nice autogen names if this is a Q_PROPERTY setter:
|
||||||
|
if len(mm.Parameters) == 1 && strings.HasPrefix(mm.MethodName, "set") {
|
||||||
|
parmName = strings.ToLower(string(mm.MethodName[3])) + mm.MethodName[4:]
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Otherwise - default
|
||||||
|
parmName = fmt.Sprintf("param%d", paramCounter+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block reserved Go words, replace with generic parameters
|
||||||
|
if parmName == "default" || parmName == "const" || parmName == "func" {
|
||||||
|
parmName += "Val"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the name for the existing nth parameter
|
||||||
|
mm.Parameters[paramCounter].ParameterName = parmName
|
||||||
|
|
||||||
|
// If this parameter has any internal AST nodes of its
|
||||||
|
// own, assume it means it's an optional parameter
|
||||||
|
if _, ok := methodObj["inner"]; ok {
|
||||||
|
mm.Parameters[paramCounter].Optional = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next
|
||||||
|
paramCounter++
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Something else inside a declaration??
|
||||||
|
fmt.Printf("==> NOT IMPLEMENTED CXXMethodDecl->%q\n", methodObj["kind"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// parseTypeString converts a string like
|
// parseTypeString converts a string like
|
||||||
// - `QString (const char *, const char *, int)`
|
// - `QString (const char *, const char *, int)`
|
||||||
// - `void (const QKeySequence \u0026)`
|
// - `void (const QKeySequence \u0026)`
|
||||||
|
@ -68,10 +68,6 @@ func emitParametersCabi(m CppMethod, selfType string) string {
|
|||||||
// Go: converted to native Go string
|
// Go: converted to native Go string
|
||||||
if m.ReturnType.ParameterType == "QString" {
|
if m.ReturnType.ParameterType == "QString" {
|
||||||
tmp = append(tmp, "char** _out, size_t* _out_Strlen")
|
tmp = append(tmp, "char** _out, size_t* _out_Strlen")
|
||||||
/*
|
|
||||||
} else if m.ReturnType.QtClassType() && !m.ReturnType.Pointer {
|
|
||||||
tmp = append(tmp, "P"+m.ReturnType.ParameterType+" _out")
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(tmp, ", ")
|
return strings.Join(tmp, ", ")
|
||||||
@ -167,7 +163,7 @@ extern "C" {
|
|||||||
for _, c := range src.Classes {
|
for _, c := range src.Classes {
|
||||||
|
|
||||||
for i, ctor := range c.Ctors {
|
for i, ctor := range c.Ctors {
|
||||||
ret.WriteString(fmt.Sprintf("P%s %s_new%s(%s);\n", c.ClassName, maybeSuffix(i), emitParametersCabi(ctor, "")))
|
ret.WriteString(fmt.Sprintf("P%s %s_new%s(%s);\n", c.ClassName, c.ClassName, maybeSuffix(i), emitParametersCabi(ctor, "")))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range c.Methods {
|
for _, m := range c.Methods {
|
||||||
@ -208,7 +204,7 @@ func emitBindingCpp(src *CppParsedHeader, filename string) (string, error) {
|
|||||||
"\treturn new %s(%s);\n"+
|
"\treturn new %s(%s);\n"+
|
||||||
"}\n"+
|
"}\n"+
|
||||||
"\n",
|
"\n",
|
||||||
c.ClassName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
c.ClassName, c.ClassName, maybeSuffix(i), emitParametersCabi(ctor, ""),
|
||||||
preamble,
|
preamble,
|
||||||
c.ClassName, forwarding,
|
c.ClassName, forwarding,
|
||||||
))
|
))
|
||||||
|
Loading…
Reference in New Issue
Block a user