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