Merge pull request #962 from prometheus/fabxc/un-vec

Implement unary expression for vector types.
This commit is contained in:
Fabian Reinartz 2015-08-04 16:44:34 +02:00
commit e46e93dcba
3 changed files with 46 additions and 15 deletions

View file

@ -691,11 +691,19 @@ func (ev *evaluator) eval(expr Expr) Value {
return &String{Value: e.Val, Timestamp: ev.Timestamp} return &String{Value: e.Val, Timestamp: ev.Timestamp}
case *UnaryExpr: case *UnaryExpr:
smpl := ev.evalScalar(e.Expr) se := ev.evalOneOf(e.Expr, ExprScalar, ExprVector)
// Only + and - are possible operators.
if e.Op == itemSUB { if e.Op == itemSUB {
smpl.Value = -smpl.Value switch v := se.(type) {
case *Scalar:
v.Value = -v.Value
case Vector:
for i, sv := range v {
v[i].Value = -sv.Value
}
}
} }
return smpl return se
case *VectorSelector: case *VectorSelector:
return ev.vectorSelector(e) return ev.vectorSelector(e)

View file

@ -1075,7 +1075,9 @@ func (p *parser) checkType(node Node) (typ ExprType) {
if n.Op != itemADD && n.Op != itemSUB { if n.Op != itemADD && n.Op != itemSUB {
p.errorf("only + and - operators allowed for unary expressions") p.errorf("only + and - operators allowed for unary expressions")
} }
p.expectType(n.Expr, ExprScalar, "unary expression") if t := p.checkType(n.Expr); t != ExprScalar && t != ExprVector {
p.errorf("unary expression only allowed on expressions of type scalar or vector, got %q", t)
}
case *NumberLiteral, *MatrixSelector, *StringLiteral, *VectorSelector: case *NumberLiteral, *MatrixSelector, *StringLiteral, *VectorSelector:
// Nothing to do for terminals. // Nothing to do for terminals.

View file

@ -123,6 +123,26 @@ var testExpr = []struct {
}}, }},
}, },
}, },
}, {
input: "-some_metric", expected: &UnaryExpr{
Op: itemSUB,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: clientmodel.MetricNameLabel, Value: "some_metric"},
},
},
},
}, {
input: "+some_metric", expected: &UnaryExpr{
Op: itemADD,
Expr: &VectorSelector{
Name: "some_metric",
LabelMatchers: metric.LabelMatchers{
{Type: metric.Equal, Name: clientmodel.MetricNameLabel, Value: "some_metric"},
},
},
},
}, { }, {
input: "", input: "",
fail: true, fail: true,
@ -191,14 +211,18 @@ var testExpr = []struct {
input: "1 =~ 1", input: "1 =~ 1",
fail: true, fail: true,
errMsg: "could not parse remaining input \"=~ 1\"...", errMsg: "could not parse remaining input \"=~ 1\"...",
}, {
input: "-some_metric",
fail: true,
errMsg: "expected type scalar in unary expression, got vector",
}, { }, {
input: `-"string"`, input: `-"string"`,
fail: true, fail: true,
errMsg: "expected type scalar in unary expression, got string", errMsg: `unary expression only allowed on expressions of type scalar or vector, got "string"`,
}, {
input: `-test[5m]`,
fail: true,
errMsg: `unary expression only allowed on expressions of type scalar or vector, got "matrix"`,
}, {
input: `*test`,
fail: true,
errMsg: "no valid expression found",
}, },
// Vector binary operations. // Vector binary operations.
{ {
@ -950,18 +974,15 @@ var testExpr = []struct {
input: "-=", input: "-=",
fail: true, fail: true,
errMsg: `no valid expression found`, errMsg: `no valid expression found`,
}, }, {
{
input: "++-++-+-+-<", input: "++-++-+-+-<",
fail: true, fail: true,
errMsg: `no valid expression found`, errMsg: `no valid expression found`,
}, }, {
{
input: "e-+=/(0)", input: "e-+=/(0)",
fail: true, fail: true,
errMsg: `no valid expression found`, errMsg: `no valid expression found`,
}, }, {
{
input: "-If", input: "-If",
fail: true, fail: true,
errMsg: `no valid expression found`, errMsg: `no valid expression found`,