From ce654da793cf85122e71dd90f12dbf0266f8e4f5 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Thu, 20 Feb 2025 17:11:04 +0800 Subject: [PATCH] gogensig:reuse names --- .../llcppsymg/_cmptest/names_test/llgo.expect | 50 +++++++ _xtool/llcppsymg/_cmptest/names_test/names.go | 123 ++++++++++++++++ .../llcppsymg/_cmptest/parse_test/llgo.expect | 2 +- _xtool/llcppsymg/names/names.go | 122 ++++++++++++++-- cmd/gogensig/convert/headerfile.go | 2 +- cmd/gogensig/convert/names/names.go | 135 ------------------ cmd/gogensig/convert/package.go | 2 +- cmd/gogensig/convert/package_test.go | 2 +- cmd/gogensig/convert/type.go | 2 +- 9 files changed, 286 insertions(+), 154 deletions(-) delete mode 100644 cmd/gogensig/convert/names/names.go diff --git a/_xtool/llcppsymg/_cmptest/names_test/llgo.expect b/_xtool/llcppsymg/_cmptest/names_test/llgo.expect index b4543c0a..717438a9 100644 --- a/_xtool/llcppsymg/_cmptest/names_test/llgo.expect +++ b/_xtool/llcppsymg/_cmptest/names_test/llgo.expect @@ -8,6 +8,56 @@ Before: GetReal After: GetReal Before: GetBoolean After: GetBoolean Before: INIReader After: Reader +=== Test NameMapper === + +Testing GetUniqueGoName: +Input: lua_closethread, Output: Closethread true +Input: luaL_checknumber, Output: Checknumber true +Input: _gmp_err, Output: X_gmpErr true +Input: fn_123illegal, Output: X123illegal true +Input: fts5_tokenizer, Output: Fts5Tokenizer true +Input: Fts5Tokenizer, Output: Fts5Tokenizer__1 true +Input: normal_var, Output: Normal_var true +Input: Cameled, Output: Cameled false + +=== Test PubName === +Input: sqlite_file, Output: SqliteFile +Input: _gmp_err, Output: X_gmpErr +Input: 123illegal, Output: X123illegal +Input: alreadyCamel, Output: AlreadyCamel +Input: _x__y, Output: X_xY +Input: _x_y, Output: X_xY +Input: _x___y, Output: X_xY +Input: x_y, Output: XY +Input: x__y, Output: XY +Input: x_y_, Output: XY +Input: x__y_, Output: XY +Input: _, Output: X_ +Input: __, Output: X__ +Input: ___, Output: X___ + +=== Test ExportName === +Input: sqlite_file, Output: Sqlite_file +Input: _sqlite_file, Output: X_sqlite_file +Input: 123illegal, Output: X123illegal +Input: CODE_MASK, Output: CODE_MASK +Input: _CODE_MASK, Output: X_CODE_MASK +Input: _x__y, Output: X_x__y +Input: _x_y, Output: X_x_y +Input: _x___y, Output: X_x___y +Input: x_y, Output: X_y +Input: x__y, Output: X__y +Input: x_y_, Output: X_y_ +Input: x__y_, Output: X__y_ +Input: _, Output: X_ +Input: __, Output: X__ +Input: ___, Output: X___ + +=== Test HeaderFileToGo === +Input: /path/to/foo.h, Output: foo.go +Input: /path/to/_intptr.h, Output: X_intptr.go +Input: header.h, Output: header.go +Input: _impl.h, Output: X_impl.go #stderr diff --git a/_xtool/llcppsymg/_cmptest/names_test/names.go b/_xtool/llcppsymg/_cmptest/names_test/names.go index bd16fafe..a37e2e6e 100644 --- a/_xtool/llcppsymg/_cmptest/names_test/names.go +++ b/_xtool/llcppsymg/_cmptest/names_test/names.go @@ -9,6 +9,10 @@ import ( func main() { TestToGoName() + TestNameMapper() + TestPubName() + TestExportName() + TestHeaderFileToGo() } func TestToGoName() { @@ -36,3 +40,122 @@ func TestToGoName() { } fmt.Println() } + +func TestNameMapper() { + fmt.Println("=== Test NameMapper ===") + + mapper := names.NewNameMapper() + testCases := []struct { + name string + trimPrefixes []string + toCamel bool + expected string + expectChange bool + }{ + {"lua_closethread", []string{"lua_", "luaL_"}, true, "Closethread", true}, + {"luaL_checknumber", []string{"lua_", "luaL_"}, true, "Checknumber", true}, + {"_gmp_err", []string{}, true, "X_gmpErr", true}, + {"fn_123illegal", []string{"fn_"}, true, "X123illegal", true}, + {"fts5_tokenizer", []string{}, true, "Fts5Tokenizer", true}, + {"Fts5Tokenizer", []string{}, true, "Fts5Tokenizer__1", true}, + {"normal_var", []string{}, false, "Normal_var", true}, + {"Cameled", []string{}, false, "Cameled", false}, + } + + fmt.Println("\nTesting GetUniqueGoName:") + for _, tc := range testCases { + result, changed := mapper.GetUniqueGoName(tc.name, tc.trimPrefixes, tc.toCamel) + if result != tc.expected || changed != tc.expectChange { + fmt.Printf("Input: %s, Expected: %s %t, Got: %s %t\n", tc.name, tc.expected, tc.expectChange, result, changed) + } else { + fmt.Printf("Input: %s, Output: %s %t\n", tc.name, result, changed) + } + } +} + +func TestPubName() { + fmt.Println("\n=== Test PubName ===") + testCases := []struct { + input string + expected string + }{ + {"sqlite_file", "SqliteFile"}, + {"_gmp_err", "X_gmpErr"}, + {"123illegal", "X123illegal"}, + {"alreadyCamel", "AlreadyCamel"}, + {"_x__y", "X_xY"}, + {"_x_y", "X_xY"}, + {"_x___y", "X_xY"}, + {"x_y", "XY"}, + {"x__y", "XY"}, + {"x_y_", "XY"}, + {"x__y_", "XY"}, + {"_", "X_"}, + {"__", "X__"}, + {"___", "X___"}, + } + + for _, tc := range testCases { + result := names.PubName(tc.input) + if result != tc.expected { + fmt.Printf("Input: %s, Expected: %s, Got: %s\n", tc.input, tc.expected, result) + } else { + fmt.Printf("Input: %s, Output: %s\n", tc.input, result) + } + } +} + +func TestExportName() { + fmt.Println("\n=== Test ExportName ===") + testCases := []struct { + input string + expected string + }{ + {"sqlite_file", "Sqlite_file"}, + {"_sqlite_file", "X_sqlite_file"}, + {"123illegal", "X123illegal"}, + {"CODE_MASK", "CODE_MASK"}, + {"_CODE_MASK", "X_CODE_MASK"}, + {"_x__y", "X_x__y"}, + {"_x_y", "X_x_y"}, + {"_x___y", "X_x___y"}, + {"x_y", "X_y"}, + {"x__y", "X__y"}, + {"x_y_", "X_y_"}, + {"x__y_", "X__y_"}, + {"_", "X_"}, + {"__", "X__"}, + {"___", "X___"}, + } + + for _, tc := range testCases { + result := names.ExportName(tc.input) + if result != tc.expected { + fmt.Printf("Input: %s, Expected: %s, Got: %s\n", tc.input, tc.expected, result) + } else { + fmt.Printf("Input: %s, Output: %s\n", tc.input, result) + } + } +} + +func TestHeaderFileToGo() { + fmt.Println("\n=== Test HeaderFileToGo ===") + testCases := []struct { + input string + expected string + }{ + {"/path/to/foo.h", "foo.go"}, + {"/path/to/_intptr.h", "X_intptr.go"}, + {"header.h", "header.go"}, + {"_impl.h", "X_impl.go"}, + } + + for _, tc := range testCases { + result := names.HeaderFileToGo(tc.input) + if result != tc.expected { + fmt.Printf("Input: %s, Expected: %s, Got: %s\n", tc.input, tc.expected, result) + } else { + fmt.Printf("Input: %s, Output: %s\n", tc.input, result) + } + } +} diff --git a/_xtool/llcppsymg/_cmptest/parse_test/llgo.expect b/_xtool/llcppsymg/_cmptest/parse_test/llgo.expect index adfdb4bc..2e85eba2 100644 --- a/_xtool/llcppsymg/_cmptest/parse_test/llgo.expect +++ b/_xtool/llcppsymg/_cmptest/parse_test/llgo.expect @@ -41,7 +41,7 @@ Symbol Map GoName: InitWindow, ProtoName In HeaderFile: InitWindow(int, int, con === Test Case: InvalidReceiver typ.canonicalType.Kind == clang.TypePointer === Parsed Symbols: -Symbol Map GoName: X__MpzSetUiSafe, ProtoName In HeaderFile: __mpz_set_ui_safe(mpz_ptr, unsigned long), MangledName: __mpz_set_ui_safe +Symbol Map GoName: X__mpzSetUiSafe, ProtoName In HeaderFile: __mpz_set_ui_safe(mpz_ptr, unsigned long), MangledName: __mpz_set_ui_safe #stderr diff --git a/_xtool/llcppsymg/names/names.go b/_xtool/llcppsymg/names/names.go index 6deb7f8c..163a78b0 100644 --- a/_xtool/llcppsymg/names/names.go +++ b/_xtool/llcppsymg/names/names.go @@ -1,14 +1,71 @@ package names import ( + "fmt" + "path/filepath" "strings" + "unicode" ) +// NameMapper handles name mapping and uniqueness for Go symbols +type NameMapper struct { + count map[string]int // tracks count of each public name for uniqueness + mapping map[string]string // maps original c names to Go names,like: foo(in c) -> Foo(in go) +} + +func NewNameMapper() *NameMapper { + return &NameMapper{ + count: make(map[string]int), + mapping: make(map[string]string), + } +} + +// returns a unique Go name for an original name +// For every go name, it will be unique. +func (m *NameMapper) GetUniqueGoName(name string, trimPrefixes []string, toCamel bool) (string, bool) { + pubName, exist := m.genGoName(name, trimPrefixes, toCamel) + if exist { + return pubName, pubName != name + } + + count := m.count[pubName] + m.count[pubName]++ + if count > 0 { + pubName = fmt.Sprintf("%s__%d", pubName, count) + } + + return pubName, pubName != name +} + +// returns the Go name for an original name,if the name is already mapped,return the mapped name +func (m *NameMapper) genGoName(name string, trimPrefixes []string, toCamel bool) (string, bool) { + if goName, exists := m.mapping[name]; exists { + if goName == "" { + return name, true + } + return goName, true + } + name = removePrefixedName(name, trimPrefixes) + if toCamel { + return PubName(name), false + } else { + return ExportName(name), false + } +} + +func (m *NameMapper) SetMapping(originName, newName string) { + value := "" + if originName != newName { + value = newName + } + m.mapping[originName] = value +} + func GoName(name string, trimPrefixes []string, inCurPkg bool) string { if inCurPkg { name = removePrefixedName(name, trimPrefixes) } - return pubName(name) + return PubName(name) } func removePrefixedName(name string, trimPrefixes []string) string { @@ -23,26 +80,63 @@ func removePrefixedName(name string, trimPrefixes []string) string { return name } -func pubName(name string) string { +func PubName(name string) string { if len(name) == 0 { return name } - toCamelCase := func(s string) string { - parts := strings.Split(s, "_") - for i := 0; i < len(parts); i++ { - if len(parts[i]) > 0 { - parts[i] = strings.ToUpper(parts[i][:1]) + parts[i][1:] - } - } - return strings.Join(parts, "") - } - if name[0] == '_' { + fChar := name[0] + if fChar == '_' { i := 0 for i < len(name) && name[i] == '_' { i++ } prefix := name[:i] - return "X" + prefix + toCamelCase(name[i:]) + return "X" + prefix + ToCamelCase(name[i:], false) + } + if unicode.IsDigit(rune(fChar)) { + return "X" + ToCamelCase(name, false) + } + return ToCamelCase(name, true) +} + +func ToCamelCase(s string, firstPartUpper bool) string { + parts := strings.Split(s, "_") + result := []string{} + for i, part := range parts { + if i == 0 && !firstPartUpper { + result = append(result, part) + continue + } + if len(part) > 0 { + result = append(result, strings.ToUpper(part[:1])+part[1:]) + } + } + return strings.Join(result, "") +} + +// Only Make it Public,no turn to other camel method +func ExportName(name string) string { + fChar := name[0] + if fChar == '_' || unicode.IsDigit(rune(fChar)) { + return "X" + name + } + return UpperFirst(name) +} + +func UpperFirst(name string) string { + return strings.ToUpper(name[:1]) + name[1:] +} + +// /path/to/foo.h -> foo.go +// /path/to/_intptr.h -> X_intptr.go +func HeaderFileToGo(incPath string) string { + _, fileName := filepath.Split(incPath) + ext := filepath.Ext(fileName) + if len(ext) > 0 { + fileName = strings.TrimSuffix(fileName, ext) + } + if strings.HasPrefix(fileName, "_") { + fileName = "X" + fileName } - return toCamelCase(name) + return fileName + ".go" } diff --git a/cmd/gogensig/convert/headerfile.go b/cmd/gogensig/convert/headerfile.go index badc72ac..f3a6b08c 100644 --- a/cmd/gogensig/convert/headerfile.go +++ b/cmd/gogensig/convert/headerfile.go @@ -1,7 +1,7 @@ package convert import ( - "github.com/goplus/llcppg/cmd/gogensig/convert/names" + "github.com/goplus/llcppg/_xtool/llcppsymg/names" ) type HeaderFile struct { diff --git a/cmd/gogensig/convert/names/names.go b/cmd/gogensig/convert/names/names.go deleted file mode 100644 index c2dee9a6..00000000 --- a/cmd/gogensig/convert/names/names.go +++ /dev/null @@ -1,135 +0,0 @@ -package names - -import ( - "fmt" - "path/filepath" - "strings" - "unicode" -) - -// NameMapper handles name mapping and uniqueness for Go symbols -type NameMapper struct { - count map[string]int // tracks count of each public name for uniqueness - mapping map[string]string // maps original c names to Go names,like: foo(in c) -> Foo(in go) -} - -func NewNameMapper() *NameMapper { - return &NameMapper{ - count: make(map[string]int), - mapping: make(map[string]string), - } -} - -// returns a unique Go name for an original name -// For every go name, it will be unique. -func (m *NameMapper) GetUniqueGoName(name string, trimPrefixes []string, toCamel bool) (string, bool) { - pubName, exist := m.genGoName(name, trimPrefixes, toCamel) - if exist { - return pubName, pubName != name - } - - count := m.count[pubName] - m.count[pubName]++ - if count > 0 { - pubName = fmt.Sprintf("%s__%d", pubName, count) - } - - return pubName, pubName != name -} - -// returns the Go name for an original name,if the name is already mapped,return the mapped name -func (m *NameMapper) genGoName(name string, trimPrefixes []string, toCamel bool) (string, bool) { - if goName, exists := m.mapping[name]; exists { - if goName == "" { - return name, true - } - return goName, true - } - name = removePrefixedName(name, trimPrefixes) - if toCamel { - return PubName(name), false - } else { - return ExportName(name), false - } -} - -func (m *NameMapper) SetMapping(originName, newName string) { - value := "" - if originName != newName { - value = newName - } - m.mapping[originName] = value -} - -func removePrefixedName(name string, trimPrefixes []string) string { - if len(trimPrefixes) == 0 { - return name - } - for _, prefix := range trimPrefixes { - if strings.HasPrefix(name, prefix) { - return strings.TrimPrefix(name, prefix) - } - } - return name -} - -func ToCamelCase(s string, firstPartUpper bool) string { - parts := strings.Split(s, "_") - result := []string{} - for i, part := range parts { - if i == 0 && !firstPartUpper { - result = append(result, part) - continue - } - if len(part) > 0 { - result = append(result, strings.ToUpper(part[:1])+part[1:]) - } - } - return strings.Join(result, "") -} - -func PubName(name string) string { - if len(name) == 0 { - return name - } - fChar := name[0] - if fChar == '_' { - i := 0 - for i < len(name) && name[i] == '_' { - i++ - } - prefix := name[:i] - return "X" + prefix + ToCamelCase(name[i:], false) - } - if unicode.IsDigit(rune(fChar)) { - return "X" + ToCamelCase(name, false) - } - return ToCamelCase(name, true) -} - -// Only Make it Public,no turn to other camel method -func ExportName(name string) string { - fChar := name[0] - if fChar == '_' || unicode.IsDigit(rune(fChar)) { - return "X" + name - } - return UpperFirst(name) -} - -func UpperFirst(name string) string { - return strings.ToUpper(name[:1]) + name[1:] -} - -// /path/to/foo.h -> foo.go -// /path/to/_intptr.h -> X_intptr.go -func HeaderFileToGo(incPath string) string { - _, fileName := filepath.Split(incPath) - ext := filepath.Ext(fileName) - if len(ext) > 0 { - fileName = strings.TrimSuffix(fileName, ext) - } - if strings.HasPrefix(fileName, "_") { - fileName = "X" + fileName - } - return fileName + ".go" -} diff --git a/cmd/gogensig/convert/package.go b/cmd/gogensig/convert/package.go index 16500076..16931f80 100644 --- a/cmd/gogensig/convert/package.go +++ b/cmd/gogensig/convert/package.go @@ -12,9 +12,9 @@ import ( goast "go/ast" "github.com/goplus/gogen" + "github.com/goplus/llcppg/_xtool/llcppsymg/names" "github.com/goplus/llcppg/ast" cfg "github.com/goplus/llcppg/cmd/gogensig/config" - "github.com/goplus/llcppg/cmd/gogensig/convert/names" "github.com/goplus/llcppg/cmd/gogensig/dbg" "github.com/goplus/llcppg/cmd/gogensig/errs" ctoken "github.com/goplus/llcppg/token" diff --git a/cmd/gogensig/convert/package_test.go b/cmd/gogensig/convert/package_test.go index dfa3c74d..aeea7e4a 100644 --- a/cmd/gogensig/convert/package_test.go +++ b/cmd/gogensig/convert/package_test.go @@ -8,11 +8,11 @@ import ( "testing" "github.com/goplus/gogen" + "github.com/goplus/llcppg/_xtool/llcppsymg/names" "github.com/goplus/llcppg/ast" "github.com/goplus/llcppg/cmd/gogensig/cmp" cfg "github.com/goplus/llcppg/cmd/gogensig/config" "github.com/goplus/llcppg/cmd/gogensig/convert" - "github.com/goplus/llcppg/cmd/gogensig/convert/names" "github.com/goplus/llcppg/cmd/gogensig/dbg" "github.com/goplus/llcppg/llcppg" "github.com/goplus/mod/gopmod" diff --git a/cmd/gogensig/convert/type.go b/cmd/gogensig/convert/type.go index 7aade06c..5bce6531 100644 --- a/cmd/gogensig/convert/type.go +++ b/cmd/gogensig/convert/type.go @@ -12,9 +12,9 @@ import ( "unsafe" "github.com/goplus/gogen" + "github.com/goplus/llcppg/_xtool/llcppsymg/names" "github.com/goplus/llcppg/ast" "github.com/goplus/llcppg/cmd/gogensig/config" - "github.com/goplus/llcppg/cmd/gogensig/convert/names" "github.com/goplus/llcppg/cmd/gogensig/convert/sizes" "github.com/goplus/llcppg/cmd/gogensig/errs" )