diff options
| author | Matthew Dempsky <mdempsky@google.com> | 2023-08-23 13:52:25 -0700 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-08-24 07:17:27 +0000 |
| commit | d5c5808534f0ad97333b1fd5fff81998f44986fe (patch) | |
| tree | 5fb63e5dd9910566ecf7f86fca171e95d20fe61c /src/cmd/compile/internal/syntax/parser.go | |
| parent | 43e69b330a71e0d101bd57f0a1ea83bc4da259f3 (diff) | |
| download | go-d5c5808534f0ad97333b1fd5fff81998f44986fe.tar.xz | |
cmd/compile/internal/syntax: add Unparen and UnpackListExpr helpers
We've added Unparen to go/ast, so add syntax.Unparen to be
consistent (and because it's similarly useful).
Also, types2 and noder both have similar functions for unpacking
ListExprs, so might as well add a common implementation in package
syntax too.
Finally, addressing the TODO: UnpackListExpr is small enough to be
inlined (when default optimizations are enabled), and for typical uses
of UnpackListExpr (e.g., "range UnpackListExpr(x)") the single-element
slice result is stack allocated in the caller. This CL adds a test
using testing.AllocsPerRun to ensure this remains so in the future.
Change-Id: I96a5591d202193ed5bf1ce6f290919107e3dc01b
Reviewed-on: https://go-review.googlesource.com/c/go/+/522336
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/syntax/parser.go')
| -rw-r--r-- | src/cmd/compile/internal/syntax/parser.go | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index b5602fcff7..7085287cad 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -885,7 +885,7 @@ func (p *parser) unaryExpr() Expr { p.next() // unaryExpr may have returned a parenthesized composite literal // (see comment in operand) - remove parentheses if any - x.X = unparen(p.unaryExpr()) + x.X = Unparen(p.unaryExpr()) return x } @@ -965,7 +965,7 @@ func (p *parser) callStmt() *CallStmt { p.next() x := p.pexpr(nil, p.tok == _Lparen) // keep_parens so we can report error below - if t := unparen(x); t != x { + if t := Unparen(x); t != x { p.errorAt(x.Pos(), fmt.Sprintf("expression in %s must not be parenthesized", s.Tok)) // already progressed, no need to advance x = t @@ -1190,7 +1190,7 @@ loop: case _Lbrace: // operand may have returned a parenthesized complit // type; accept it but complain if we have a complit - t := unparen(x) + t := Unparen(x) // determine if '{' belongs to a composite literal or a block statement complit_ok := false switch t.(type) { @@ -2812,8 +2812,8 @@ func (p *parser) typeList(strict bool) (x Expr, comma bool) { return } -// unparen removes all parentheses around an expression. -func unparen(x Expr) Expr { +// Unparen returns e with any enclosing parentheses stripped. +func Unparen(x Expr) Expr { for { p, ok := x.(*ParenExpr) if !ok { @@ -2823,3 +2823,15 @@ func unparen(x Expr) Expr { } return x } + +// UnpackListExpr unpacks a *ListExpr into a []Expr. +func UnpackListExpr(x Expr) []Expr { + switch x := x.(type) { + case nil: + return nil + case *ListExpr: + return x.ElemList + default: + return []Expr{x} + } +} |
