Repository: goplus/gop
Pull request #1562 (2023-11-27 02:19:40)

cl: mixed overload


Patch:
diff --git a/cl/compile.go b/cl/compile.go
index 24837727..65558388 100644
--- a/cl/compile.go
+++ b/cl/compile.go
@@ -19,6 +19,7 @@ package cl
 
 import (
 	"fmt"
+	"go/constant"
 	"go/types"
 	"log"
 	"os"
@@ -26,6 +27,7 @@ import (
 	"reflect"
 	"sort"
 	"strings"
+	_ "unsafe"
 
 	"github.com/goplus/gop/ast"
 	"github.com/goplus/gop/ast/fromgo"
@@ -563,6 +565,20 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 			}
 		}
 	}
+
+	gofiles := make([]*ast.File, 0, len(pkg.GoFiles))
+	for fpath, gof := range pkg.GoFiles {
+		f := fromgo.ASTFile(gof, 0)
+		gofiles = append(gofiles, f)
+		ctx := &blockCtx{
+			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir,
+			imports: make(map[string]pkgImp),
+		}
+		preloadFile(p, ctx, fpath, f, false, false)
+	}
+
+	initGopPkg(ctx, p)
+
 	for fpath, f := range files {
 		fileLine := !conf.NoFileLine
 		fileScope := types.NewScope(p.Types.Scope(), f.Pos(), f.End(), fpath)
@@ -577,17 +593,6 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 		preloadGopFile(p, ctx, fpath, f, conf)
 	}
 
-	gofiles := make([]*ast.File, 0, len(pkg.GoFiles))
-	for fpath, gof := range pkg.GoFiles {
-		f := fromgo.ASTFile(gof, 0)
-		gofiles = append(gofiles, f)
-		ctx := &blockCtx{
-			pkg: p, pkgCtx: ctx, cb: p.CB(), targetDir: targetDir,
-			imports: make(map[string]pkgImp),
-		}
-		preloadFile(p, ctx, fpath, f, false, false)
-	}
-
 	// sort files
 	type File struct {
 		*ast.File
@@ -636,6 +641,32 @@ func NewPackage(pkgPath string, pkg *ast.Package, conf *Config) (p *gox.Package,
 	return
 }
 
+const (
+	gopPackage = "GopPackage"
+)
+
+func isOverloadFunc(name string) bool {
+	n := len(name)
+	return n > 3 && name[n-3:n-1] == "__"
+}
+
+//go:linkname initThisGopPkg github.com/goplus/gox.initThisGopPkg
+func initThisGopPkg(pkg *types.Package)
+
+func initGopPkg(ctx *pkgCtx, pkg *gox.Package) {
+	for name, f := range ctx.syms {
+		if _, ok := f.(*typeLoader); ok {
+			ctx.loadType(name)
+		} else if isOverloadFunc(name) {
+			ctx.loadSymbol(name)
+		}
+	}
+	if pkg.Types.Scope().Lookup(gopPackage) == nil {
+		pkg.Types.Scope().Insert(types.NewConst(token.NoPos, pkg.Types, gopPackage, nil, constant.MakeBool(true)))
+	}
+	initThisGopPkg(pkg.Types)
+}
+
 func hasMethod(o types.Object, name string) bool {
 	if obj, ok := o.(*types.TypeName); ok {
 		if t, ok := obj.Type().(*types.Named); ok {


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index 3f91ef2c..7fcbe6f0 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -4714,3 +4714,273 @@ func main() {
 	}
 	gopClTestEx(t, &conf, "main", src, expected)
 }
+
+func TestMixedOverload(t *testing.T) {
+	gopMixedClTest(t, "main", `
+package main
+
+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)) {
+}
+`, `
+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 => {
+}
+n := &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
+
+type Mesh struct {
+}
+
+func (p *Mesh) Name() string {
+	return "hello"
+}
+
+var m1 = &Mesh{}
+var m2 = &Mesh{}
+
+func main() {
+	OnKey__0("hello", func() {
+	})
+	OnKey__1("hello", func(key string) {
+	})
+	OnKey__2([]string{"1"}, func() {
+	})
+	OnKey__3([]string{"2"}, func(key string) {
+	})
+	OnKey__4([]Mesher{m1, m2}, func() {
+	})
+	OnKey__5([]Mesher{m1, m2}, func(key Mesher) {
+	})
+	OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
+	})
+	OnKey__7([]string{"a"}, []Mesher{m1, m2}, func(key string) {
+	})
+	OnKey__6([]string{"a"}, nil, func(key string) {
+	})
+	n := &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([]Mesher{m1, m2}, func() {
+	})
+	n.OnKey__5([]Mesher{m1, m2}, func(key Mesher) {
+	})
+	n.OnKey__6([]string{"a"}, []string{"b"}, func(key string) {
+	})
+	n.OnKey__7([]string{"a"}, []Mesher{m1, m2}, func(key string) {
+	})
+	n.OnKey__6([]string{"a"}, nil, func(key string) {
+	})
+}
+`)
+}
+
+func TestMixedOverloadOp(t *testing.T) {
+	gopMixedClTest(t, "main", `package main
+
+import "fmt"
+
+type foo struct {
+}
+
+func (a *foo) Gop_Add(b *foo) *foo {
+	fmt.Println("a + b")
+	return &foo{}
+}
+func (a foo) Gop_Sub(b foo) foo {
+	fmt.Println("a - b")
+	return foo{}
+}
+func (a foo) Gop_NE(b foo) bool {
+	fmt.Println("a!=b")
+	return true
+}
+func (a foo) Gop_Neg() *foo {
+	fmt.Println("-a")
+	return &foo{}
+}
+func (a foo) Gop_Inc() {
+	fmt.Println("a++")
+}
+`, `
+var a, b foo
+var c = a - b
+var d = -a
+var e = a!=b
+`, `package main
+
+var a, b foo
+var c = a.Gop_Sub(b)
+var d = a.Gop_Neg()
+var e = a.Gop_NE(b)
+`)
+}
+
+func TestMixedVector3(t *testing.T) {
+	gopMixedClTest(t, "main", `package main
+type Vector3 struct {
+	x, y, z float64
+}
+func (a Vector3) Gop_Add__0(n int) Vector3 {
+	return Vector3{}
+}
+func (a Vector3) Gop_Add__1(n float64) Vector3 {
+	return Vector3{}
+}
+func (a Vector3) Gop_Add__2(n Vector3) Vector3 {
+	return Vector3{}
+}
+func (a *Vector3) Gop_AddAssign(n Vector3) {
+}
+
+func (a Vector3) Gop_Rcast__0() int {
+	return 0
+}
+func (a Vector3) Gop_Rcast__1() float64 {
+	return 0
+}
+
+func Vector3_Cast__0(x int) Vector3 {
+	return Vector3{}
+}
+func Vector3_Cast__1(x float64) Vector3 {
+	return Vector3{}
+}
+func Vector3_Init__0(x int) Vector3 {
+	return Vector3{}
+}
+func Vector3_Init__1(x float64) Vector3 {
+	return Vector3{}
+}
+`, `
+var a Vector3
+var b int
+var c float64
+_ = a+b
+_ = a+100
+_ = a+c
+_ = 100+a
+_ = Vector3(b)+a
+_ = b+int(a)
+a += b
+a += c
+`, `package main
+
+var a Vector3
+var b int
+var c float64
+
+func main() {
+	_ = a.Gop_Add__0(b)
+	_ = a.Gop_Add__0(100)
+	_ = a.Gop_Add__1(c)
+	_ = Vector3_Init__0(100) + a
+	_ = Vector3_Cast__0(b).Gop_Add__2(a)
+	_ = b + a.Gop_Rcast__0()
+	a.Gop_AddAssign(Vector3_Init__0(b))
+	a.Gop_AddAssign(Vector3_Init__1(c))
+}
+`)
+}