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

static method #424

Merged
merged 1 commit into from
Apr 12, 2024
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
6 changes: 5 additions & 1 deletion builtin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,10 @@ func TestErrMethodSig(t *testing.T) {
arg := &Element{
Type: &TypeType{typ: types.NewPointer(recv)},
}
methodSigOf(method, memberFlagMethodToFunc, arg, &ast.SelectorExpr{Sel: ast.NewIdent("bar")})
ret := &Element{
Val: &ast.SelectorExpr{Sel: ast.NewIdent("bar")},
}
pkg.cb.methodSigOf(method, memberFlagMethodToFunc, arg, ret)
})
}

Expand Down Expand Up @@ -797,6 +800,7 @@ func TestTypeEx(t *testing.T) {
&unboundMapElemType{},
&TyOverloadFunc{},
&TyOverloadMethod{},
&TyStaticMethod{},
&TyTemplateRecvMethod{},
&TyInstruction{},
&TyOverloadNamed{Obj: types.NewTypeName(0, pkg.Types, "bar", tyInt)},
Expand Down
40 changes: 22 additions & 18 deletions codebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -1740,16 +1740,9 @@ func (p *CodeBuilder) method(
}

sel := selector(arg, found.Name())
ret := &internal.Elem{
Val: sel,
Type: methodSigOf(typ, flag, arg, sel),
Src: src,
}
// TODO: We should take `methodSigOf` more seriously
if trm, ok := ret.Type.(*TyTemplateRecvMethod); ok {
o := trm.Func
ret.Val = toObjectExpr(p.pkg, o)
ret.Type = o.Type()
ret := &internal.Elem{Val: sel, Src: src}
if t, set := p.methodSigOf(typ, flag, arg, ret); set {
ret.Type = t
}
p.stk.Ret(1, ret)

Expand Down Expand Up @@ -1869,7 +1862,7 @@ func toFuncSig(sig *types.Signature, recv *types.Var) *types.Signature {
func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature {
sig := o.Type().(*types.Signature)
recv := sig.Recv()
if recv == nil {
if recv == nil { // special signature
fn.Val = toObjectExpr(pkg, o)
return sig
}
Expand All @@ -1880,20 +1873,24 @@ func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature
return toFuncSig(sig, recv)
}

func methodSigOf(typ types.Type, flag MemberFlag, arg *Element, sel *ast.SelectorExpr) types.Type {
func (p *CodeBuilder) methodSigOf(typ types.Type, flag MemberFlag, arg, ret *Element) (types.Type, bool) {
if flag != memberFlagMethodToFunc {
return methodCallSig(typ)
return methodCallSig(typ), true
}

sig := typ.(*types.Signature)
if t, ok := CheckFuncEx(sig); ok {
if trm, ok := t.(*TyTemplateRecvMethod); ok {
// TODO: We should take `methodSigOf` more seriously
return trm
switch ext := t.(type) {
case *TyStaticMethod:
return p.funcExSigOf(ext.Func, ret)
case *TyTemplateRecvMethod:
return p.funcExSigOf(ext.Func, ret)
}
return typ
// TODO: We should take `methodSigOf` more seriously
return typ, true
}

sel := ret.Val.(*ast.SelectorExpr)
at := arg.Type.(*TypeType).typ
recv := sig.Recv().Type()
_, isPtr := recv.(*types.Pointer) // recv is a pointer
Expand All @@ -1909,12 +1906,19 @@ func methodSigOf(typ types.Type, flag MemberFlag, arg *Element, sel *ast.Selecto
}
sel.X = &ast.ParenExpr{X: sel.X}

return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at))
return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at)), true
}

func (p *CodeBuilder) funcExSigOf(o types.Object, ret *Element) (types.Type, bool) {
ret.Val = toObjectExpr(p.pkg, o)
ret.Type = o.Type()
return nil, false
}

func methodCallSig(typ types.Type) types.Type {
sig := typ.(*types.Signature)
if _, ok := CheckFuncEx(sig); ok {
// TODO: We should take `methodSigOf` more seriously
return typ
}
return types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic())
Expand Down
15 changes: 15 additions & 0 deletions func_ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,21 @@ func (p *tyTypeAsParams) funcEx() {}

// ----------------------------------------------------------------------------

type TyStaticMethod struct {
Func types.Object
}

func (p *TyStaticMethod) Obj() types.Object { return p.Func }
func (p *TyStaticMethod) Underlying() types.Type { return p }
func (p *TyStaticMethod) String() string { return "TyStaticMethod" }
func (p *TyStaticMethod) funcEx() {}

func NewStaticMethod(typ *types.Named, pos token.Pos, pkg *types.Package, name string, fn types.Object) *types.Func {
return newMethodEx(typ, pos, pkg, name, &TyStaticMethod{fn})
}

// ----------------------------------------------------------------------------

type TyTemplateRecvMethod struct {
Func types.Object
}
Expand Down
16 changes: 16 additions & 0 deletions gop_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,22 @@ func bar(v *foo.Foo2) {

// ----------------------------------------------------------------------------

func TestStaticMethod(t *testing.T) {
pkg := newMainPackage()
bar := pkg.Import("github.com/goplus/gogen/internal/bar")
pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
Typ(bar.Ref("Game").Type()).MemberVal("New").Call(0).EndStmt().
End()
domTest(t, pkg, `package main

import "github.com/goplus/gogen/internal/bar"

func main() {
bar.Gops_Game_New()
}
`)
}

func TestTemplateRecvMethod(t *testing.T) {
pkg := newMainPackage()
bar := pkg.Import("github.com/goplus/gogen/internal/bar")
Expand Down
62 changes: 45 additions & 17 deletions import.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,20 @@ func isGopoConst(name string) bool {
}

func isGopFunc(name string) bool {
return isOverload(name) || strings.HasPrefix(name, goptPrefix) || strings.HasPrefix(name, gopxPrefix)
return isOverload(name) || isGopCommon(name)
}

func isOverload(name string) bool {
n := len(name)
return n > 3 && name[n-3:n-1] == "__"
}

// Gop?_xxx
func isGopCommon(name string) bool {
const n = len(commonPrefix)
return len(name) > n+2 && name[n+1] == '_' && name[:n] == commonPrefix
}

// InitThisGopPkg initializes a Go+ package.
func InitThisGopPkg(pkg *types.Package) {
scope := pkg.Scope()
Expand Down Expand Up @@ -130,7 +136,7 @@ func InitThisGopPkg(pkg *types.Package) {
key := omthd{nil, name[:len(name)-3]}
overloads[key] = append(overloads[key], o)
} else {
checkGoptGopx(pkg, scope, name, o)
checkGoptsx(pkg, scope, name, o)
}
}
for _, gopoName := range gopos {
Expand Down Expand Up @@ -235,29 +241,51 @@ func checkTypeMethod(scope *types.Scope, name string) (omthd, string) {
// Gopx_Func
// Gopt_TypeName_Method
// Gopt__TypeName__Method
func checkGoptGopx(pkg *types.Package, scope *types.Scope, name string, o types.Object) {
if strings.HasPrefix(name, goptPrefix) { // Gopt_xxx
name = name[len(goptPrefix):]
if m, tname := checkTypeMethod(pkg.Scope(), name); m.typ != nil {
// Gops_TypeName_Method
// Gops__TypeName__Method
func checkGoptsx(pkg *types.Package, scope *types.Scope, name string, o types.Object) {
const n = len(commonPrefix)
const n2 = n + 2
if isGopCommon(name) {
switch ch := name[n]; ch {
case gopsCh, goptCh: // Gops_xxx, Gopt_xxx
name = name[n2:]
if m, tname := checkTypeMethod(pkg.Scope(), name); m.typ != nil {
if ch == goptCh {
if debugImport {
log.Println("==> NewTemplateRecvMethod", tname, m.name)
}
NewTemplateRecvMethod(m.typ, token.NoPos, pkg, m.name, o)
} else {
if debugImport {
log.Println("==> NewStaticMethod", tname, m.name)
}
NewStaticMethod(m.typ, token.NoPos, pkg, m.name, o)
}
}
case gopxCh: // Gopx_xxx
aname := name[n2:]
o := newFuncEx(token.NoPos, pkg, nil, aname, &tyTypeAsParams{o})
scope.Insert(o)
if debugImport {
log.Println("==> NewTemplateRecvMethod", tname, m.name)
log.Println("==> AliasFunc", name, "=>", aname)
}
NewTemplateRecvMethod(m.typ, token.NoPos, pkg, m.name, o)
}
} else if strings.HasPrefix(name, gopxPrefix) { // Gopx_xxx
aname := name[len(gopxPrefix):]
o := newFuncEx(token.NoPos, pkg, nil, aname, &tyTypeAsParams{o})
scope.Insert(o)
if debugImport {
log.Println("==> AliasFunc", name, "=>", aname)
}
}
}

const (
commonPrefix = "Gop"

goptCh = 't' // template method
gopsCh = 's' // static method
gopxCh = 'x' // type as parameters function/method

goptPrefix = "Gopt_" // template method
gopoPrefix = "Gopo_" // overload function/method
gopsPrefix = "Gops_" // static method
gopxPrefix = "Gopx_" // type as parameters function/method
gopoPrefix = "Gopo_" // overload function/method

gopPackage = "GopPackage"
gopPkgInit = "__gop_inited"
)
Expand Down Expand Up @@ -289,7 +317,7 @@ func newOverload(pkg *types.Package, scope *types.Scope, m omthd, fns []types.Ob
}
o := NewOverloadFunc(token.NoPos, pkg, m.name, fns...)
scope.Insert(o)
checkGoptGopx(pkg, scope, m.name, o)
checkGoptsx(pkg, scope, m.name, o)
} else {
if debugImport {
log.Println("==> NewOverloadMethod", m.typ.Obj().Name(), m.name)
Expand Down
4 changes: 4 additions & 0 deletions internal/bar/bar.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ func Gopt_Game_Run(game Gamer, resource string) {
game.RunLoop()
}

func Gops_Game_New() *Game {
return nil
}

// -----------------------------------------------------------------------------
Loading