Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cl: mixed overload #1562

Merged
merged 3 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 42 additions & 11 deletions cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ package cl

import (
"fmt"
"go/constant"
"go/types"
"log"
"os"
"path/filepath"
"reflect"
"sort"
"strings"
_ "unsafe"

"github.com/goplus/gop/ast"
"github.com/goplus/gop/ast/fromgo"
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
270 changes: 270 additions & 0 deletions cl/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
}
`)
}