diff --git a/README.md b/README.md
index ae43975..141b907 100644
--- a/README.md
+++ b/README.md
@@ -131,7 +131,7 @@ BinaryExpr {
VectorMatching = ...
}
```
-All non-value AST types are mutable and can also be updated in place using a visitor such as `DepthFirstExpressionVisitor`.
+Deep cloning of `Expr` is also supported via `Expr.DeepClone()`. Additionally all `Expr` AST types are mutable and can also be updated in place using a visitor such as `DepthFirstExpressionVisitor`.
### Emitting PromQL expressions
An Abstract Syntax Tree can be converted back to its PromQL string representation, e.g:
diff --git a/src/PromQL.Parser/Ast.cs b/src/PromQL.Parser/Ast.cs
index 3798b29..a3f5549 100644
--- a/src/PromQL.Parser/Ast.cs
+++ b/src/PromQL.Parser/Ast.cs
@@ -1,16 +1,16 @@
using System;
using System.Collections.Immutable;
+using System.Linq;
using System.Text;
using ExhaustiveMatching;
using Superpower.Model;
-using Superpower.Parsers;
namespace PromQL.Parser.Ast
{
///
/// Base of all PromQL syntactic components.
///
- public interface IPromQlNode
+ public interface IPromQlNode
{
void Accept(IVisitor visitor);
TextSpan? Span { get; }
@@ -35,6 +35,12 @@ public interface IPromQlNode
public interface Expr : IPromQlNode
{
ValueType Type { get; }
+
+ ///
+ /// Makes a deep clone of an expression.
+ ///
+ ///
+ public Expr DeepClone();
}
///
@@ -67,6 +73,7 @@ public AggregateExpr(AggregateOperator @operator, Expr expr, Expr param, bool wi
public ValueType Type => ValueType.Vector;
public void Accept(IVisitor visitor) => visitor.Visit(this);
+ public Expr DeepClone() => this with {Expr = Expr.DeepClone(), Param = Param?.DeepClone() };
}
///
@@ -95,6 +102,8 @@ public ValueType Type
return ValueType.Vector;
}
}
+
+ public Expr DeepClone() => this with { LeftHandSide = LeftHandSide.DeepClone(), RightHandSide = RightHandSide.DeepClone() };
}
///
@@ -119,10 +128,10 @@ public VectorMatching(bool returnBool) : this (DefaultMatchCardinality, Immutabl
{
}
- public Operators.VectorMatchCardinality MatchCardinality { get; set; } = MatchCardinality;
- public bool On { get; set; } = On;
- public ImmutableArray Include { get; set; } = Include;
- public bool ReturnBool { get; set; } = ReturnBool;
+ public Operators.VectorMatchCardinality MatchCardinality { get; internal set; } = MatchCardinality;
+ public bool On { get; } = On;
+ public ImmutableArray Include { get; internal set; } = Include;
+ public bool ReturnBool { get; } = ReturnBool;
public void Accept(IVisitor visitor) => visitor.Visit(this);
};
@@ -146,6 +155,8 @@ public FunctionCall(Function function, params Expr[] args)
public void Accept(IVisitor visitor) => visitor.Visit(this);
+ public Expr DeepClone() => this with { Args = Args.Select(a => a.DeepClone()).ToImmutableArray() };
+
protected virtual bool PrintMembers(StringBuilder builder)
{
builder.AppendLine($"{nameof(Function)} = {Function.Name}, ");
@@ -161,6 +172,7 @@ public record ParenExpression(Expr Expr, TextSpan? Span = null) : Expr
public Expr Expr { get; set; } = Expr;
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => Expr.Type;
+ public Expr DeepClone() => this with { Expr = Expr.DeepClone() };
}
public record OffsetExpr(Expr Expr, Duration Duration, TextSpan? Span = null) : Expr
@@ -169,6 +181,7 @@ public record OffsetExpr(Expr Expr, Duration Duration, TextSpan? Span = null) :
public Duration Duration { get; set; } = Duration;
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => Expr.Type;
+ public Expr DeepClone() => this with { Expr = Expr.DeepClone() };
}
public record MatrixSelector(VectorSelector Vector, Duration Duration, TextSpan? Span = null) : Expr
@@ -177,6 +190,7 @@ public record MatrixSelector(VectorSelector Vector, Duration Duration, TextSpan?
public Duration Duration { get; set; } = Duration;
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => ValueType.Matrix;
+ public Expr DeepClone() => this with { };
}
public record UnaryExpr(Operators.Unary Operator, Expr Expr, TextSpan? Span = null) : Expr
@@ -186,6 +200,7 @@ public record UnaryExpr(Operators.Unary Operator, Expr Expr, TextSpan? Span = nu
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => Expr.Type;
+ public Expr DeepClone() => this with { Expr = Expr.DeepClone() };
}
public record VectorSelector : Expr
@@ -216,11 +231,12 @@ public VectorSelector(MetricIdentifier metricIdentifier, LabelMatchers labelMatc
public ValueType Type => ValueType.Vector;
public void Accept(IVisitor visitor) => visitor.Visit(this);
+ public Expr DeepClone() => this with { };
}
public record LabelMatchers(ImmutableArray Matchers, TextSpan? Span = null) : IPromQlNode
{
- protected virtual bool PrintMembers(System.Text.StringBuilder builder)
+ protected virtual bool PrintMembers(StringBuilder builder)
{
builder.Append($"{nameof(Matchers)} = ");
Matchers.PrintArray(builder);
@@ -247,6 +263,7 @@ public record NumberLiteral(double Value, TextSpan? Span = null) : Expr
{
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => ValueType.Scalar;
+ public Expr DeepClone() => this with { };
}
public record Duration(TimeSpan Value, TextSpan? Span = null) : IPromQlNode
@@ -258,6 +275,7 @@ public record StringLiteral(char Quote, string Value, TextSpan? Span = null) : E
{
public void Accept(IVisitor visitor) => visitor.Visit(this);
public ValueType Type => ValueType.String;
+ public Expr DeepClone() => this with { };
}
public record SubqueryExpr(Expr Expr, Duration Range, Duration? Step = null, TextSpan? Span = null) : Expr
@@ -268,6 +286,7 @@ public record SubqueryExpr(Expr Expr, Duration Range, Duration? Step = null, Tex
public ValueType Type => ValueType.Matrix;
public void Accept(IVisitor visitor) => visitor.Visit(this);
+ public Expr DeepClone() => this with { Expr = Expr.DeepClone() };
}
internal static class Extensions
@@ -278,7 +297,7 @@ internal static void PrintArray(this ImmutableArray arr, System.Text.Strin
sb.Append("[ ");
for (int i = 0; i < arr.Length; i++)
{
- sb.Append(arr[i].ToString());
+ sb.Append(arr[i]);
if (i < arr.Length - 1)
sb.Append(", ");
}