Skip to content

Commit 25d8a4f

Browse files
authored
Merge pull request #424 from xushiwei/q
static method
2 parents 38d5489 + 42a7df0 commit 25d8a4f

File tree

6 files changed

+107
-36
lines changed

6 files changed

+107
-36
lines changed

builtin_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,10 @@ func TestErrMethodSig(t *testing.T) {
206206
arg := &Element{
207207
Type: &TypeType{typ: types.NewPointer(recv)},
208208
}
209-
methodSigOf(method, memberFlagMethodToFunc, arg, &ast.SelectorExpr{Sel: ast.NewIdent("bar")})
209+
ret := &Element{
210+
Val: &ast.SelectorExpr{Sel: ast.NewIdent("bar")},
211+
}
212+
pkg.cb.methodSigOf(method, memberFlagMethodToFunc, arg, ret)
210213
})
211214
}
212215

@@ -797,6 +800,7 @@ func TestTypeEx(t *testing.T) {
797800
&unboundMapElemType{},
798801
&TyOverloadFunc{},
799802
&TyOverloadMethod{},
803+
&TyStaticMethod{},
800804
&TyTemplateRecvMethod{},
801805
&TyInstruction{},
802806
&TyOverloadNamed{Obj: types.NewTypeName(0, pkg.Types, "bar", tyInt)},

codebuild.go

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,16 +1740,9 @@ func (p *CodeBuilder) method(
17401740
}
17411741

17421742
sel := selector(arg, found.Name())
1743-
ret := &internal.Elem{
1744-
Val: sel,
1745-
Type: methodSigOf(typ, flag, arg, sel),
1746-
Src: src,
1747-
}
1748-
// TODO: We should take `methodSigOf` more seriously
1749-
if trm, ok := ret.Type.(*TyTemplateRecvMethod); ok {
1750-
o := trm.Func
1751-
ret.Val = toObjectExpr(p.pkg, o)
1752-
ret.Type = o.Type()
1743+
ret := &internal.Elem{Val: sel, Src: src}
1744+
if t, set := p.methodSigOf(typ, flag, arg, ret); set {
1745+
ret.Type = t
17531746
}
17541747
p.stk.Ret(1, ret)
17551748

@@ -1869,7 +1862,7 @@ func toFuncSig(sig *types.Signature, recv *types.Var) *types.Signature {
18691862
func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature {
18701863
sig := o.Type().(*types.Signature)
18711864
recv := sig.Recv()
1872-
if recv == nil {
1865+
if recv == nil { // special signature
18731866
fn.Val = toObjectExpr(pkg, o)
18741867
return sig
18751868
}
@@ -1880,20 +1873,24 @@ func methodToFuncSig(pkg *Package, o types.Object, fn *Element) *types.Signature
18801873
return toFuncSig(sig, recv)
18811874
}
18821875

1883-
func methodSigOf(typ types.Type, flag MemberFlag, arg *Element, sel *ast.SelectorExpr) types.Type {
1876+
func (p *CodeBuilder) methodSigOf(typ types.Type, flag MemberFlag, arg, ret *Element) (types.Type, bool) {
18841877
if flag != memberFlagMethodToFunc {
1885-
return methodCallSig(typ)
1878+
return methodCallSig(typ), true
18861879
}
18871880

18881881
sig := typ.(*types.Signature)
18891882
if t, ok := CheckFuncEx(sig); ok {
1890-
if trm, ok := t.(*TyTemplateRecvMethod); ok {
1891-
// TODO: We should take `methodSigOf` more seriously
1892-
return trm
1883+
switch ext := t.(type) {
1884+
case *TyStaticMethod:
1885+
return p.funcExSigOf(ext.Func, ret)
1886+
case *TyTemplateRecvMethod:
1887+
return p.funcExSigOf(ext.Func, ret)
18931888
}
1894-
return typ
1889+
// TODO: We should take `methodSigOf` more seriously
1890+
return typ, true
18951891
}
18961892

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

1912-
return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at))
1909+
return toFuncSig(sig, types.NewVar(token.NoPos, nil, "", at)), true
1910+
}
1911+
1912+
func (p *CodeBuilder) funcExSigOf(o types.Object, ret *Element) (types.Type, bool) {
1913+
ret.Val = toObjectExpr(p.pkg, o)
1914+
ret.Type = o.Type()
1915+
return nil, false
19131916
}
19141917

19151918
func methodCallSig(typ types.Type) types.Type {
19161919
sig := typ.(*types.Signature)
19171920
if _, ok := CheckFuncEx(sig); ok {
1921+
// TODO: We should take `methodSigOf` more seriously
19181922
return typ
19191923
}
19201924
return types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic())

func_ext.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,21 @@ func (p *tyTypeAsParams) funcEx() {}
215215

216216
// ----------------------------------------------------------------------------
217217

218+
type TyStaticMethod struct {
219+
Func types.Object
220+
}
221+
222+
func (p *TyStaticMethod) Obj() types.Object { return p.Func }
223+
func (p *TyStaticMethod) Underlying() types.Type { return p }
224+
func (p *TyStaticMethod) String() string { return "TyStaticMethod" }
225+
func (p *TyStaticMethod) funcEx() {}
226+
227+
func NewStaticMethod(typ *types.Named, pos token.Pos, pkg *types.Package, name string, fn types.Object) *types.Func {
228+
return newMethodEx(typ, pos, pkg, name, &TyStaticMethod{fn})
229+
}
230+
231+
// ----------------------------------------------------------------------------
232+
218233
type TyTemplateRecvMethod struct {
219234
Func types.Object
220235
}

gop_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,22 @@ func bar(v *foo.Foo2) {
976976

977977
// ----------------------------------------------------------------------------
978978

979+
func TestStaticMethod(t *testing.T) {
980+
pkg := newMainPackage()
981+
bar := pkg.Import("github.com/goplus/gogen/internal/bar")
982+
pkg.NewFunc(nil, "main", nil, nil, false).BodyStart(pkg).
983+
Typ(bar.Ref("Game").Type()).MemberVal("New").Call(0).EndStmt().
984+
End()
985+
domTest(t, pkg, `package main
986+
987+
import "github.com/goplus/gogen/internal/bar"
988+
989+
func main() {
990+
bar.Gops_Game_New()
991+
}
992+
`)
993+
}
994+
979995
func TestTemplateRecvMethod(t *testing.T) {
980996
pkg := newMainPackage()
981997
bar := pkg.Import("github.com/goplus/gogen/internal/bar")

import.go

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,20 @@ func isGopoConst(name string) bool {
8181
}
8282

8383
func isGopFunc(name string) bool {
84-
return isOverload(name) || strings.HasPrefix(name, goptPrefix) || strings.HasPrefix(name, gopxPrefix)
84+
return isOverload(name) || isGopCommon(name)
8585
}
8686

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

92+
// Gop?_xxx
93+
func isGopCommon(name string) bool {
94+
const n = len(commonPrefix)
95+
return len(name) > n+2 && name[n+1] == '_' && name[:n] == commonPrefix
96+
}
97+
9298
// InitThisGopPkg initializes a Go+ package.
9399
func InitThisGopPkg(pkg *types.Package) {
94100
scope := pkg.Scope()
@@ -130,7 +136,7 @@ func InitThisGopPkg(pkg *types.Package) {
130136
key := omthd{nil, name[:len(name)-3]}
131137
overloads[key] = append(overloads[key], o)
132138
} else {
133-
checkGoptGopx(pkg, scope, name, o)
139+
checkGoptsx(pkg, scope, name, o)
134140
}
135141
}
136142
for _, gopoName := range gopos {
@@ -235,29 +241,51 @@ func checkTypeMethod(scope *types.Scope, name string) (omthd, string) {
235241
// Gopx_Func
236242
// Gopt_TypeName_Method
237243
// Gopt__TypeName__Method
238-
func checkGoptGopx(pkg *types.Package, scope *types.Scope, name string, o types.Object) {
239-
if strings.HasPrefix(name, goptPrefix) { // Gopt_xxx
240-
name = name[len(goptPrefix):]
241-
if m, tname := checkTypeMethod(pkg.Scope(), name); m.typ != nil {
244+
// Gops_TypeName_Method
245+
// Gops__TypeName__Method
246+
func checkGoptsx(pkg *types.Package, scope *types.Scope, name string, o types.Object) {
247+
const n = len(commonPrefix)
248+
const n2 = n + 2
249+
if isGopCommon(name) {
250+
switch ch := name[n]; ch {
251+
case gopsCh, goptCh: // Gops_xxx, Gopt_xxx
252+
name = name[n2:]
253+
if m, tname := checkTypeMethod(pkg.Scope(), name); m.typ != nil {
254+
if ch == goptCh {
255+
if debugImport {
256+
log.Println("==> NewTemplateRecvMethod", tname, m.name)
257+
}
258+
NewTemplateRecvMethod(m.typ, token.NoPos, pkg, m.name, o)
259+
} else {
260+
if debugImport {
261+
log.Println("==> NewStaticMethod", tname, m.name)
262+
}
263+
NewStaticMethod(m.typ, token.NoPos, pkg, m.name, o)
264+
}
265+
}
266+
case gopxCh: // Gopx_xxx
267+
aname := name[n2:]
268+
o := newFuncEx(token.NoPos, pkg, nil, aname, &tyTypeAsParams{o})
269+
scope.Insert(o)
242270
if debugImport {
243-
log.Println("==> NewTemplateRecvMethod", tname, m.name)
271+
log.Println("==> AliasFunc", name, "=>", aname)
244272
}
245-
NewTemplateRecvMethod(m.typ, token.NoPos, pkg, m.name, o)
246-
}
247-
} else if strings.HasPrefix(name, gopxPrefix) { // Gopx_xxx
248-
aname := name[len(gopxPrefix):]
249-
o := newFuncEx(token.NoPos, pkg, nil, aname, &tyTypeAsParams{o})
250-
scope.Insert(o)
251-
if debugImport {
252-
log.Println("==> AliasFunc", name, "=>", aname)
253273
}
254274
}
255275
}
256276

257277
const (
278+
commonPrefix = "Gop"
279+
280+
goptCh = 't' // template method
281+
gopsCh = 's' // static method
282+
gopxCh = 'x' // type as parameters function/method
283+
258284
goptPrefix = "Gopt_" // template method
259-
gopoPrefix = "Gopo_" // overload function/method
285+
gopsPrefix = "Gops_" // static method
260286
gopxPrefix = "Gopx_" // type as parameters function/method
287+
gopoPrefix = "Gopo_" // overload function/method
288+
261289
gopPackage = "GopPackage"
262290
gopPkgInit = "__gop_inited"
263291
)
@@ -289,7 +317,7 @@ func newOverload(pkg *types.Package, scope *types.Scope, m omthd, fns []types.Ob
289317
}
290318
o := NewOverloadFunc(token.NoPos, pkg, m.name, fns...)
291319
scope.Insert(o)
292-
checkGoptGopx(pkg, scope, m.name, o)
320+
checkGoptsx(pkg, scope, m.name, o)
293321
} else {
294322
if debugImport {
295323
log.Println("==> NewOverloadMethod", m.typ.Obj().Name(), m.name)

internal/bar/bar.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,8 @@ func Gopt_Game_Run(game Gamer, resource string) {
3333
game.RunLoop()
3434
}
3535

36+
func Gops_Game_New() *Game {
37+
return nil
38+
}
39+
3640
// -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)