Implement unary expression for vector types.

Closes #956
This commit is contained in:
Fabian Reinartz 2015-08-04 14:57:34 +02:00
parent c322422412
commit 579fdf65e2
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}
case *UnaryExpr:
smpl := ev.evalScalar(e.Expr)
se := ev.evalOneOf(e.Expr, ExprScalar, ExprVector)
// Only + and - are possible operators.
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:
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 {
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:
// 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: "",
fail: true,
@ -191,14 +211,18 @@ var testExpr = []struct {
input: "1 =~ 1",
fail: true,
errMsg: "could not parse remaining input \"=~ 1\"...",
}, {
input: "-some_metric",
fail: true,
errMsg: "expected type scalar in unary expression, got vector",
}, {
input: `-"string"`,
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.
{
@ -950,18 +974,15 @@ var testExpr = []struct {
input: "-=",
fail: true,
errMsg: `no valid expression found`,
},
{
}, {
input: "++-++-+-+-<",
fail: true,
errMsg: `no valid expression found`,
},
{
}, {
input: "e-+=/(0)",
fail: true,
errMsg: `no valid expression found`,
},
{
}, {
input: "-If",
fail: true,
errMsg: `no valid expression found`,