Repository: goplus/gop
Pull request #1737 (2024-02-13 12:00:28)

TestSpxGopExec, checkCommandWithoutArgs


Patch:
diff --git a/cl/expr.go b/cl/expr.go
index 0495b708..e79f649a 100644
--- a/cl/expr.go
+++ b/cl/expr.go
@@ -236,7 +236,9 @@ func compileExpr(ctx *blockCtx, expr ast.Expr, inFlags ...int) {
 		if inFlags != nil {
 			flags |= inFlags[0]
 		}
-		compileIdent(ctx, v, flags)
+		if _, kind := compileIdent(ctx, v, flags); kind == objGopExec {
+			ctx.cb.Val(v.Name, v).CallWith(1, 0, v) // for support Gop_Exec, see TestSpxGopExec
+		}
 	case *ast.BasicLit:
 		compileBasicLit(ctx, v)
 	case *ast.CallExpr:
diff --git a/cl/internal/spx/game.go b/cl/internal/spx/game.go
index 0c591af5..e35c87da 100644
--- a/cl/internal/spx/game.go
+++ b/cl/internal/spx/game.go
@@ -29,6 +29,10 @@ type MyGame struct {
 func Gopt_MyGame_Main(game interface{}) {
 }
 
+func (p *MyGame) Capout(doSth func()) (string, error) {
+	return "", nil
+}
+
 func (p *MyGame) Gop_Exec(name string, args ...any) {
 }
 
diff --git a/cl/stmt.go b/cl/stmt.go
index 2eeec181..73856072 100644
--- a/cl/stmt.go
+++ b/cl/stmt.go
@@ -110,13 +110,11 @@ func compileStmt(ctx *blockCtx, stmt ast.Stmt) {
 	commentStmt(ctx, stmt)
 	switch v := stmt.(type) {
 	case *ast.ExprStmt:
-		inFlags := 0
-		if isCommandWithoutArgs(v.X) {
-			inFlags = clCommandWithoutArgs
-		}
-		compileExpr(ctx, v.X, inFlags)
+		x := v.X
+		inFlags := checkCommandWithoutArgs(x)
+		compileExpr(ctx, x, inFlags)
 		if inFlags != 0 && gox.IsFunc(ctx.cb.InternalStack().Get(-1).Type) {
-			ctx.cb.CallWith(0, 0, v.X)
+			ctx.cb.CallWith(0, 0, x)
 		}
 	case *ast.AssignStmt:
 		compileAssignStmt(ctx, v)
@@ -163,16 +161,19 @@ func compileStmt(ctx *blockCtx, stmt ast.Stmt) {
 	ctx.cb.EndStmt()
 }
 
-func isCommandWithoutArgs(x ast.Expr) bool {
+func checkCommandWithoutArgs(x ast.Expr) int {
+	if _, ok := x.(*ast.Ident); ok {
+		return clCommandWithoutArgs | clCommandIdent // for support Gop_Exec, see TestSpxGopExec
+	}
 retry:
-	switch t := x.(type) {
-	case *ast.Ident:
-		return true
-	case *ast.SelectorExpr:
-		x = t.X
+	if v, ok := x.(*ast.SelectorExpr); ok {
+		x = v.X
 		goto retry
 	}
-	return false
+	if _, ok := x.(*ast.Ident); ok {
+		return clCommandWithoutArgs
+	}
+	return 0
 }
 
 func compileReturnStmt(ctx *blockCtx, expr *ast.ReturnStmt) {


Test patch:
diff --git a/cl/builtin_test.go b/cl/builtin_test.go
index c44fa00e..a039df7b 100644
--- a/cl/builtin_test.go
+++ b/cl/builtin_test.go
@@ -305,12 +305,12 @@ func TestHandleRecover(t *testing.T) {
 	ctx.handleRecover(100)
 }
 
-func TestCanAutoCall(t *testing.T) {
-	if !isCommandWithoutArgs(
+func TestCheckCommandWithoutArgs(t *testing.T) {
+	if checkCommandWithoutArgs(
 		&ast.SelectorExpr{
 			X:   &ast.SelectorExpr{X: ast.NewIdent("foo"), Sel: ast.NewIdent("bar")},
 			Sel: ast.NewIdent("val"),
-		}) {
+		}) != clCommandWithoutArgs {
 		t.Fatal("TestCanAutoCall failed")
 	}
 }
diff --git a/cl/compile_spx_test.go b/cl/compile_spx_test.go
index 04c7780a..347cefa1 100644
--- a/cl/compile_spx_test.go
+++ b/cl/compile_spx_test.go
@@ -256,6 +256,8 @@ func (this *index) onInit() {
 func TestSpxGopExec(t *testing.T) {
 	gopSpxTest(t, `
 vim "a.txt"
+capout => { ls }
+capout => { ls "-l" }
 `, ``, `package main
 
 import "github.com/goplus/gop/cl/internal/spx"
@@ -270,6 +272,12 @@ type index struct {
 
 func (this *index) MainEntry() {
 	this.Gop_Exec("vim", "a.txt")
+	this.Capout(func() {
+		this.Gop_Exec("ls")
+	})
+	this.Capout(func() {
+		this.Gop_Exec("ls", "-l")
+	})
 }
 func main() {
 	spx.Gopt_MyGame_Main(new(index))