Fauna v10 .NET/C# Driver 1.0.0
 
Loading...
Searching...
No Matches
SubQuerySwitch.cs
Go to the documentation of this file.
1using System.Linq.Expressions;
2using System.Reflection;
3using Fauna.Util;
6
7namespace Fauna.Linq;
8
9internal class SubQuerySwitch : DefaultExpressionSwitch<Query>
10{
11 private readonly LookupTable _lookup;
12
13 public SubQuerySwitch(LookupTable lookup)
14 {
15 _lookup = lookup;
16 }
17
18 protected override Query ApplyDefault(Expression? expr) =>
19 throw IQuerySource.Fail(expr);
20
21 protected override Query ConstantExpr(ConstantExpression expr)
22 {
23 return expr.Value switch
24 {
25 DataContext.ICollection col => QH.CollectionAll(col),
26 DataContext.IIndex idx => QH.CollectionIndex(idx),
27 _ => QH.Const(expr.Value)
28 };
29 }
30
31 protected override Query LambdaExpr(LambdaExpression expr)
32 {
33 var ps = expr.Parameters;
34 var pinner = string.Join(", ", ps.Select(p => p.Name));
35 var param = ps.Count() == 1 ? pinner : $"({pinner})";
36 var arrow = QH.Expr($"{param} =>");
37
38 return arrow.Concat(QH.Parens(Apply(expr.Body)));
39 }
40
41 protected override Query ParameterExpr(ParameterExpression expr) => QH.Expr(expr.Name!);
42
43 protected override Query BinaryExpr(BinaryExpression expr)
44 {
45 var op = expr.NodeType switch
46 {
47 ExpressionType.Add => "+",
48 ExpressionType.AddChecked => "+",
49 ExpressionType.And => "&", // bitwise
50 ExpressionType.AndAlso => "&&", // boolean
51 // ExpressionType.ArrayIndex => ,
52 ExpressionType.Coalesce => "??",
53 ExpressionType.Divide => "/",
54 ExpressionType.Equal => "==",
55 ExpressionType.ExclusiveOr => "^",
56 ExpressionType.GreaterThan => ">",
57 ExpressionType.GreaterThanOrEqual => ">=",
58 ExpressionType.LeftShift => "<<",
59 ExpressionType.LessThan => "<",
60 ExpressionType.LessThanOrEqual => "<=",
61 ExpressionType.Modulo => "%",
62 ExpressionType.Multiply => "*",
63 ExpressionType.MultiplyChecked => "*",
64 ExpressionType.NotEqual => "!=",
65 ExpressionType.Or => "|", // bitwise
66 ExpressionType.OrElse => "||", // boolean
67 ExpressionType.Power => "**",
68 ExpressionType.RightShift => ">>",
69 ExpressionType.Subtract => "-",
70 ExpressionType.SubtractChecked => "-",
71 _ => throw IQuerySource.Fail(expr)
72 };
73
74 var lhs = Apply(expr.Left);
75 var rhs = Apply(expr.Right);
76
77 return QH.Parens(QH.Op(lhs, op, rhs));
78 }
79
80 protected override Query CallExpr(MethodCallExpression expr)
81 {
82 var (callee, args, ext) = Expressions.GetCalleeAndArgs(expr);
83 var name = _lookup.MethodLookup(expr.Method, callee)?.Name;
84 if (name is null) throw IQuerySource.Fail(expr);
85 return QH.MethodCall(Apply(callee), name, ApplyAll(args));
86 }
87
88 protected override Query MemberAccessExpr(MemberExpression expr)
89 {
90 var callee = expr.Expression;
91 if (callee is null)
92 {
93 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
94 return QH.Const(val);
95 }
96 else if (callee.Type.IsClosureType())
97 {
98 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
99 return QH.Const(val);
100 }
101
102 switch (Apply(callee))
103 {
104 case QueryVal v:
105 var c = Expression.Constant(v.Unwrap);
106 var access = Expression.PropertyOrField(c, expr.Member.Name);
107 var val = Expression.Lambda(access).Compile().DynamicInvoke();
108 return QH.Const(val);
109
110 case var q:
111 var name = expr.Member is PropertyInfo prop ?
112 _lookup.FieldLookup(prop, callee)?.Name :
113 null;
114
115 if (name is null) throw IQuerySource.Fail(expr);
116 return QH.FieldAccess(q, name);
117 }
118 }
119}
Fauna.Linq.IntermediateQueryHelpers QH
Represents the abstract base class for constructing FQL queries.
Definition Query.cs:11
Represents a generic value holder for FQL queries. This class allows embedding values of various type...
Definition QueryVal.cs:10