diff --git a/internal/gogrep/compile.go b/internal/gogrep/compile.go index 7c17ee03..7e267a53 100644 --- a/internal/gogrep/compile.go +++ b/internal/gogrep/compile.go @@ -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")) } diff --git a/internal/gogrep/compile_test.go b/internal/gogrep/compile_test.go index 2809a787..3f13a242 100644 --- a/internal/gogrep/compile_test.go +++ b/internal/gogrep/compile_test.go @@ -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 { diff --git a/internal/gogrep/match.go b/internal/gogrep/match.go index e825034c..ee14e13b 100644 --- a/internal/gogrep/match.go +++ b/internal/gogrep/match.go @@ -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) diff --git a/internal/gogrep/match_test.go b/internal/gogrep/match_test.go index d05d697a..2dd49378 100644 --- a/internal/gogrep/match_test.go +++ b/internal/gogrep/match_test.go @@ -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]`}, @@ -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}`},