/
RangeExpression.cs
75 lines (66 loc) · 2.81 KB
/
RangeExpression.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System.Linq.Expressions;
using System.Reflection;
using Debug = System.Diagnostics.Debug;
namespace DotNext.Linq.Expressions;
/// <summary>
/// Expresses construction of <see cref="Range"/>.
/// </summary>
public sealed class RangeExpression : CustomExpression
{
/// <summary>
/// Initializes a new range with the specified starting and ending indexes.
/// </summary>
/// <param name="start">The inclusive start index of the range.</param>
/// <param name="end">The exclusive end index of the range.</param>
public RangeExpression(ItemIndexExpression? start = null, ItemIndexExpression? end = null)
{
Start = start ?? ItemIndexExpression.First;
End = end ?? ItemIndexExpression.Last;
}
/// <summary>
/// Gets the inclusive start index of the range.
/// </summary>
/// <value>The inclusive start index of the range.</value>
public ItemIndexExpression Start { get; }
/// <summary>
/// Gets the exclusive end index of the range.
/// </summary>
/// <value>The end index of the range.</value>
public ItemIndexExpression End { get; }
/// <summary>
/// Gets result type of asynchronous operation.
/// </summary>
public override Type Type => typeof(Range);
private static Expression GetOffsetAndLength(Expression range, Expression length)
=> Call(range, nameof(Range.GetOffsetAndLength), null, length);
internal static Expression GetOffsetAndLength(Expression range, Expression length, out ParameterExpression offsetAndLength, out MemberExpression offsetField, out MemberExpression lengthField)
{
var result = GetOffsetAndLength(range, length);
offsetAndLength = Variable(result.Type);
offsetField = Field(offsetAndLength, nameof(ValueTuple<int, int>.Item1));
lengthField = Field(offsetAndLength, nameof(ValueTuple<int, int>.Item2));
return result;
}
/// <summary>
/// Translates this expression into predefined set of expressions
/// using Lowering technique.
/// </summary>
/// <returns>Translated expression.</returns>
public override Expression Reduce()
{
ConstructorInfo? ctor = typeof(Range).GetConstructor([typeof(Index), typeof(Index)]);
Debug.Assert(ctor is not null);
return New(ctor, Start.Reduce(), End.Reduce());
}
/// <summary>
/// Visit children expressions.
/// </summary>
/// <param name="visitor">Expression visitor.</param>
/// <returns>Potentially modified expression if one of children expressions is modified during visit.</returns>
protected override RangeExpression VisitChildren(ExpressionVisitor visitor)
{
var start = Start.Visit(visitor);
var end = End.Visit(visitor);
return ReferenceEquals(start, Start) && ReferenceEquals(end, End) ? this : new(start, end);
}
}