Repository: goplus/gop
Pull request #1584 (2023-12-15 12:42:24)

cl: fnType support TyTemplateRecvMethod overload funcs
- support TyTemplateRecvMethod overload funcs
- fix lambda variadic func call 
   eg. ( func OnKey__9(a, b string, fn ...func(x int) int) )


Patch:
diff --git a/cl/expr.go b/cl/expr.go
index fbb06724..1d1576e9 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -457,18 +457,18 @@ func compilePkgRef(ctx *blockCtx, at *gox.PkgRef, x *ast.Ident, flags, pkgKind i
 type fnType struct {
 	next     *fnType
 	params   *types.Tuple
-	n1       int
+	base     int
+	size     int
 	variadic bool
 	typetype bool
-	inited   bool
 }
 
 func (p *fnType) arg(i int, ellipsis bool) types.Type {
-	if i < p.n1 {
-		return p.params.At(i).Type()
+	if i+p.base < p.size {
+		return p.params.At(i + p.base).Type()
 	}
 	if p.variadic {
-		t := p.params.At(p.n1).Type()
+		t := p.params.At(p.size).Type()
 		if ellipsis {
 			return t
 		}
@@ -477,35 +477,62 @@ func (p *fnType) arg(i int, ellipsis bool) types.Type {
 	return nil
 }
 
-func (p *fnType) init(t *types.Signature) {
+func (p *fnType) init(base int, t *types.Signature) {
+	p.base = base
 	p.params, p.variadic = t.Params(), t.Variadic()
-	p.n1 = p.params.Len()
+	p.size = p.params.Len()
 	if p.variadic {
-		p.n1--
+		p.size--
 	}
 }
 
 func (p *fnType) initTypeType(t *gox.TypeType) {
 	param := types.NewParam(0, nil, "", t.Type())
 	p.params, p.typetype = types.NewTuple(param), true
-	p.n1 = 1
+	p.size = 1
 }
 
-func (p *fnType) initWith(fnt types.Type, idx, nin int) {
-	if p.inited {
-		return
+func (p *fnType) load(fnt types.Type) {
+	switch v := fnt.(type) {
+	case *gox.TypeType:
+		p.initTypeType(v)
+	case *types.Signature:
+		if typ, ok := gox.CheckFuncEx(v); ok {
+			switch t := typ.(type) {
+			case *gox.TyOverloadFunc:
+				p.initFuncs(0, t.Funcs...)
+				return
+			case *gox.TyOverloadMethod:
+				p.initFuncs(0, t.Methods...)
+				return
+			case *gox.TyTemplateRecvMethod:
+				if tsig, ok := t.Func.Type().(*types.Signature); ok {
+					if ex, ok := gox.CheckFuncEx(tsig); ok {
+						if t, ok := ex.(*gox.TyOverloadFunc); ok {
+							p.initFuncs(1, t.Funcs...)
+							return
+						}
+					}
+				}
+				p.initFuncs(1, t.Func)
+				return
+			}
+		}
+		p.init(0, v)
 	}
-	p.inited = true
-	if t, ok := fnt.(*gox.TypeType); ok {
-		p.initTypeType(t)
-	} else if t := gox.CheckSignatures(fnt, idx, nin); t != nil {
-		p.init(t[0])
-		for i := 1; i < len(t); i++ {
-			fn := &fnType{}
-			fn.inited = true
-			fn.init(t[i])
-			p.next = fn
-			p = p.next
+}
+
+func (p *fnType) initFuncs(base int, funcs ...types.Object) {
+	for i, obj := range funcs {
+		if sig, ok := obj.Type().(*types.Signature); ok {
+			if i == 0 {
+				p.init(base, sig)
+			} else {
+				fn := &fnType{}
+				fn.init(base, sig)
+				p.next = fn
+				p = p.next
+			}
 		}
 	}
 }
@@ -538,13 +565,11 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
 	if (inFlags & clCallWithTwoValue) != 0 {
 		flags |= gox.InstrFlagTwoValue
 	}
-	var fn *fnType = &fnType{}
+	fn := &fnType{}
+	fn.load(fnt)
 	for fn != nil {
-		err := compileCallArgs(fn, fnt, ctx, v, ellipsis, flags)
+		err := compileCallArgs(fn, ctx, v, ellipsis, flags)
 		if err == nil {
-			if rec := ctx.recorder(); rec != nil {
-				rec.recordCallExpr(ctx, v, fnt)
-			}
 			break
 		}
 		if fn.next == nil {
@@ -552,9 +577,12 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
 		}
 		fn = fn.next
 	}
+	if rec := ctx.recorder(); rec != nil {
+		rec.recordCallExpr(ctx, v, fnt)
+	}
 }
 
-func compileCallArgs(fn *fnType, fnt types.Type, ctx *blockCtx, v *ast.CallExpr, ellipsis bool, flags gox.InstrFlags) (err error) {
+func compileCallArgs(fn *fnType, ctx *blockCtx, v *ast.CallExpr, ellipsis bool, flags gox.InstrFlags) (err error) {
 	n := ctx.cb.InternalStack().Len()
 	defer func() {
 		if r := recover(); r != nil {
@@ -570,18 +598,14 @@ func compileCallArgs(fn *fnType, fnt types.Type, ctx *blockCtx, v *ast.CallExpr,
 	for i, arg := range v.Args {
 		switch expr := arg.(type) {
 		case *ast.LambdaExpr:
-			fn.initWith(fnt, i, len(expr.Lhs))
-			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, true), clLambaArgument, v.Fun)
+			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, ellipsis), clLambaArgument, v.Fun)
 			compileLambdaExpr(ctx, expr, sig)
 		case *ast.LambdaExpr2:
-			fn.initWith(fnt, i, len(expr.Lhs))
-			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, true), clLambaArgument, v.Fun)
+			sig := checkLambdaFuncType(ctx, expr, fn.arg(i, ellipsis), clLambaArgument, v.Fun)
 			compileLambdaExpr2(ctx, expr, sig)
 		case *ast.CompositeLit:
-			fn.initWith(fnt, i, -1)
 			compileCompositeLit(ctx, expr, fn.arg(i, ellipsis), true)
 		case *ast.SliceLit:
-			fn.initWith(fnt, i, -2)
 			t := fn.arg(i, ellipsis)
 			switch t.(type) {
 			case *types.Slice:
diff --git a/cl/internal/overload/foo/foo.go b/cl/internal/overload/foo/foo.go
index ec75b1fc..a670cc57 100644
--- a/cl/internal/overload/foo/foo.go
+++ b/cl/internal/overload/foo/foo.go
@@ -33,6 +33,9 @@ func (m *N) OnKey__6(a []string, b []string, fn func(key string)) {
 func (m *N) OnKey__7(a []string, b []Mesher, fn func(key string)) {
 }
 
+func (m *N) OnKey__8(x int, y int) {
+}
+
 func OnKey__0(a string, fn func()) {
 }
 
@@ -56,3 +59,6 @@ func OnKey__6(a []string, b []string, fn func(key string)) {
 
 func OnKey__7(a []string, b []Mesher, fn func(key string)) {
 }
+
+func OnKey__8(x int, y int) {
+}
diff --git a/cl/internal/spx/sprite.go b/cl/internal/spx/sprite.go
index b6b0615f..bdcf7c22 100644
--- a/cl/internal/spx/sprite.go
+++ b/cl/internal/spx/sprite.go
@@ -43,8 +43,42 @@ func (p *Sprite) Position() *pkg.Vector {
 	return &p.pos
 }
 
+type Mesher interface {
+	Name() string
+}
+
 func Gopt_Sprite_Clone__0(sprite interface{}) {
 }
 
 func Gopt_Sprite_Clone__1(sprite interface{}, data interface{}) {
 }
+
+func Gopt_Sprite_OnKey__0(sprite interface{}, a string, fn func()) {
+}
+
+func Gopt_Sprite_OnKey__1(sprite interface{}, a string, fn func(key string)) {
+}
+
+func Gopt_Sprite_OnKey__2(sprite interface{}, a []string, fn func()) {
+}
+
+func Gopt_Sprite_OnKey__3(sprite interface{}, a []string, fn func(key string)) {
+}
+
+func Gopt_Sprite_OnKey__4(sprite interface{}, a []Mesher, fn func()) {
+}
+
+func Gopt_Sprite_OnKey__5(sprite interface{}, a []Mesher, fn func(key Mesher)) {
+}
+
+func Gopt_Sprite_OnKey__6(sprite interface{}, a []string, b []string, fn func(key string)) {
+}
+
+func Gopt_Sprite_OnKey__7(sprite interface{}, a []string, b []Mesher, fn func(key string)) {
+}
+
+func Gopt_Sprite_OnKey__8(sprite interface{}, x int, y int) {
+}
+
+func Gopt_Sprite_OnKey2(sprite interface{}, a string, fn func(key string)) {
+}
diff --git a/cmd/make.go b/cmd/make.go
index d04c52c4..2886a84b 100644
--- a/cmd/make.go
+++ b/cmd/make.go
@@ -34,7 +34,7 @@ import (
 )
 
 func checkPathExist(path string, isDir bool) bool {
-	stat, err := os.Lstat(path) // Note: os.Lstat() will not follow the symbolic link.
+	stat, err := os.Stat(path)
 	isExists := !os.IsNotExist(err)
 	if isDir {
 		return isExists && stat.IsDir()
diff --git a/go.mod b/go.mod
index 31e089c5..7dacf2d4 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,7 @@ require (
 	github.com/goplus/c2go v0.7.18
 	github.com/goplus/gox v1.13.1
 	github.com/goplus/mod v0.11.10-0.20231210062211-b9032d0f7810
-	github.com/qiniu/x v1.13.2
+	github.com/qiniu/x v1.13.1
 	golang.org/x/tools v0.16.1
 )
 
diff --git a/go.sum b/go.sum
index a154d83f..5cbf501a 100644
--- a/go.sum
+++ b/go.sum
@@ -19,9 +19,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/qiniu/x v1.13.1 h1:hi7tkXFq6BWGbBpMoLV7kvA2elop69j6Kl7TlxnFAiU=
 github.com/qiniu/x v1.13.1/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
-github.com/qiniu/x v1.13.2 h1:mgWOfB9Rpk6AEtlBoObZVxH+b2FHSntYrxc4KX5Ta98=
-github.com/qiniu/x v1.13.2/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=


Test patch:
diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go
index cbb010e7..4817c105 100644
--- a/cl/compile_spx_test.go
+++ b/cl/compile_spx_test.go
@@ -792,3 +792,104 @@ func (this *Kai) onMsg(msg string) {
 }
 `, "Game.tgmx", "Kai.tspx")
 }
+
+func TestSpxOverload(t *testing.T) {
+	gopSpxTestEx(t, `
+var (
+	Kai Kai
+)
+
+func onInit() {
+	Kai.onKey "hello", key => {
+	}
+}
+`, `
+var (
+	a int
+)
+
+type Mesh struct {
+}
+
+func (p *Mesh) Name() string {
+	return "hello"
+}
+
+var (
+	m1 = &Mesh{}
+	m2 = &Mesh{}
+)
+
+onKey "hello", => {
+}
+onKey "hello", key => {
+}
+onKey ["1"], => {
+}
+onKey ["2"], key => {
+}
+onKey [m1, m2], => {
+}
+onKey [m1, m2], key => {
+}
+onKey ["a"], ["b"], key => {
+}
+onKey ["a"], [m1, m2], key => {
+}
+onKey ["a"], nil, key => {
+}
+onKey 100, 200
+onKey2 "hello", key => {
+}
+`, `package main
+
+import "github.com/goplus/gop/cl/internal/spx"
+
+type Mesh struct {
+}
+type Kai struct {
+	spx.Sprite
+	*Game
+	a int
+}
+type Game struct {
+	*spx.MyGame
+	Kai Kai
+}
+
+func (this *Game) onInit() {
+	spx.Gopt_Sprite_OnKey__1(this.Kai, "hello", func(key string) {
+	})
+}
+func (p *Mesh) Name() string {
+	return "hello"
+}
+
+var m1 = &Mesh{}
+var m2 = &Mesh{}
+
+func (this *Kai) Main() {
+	spx.Gopt_Sprite_OnKey__0(this, "hello", func() {
+	})
+	spx.Gopt_Sprite_OnKey__1(this, "hello", func(key string) {
+	})
+	spx.Gopt_Sprite_OnKey__2(this, []string{"1"}, func() {
+	})
+	spx.Gopt_Sprite_OnKey__3(this, []string{"2"}, func(key string) {
+	})
+	spx.Gopt_Sprite_OnKey__4(this, []spx.Mesher{m1, m2}, func() {
+	})
+	spx.Gopt_Sprite_OnKey__5(this, []spx.Mesher{m1, m2}, func(key spx.Mesher) {
+	})
+	spx.Gopt_Sprite_OnKey__6(this, []string{"a"}, []string{"b"}, func(key string) {
+	})
+	spx.Gopt_Sprite_OnKey__7(this, []string{"a"}, []spx.Mesher{m1, m2}, func(key string) {
+	})
+	spx.Gopt_Sprite_OnKey__6(this, []string{"a"}, nil, func(key string) {
+	})
+	spx.Gopt_Sprite_OnKey__8(this, 100, 200)
+	spx.Gopt_Sprite_OnKey2(this, "hello", func(key string) {
+	})
+}
+`, "Game.tgmx", "Kai.tspx")
+}
diff --git a/cl/compile_test.go b/cl/compile_test.go
index 7fcbe6f0..42397d3b 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -4476,16 +4476,18 @@ foo.onKey ["1"], => {
 }
 foo.onKey ["2"], key => {
 }
-foo.onKey [m1,m2], => {
+foo.onKey [m1, m2], => {
 }
-foo.onKey [m1,m2], key => {
+foo.onKey [m1, m2], key => {
 }
 foo.onKey ["a"], ["b"], key => {
 }
-foo.onKey ["a"], [m1,m2], key => {
+foo.onKey ["a"], [m1, m2], key => {
 }
-foo.onKey ["a"],nil,key => {
+foo.onKey ["a"], nil, key => {
 }
+foo.onKey 100, 200
+
 n := &foo.N{}
 n.onKey "hello", => {
 }
@@ -4495,16 +4497,17 @@ n.onKey ["1"], => {
 }
 n.onKey ["2"], key => {
 }
-n.onKey [m1,m2], => {
+n.onKey [m1, m2], => {
 }
-n.onKey [m1,m2], key => {
+n.onKey [m1, m2], key => {
 }
 n.onKey ["a"], ["b"], key => {
 }
-n.onKey ["a"], [m1,m2], key => {
+n.onKey ["a"], [m1, m2], key => {
 }
-n.onKey ["a"],nil,key => {
+n.onKey ["a"], nil, key => {
 }
+n.onKey 100, 200
 `, `package main
 
 import "github.com/goplus/gop/cl/internal/overload/foo"
@@ -4538,6 +4541,7 @@ func main() {
 	})
 	foo.OnKey__6([]string{"a"}, nil, func(key string) {
 	})
+	foo.OnKey__8(100, 200)
 	n := &foo.N{}
 	n.OnKey__0("hello", func() {
 	})
@@ -4557,6 +4561,7 @@ func main() {
 	})
 	n.OnKey__6([]string{"a"}, nil, func(key string) {
 	})
+	n.OnKey__8(100, 200)
 }
 `)
 }
@@ -4750,6 +4755,10 @@ func (m *N) OnKey__6(a []string, b []string, fn func(key string)) {
 func (m *N) OnKey__7(a []string, b []Mesher, fn func(key string)) {
 }
 
+func (m *N) OnKey__8(x int, y int) {
+}
+
+
 func OnKey__0(a string, fn func()) {
 }
 
@@ -4773,6 +4782,15 @@ func OnKey__6(a []string, b []string, fn func(key string)) {
 
 func OnKey__7(a []string, b []Mesher, fn func(key string)) {
 }
+
+func OnKey__8(x int, y int) {
+}
+
+func OnKey__9(a, b string, fn ...func(x int) int) {
+}
+
+func OnKey__a(a, b string, v ...int) {
+}
 `, `
 type Mesh struct {
 }
@@ -4794,16 +4812,23 @@ OnKey ["1"], => {
 }
 OnKey ["2"], key => {
 }
-OnKey [m1,m2], => {
+OnKey [m1, m2], => {
 }
-OnKey [m1,m2], key => {
+OnKey [m1, m2], key => {
 }
 OnKey ["a"], ["b"], key => {
 }
-OnKey ["a"], [m1,m2], key => {
+OnKey ["a"], [m1, m2], key => {
+}
+OnKey ["a"], nil, key => {
 }
-OnKey ["a"],nil,key => {
+OnKey 100, 200
+OnKey "a", "b", x => x * x, x => {
+	return x * 2
 }
+OnKey "a", "b", 1, 2, 3
+OnKey("a", "b", [1, 2, 3]...)
+
 n := &N{}
 n.onKey "hello", => {
 }
@@ -4813,16 +4838,17 @@ n.onKey ["1"], => {
 }
 n.onKey ["2"], key => {
 }
-n.onKey [m1,m2], => {
+n.onKey [m1, m2], => {
 }
-n.onKey [m1,m2], key => {
+n.onKey [m1, m2], key => {
 }
 n.onKey ["a"], ["b"], key => {
 }
-n.onKey ["a"], [m1,m2], key => {
+n.onKey ["a"], [m1, m2], key => {
 }
-n.onKey ["a"],nil,key => {
+n.onKey ["a"], nil, key => {
 }
+n.onKey 100, 200
 `, `package main
 
 type Mesh struct {
@@ -4854,6 +4880,14 @@ func main() {
 	})
 	OnKey__6([]string{"a"}, nil, func(key string) {
 	})
+	OnKey__8(100, 200)
+	OnKey__9("a", "b", func(x int) int {
+		return x * x
+	}, func(x int) int {
+		return x * 2
+	})
+	OnKey__a("a", "b", 1, 2, 3)
+	OnKey__a("a", "b", []int{1, 2, 3}...)
 	n := &N{}
 	n.OnKey__0("hello", func() {
 	})
@@ -4873,6 +4907,7 @@ func main() {
 	})
 	n.OnKey__6([]string{"a"}, nil, func(key string) {
 	})
+	n.OnKey__8(100, 200)
 }
 `)
 }