Repository: goplus/gop
Pull request #1361 (2023-02-20 03:11:14)

parser: fix command style Not expr
fix https://github.com/goplus/gop/issues/1360


Patch:
diff --git a/parser/parser.go b/parser/parser.go
index c217b70a..3d6f9fc0 100644
--- a/parser/parser.go
+++ b/parser/parser.go
@@ -25,7 +25,6 @@
 // treated like an ordinary parameter list and thus may contain multiple
 // entries where the spec permits exactly one. Consequently, the corresponding
 // field in the AST (ast.FuncDecl.Recv) field is not restricted to one entry.
-//
 package parser
 
 import (
@@ -198,7 +197,6 @@ var unresolved = new(ast.Object)
 // the object it denotes. If no object is found and collectUnresolved is
 // set, x is marked as unresolved and collected in the list of unresolved
 // identifiers.
-//
 func (p *parser) tryResolve(x ast.Expr, collectUnresolved bool) {
 	// nothing to do if x is not an identifier or the blank identifier
 	ident, _ := x.(*ast.Ident)
@@ -316,7 +314,6 @@ func (p *parser) consumeComment() (comment *ast.Comment, endline int) {
 // comments list, and return it together with the line at which
 // the last comment in the group ends. A non-comment token or n
 // empty lines terminate a comment group.
-//
 func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline int) {
 	var list []*ast.Comment
 	endline = p.file.Line(p.pos)
@@ -347,7 +344,6 @@ func (p *parser) consumeCommentGroup(n int) (comments *ast.CommentGroup, endline
 //
 // Lead and line comments may be considered documentation that is
 // stored in the AST.
-//
 func (p *parser) next() {
 	p.leadComment = nil
 	p.lineComment = nil
@@ -449,7 +445,6 @@ func (p *parser) expect2(tok token.Token) (pos token.Pos) {
 
 // expectClosing is like expect but provides a better error message
 // for the common case of a missing comma before a newline.
-//
 func (p *parser) expectClosing(tok token.Token, context string) token.Pos {
 	if p.tok != tok && p.tok == token.SEMICOLON && p.lit == "\n" {
 		p.error(p.pos, "missing ',' before newline in "+context)
@@ -571,7 +566,6 @@ var exprEnd = map[token.Token]bool{
 // token positions are invalid due to parse errors, the resulting end position
 // may be past the file's EOF position, which would lead to panics if used
 // later on.
-//
 func (p *parser) safePos(pos token.Pos) (res token.Pos) {
 	defer func() {
 		if recover() != nil {
@@ -1597,7 +1591,6 @@ func (p *parser) parseFuncTypeOrLit() ast.Expr {
 // parseOperand may return an expression or a raw type (incl. array
 // types of the form [...]T. Callers must verify the result.
 // If lhs is set and the result is an identifier, it is not resolved.
-//
 func (p *parser) parseOperand(lhs, allowTuple, allowCmd bool) (x ast.Expr, isTuple bool) {
 	if p.trace {
 		defer un(trace(p, "Operand"))
@@ -2199,7 +2192,14 @@ L:
 			} else {
 				break L
 			}
-		case token.NOT, token.QUESTION:
+		case token.NOT:
+			if allowCmd && p.isCmd(x) {
+				x = p.parseCallOrConversion(p.checkExprOrType(x), true)
+			} else {
+				x = &ast.ErrWrapExpr{X: x, Tok: token.NOT, TokPos: p.pos}
+				p.next()
+			}
+		case token.QUESTION:
 			x = &ast.ErrWrapExpr{X: x, Tok: p.tok, TokPos: p.pos}
 			p.next()
 		default:


Test patch:
diff --git a/cl/compile_test.go b/cl/compile_test.go
index c0fd8241..a05508e3 100644
--- a/cl/compile_test.go
+++ b/cl/compile_test.go
@@ -4267,3 +4267,40 @@ func main() {
 }
 `)
 }
+
+func TestCommandNotExpr(t *testing.T) {
+	gopClTest(t, `
+println !true
+`, `package main
+
+import fmt "fmt"
+
+func main() {
+	fmt.Println(false)
+}
+`)
+	gopClTest(t, `
+a := true
+println !a
+`, `package main
+
+import fmt "fmt"
+
+func main() {
+	a := true
+	fmt.Println(!a)
+}
+`)
+	gopClTest(t, `
+println !func() bool { return true }()
+`, `package main
+
+import fmt "fmt"
+
+func main() {
+	fmt.Println(!func() bool {
+		return true
+	}())
+}
+`)
+}
diff --git a/parser/_testdata/cmdlinestyle3/cmd3.gop b/parser/_testdata/cmdlinestyle3/cmd3.gop
index b1f81ffd..921db5f9 100644
--- a/parser/_testdata/cmdlinestyle3/cmd3.gop
+++ b/parser/_testdata/cmdlinestyle3/cmd3.gop
@@ -1,1 +1,2 @@
 println &x
+println !x
diff --git a/parser/_testdata/cmdlinestyle3/parser.expect b/parser/_testdata/cmdlinestyle3/parser.expect
index 762e943c..8335924b 100644
--- a/parser/_testdata/cmdlinestyle3/parser.expect
+++ b/parser/_testdata/cmdlinestyle3/parser.expect
@@ -25,3 +25,15 @@ ast.FuncDecl:
                   X:
                     ast.Ident:
                       Name: x
+        ast.ExprStmt:
+          X:
+            ast.CallExpr:
+              Fun:
+                ast.Ident:
+                  Name: println
+              Args:
+                ast.UnaryExpr:
+                  Op: !
+                  X:
+                    ast.Ident:
+                      Name: x