Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codegen refactor and cleanup #391

Merged
merged 7 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions cmd/codegen/arguments_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,18 @@ func getArgWrapper(
pureType = TrimSuffix(pureType, "*")
isPointer = true
}

_, isRefTypedef := context.refTypedefs[pureType]
_, isEnum := context.enumNames[pureType]
_, isRefEnum := context.refEnumNames[pureType]

if goEnumName := pureType; IsEnum(goEnumName, context.enumNames) {
if isEnum || isRefEnum {
srcPkg := context.flags.packageName
if isRefTypedef {
srcPkg = context.flags.refPackageName
}

goType := prefixGoPackage(goEnumName.renameGoIdentifier(context), GoIdentifier(srcPkg), context)
goType := prefixGoPackage(pureType.renameGoIdentifier(context), GoIdentifier(srcPkg), context)

if isPointer {
argDeclaration = fmt.Sprintf("%s *%s", a.Name, goType)
Expand Down Expand Up @@ -298,7 +301,7 @@ for i, %[1]sV := range %[1]sArg {
}

_, shouldSkipRefTypedef := context.preset.SkipTypedefs[pureType]
if context.structNames[pureType] || context.typedefsNames[pureType] || (isRefTypedef && !shouldSkipRefTypedef) {
if context.typedefsNames[pureType] || (isRefTypedef && !shouldSkipRefTypedef) {
srcPkg := context.flags.packageName
if isRefTypedef {
srcPkg = context.flags.refPackageName
Expand Down
7 changes: 1 addition & 6 deletions cmd/codegen/gengo.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,7 @@ func IsCallbackTypedef(s string) bool {
}

func IsStructName(name CIdentifier, ctx *Context) bool {
_, ok := ctx.structNames[name]
return ok
}

func IsEnum(name CIdentifier, enums map[CIdentifier]bool) bool {
_, ok := enums[name]
_, ok := ctx.typedefsNames[name]
return ok
}

Expand Down
10 changes: 5 additions & 5 deletions cmd/codegen/gengo_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func GenerateGoFuncs(
) error {
generator := &goFuncsGenerator{
prefix: context.prefix,
structNames: context.typedefsNames,
typedefsNames: context.typedefsNames,
enumNames: context.enumNames,
refTypedefs: context.refTypedefs,
context: context,
Expand Down Expand Up @@ -101,7 +101,7 @@ func GenerateGoFuncs(
// goFuncsGenerator is an internal state of GO funcs' generator
type goFuncsGenerator struct {
prefix string
structNames map[CIdentifier]bool
typedefsNames map[CIdentifier]bool
enumNames map[CIdentifier]bool
refTypedefs map[CIdentifier]bool

Expand Down Expand Up @@ -150,9 +150,9 @@ func (g *goFuncsGenerator) GenerateFunction(f FuncDef, args []GoIdentifier, argW
} else {
returnTypeType = returnTypeVoid
}
} else if HasSuffix(f.Ret, "*") && (g.structNames[TrimSuffix(f.Ret, "*")] || g.structNames[TrimSuffix(TrimPrefix(f.Ret, "const "), "*")]) {
} else if HasSuffix(f.Ret, "*") && (g.typedefsNames[TrimSuffix(f.Ret, "*")] || g.typedefsNames[TrimSuffix(TrimPrefix(f.Ret, "const "), "*")]) {
returnTypeType = returnTypeStructPtr
} else if f.StructGetter && g.structNames[f.Ret] {
} else if f.StructGetter && g.typedefsNames[f.Ret] {
returnTypeType = returnTypeStruct
} else if f.Constructor {
returnTypeType = returnTypeConstructor
Expand Down Expand Up @@ -366,7 +366,7 @@ func (g *goFuncsGenerator) generateFuncArgs(f FuncDef) (args []GoIdentifier, arg
decl, wrapper, err := getArgWrapper(
&a,
i == 0 && f.StructSetter,
f.StructGetter && g.structNames[a.Type],
f.StructGetter && g.typedefsNames[a.Type],
g.context,
)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion cmd/codegen/gengo_typedefs.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ func GenerateTypedefs(
continue
}

if IsEnum(k, ctx.enumNames) /*|| IsStructName(k, structs)*/ {
_, isEnum := ctx.enumNames[k]
_, isRefEnum := ctx.refEnumNames[k]
if isEnum || isRefEnum {
if ctx.flags.showGenerated {
glg.Infof("typedef %s has extended deffinition in structs_and_enums.json. Will generate later", k)
}
Expand Down
24 changes: 14 additions & 10 deletions cmd/codegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const (
)

// this cextracts enums and structs names from json file.
func getEnumAndStructNames(enumJsonBytes []byte, context *Context) (enumNames []EnumIdentifier, structNames []CIdentifier, err error) {
func getEnumAndStructNames(enumJsonBytes []byte, context *Context) (enumNames []EnumIdentifier, typedefsNames []CIdentifier, err error) {
enums, err := getEnumDefs(enumJsonBytes)
if err != nil {
return nil, nil, fmt.Errorf("cannot get enum definitions: %w", err)
Expand All @@ -34,7 +34,7 @@ func getEnumAndStructNames(enumJsonBytes []byte, context *Context) (enumNames []

for _, s := range structs {
if shouldSkipStruct := context.preset.SkipStructs[s.Name]; !shouldSkipStruct {
structNames = append(structNames, s.Name)
typedefsNames = append(typedefsNames, s.Name)
}
}

Expand Down Expand Up @@ -116,20 +116,24 @@ func loadData(f *flags) (*jsonData, error) {

// this will store json data processed by appropiate pre-rocessors
type Context struct {
// prefix for generated files (prefix_fileType.go)
prefix string

// plain idata loaded from json
funcs []FuncDef
structs []StructDef
enums []EnumDef
typedefs *Typedefs

prefix string

funcNames map[CIdentifier]bool
// ghese fields are filled by parser while it generates code.
enumNames map[CIdentifier]bool
structNames map[CIdentifier]bool
typedefsNames map[CIdentifier]bool

// contains helper C functions to get/set struct fields
// of array types
arrayIndexGetters map[CIdentifier]CIdentifier

// contains identifiers from other package (usually imgui).
refStructNames map[CIdentifier]bool
refEnumNames map[CIdentifier]bool
refTypedefs map[CIdentifier]bool
Expand Down Expand Up @@ -184,7 +188,7 @@ func parseJson(jsonData *jsonData) (*Context, error) {
}

_, structs, err := getEnumAndStructNames(jsonData.structAndEnums, result)
result.structNames = SliceToMap(structs)
result.typedefsNames = SliceToMap(structs)
if err != nil {
return nil, fmt.Errorf("cannot get reference struct and enums names: %w", err)
}
Expand Down Expand Up @@ -232,15 +236,15 @@ func main() {
glg.Fatalf("Generating enum names: %v", err)
}

context.enumNames = MergeMaps(SliceToMap(enumNames), context.refEnumNames)
context.enumNames = SliceToMap(enumNames)

// 1.2. Generate Go typedefs
callbacks, err := GenerateTypedefs(context.typedefs, context.structs, context)
typedefsNames, err := GenerateTypedefs(context.typedefs, context.structs, context)
if err != nil {
log.Panic(err)
}

context.structNames = SliceToMap(callbacks)
context.typedefsNames = SliceToMap(typedefsNames)

// 1.3. Generate C wrapper
validFuncs, err := generateCppWrapper(flags.prefix, flags.include, context.funcs, context)
Expand Down
39 changes: 21 additions & 18 deletions cmd/codegen/return_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,16 @@ func getReturnWrapper(
"void*": simpleR("unsafe.Pointer", "unsafe.Pointer"),
}

isPointer := HasSuffix(t, "*")
pureType := TrimPrefix(TrimSuffix(t, "*"), "const ")
// check if pureType is a declared type (struct or something else from typedefs)
_, isRefStruct := context.refStructNames[pureType]
_, isRefTypedef := context.refTypedefs[pureType]
_, isEnum := context.enumNames[pureType]
_, isRefEnum := context.refEnumNames[pureType]
_, shouldSkipRefTypedef := context.preset.SkipTypedefs[pureType]
_, isStruct := context.structNames[pureType]
isStruct = isStruct || ((isRefStruct || (isRefTypedef && !IsEnum(pureType, context.refEnumNames))) && !shouldSkipRefTypedef)
_, isStruct := context.typedefsNames[pureType]
isStruct = isStruct || ((isRefStruct || (isRefTypedef && !isRefEnum)) && !shouldSkipRefTypedef)
w, known := returnWrapperMap[t]
// check if is array (match regex)
isArray, err := regexp.Match(".*\\[\\d+\\]", []byte(t))
Expand All @@ -96,25 +99,32 @@ func getReturnWrapper(

_, shouldSkipStruct := context.preset.SkipStructs[pureType]

pureType = TrimPrefix(t, "const ")
switch {
case known:
return w, nil
// case (context.structNames[t] || context.refStructNames[t]) && !shouldSkipStruct(t):
case !HasSuffix(t, "*") && isStruct && !shouldSkipStruct:
// case (context.typedefsNames[t] || context.refStructNames[t]) && !shouldSkipStruct(t):
case !isPointer && isStruct && !shouldSkipStruct:
return returnWrapper{
returnType: prefixGoPackage(pureType.renameGoIdentifier(context), srcPackage, context),
// this is a small trick as using prefixGoPackage isn't in fact intended to be used in such a way, but it should treat the whole string as a "type" and prefix it correctly
returnStmt: string(prefixGoPackage(GoIdentifier(fmt.Sprintf("*New%sFromC(func() *C.%s {result := %%s; return &result}())", pureType.renameGoIdentifier(context), pureType)), srcPackage, context)),
CType: GoIdentifier(fmt.Sprintf("C.%s", pureType)),
}, nil
case IsEnum(t, context.enumNames):
case isEnum || isRefEnum:
goType := prefixGoPackage(pureType.renameGoIdentifier(context), srcPackage, context)
return returnWrapper{
returnType: goType,
returnStmt: fmt.Sprintf("%s(%%s)", goType),
CType: GoIdentifier(fmt.Sprintf("C.%s", pureType)),
}, nil
if isPointer {
return returnWrapper{
returnType: "*" + goType,
returnStmt: fmt.Sprintf("(*%s)(%%s)", goType),
CType: GoIdentifier(fmt.Sprintf("*C.%s", TrimSuffix(pureType, "*"))),
}, nil
} else {
return returnWrapper{
returnType: goType,
returnStmt: fmt.Sprintf("%s(%%s)", goType),
CType: GoIdentifier(fmt.Sprintf("C.%s", pureType)),
}, nil
}
case HasPrefix(t, "ImVector_") &&
!(HasSuffix(t, "*") || HasSuffix(t, "]")):
pureType := CIdentifier(TrimPrefix(t, "ImVector_") + "*")
Expand All @@ -133,13 +143,6 @@ func getReturnWrapper(
returnStmt: fmt.Sprintf("vectors.NewVectorFromC(%%[1]s.Size, %%[1]s.Capacity, %s)", fmt.Sprintf(rw.returnStmt, "%[1]s.Data")),
CType: GoIdentifier(fmt.Sprintf("*C.%s", pureType)),
}, nil
case HasSuffix(t, "*") && IsEnum(TrimSuffix(t, "*"), context.enumNames):
goType := prefixGoPackage("*"+TrimSuffix(pureType, "*").renameGoIdentifier(context), srcPackage, context)
return returnWrapper{
returnType: goType,
returnStmt: fmt.Sprintf("(%s)(%%s)", goType),
CType: GoIdentifier(fmt.Sprintf("*C.%s", TrimSuffix(pureType, "*"))),
}, nil
case HasSuffix(t, "*") && isStruct && !shouldSkipStruct:
goType := prefixGoPackage("*"+TrimSuffix(pureType, "*").renameGoIdentifier(context), srcPackage, context)
return returnWrapper{
Expand Down
Loading
Loading