///|
pub(all) enum MatchOp {
  Equal
  NotEqual
  Regex
  NotRegex
} derive(Eq, @debug.Debug)

///|
pub(all) struct LabelMatcher {
  name : String
  op : MatchOp
  value : String
} derive(Eq, @debug.Debug)

///|
pub(all) enum UnaryOp {
  Neg
  Pos
} derive(Eq, @debug.Debug)

///|
pub(all) enum BinaryOp {
  Add
  Sub
  Mul
  Div
  Mod
  Pow
  Eq
  Neq
  Gt
  Lt
  Gte
  Lte
  And
  Or
  Unless
} derive(Eq, @debug.Debug)

///|
pub(all) enum AggOp {
  Sum
  Avg
  Min
  Max
  Count
  TopK
  BottomK
} derive(Eq, @debug.Debug)

///|
pub(all) enum GroupSide {
  NoGroup
  GroupLeft
  GroupRight
} derive(Eq, @debug.Debug)

///|
pub(all) struct VectorMatch {
  on : Bool
  labels : Array[String]
  side : GroupSide
  include_labels : Array[String]
} derive(Eq, @debug.Debug)

///|
pub(all) struct Selector {
  metric : String
  matchers : Array[LabelMatcher]
  range_ms : Double?
  offset_ms : Double
  at_ms : Double?
} derive(Eq, @debug.Debug)

///|
pub(all) enum Expr {
  Number(Double)
  StringLiteral(String)
  Selector(Selector)
  Call(String, Array[Expr])
  Aggregate(AggOp, Array[Expr], Bool, Array[String])
  Unary(UnaryOp, Expr)
  Binary(BinaryOp, Expr, Expr, Bool, VectorMatch?)
} derive(Eq, @debug.Debug)