Skip to content

Commit

Permalink
cl: record def for ast.OverloadFuncDecl
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Apr 24, 2024
1 parent 64a3001 commit c450177
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 35 deletions.
18 changes: 13 additions & 5 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type Recorder interface {
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
// *ast.Field anonymous parameter *Var (incl. unnamed results)
// *ast.FunLit function literal in *ast.OverloadFuncDecl
//
Implicit(node ast.Node, obj types.Object)

Expand Down Expand Up @@ -1085,7 +1086,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
}
recv = otyp
if ctx.rec != nil {
ctx.rec.Refer(recv, recv.Name)
ctx.rec.ReferUse(recv, recv.Name)
}
}
onames := make([]string, 0, 4)
Expand All @@ -1103,7 +1104,7 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
ctx.lbinames = append(ctx.lbinames, expr.Name)
exov = true
if ctx.rec != nil {
ctx.rec.Refer(expr, expr.Name)
ctx.rec.ReferUse(expr, expr.Name)
}
case *ast.SelectorExpr:
if d.Recv == nil {
Expand All @@ -1120,8 +1121,8 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
ctx.lbinames = append(ctx.lbinames, recv)
exov = true
if ctx.rec != nil {
ctx.rec.Refer(rtyp, rtyp.Name)
ctx.rec.Refer(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
ctx.rec.ReferUse(rtyp, rtyp.Name)
ctx.rec.ReferUse(expr.Sel, rtyp.Name+"."+expr.Sel.Name)
}
case *ast.FuncLit:
if d.Recv != nil && !d.Operator {
Expand All @@ -1131,9 +1132,13 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
name1 := overloadFuncName(name.Name, idx)
onames = append(onames, "") // const Gopo_xxx = "xxxInt,,xxxFloat"
ctx.lbinames = append(ctx.lbinames, name1)
id := &ast.Ident{NamePos: expr.Pos(), Name: name1}
if ctx.rec != nil {
ctx.rec.ReferDef(id, expr)
}
preloadFuncDecl(&ast.FuncDecl{
Doc: d.Doc,
Name: &ast.Ident{NamePos: expr.Pos(), Name: name1},
Name: id,
Type: expr.Type,
Body: expr.Body,
})
Expand All @@ -1160,6 +1165,9 @@ func preloadFile(p *gogen.Package, ctx *blockCtx, f *ast.File, goFile string, ge
},
})
ctx.lbinames = append(ctx.lbinames, oname)
if ctx.rec != nil {
ctx.rec.ReferDef(d.Name, d)
}
}

default:
Expand Down
37 changes: 28 additions & 9 deletions cl/recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,42 @@ import (

type goxRecorder struct {
Recorder
types map[ast.Expr]types.TypeAndValue
refers map[string][]*ast.Ident
types map[ast.Expr]types.TypeAndValue
referDefs map[*ast.Ident]ast.Node
referUses map[string][]*ast.Ident
}

func newRecorder(rec Recorder) *goxRecorder {
types := make(map[ast.Expr]types.TypeAndValue)
refers := make(map[string][]*ast.Ident)
return &goxRecorder{rec, types, refers}
referDefs := make(map[*ast.Ident]ast.Node)
referUses := make(map[string][]*ast.Ident)
return &goxRecorder{rec, types, referDefs, referUses}
}

// Refer maps identifiers to name for ast.OverloadFuncDecl.
func (p *goxRecorder) Refer(ident *ast.Ident, name string) {
p.refers[name] = append(p.refers[name], ident)
// Refer uses maps identifiers to name for ast.OverloadFuncDecl.
func (p *goxRecorder) ReferUse(ident *ast.Ident, name string) {
p.referUses[name] = append(p.referUses[name], ident)
}

// Refer def maps for ast.FuncLit or ast.OverloadFuncDecl.
func (p *goxRecorder) ReferDef(ident *ast.Ident, node ast.Node) {
p.referDefs[ident] = node
}

// Complete computes the types record.
func (p *goxRecorder) Complete(scope *types.Scope) {
for name, idents := range p.refers {
for id, node := range p.referDefs {
if obj := scope.Lookup(id.Name); obj != nil {
switch fn := node.(type) {
case *ast.FuncLit:
p.recordFuncLit(fn, obj.Type())
p.Implicit(node, obj)
case *ast.OverloadFuncDecl:
p.Def(id, obj)
}
}
}
for name, idents := range p.referUses {
pos := strings.Index(name, ".")
if pos == -1 {
if obj := scope.Lookup(name); obj != nil {
Expand All @@ -71,7 +89,8 @@ func (p *goxRecorder) Complete(scope *types.Scope) {
}
}
p.types = nil
p.refers = nil
p.referDefs = nil
p.referUses = nil
}

// Member maps identifiers to the objects they denote.
Expand Down
1 change: 1 addition & 0 deletions x/typesutil/gopinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type Info struct {
// *ast.ImportSpec *PkgName for imports without renames
// *ast.CaseClause type-specific *Var for each type switch case clause (incl. default)
// *ast.Field anonymous parameter *Var (incl. unnamed results)
// *ast.FunLit function literal in *ast.OverloadFuncDecl
//
Implicits map[ast.Node]types.Object

Expand Down
140 changes: 119 additions & 21 deletions x/typesutil/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2018,22 +2018,26 @@ Mul 100,200,300
008: 7: 9 | a *ast.Ident | var : float64 | variable
009: 7: 9 | a * b *ast.BinaryExpr | value : float64 | value
010: 7:13 | b *ast.Ident | var : float64 | variable
011: 13:15 | int *ast.Ident | type : int | type
012: 13:20 | int *ast.Ident | type : int | type
013: 14:10 | x *ast.Ident | var : int | variable
014: 14:10 | x * y *ast.BinaryExpr | value : int | value
015: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
016: 14:14 | y *ast.Ident | var : int | variable
017: 14:18 | z *ast.Ident | var : int | variable
018: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
019: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
020: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
021: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
022: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
023: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
024: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
025: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
026: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
011: 13: 2 | func(x, y, z int) int *ast.FuncType | type : func(x int, y int, z int) int | type
012: 13: 2 | func(x, y, z int) int {
return x * y * z
} *ast.FuncLit | value : func(x int, y int, z int) int | value
013: 13:15 | int *ast.Ident | type : int | type
014: 13:20 | int *ast.Ident | type : int | type
015: 14:10 | x *ast.Ident | var : int | variable
016: 14:10 | x * y *ast.BinaryExpr | value : int | value
017: 14:10 | x * y * z *ast.BinaryExpr | value : int | value
018: 14:14 | y *ast.Ident | var : int | variable
019: 14:18 | z *ast.Ident | var : int | variable
020: 18: 1 | Mul *ast.Ident | value : func(a int, b int) int | value
021: 18: 1 | Mul 100, 200 *ast.CallExpr | value : int | value
022: 18: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
023: 18: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
024: 19: 1 | Mul *ast.Ident | value : func(x int, y int, z int) int | value
025: 19: 1 | Mul 100, 200, 300 *ast.CallExpr | value : int | value
026: 19: 5 | 100 *ast.BasicLit | value : untyped int = 100 | constant
027: 19: 9 | 200 *ast.BasicLit | value : untyped int = 200 | constant
028: 19:13 | 300 *ast.BasicLit | value : untyped int = 300 | constant
== defs ==
000: 0: 0 | Gopo_Mul | const main.Gopo_Mul untyped string
001: 2: 6 | MulInt | func main.MulInt(a int, b int) int
Expand All @@ -2042,11 +2046,12 @@ Mul 100,200,300
004: 6: 6 | MulFloat | func main.MulFloat(a float64, b float64) float64
005: 6:15 | a | var a float64
006: 6:18 | b | var b float64
007: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
008: 13: 7 | x | var x int
009: 13:10 | y | var y int
010: 13:13 | z | var z int
011: 18: 1 | main | func main.main()
007: 10: 6 | Mul | func main.Mul(__gop_overload_args__ interface{_()})
008: 13: 2 | Mul__2 | func main.Mul__2(x int, y int, z int) int
009: 13: 7 | x | var x int
010: 13:10 | y | var y int
011: 13:13 | z | var z int
012: 18: 1 | main | func main.main()
== uses ==
000: 2:18 | int | type int
001: 2:23 | int | type int
Expand Down Expand Up @@ -2145,3 +2150,96 @@ var d = a.mul(c)
017: 20:11 | mul | func (*main.foo).mulFoo(b *main.foo) *main.foo
018: 20:15 | c | var main.c *main.foo`)
}

func TestGopOverloadDecl(t *testing.T) {
testGopInfo(t, `
func addInt0() {
}
func addInt1(i int) {
}
func addInt2(i, j int) {
}
var addInt3 = func(i, j, k int) {
}
func add = (
addInt0
addInt1
addInt2
addInt3
func(a, b string) string {
return a + b
}
)
func init() {
add 100, 200
add 100, 200, 300
add("hello", "world")
}
`, ``, `== types ==
000: 0: 0 | "addInt0,addInt1,addInt2,addInt3," *ast.BasicLit | value : untyped string = "addInt0,addInt1,addInt2,addInt3," | constant
001: 5:16 | int *ast.Ident | type : int | type
002: 8:19 | int *ast.Ident | type : int | type
003: 11:15 | func(i, j, k int) *ast.FuncType | type : func(i int, j int, k int) | type
004: 11:15 | func(i, j, k int) {
} *ast.FuncLit | value : func(i int, j int, k int) | value
005: 11:28 | int *ast.Ident | type : int | type
006: 19: 2 | func(a, b string) string *ast.FuncType | type : func(a string, b string) string | type
007: 19: 2 | func(a, b string) string {
return a + b
} *ast.FuncLit | value : func(a string, b string) string | value
008: 19:12 | string *ast.Ident | type : string | type
009: 19:20 | string *ast.Ident | type : string | type
010: 20:10 | a *ast.Ident | var : string | variable
011: 20:10 | a + b *ast.BinaryExpr | value : string | value
012: 20:14 | b *ast.Ident | var : string | variable
013: 25: 2 | add *ast.Ident | value : func(i int, j int) | value
014: 25: 2 | add 100, 200 *ast.CallExpr | void : () | no value
015: 25: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
016: 25:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
017: 26: 2 | add *ast.Ident | var : func(i int, j int, k int) | variable
018: 26: 2 | add 100, 200, 300 *ast.CallExpr | void : () | no value
019: 26: 6 | 100 *ast.BasicLit | value : untyped int = 100 | constant
020: 26:11 | 200 *ast.BasicLit | value : untyped int = 200 | constant
021: 26:16 | 300 *ast.BasicLit | value : untyped int = 300 | constant
022: 27: 2 | add *ast.Ident | value : func(a string, b string) string | value
023: 27: 2 | add("hello", "world") *ast.CallExpr | value : string | value
024: 27: 6 | "hello" *ast.BasicLit | value : untyped string = "hello" | constant
025: 27:15 | "world" *ast.BasicLit | value : untyped string = "world" | constant
== defs ==
000: 0: 0 | Gopo_add | const main.Gopo_add untyped string
001: 2: 6 | addInt0 | func main.addInt0()
002: 5: 6 | addInt1 | func main.addInt1(i int)
003: 5:14 | i | var i int
004: 8: 6 | addInt2 | func main.addInt2(i int, j int)
005: 8:14 | i | var i int
006: 8:17 | j | var j int
007: 11: 5 | addInt3 | var main.addInt3 func(i int, j int, k int)
008: 11:20 | i | var i int
009: 11:23 | j | var j int
010: 11:26 | k | var k int
011: 14: 6 | add | func main.add(__gop_overload_args__ interface{_()})
012: 19: 2 | add__4 | func main.add__4(a string, b string) string
013: 19: 7 | a | var a string
014: 19:10 | b | var b string
015: 24: 6 | init | func main.init()
== uses ==
000: 5:16 | int | type int
001: 8:19 | int | type int
002: 11:28 | int | type int
003: 15: 2 | addInt0 | func main.addInt0()
004: 16: 2 | addInt1 | func main.addInt1(i int)
005: 17: 2 | addInt2 | func main.addInt2(i int, j int)
006: 18: 2 | addInt3 | var main.addInt3 func(i int, j int, k int)
007: 19:12 | string | type string
008: 19:20 | string | type string
009: 20:10 | a | var a string
010: 20:14 | b | var b string
011: 25: 2 | add | func main.addInt2(i int, j int)
012: 26: 2 | add | var main.addInt3 func(i int, j int, k int)
013: 27: 2 | add | func main.add__4(a string, b string) string`)
}

0 comments on commit c450177

Please sign in to comment.