Skip to content

Commit

Permalink
gogensig:collect node ref & convert in order
Browse files Browse the repository at this point in the history
  • Loading branch information
luoliwoshang committed Jan 26, 2025
1 parent ea2a80d commit d1303b1
Show file tree
Hide file tree
Showing 7 changed files with 661 additions and 77 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
===== _typedef_autogen_link.go =====
package _typedef

const LLGoPackage string = "link: $(pkg-config --libs xxx);"

===== temp.go =====
package _typedef
package typedef

import (
"github.com/goplus/llgo/c"
Expand Down Expand Up @@ -40,6 +35,11 @@ const (
FITEMD F = 1
)

===== typedef_autogen_link.go =====
package typedef

const LLGoPackage string = "link: $(pkg-config --libs xxx);"

===== llcppg.pub =====
a A
b B
Expand Down
222 changes: 216 additions & 6 deletions cmd/gogensig/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package convert

import (
"errors"
"fmt"
"log"
"strings"

Expand All @@ -26,6 +27,8 @@ type AstConvertConfig struct {
OutputDir string
}

type ConverterConfig = AstConvertConfig

func NewAstConvert(config *AstConvertConfig) (*AstConvert, error) {
if config == nil {
return nil, errors.New("config is nil")
Expand Down Expand Up @@ -185,18 +188,73 @@ func (p *AstConvert) WritePkgFiles() {
}
}

type TypeCollector struct {
Types *Types
type Converter struct {
Types *Types
FileSet []*ast.FileEntry
Pkg *Package

files map[string]*ast.FileEntry
}

func NewTypeCollector() *TypeCollector {
return &TypeCollector{
func NewConverter(config *ConverterConfig) (*Converter, error) {
if config == nil {
return nil, errors.New("config is nil")
}

Check warning on line 202 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L201-L202

Added lines #L201 - L202 were not covered by tests
symbTable, err := cfg.NewSymbolTable(config.SymbFile)
if err != nil {
if dbg.GetDebugError() {
log.Printf("Can't get llcppg.symb.json from %s Use empty table\n", config.SymbFile)
}
symbTable = cfg.CreateSymbolTable([]cfg.SymbolEntry{})
}

conf, err := cfg.GetCppgCfgFromPath(config.CfgFile)
if err != nil {
if dbg.GetDebugError() {
log.Printf("Cant get llcppg.cfg from %s Use empty config\n", config.CfgFile)
}
conf = &cppgtypes.Config{}

Check warning on line 216 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L213-L216

Added lines #L213 - L216 were not covered by tests
}

pubs, err := cfg.GetPubFromPath(config.PubFile)
if err != nil {
return nil, err
}

Check warning on line 222 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L221-L222

Added lines #L221 - L222 were not covered by tests

pkg := NewPackage(&PackageConfig{
PkgBase: PkgBase{
PkgPath: ".",
CppgConf: conf,
Pubs: pubs,
},
Name: config.PkgName,
OutputDir: config.OutputDir,
SymbolTable: symbTable,
})
return &Converter{
Types: NewTypes(),
files: make(map[string]*ast.FileEntry),
Pkg: pkg,
}, nil
}

func (p *Converter) Start() error {
order, err := p.BuildOrder()
if err != nil {
return err
}

Check warning on line 245 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L244-L245

Added lines #L244 - L245 were not covered by tests
p.Process(order)
p.Pkg.WritePkgFiles()
p.Pkg.WriteLinkFile()
p.Pkg.WritePubFile()
return nil
}

func (p *TypeCollector) Collect(files []*ast.FileEntry) *Types {
func (p *Converter) Collect(files []*ast.FileEntry) {
p.FileSet = files
for _, file := range files {
// for lookup file by path
p.files[file.Path] = file
for _, decl := range file.Doc.Decls {
switch d := decl.(type) {
case *ast.TypeDecl:
Expand All @@ -210,5 +268,157 @@ func (p *TypeCollector) Collect(files []*ast.FileEntry) *Types {
}
}
}
return p.Types
p.CollectDeps(files)
}

func (p *Converter) Process(orderedUSR []string) error {
// Register Decl without type to keep type order
for _, file := range p.FileSet {
p.Pkg.SetCurFile(Hfile(p.Pkg, file))
for _, decl := range file.Doc.Decls {
switch decl := decl.(type) {
case *ast.TypedefDecl:
p.Pkg.RegisterDecl(decl.Name.USR)
case *ast.EnumTypeDecl:
p.Pkg.RegisterEnumDecl(decl.Name.USR)
case *ast.TypeDecl:
p.Pkg.RegisterDecl(decl.Name.USR)
}
}
}

for _, usr := range orderedUSR {
typ, ok := p.Types.Lookup(usr)
if !ok {
return fmt.Errorf("expect %s, but not found", usr)
}

Check warning on line 294 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L293-L294

Added lines #L293 - L294 were not covered by tests
switch decl := typ.(type) {
case *ast.TypeDecl:
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File]))
p.Pkg.ConvertTypeDecl(decl)
case *ast.EnumTypeDecl:
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File]))
p.Pkg.ConvertEnumTypeDecl(decl)
case *ast.TypedefDecl:
p.Pkg.SetCurFile(Hfile(p.Pkg, p.files[decl.DeclBase.Loc.File]))
p.Pkg.ConvertTypedefDecl(decl)
}
}
return nil
}

func (p *Converter) CollectDeps(files []*ast.FileEntry) {
for _, file := range files {
for _, decl := range file.Doc.Decls {
switch d := decl.(type) {
case *ast.TypeDecl:
p.depType(d.Name.USR, d.Type)
case *ast.TypedefDecl:
p.depType(d.Name.USR, d.Type)
case *ast.EnumTypeDecl:
p.depType(d.Name.USR, d.Type)
case *ast.FuncDecl:
p.depType(d.Name.USR, d.Type)

Check warning on line 321 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L320-L321

Added lines #L320 - L321 were not covered by tests
}
}
}
}

func (p *Converter) depType(usr string, expr ast.Expr) {
switch t := expr.(type) {
case *ast.BuiltinType:
case *ast.Variadic:
case *ast.PointerType:
p.depType(usr, t.X)

Check warning on line 332 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L330-L332

Added lines #L330 - L332 were not covered by tests
case *ast.Ident, *ast.ScopingExpr, *ast.TagExpr:
p.depIdentRefer(usr, t)
case *ast.Field:
p.depType(usr, t.Type)
case *ast.FieldList:
for _, field := range t.List {
p.depType(usr, field.Type)
}
case *ast.FuncType:
p.depType(usr, t.Params)
p.depType(usr, t.Ret)
case *ast.ArrayType:
p.depType(usr, t.Elt)

Check warning on line 345 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L335-L345

Added lines #L335 - L345 were not covered by tests
case *ast.RecordType:
for _, field := range t.Fields.List {
p.depType(usr, field.Type)
}
}
}

func (p *Converter) depIdentRefer(usr string, expr ast.Expr) {
switch t := expr.(type) {
case *ast.Ident:
p.Types.RecordDep(usr, t.USR)
case *ast.ScopingExpr:
p.depIdentRefer(usr, t.X)

Check warning on line 358 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L357-L358

Added lines #L357 - L358 were not covered by tests
case *ast.TagExpr:
p.depIdentRefer(usr, t.Name)
}
}

func (p *Converter) BuildOrder() ([]string, error) {
visited := make(map[string]bool)
temp := make(map[string]bool)
var order []string

var visit func(string) error
visit = func(usr string) error {
if temp[usr] {
return fmt.Errorf("cyclic dependency detected at USR: %s", usr)
}

Check warning on line 373 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L372-L373

Added lines #L372 - L373 were not covered by tests
if visited[usr] {
return nil
}

temp[usr] = true
for _, depUSR := range p.Types.Deps[usr] {
if err := visit(depUSR); err != nil {
return err
}

Check warning on line 382 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L381-L382

Added lines #L381 - L382 were not covered by tests
}

temp[usr] = false
visited[usr] = true
order = append(order, usr)
return nil
}

for usr := range p.Types.Defs {
if !visited[usr] {
if err := visit(usr); err != nil {
return nil, err
}

Check warning on line 395 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L394-L395

Added lines #L394 - L395 were not covered by tests
}
}

return order, nil
}

func Hfile(pkg *Package, file *ast.FileEntry) *HeaderFile {
inPkgIncPath := false
incPaths, notFounds, err := pkg.GetIncPaths()
if len(notFounds) > 0 {
log.Println("failed to find some include paths: \n", notFounds)
if err != nil {
log.Println("failed to get any include paths: \n", err.Error())
}

Check warning on line 409 in cmd/gogensig/convert/convert.go

View check run for this annotation

Codecov / codecov/patch

cmd/gogensig/convert/convert.go#L406-L409

Added lines #L406 - L409 were not covered by tests
}
for _, includePath := range incPaths {
if includePath == file.Path {
inPkgIncPath = true
break
}
}
return &HeaderFile{
File: file.Path,
IncPath: file.IncPath,
IsHeaderFile: true,
InCurPkg: inPkgIncPath,
IsSys: file.IsSys,
}
}
Loading

0 comments on commit d1303b1

Please sign in to comment.