Skip to content

Commit

Permalink
gogensig:reuse names
Browse files Browse the repository at this point in the history
  • Loading branch information
luoliwoshang committed Feb 20, 2025
1 parent 40c6fb1 commit ce654da
Show file tree
Hide file tree
Showing 9 changed files with 286 additions and 154 deletions.
50 changes: 50 additions & 0 deletions _xtool/llcppsymg/_cmptest/names_test/llgo.expect
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
123 changes: 123 additions & 0 deletions _xtool/llcppsymg/_cmptest/names_test/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import (

func main() {
TestToGoName()
TestNameMapper()
TestPubName()
TestExportName()
TestHeaderFileToGo()
}

func TestToGoName() {
Expand Down Expand Up @@ -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)
}
}
}
2 changes: 1 addition & 1 deletion _xtool/llcppsymg/_cmptest/parse_test/llgo.expect
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
122 changes: 108 additions & 14 deletions _xtool/llcppsymg/names/names.go
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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"
}
2 changes: 1 addition & 1 deletion cmd/gogensig/convert/headerfile.go
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
Loading

0 comments on commit ce654da

Please sign in to comment.