diff --git a/cl/compile.go b/cl/compile.go index 248377275..655583885 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 { diff --git a/cl/compile_test.go b/cl/compile_test.go index 3f91ef2c8..7fcbe6f02 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)) +} +`) +}