Repository: goplus/gop
Pull request #1402 (2023-08-04 03:38:09)

cl: overload func match check
add multiple overload func match linked check.
https://github.com/visualfc/gop/blob/overload/cl/compile_test.go#L4410


Patch:
diff --git a/cl/expr.go b/cl/expr.go
index 2412d6f6..6349d347 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -430,6 +430,7 @@ func compilePkgRef(ctx *blockCtx, at *gox.PkgRef, x *ast.Ident, flags, pkgKind i
 }
 
 type fnType struct {
+	next     *fnType
 	params   *types.Tuple
 	n1       int
 	variadic bool
@@ -472,8 +473,15 @@ func (p *fnType) initWith(fnt types.Type, idx, nin int) {
 	p.inited = true
 	if t, ok := fnt.(*gox.TypeType); ok {
 		p.initTypeType(t)
-	} else if t := gox.CheckSignature(fnt, idx, nin); t != nil {
-		p.init(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
+		}
 	}
 }
 
@@ -496,7 +504,6 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
 	default:
 		compileExpr(ctx, fn)
 	}
-	var fn fnType
 	var fnt = ctx.cb.Get(-1).Type
 	var flags gox.InstrFlags
 	var ellipsis = v.Ellipsis != gotoken.NoPos
@@ -506,6 +513,27 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
 	if (inFlags & clCallWithTwoValue) != 0 {
 		flags |= gox.InstrFlagTwoValue
 	}
+	var fn *fnType = &fnType{}
+	for fn != nil {
+		err := compileCallArgs(fn, fnt, ctx, v, ellipsis, flags)
+		if err == nil {
+			break
+		}
+		if fn.next == nil {
+			panic(err)
+		}
+		fn = fn.next
+	}
+}
+
+func compileCallArgs(fn *fnType, fnt types.Type, ctx *blockCtx, v *ast.CallExpr, ellipsis bool, flags gox.InstrFlags) (err error) {
+	n := ctx.cb.InternalStack().Len()
+	defer func() {
+		if v := recover(); v != nil {
+			err = v.(error)
+			ctx.cb.InternalStack().SetLen(n)
+		}
+	}()
 	for i, arg := range v.Args {
 		switch expr := arg.(type) {
 		case *ast.LambdaExpr:
@@ -520,34 +548,31 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
 			fn.initWith(fnt, i, -1)
 			compileCompositeLit(ctx, expr, fn.arg(i, ellipsis), true)
 		case *ast.SliceLit:
-			if len(v.Args) == 1 {
-				fn.initWith(fnt, i, -2)
-				t := fn.arg(i, ellipsis)
-				switch t.(type) {
-				case *types.Slice:
-				case *types.Named:
-					if _, ok := getUnderlying(ctx, t).(*types.Slice); !ok {
-						t = nil
-					}
-				default:
+			fn.initWith(fnt, i, -2)
+			t := fn.arg(i, ellipsis)
+			switch t.(type) {
+			case *types.Slice:
+			case *types.Named:
+				if _, ok := getUnderlying(ctx, t).(*types.Slice); !ok {
 					t = nil
 				}
-				typetype := fn.typetype && t != nil
-				if typetype {
-					ctx.cb.InternalStack().Pop()
-				}
-				compileSliceLit(ctx, expr, t)
-				if typetype {
-					return
-				}
-			} else {
-				compileSliceLit(ctx, expr, nil)
+			default:
+				t = nil
+			}
+			typetype := fn.typetype && t != nil
+			if typetype {
+				ctx.cb.InternalStack().Pop()
+			}
+			compileSliceLit(ctx, expr, t)
+			if typetype {
+				return
 			}
 		default:
 			compileExpr(ctx, arg)
 		}
 	}
 	ctx.cb.CallWith(len(v.Args), flags, v)
+	return
 }
 
 type clLambaFlag string
@@ -862,6 +887,7 @@ func compileSliceLit(ctx *blockCtx, v *ast.SliceLit, typ types.Type) {
 	} else {
 		ctx.cb.SliceLit(typ, n)
 	}
+	return
 }
 
 func compileRangeExpr(ctx *blockCtx, v *ast.RangeExpr) {
diff --git a/cl/internal/overload/foo/foo.go b/cl/internal/overload/foo/foo.go
new file mode 100644
index 00000000..ec75b1fc
--- /dev/null
+++ b/cl/internal/overload/foo/foo.go
@@ -0,0 +1,58 @@
+package foo
+
+const GopPackage = true
+
+type Mesher interface {
+	Name() string
+}
+
+type N struct {
+}
+
+func (m *N) OnKey__0(a string, fn func()) {
+}
+
+func (m *N) OnKey__1(a string, fn func(key string)) {
+}
+
+func (m *N) OnKey__2(a []string, fn func()) {
+}
+
+func (m *N) OnKey__3(a []string, fn func(key string)) {
+}
+
+func (m *N) OnKey__4(a []Mesher, fn func()) {
+}
+
+func (m *N) OnKey__5(a []Mesher, fn func(key Mesher)) {
+}
+
+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 OnKey__0(a string, fn func()) {
+}
+
+func OnKey__1(a string, fn func(key string)) {
+}
+
+func OnKey__2(a []string, fn func()) {
+}
+
+func OnKey__3(a []string, fn func(key string)) {
+}
+
+func OnKey__4(a []Mesher, fn func()) {
+}
+
+func OnKey__5(a []Mesher, fn func(key Mesher)) {
+}
+
+func OnKey__6(a []string, b []string, fn func(key string)) {
+}
+
+func OnKey__7(a []string, b []Mesher, fn func(key string)) {
+}
diff --git a/go.mod b/go.mod
index 55a6de2d..c433c26e 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.16
 
 require (
 	github.com/goplus/c2go v0.7.13
-	github.com/goplus/gox v1.11.36
+	github.com/goplus/gox v1.11.37
 	github.com/goplus/libc v0.3.13
 	github.com/goplus/mod v0.10.1
 	github.com/qiniu/x v1.11.9
diff --git a/go.sum b/go.sum
index ee4f911d..807da170 100644
--- a/go.sum
+++ b/go.sum
@@ -7,8 +7,8 @@ github.com/goplus/c2go v0.7.13 h1:188dkHVVS3Qn/cwFtFwNgvlgjY2tBrZRjugv8icolt4=
 github.com/goplus/c2go v0.7.13/go.mod h1:s5NULWzUKi3erd3l4ahvpq+3qDGOvMjGb00a5o3h6zk=
 github.com/goplus/gox v1.11.21/go.mod h1:wRCRSNukie4cDqADF4w0Btc2Gk6V3p3V6hI5+rsVqa8=
 github.com/goplus/gox v1.11.32/go.mod h1:hdKq5ghywtKWnBJNQNVBkPITmWCqCFRwwd2LTYTfg2U=
-github.com/goplus/gox v1.11.36 h1:OUkGM117o1WwOf2SB2DZHHHTOybOXbqu8BrSL95cXZE=
-github.com/goplus/gox v1.11.36/go.mod h1:l1p0XjHQoFhQQZqEtJjMt8o0CuvS3iE5PIGwwTHsgQ4=
+github.com/goplus/gox v1.11.37 h1:8oAXjokhvttO/4NZgfAJ02GE9OivbX2VSsEJWu3fGng=
+github.com/goplus/gox v1.11.37/go.mod h1:NkgUJWIjKxrhUwM4bgyUt3ZE0WlTunqfksMzrbnh7V8=
 github.com/goplus/libc v0.3.13 h1:2yHG8ghezBTK3Da7Fw1lNiitmt+Va+RzwKJ5GuqypCQ=
 github.com/goplus/libc v0.3.13/go.mod h1:xqG4/g3ilKBE/UDn5vkaE7RRQPQPyspj7ecuMuvlQJ8=
 github.com/goplus/mod v0.9.12/go.mod h1:YoPIowz71rnLLROA4YG0AC8bzDtPRyMaQwgTRLr8ri4=
@@ -86,6 +86,6 @@ golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k=
 golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
-golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
+golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc=
+golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index 6ffe1299..acec2b7f 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -4406,3 +4406,112 @@ func (this *Rect) test() {
 }
 `, "Rect.gopx")
 }
+
+func TestOverload(t *testing.T) {
+	gopClTest(t, `
+import "github.com/goplus/gop/cl/internal/overload/foo"
+
+type Mesh struct {
+}
+
+func (p *Mesh) Name() string {
+	return "hello"
+}
+
+var (
+	m1 = &Mesh{}
+	m2 = &Mesh{}
+)
+
+foo.onKey "hello", => {
+}
+foo.onKey "hello", key => {
+}
+foo.onKey ["1"], => {
+}
+foo.onKey ["2"], key => {
+}
+foo.onKey [m1,m2], => {
+}
+foo.onKey [m1,m2], key => {
+}
+foo.onKey ["a"], ["b"], key => {
+}
+foo.onKey ["a"], [m1,m2], key => {
+}
+foo.onKey ["a"],nil,key => {
+}
+n := &foo.N{}
+n.onKey "hello", => {
+}
+n.onKey "hello", key => {
+}
+n.onKey ["1"], => {
+}
+n.onKey ["2"], key => {
+}
+n.onKey [m1,m2], => {
+}
+n.onKey [m1,m2], key => {
+}
+n.onKey ["a"], ["b"], key => {
+}
+n.onKey ["a"], [m1,m2], key => {
+}
+n.onKey ["a"],nil,key => {
+}
+`, `package main
+
+import foo "github.com/goplus/gop/cl/internal/overload/foo"
+
+type Mesh struct {
+}
+
+func (p *Mesh) Name() string {
+	return "hello"
+}
+
+var m1 = &Mesh{}
+var m2 = &Mesh{}
+
+func main() {
+	foo.OnKey__0("hello", func() {
+	})
+	foo.OnKey__1("hello", func(key string) {
+	})
+	foo.OnKey__2([]string{"1"}, func() {
+	})
+	foo.OnKey__3([]string{"2"}, func(key string) {
+	})
+	foo.OnKey__4([]foo.Mesher{m1, m2}, func() {
+	})
+	foo.OnKey__5([]foo.Mesher{m1, m2}, func(key foo.Mesher) {
+	})
+	foo.OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
+	})
+	foo.OnKey__7([]string{"a"}, []foo.Mesher{m1, m2}, func(key string) {
+	})
+	foo.OnKey__6([]string{"a"}, nil, func(key string) {
+	})
+	n := &foo.N{}
+	n.OnKey__0("hello", func() {
+	})
+	n.OnKey__1("hello", func(key string) {
+	})
+	n.OnKey__2([]string{"1"}, func() {
+	})
+	n.OnKey__3([]string{"2"}, func(key string) {
+	})
+	n.OnKey__4([]foo.Mesher{m1, m2}, func() {
+	})
+	n.OnKey__5([]foo.Mesher{m1, m2}, func(key foo.Mesher) {
+	})
+	n.OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
+	})
+	n.OnKey__7([]string{"a"}, []foo.Mesher{m1, m2}, func(key string) {
+	})
+	n.OnKey__6([]string{"a"}, nil, func(key string) {
+	})
+}
+`)
+}