diff --git a/cl/builtin_test.go b/cl/builtin_test.go index 0b4ad415f..6c553c16f 100644 --- a/cl/builtin_test.go +++ b/cl/builtin_test.go @@ -39,6 +39,13 @@ func getGoxConf() *gogen.Config { return &gogen.Config{Fset: fset, Importer: imp} } +func TestLoadExpr(t *testing.T) { + var ni nodeInterp + if v := ni.LoadExpr(&ast.Ident{Name: "x"}); v != "" { + t.Fatal("LoadExpr:", v) + } +} + func TestSimplifyPkgPath(t *testing.T) { if simplifyPkgPath("c/lua") != "github.com/goplus/llgo/c/lua" { t.Fatal("simplifyPkgPath: c/lua") diff --git a/cl/classfile.go b/cl/classfile.go index badebbc2f..0bdf1c56c 100644 --- a/cl/classfile.go +++ b/cl/classfile.go @@ -47,8 +47,9 @@ type spxObj struct { } type gmxProject struct { - gameClass string // .gmx - game gogen.Ref // Game (project base class) + gameClass string // .gmx + game gogen.Ref // Game (project base class) + spfeats spriteFeat sprite map[string]spxObj // .spx => Sprite sptypes []string // .spx scheds []string @@ -62,6 +63,43 @@ type gmxProject struct { hasMain_ bool } +type spriteFeat uint + +const ( + spriteClassfname spriteFeat = 1 << iota + spriteClassclone +) + +func spriteFeatures(game gogen.Ref) (feats spriteFeat) { + if mainFn := findMethod(game, "Main"); mainFn != nil { + sig := mainFn.Type().(*types.Signature) + if t, ok := gogen.CheckSigFuncEx(sig); ok { + if t, ok := t.(*gogen.TyTemplateRecvMethod); ok { + sig = t.Func.Type().(*types.Signature) + } + } + if sig.Variadic() { + in := sig.Params() + last := in.At(in.Len() - 1) + elt := last.Type().(*types.Slice).Elem() + if tn, ok := elt.(*types.Named); ok { + elt = tn.Underlying() + } + if intf, ok := elt.(*types.Interface); ok { + for i, n := 0, intf.NumMethods(); i < n; i++ { + switch intf.Method(i).Name() { + case "Classfname": + feats |= spriteClassfname + case "Classclone": + feats |= spriteClassclone + } + } + } + } + } + return +} + func (p *gmxProject) hasMain() bool { if !p.hasMain_ { imps := p.pkgImps @@ -165,6 +203,7 @@ func loadClass(ctx *pkgCtx, pkg *gogen.Package, file string, f *ast.File, conf * spx := p.pkgImps[0] if gt.Class != "" { p.game, p.gameIsPtr = spxRef(spx, gt.Class) + p.spfeats = spriteFeatures(p.game) } p.sprite = make(map[string]spxObj) for _, v := range gt.Works { @@ -460,6 +499,40 @@ func astFnClassfname(c *gmxClass) *ast.FuncDecl { } } +func astFnClassclone() *ast.FuncDecl { + ret := &ast.Ident{Name: "_gop_ret"} + return &ast.FuncDecl{ + Name: &ast.Ident{ + Name: "Classclone", + }, + Type: &ast.FuncType{ + Params: &ast.FieldList{}, + Results: &ast.FieldList{ + List: []*ast.Field{ + {Type: &ast.Ident{Name: "any"}}, + }, + }, + }, + Body: &ast.BlockStmt{ + List: []ast.Stmt{ + &ast.AssignStmt{ + Lhs: []ast.Expr{ret}, + Tok: token.DEFINE, + Rhs: []ast.Expr{ + &ast.StarExpr{X: &ast.Ident{Name: "this"}}, + }, + }, + &ast.ReturnStmt{ + Results: []ast.Expr{ + &ast.UnaryExpr{Op: token.AND, X: ret}, + }, + }, + }, + }, + Shadow: true, + } +} + func astEmptyEntrypoint(f *ast.File) { var entry = getEntrypoint(f) var hasEntry bool diff --git a/cl/compile.go b/cl/compile.go index eb51ba2fd..2c56fbb3c 100644 --- a/cl/compile.go +++ b/cl/compile.go @@ -226,6 +226,9 @@ func (p *nodeInterp) Caller(node ast.Node) string { func (p *nodeInterp) LoadExpr(node ast.Node) string { start := node.Pos() + if start == token.NoPos { + return "" + } pos := p.fset.Position(start) f := p.files[pos.Filename] n := int(node.End() - start) @@ -725,6 +728,8 @@ func preloadGopFile(p *gogen.Package, ctx *blockCtx, file string, f *ast.File, c var baseType types.Type var spxProj string var spxClass bool + var spxClassfname bool + var spxClassclone bool var goxTestFile bool var parent = ctx.pkgCtx if f.IsClass { @@ -760,7 +765,10 @@ func preloadGopFile(p *gogen.Package, ctx *blockCtx, file string, f *ast.File, c sp := proj.sprite[c.ext] o := sp.obj ctx.baseClass = o - baseTypeName, baseType, spxProj, spxClass = o.Name(), o.Type(), sp.proj, true + baseTypeName, baseType, spxProj = o.Name(), o.Type(), sp.proj + spxClassfname = (proj.spfeats & spriteClassfname) != 0 + spxClassclone = (proj.spfeats & spriteClassclone) != 0 + spxClass = true } } } @@ -864,9 +872,13 @@ func preloadGopFile(p *gogen.Package, ctx *blockCtx, file string, f *ast.File, c }, }}} // func Classfname() string - if spxClass { + if spxClassfname { f.Decls = append(f.Decls, astFnClassfname(c)) } + // func Classclone() any + if spxClassclone { + f.Decls = append(f.Decls, astFnClassclone()) + } } if d := f.ShadowEntry; d != nil { @@ -1298,7 +1310,7 @@ func loadFunc(ctx *blockCtx, recv *types.Var, name string, d *ast.FuncDecl, genB var pkg = ctx.pkg var sigBase *types.Signature if d.Shadow { - if recv != nil { + if recv != nil && (name == "Main" || name == "MainEntry") { if base := ctx.baseClass; base != nil { if f := findMethod(base, name); f != nil { sigBase = makeMainSig(recv, f) diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go index e6a2539e6..6f6a59522 100644 --- a/cl/compile_spx_test.go +++ b/cl/compile_spx_test.go @@ -57,9 +57,6 @@ type MyGame struct { *spx.MyGame } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func (this *MyGame) Main() { @@ -142,9 +139,6 @@ func (this *Kai) onMsg(msg string) { this.Say("Hi") } } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -199,9 +193,6 @@ func (this *index) MainEntry() { func (this *index) Main() { spx.Gopt_MyGame_Main(this) } -func (this *bar) Classfname() string { - return "bar" -} func (this *bar) Main() { } func main() { @@ -234,9 +225,6 @@ func (this *index) MainEntry() { func (this *index) Main() { spx.Gopt_MyGame_Main(this) } -func (this *bar) Classfname() string { - return "bar" -} func (this *bar) Main() { } func main() { @@ -270,9 +258,6 @@ func (this *index) MainEntry() { func (this *index) Main() { spx.Gopt_MyGame_Main(this) } -func (this *bar) Classfname() string { - return "bar" -} func (this *bar) Main() { } func main() { @@ -314,9 +299,6 @@ func (this *index) MainEntry() { func (this *index) Main() { spx.Gopt_MyGame_Main(this) } -func (this *bar) Classfname() string { - return "bar" -} func (this *bar) Main() { } func main() { @@ -372,9 +354,6 @@ func (this *bar) onInit() { this.Say("Where do you come from?", 2) this.Broadcast__0("msg2") } -func (this *bar) Classfname() string { - return "bar" -} func (this *bar) Main() { } func main() { @@ -434,9 +413,6 @@ func (this *Kai) onInit() { func (this *Kai) onCloned() { this.Say("Hi") } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -485,9 +461,6 @@ func (this *index) Main() { func (this *Kai) Main() { fmt.Println("Hi") } -func (this *Kai) Classfname() string { - return "Kai" -} func main() { new(index).Main() } @@ -533,6 +506,10 @@ func (this *Kai) Main(_gop_arg0 string) { func (this *Kai) Classfname() string { return "Kai" } +func (this *Kai) Classclone() interface{} { + _gop_ret := *this + return &_gop_ret +} func main() { new(Game).Main() } @@ -572,6 +549,10 @@ func (this *Game) Main() { func (this *Kai) Classfname() string { return "Kai" } +func (this *Kai) Classclone() interface{} { + _gop_ret := *this + return &_gop_ret +} func (this *Kai) Main(_gop_arg0 string) { this.Sprite.Main(_gop_arg0) } @@ -610,9 +591,6 @@ func (this *Game) Main() { } func (this *Kai) onMsg(msg string) { } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -650,9 +628,6 @@ func (this *Game) Main() { } func (this *Kai) onMsg(msg string) { } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -684,14 +659,8 @@ type Kai struct { func (this *Dog) Main() { fmt.Println("Hi, Sprite") } -func (this *Dog) Classfname() string { - return "Dog" -} func (this *Kai) onMsg(msg string) { } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } `, "Dog_t3spx.gox", "Kai.t3spx2") @@ -721,9 +690,6 @@ func (this *Game) MainEntry() { func (this *Game) Main() { (*spx2.Game).Main(&this.Game) } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -753,9 +719,6 @@ func (this *Game) MainEntry() { func (this *Game) Main() { (*spx2.Game).Main(&this.Game) } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -803,9 +766,6 @@ func (this *Kai) Main() { } func (this *Kai) onMsg(msg string) { } -func (this *Kai) Classfname() string { - return "Kai" -} func main() { new(Game).Main() } @@ -852,9 +812,6 @@ func (this *Kai) onMsg(msg string) { this.Say("Hi") } } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -929,9 +886,6 @@ func (this *Kai) onInit() { func (this *Kai) onCloned() { this.Say("Hi") } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -974,9 +928,6 @@ func (this *Game) Main() { } func (this *Kai) onMsg(msg string) { } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -1016,9 +967,6 @@ func (this *Game) Main() { func (this *Kai) onMsg(msg string) { this.Position().Add__0(100, 200) } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -1083,9 +1031,6 @@ func (this *Kai) onMsg(msg string) { fmt.Println(this.Vector().X) fmt.Println(this.Vector().Self().Self()) } -func (this *Kai) Classfname() string { - return "Kai" -} func (this *Kai) Main() { } func main() { @@ -1197,9 +1142,6 @@ func (this *Kai) Main() { spx.Gopt_Sprite_OnKey2(this, "hello", func(key string) { }) } -func (this *Kai) Classfname() string { - return "Kai" -} func main() { new(Game).Main() } @@ -1239,9 +1181,6 @@ func (this *caseFoo) Main() { t.Fatal("failed") }) } -func (this *caseFoo) Classfname() string { - return "Foo" -} func TestFoo(t *testing.T) { test.Gopt_Case_TestMain(new(caseFoo), t) } @@ -1270,9 +1209,6 @@ type case_foo struct { func (this *case_foo) Main() { this.T().Log("Hi") } -func (this *case_foo) Classfname() string { - return "foo" -} func Test_foo(t *testing.T) { test.Gopt_Case_TestMain(new(case_foo), t) } diff --git a/cl/internal/spx3/spx3.go b/cl/internal/spx3/spx3.go index 551fcdb16..3697a3a78 100644 --- a/cl/internal/spx3/spx3.go +++ b/cl/internal/spx3/spx3.go @@ -40,5 +40,11 @@ func (p *Sprite) Name() string { func (p *Sprite) Main(name string) {} -func Gopt_Game_Main(game interface{ initGame() }, workers ...interface{ Main(name string) }) { +type iHandler interface { + Main(name string) + Classfname() string + Classclone() any +} + +func Gopt_Game_Main(game interface{ initGame() }, workers ...iHandler) { } diff --git a/x/build/build_test.go b/x/build/build_test.go index 1bebeca94..cdc10801d 100644 --- a/x/build/build_test.go +++ b/x/build/build_test.go @@ -410,9 +410,6 @@ type MyGame struct { func (this *Cat) Main() { fmt.Println("hi") } -func (this *Cat) Classfname() string { - return "Cat" -} func (this *MyGame) Main() { spx.Gopt_MyGame_Main(this) } diff --git a/x/typesutil/info_test.go b/x/typesutil/info_test.go index 600753988..1cede6fa6 100644 --- a/x/typesutil/info_test.go +++ b/x/typesutil/info_test.go @@ -1679,61 +1679,57 @@ func onCloned() { say("Hi") } `, `== types == -000: 0: 0 | "Kai" *ast.BasicLit | value : untyped string = "Kai" | constant -001: 0: 0 | *MyGame *ast.StarExpr | type : *main.MyGame | type -002: 0: 0 | Kai *ast.Ident | type : main.Kai | type -003: 0: 0 | MyGame *ast.Ident | type : main.MyGame | type -004: 0: 0 | string *ast.Ident | type : string | type -005: 3: 4 | int *ast.Ident | type : int | type -006: 6:11 | struct { +000: 0: 0 | *MyGame *ast.StarExpr | type : *main.MyGame | type +001: 0: 0 | Kai *ast.Ident | type : main.Kai | type +002: 0: 0 | MyGame *ast.Ident | type : main.MyGame | type +003: 3: 4 | int *ast.Ident | type : int | type +004: 6:11 | struct { x int y int } *ast.StructType | type : struct{x int; y int} | type -007: 7: 4 | int *ast.Ident | type : int | type -008: 8: 4 | int *ast.Ident | type : int | type -009: 12: 2 | a *ast.Ident | var : int | variable -010: 12: 6 | 1 *ast.BasicLit | value : untyped int = 1 | constant -011: 13: 2 | clone *ast.Ident | value : func(sprite any) | value -012: 14: 2 | clone *ast.Ident | value : func(sprite any, data any) | value -013: 14: 2 | clone info{1, 2} *ast.CallExpr | void : () | no value -014: 14: 8 | info *ast.Ident | type : main.info | type -015: 14: 8 | info{1, 2} *ast.CompositeLit | value : main.info | value -016: 14:13 | 1 *ast.BasicLit | value : untyped int = 1 | constant -017: 14:15 | 2 *ast.BasicLit | value : untyped int = 2 | constant -018: 15: 2 | clone *ast.Ident | value : func(sprite any, data any) | value -019: 15: 2 | clone &info{1, 2} *ast.CallExpr | void : () | no value -020: 15: 8 | &info{1, 2} *ast.UnaryExpr | value : *main.info | value -021: 15: 9 | info *ast.Ident | type : main.info | type -022: 15: 9 | info{1, 2} *ast.CompositeLit | value : main.info | value -023: 15:14 | 1 *ast.BasicLit | value : untyped int = 1 | constant -024: 15:16 | 2 *ast.BasicLit | value : untyped int = 2 | constant -025: 19: 2 | say *ast.Ident | value : func(msg string, secs ...float64) | value -026: 19: 2 | say("Hi") *ast.CallExpr | void : () | no value -027: 19: 6 | "Hi" *ast.BasicLit | value : untyped string = "Hi" | constant +005: 7: 4 | int *ast.Ident | type : int | type +006: 8: 4 | int *ast.Ident | type : int | type +007: 12: 2 | a *ast.Ident | var : int | variable +008: 12: 6 | 1 *ast.BasicLit | value : untyped int = 1 | constant +009: 13: 2 | clone *ast.Ident | value : func(sprite any) | value +010: 14: 2 | clone *ast.Ident | value : func(sprite any, data any) | value +011: 14: 2 | clone info{1, 2} *ast.CallExpr | void : () | no value +012: 14: 8 | info *ast.Ident | type : main.info | type +013: 14: 8 | info{1, 2} *ast.CompositeLit | value : main.info | value +014: 14:13 | 1 *ast.BasicLit | value : untyped int = 1 | constant +015: 14:15 | 2 *ast.BasicLit | value : untyped int = 2 | constant +016: 15: 2 | clone *ast.Ident | value : func(sprite any, data any) | value +017: 15: 2 | clone &info{1, 2} *ast.CallExpr | void : () | no value +018: 15: 8 | &info{1, 2} *ast.UnaryExpr | value : *main.info | value +019: 15: 9 | info *ast.Ident | type : main.info | type +020: 15: 9 | info{1, 2} *ast.CompositeLit | value : main.info | value +021: 15:14 | 1 *ast.BasicLit | value : untyped int = 1 | constant +022: 15:16 | 2 *ast.BasicLit | value : untyped int = 2 | constant +023: 19: 2 | say *ast.Ident | value : func(msg string, secs ...float64) | value +024: 19: 2 | say("Hi") *ast.CallExpr | void : () | no value +025: 19: 6 | "Hi" *ast.BasicLit | value : untyped string = "Hi" | constant == defs == -000: 0: 0 | Classfname | func (*main.Kai).Classfname() string -001: 0: 0 | Main | func (*main.Kai).Main() -002: 0: 0 | this | var this *main.Kai -003: 3: 2 | a | field a int -004: 6: 6 | info | type main.info struct{x int; y int} -005: 7: 2 | x | field x int -006: 8: 2 | y | field y int -007: 11: 6 | onInit | func (*main.Kai).onInit() -008: 18: 6 | onCloned | func (*main.Kai).onCloned() +000: 0: 0 | Main | func (*main.Kai).Main() +001: 0: 0 | this | var this *main.Kai +002: 3: 2 | a | field a int +003: 6: 6 | info | type main.info struct{x int; y int} +004: 7: 2 | x | field x int +005: 8: 2 | y | field y int +006: 11: 6 | onInit | func (*main.Kai).onInit() +007: 18: 6 | onCloned | func (*main.Kai).onCloned() == uses == 000: 0: 0 | Kai | type main.Kai struct{github.com/goplus/gop/cl/internal/spx.Sprite; *main.MyGame; a int} 001: 0: 0 | MyGame | type main.MyGame struct{*github.com/goplus/gop/cl/internal/spx.MyGame} -002: 0: 0 | string | type string -003: 3: 4 | int | type int -004: 7: 4 | int | type int -005: 8: 4 | int | type int -006: 12: 2 | a | field a int -007: 13: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__0(sprite any) -008: 14: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__1(sprite any, data any) -009: 14: 8 | info | type main.info struct{x int; y int} -010: 15: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__1(sprite any, data any) -011: 15: 9 | info | type main.info struct{x int; y int} -012: 19: 2 | say | func (*github.com/goplus/gop/cl/internal/spx.Sprite).Say(msg string, secs ...float64) +002: 3: 4 | int | type int +003: 7: 4 | int | type int +004: 8: 4 | int | type int +005: 12: 2 | a | field a int +006: 13: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__0(sprite any) +007: 14: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__1(sprite any, data any) +008: 14: 8 | info | type main.info struct{x int; y int} +009: 15: 2 | clone | func github.com/goplus/gop/cl/internal/spx.Gopt_Sprite_Clone__1(sprite any, data any) +010: 15: 9 | info | type main.info struct{x int; y int} +011: 19: 2 | say | func (*github.com/goplus/gop/cl/internal/spx.Sprite).Say(msg string, secs ...float64) == overloads == 000: 13: 2 | clone | func (github.com/goplus/gop/cl/internal/spx.Sprite).Clone(__gop_overload_args__ interface{_()}) 001: 14: 2 | clone | func (github.com/goplus/gop/cl/internal/spx.Sprite).Clone(__gop_overload_args__ interface{_()})