Skip to content

Commit

Permalink
internal/gogrep: add support for $*_ in slice expr members (#284)
Browse files Browse the repository at this point in the history
`$*_` inside a slice expression encodes an optional
slice expression member: it could be nil or set to something
that is non-nil.
  • Loading branch information
quasilyte authored Oct 15, 2021
1 parent af7b672 commit a0c5279
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 21 deletions.
30 changes: 15 additions & 15 deletions internal/gogrep/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,31 +534,31 @@ func (c *compiler) compileSliceExpr(n *ast.SliceExpr) {
switch {
case n.Low == nil && n.High == nil && !n.Slice3:
c.emitInstOp(opSliceExpr)
c.compileExpr(n.X)
c.compileOptExpr(n.X)
case n.Low != nil && n.High == nil && !n.Slice3:
c.emitInstOp(opSliceFromExpr)
c.compileExpr(n.X)
c.compileExpr(n.Low)
c.compileOptExpr(n.X)
c.compileOptExpr(n.Low)
case n.Low == nil && n.High != nil && !n.Slice3:
c.emitInstOp(opSliceToExpr)
c.compileExpr(n.X)
c.compileExpr(n.High)
c.compileOptExpr(n.X)
c.compileOptExpr(n.High)
case n.Low != nil && n.High != nil && !n.Slice3:
c.emitInstOp(opSliceFromToExpr)
c.compileExpr(n.X)
c.compileExpr(n.Low)
c.compileExpr(n.High)
c.compileOptExpr(n.X)
c.compileOptExpr(n.Low)
c.compileOptExpr(n.High)
case n.Low == nil && n.Slice3:
c.emitInstOp(opSliceToCapExpr)
c.compileExpr(n.X)
c.compileExpr(n.High)
c.compileExpr(n.Max)
c.compileOptExpr(n.X)
c.compileOptExpr(n.High)
c.compileOptExpr(n.Max)
case n.Low != nil && n.Slice3:
c.emitInstOp(opSliceFromToCapExpr)
c.compileExpr(n.X)
c.compileExpr(n.Low)
c.compileExpr(n.High)
c.compileExpr(n.Max)
c.compileOptExpr(n.X)
c.compileOptExpr(n.Low)
c.compileOptExpr(n.High)
c.compileOptExpr(n.Max)
default:
panic(c.errorf(n, "unexpected slice expr"))
}
Expand Down
13 changes: 13 additions & 0 deletions internal/gogrep/compile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,19 @@ func TestCompileWildcard(t *testing.T) {
` • • NodeSeq`,
` • • End`,
},

`s[$*_:$*_]`: {
`SliceFromToExpr`,
` • Ident s`,
` • OptNode`,
` • OptNode`,
},

`s[$*_:]`: {
`SliceFromExpr`,
` • Ident s`,
` • OptNode`,
},
})

for i := range tests {
Expand Down
11 changes: 5 additions & 6 deletions internal/gogrep/match.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,24 +251,23 @@ func (m *matcher) matchNodeWithInst(inst instruction, n ast.Node) bool {
return ok && n.Low == nil && n.High == nil && m.matchNode(n.X)
case opSliceFromExpr:
n, ok := n.(*ast.SliceExpr)
return ok && n.Low != nil && n.High == nil && !n.Slice3 &&
return ok && n.High == nil && !n.Slice3 &&
m.matchNode(n.X) && m.matchNode(n.Low)
case opSliceToExpr:
n, ok := n.(*ast.SliceExpr)
return ok && n.Low == nil && n.High != nil && !n.Slice3 &&
return ok && n.Low == nil && !n.Slice3 &&
m.matchNode(n.X) && m.matchNode(n.High)
case opSliceFromToExpr:
n, ok := n.(*ast.SliceExpr)
return ok && n.Low != nil && n.High != nil && !n.Slice3 &&
return ok && !n.Slice3 &&
m.matchNode(n.X) && m.matchNode(n.Low) && m.matchNode(n.High)
case opSliceToCapExpr:
n, ok := n.(*ast.SliceExpr)
return ok && n.Low == nil && n.High != nil && n.Max != nil &&
return ok && n.Low == nil &&
m.matchNode(n.X) && m.matchNode(n.High) && m.matchNode(n.Max)
case opSliceFromToCapExpr:
n, ok := n.(*ast.SliceExpr)
return ok && n.Low != nil && n.High != nil && n.Max != nil &&
m.matchNode(n.X) && m.matchNode(n.Low) && m.matchNode(n.High) && m.matchNode(n.Max)
return ok && m.matchNode(n.X) && m.matchNode(n.Low) && m.matchNode(n.High) && m.matchNode(n.Max)

case opIndexExpr:
n, ok := n.(*ast.IndexExpr)
Expand Down
21 changes: 21 additions & 0 deletions internal/gogrep/match_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,12 @@ func TestMatch(t *testing.T) {
{`x[:y]`, 0, `z[:y]`},
{`x[:y]`, 0, `x[:y:z]`},
{`$x[:$y]`, 1, `a[:1]`},
{`$x[:$y]`, 0, `a[:]`},
{`x[y:]`, 1, `x[y:]`},
{`x[y:]`, 0, `z[y:]`},
{`x[y:]`, 0, `x[z:]`},
{`$x[$y:]`, 1, `a[1:]`},
{`$x[$y:]`, 0, `a[:]`},
{`x[y:z]`, 1, `x[y:z]`},
{`x[y:z]`, 0, `_[y:z]`},
{`x[y:z]`, 0, `x[_:z]`},
Expand All @@ -189,6 +191,25 @@ func TestMatch(t *testing.T) {
{`x[5:y:z]`, 0, `x[5:y:_]`},
{`x[5:y:z]`, 0, `x[0:y:z]`},
{`x[5:y:z]`, 0, `x[5:y]`},
{`x[$*_:]`, 1, `x[:]`},
{`x[$*_:]`, 1, `x[1:]`},
{`x[$*_:]`, 0, `x[1:2]`},
{`x[:$*_]`, 1, `x[:]`},
{`x[:$*_]`, 1, `x[:2]`},
{`x[:$*_]`, 0, `x[1:2]`},
{`x[$*_:$*_]`, 1, `x[:]`},
{`x[$*_:$*_]`, 1, `x[1:]`},
{`x[$*_:$*_]`, 1, `x[:2]`},
{`x[$*_:$*_]`, 1, `x[1:2]`},
{`x[$*_:$*_]`, 0, `x[1:2:2]`},
{`x[$*_:$*_:$*_]`, 1, `x[:]`},
{`x[$*_:$*_:$*_]`, 1, `x[1:]`},
{`x[$*_:$*_:$*_]`, 1, `x[:2]`},
{`x[$*_:$*_:$*_]`, 1, `x[1:2]`},
{`x[$*_:$*_:$*_]`, 1, `x[1:2:2]`},
{`x[$*y:$*y]`, 1, `x[:]`},
{`x[$*y:$*y]`, 1, `x[1:1]`},
{`x[$*y:$*y]`, 0, `x[1:0]`},

// Composite literals.
{`[]int{1, $x, $x}`, 1, `[]int{1, 2, 2}`},
Expand Down

0 comments on commit a0c5279

Please sign in to comment.