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

Gop_Exec support #1736

Merged
merged 1 commit into from
Feb 13, 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
24 changes: 24 additions & 0 deletions cl/compile_spx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,30 @@ func (this *index) onInit() {
`)
}

func TestSpxGopExec(t *testing.T) {
gopSpxTest(t, `
vim "a.txt"
`, ``, `package main

import "github.com/goplus/gop/cl/internal/spx"

type bar struct {
spx.Sprite
*index
}
type index struct {
*spx.MyGame
}

func (this *index) MainEntry() {
this.Gop_Exec("vim", "a.txt")
}
func main() {
spx.Gopt_MyGame_Main(new(index))
}
`)
}

func TestSpxMethod(t *testing.T) {
gopSpxTestEx(t, `
func onInit() {
Expand Down
47 changes: 33 additions & 14 deletions cl/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,49 +64,53 @@ const (
clIdentGoto
clCallWithTwoValue
clCommandWithoutArgs
clCommandIdent
)

const (
objNormal = iota
objPkgRef
objCPkgRef
objGopExec
)

const errorPkgPath = "github.com/qiniu/x/errors"

func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (pkg gox.PkgRef, kind int) {
fvalue := (flags&clIdentSelectorExpr) != 0 || (flags&clIdentLHS) == 0
cb := ctx.cb
name := ident.Name
if name == "_" {
if fvalue {
panic(ctx.newCodeError(ident.Pos(), "cannot use _ as value"))
}
ctx.cb.VarRef(nil)
cb.VarRef(nil)
return
}

var recv *types.Var
var oldo types.Object
scope := ctx.pkg.Types.Scope()
at, o := ctx.cb.Scope().LookupParent(name, token.NoPos)
at, o := cb.Scope().LookupParent(name, token.NoPos)
if o != nil {
if at != scope && at != types.Universe { // local object
goto find
}
}

if ctx.isClass { // in a Go+ class file
if fn := ctx.cb.Func(); fn != nil {
if fn := cb.Func(); fn != nil {
sig := fn.Ancestor().Type().(*types.Signature)
if recv := sig.Recv(); recv != nil {
ctx.cb.Val(recv)
if recv = sig.Recv(); recv != nil {
cb.Val(recv)
chkFlag := flags // &^ clCommandWithoutArgs (TODO: why?)
if chkFlag&clIdentSelectorExpr != 0 {
chkFlag = clIdentCanAutoCall
}
if compileMember(ctx, ident, name, chkFlag) == nil { // class member object
return
}
ctx.cb.InternalStack().PopN(1)
cb.InternalStack().PopN(1)
}
}
}
Expand Down Expand Up @@ -150,6 +154,12 @@ func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (pkg gox.PkgRef, k
}
oldo, o = o, obj
} else if o == nil {
if (clCommandIdent&flags) != 0 && recv != nil { // for support Gop_Exec, see TestSpxGopExec
if _, e := cb.Val(recv).Member("Gop_Exec", gox.MemberFlagVal, ident); e == nil {
kind = objGopExec
return
}
}
if (clIdentGoto & flags) != 0 {
l := ident.Obj.Data.(*ast.Ident)
panic(ctx.newCodeErrorf(l.Pos(), "label %v is not defined", l.Name))
Expand All @@ -159,13 +169,13 @@ func compileIdent(ctx *blockCtx, ident *ast.Ident, flags int) (pkg gox.PkgRef, k

find:
if fvalue {
ctx.cb.Val(o, ident)
cb.Val(o, ident)
} else {
ctx.cb.VarRef(o, ident)
cb.VarRef(o, ident)
}
if rec := ctx.recorder(); rec != nil {
e := ctx.cb.Get(-1)
if oldo != nil && gox.IsTypeEx(e.Type) {
e := cb.Get(-1)
if oldo != nil && gox.IsTypeEx(e.Type) { // for builtin object
rec.recordIdent(ctx, ident, oldo)
return
}
Expand Down Expand Up @@ -564,8 +574,17 @@ func compileCallExpr(ctx *blockCtx, v *ast.CallExpr, inFlags int) {
var ifn *ast.Ident
switch fn := v.Fun.(type) {
case *ast.Ident:
compileIdent(ctx, fn, clIdentAllowBuiltin|inFlags)
ifn = fn
if v.IsCommand() { // for support Gop_Exec, see TestSpxGopExec
inFlags |= clCommandIdent
}
if _, kind := compileIdent(ctx, fn, clIdentAllowBuiltin|inFlags); kind == objGopExec {
args := make([]ast.Expr, 1, len(v.Args)+1)
args[0] = &ast.BasicLit{ValuePos: fn.NamePos, Kind: token.STRING, Value: strconv.Quote(fn.Name)}
args = append(args, v.Args...)
v = &ast.CallExpr{Fun: fn, Args: args, Ellipsis: v.Ellipsis, NoParenEnd: v.NoParenEnd}
} else {
ifn = fn
}
case *ast.SelectorExpr:
compileSelectorExpr(ctx, fn, 0)
case *ast.ErrWrapExpr:
Expand Down Expand Up @@ -615,7 +634,7 @@ func mayBuiltin(ctx *blockCtx, ifn *ast.Ident, v *ast.CallExpr, flags gox.InstrF
switch name := ifn.Name; name {
case "new", "delete":
cb := ctx.cb
cb.InternalStack().Pop()
cb.InternalStack().PopN(1)
o := ctx.pkg.Builtin().Ref(name)
cb.Val(o, ifn)
for _, arg := range v.Args {
Expand Down Expand Up @@ -665,7 +684,7 @@ func compileCallArgs(fn *fnType, ctx *blockCtx, v *ast.CallExpr, ellipsis bool,
}
typetype := fn.typetype && t != nil
if typetype {
stk.Pop()
stk.PopN(1)
}
compileSliceLit(ctx, expr, t)
if typetype {
Expand Down
3 changes: 3 additions & 0 deletions cl/internal/spx/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ type MyGame struct {
func Gopt_MyGame_Main(game interface{}) {
}

func (p *MyGame) Gop_Exec(name string, args ...any) {
}

func (p *MyGame) InitGameApp(args ...string) {
}

Expand Down