Fauna .NET Driver 0.1.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 if (expr.Value is DataContext.Collection col)
23 {
24 return QH.CollectionAll(col);
25 }
26 else if (expr.Value is DataContext.Index idx)
27 {
28 return QH.CollectionIndex(idx);
29 }
30 else
31 {
32 return QH.Const(expr.Value);
33 }
34 }
35
36 protected override Query LambdaExpr(LambdaExpression expr)
37 {
38 var ps = expr.Parameters;
39 var pinner = string.Join(", ", ps.Select(p => p.Name));
40 var param = ps.Count() == 1 ? pinner : $"({pinner})";
41 var arrow = QH.Expr($"{param} =>");
42
43 return arrow.Concat(QH.Parens(Apply(expr.Body)));
44 }
45
46 protected override Query ParameterExpr(ParameterExpression expr) => QH.Expr(expr.Name!);
47
48 protected override Query BinaryExpr(BinaryExpression expr)
49 {
50 var op = expr.NodeType switch
51 {
52 ExpressionType.Add => "+",
53 ExpressionType.AddChecked => "+",
54 ExpressionType.And => "&", // bitwise
55 ExpressionType.AndAlso => "&&", // boolean
56 // ExpressionType.ArrayIndex => ,
57 ExpressionType.Coalesce => "??",
58 ExpressionType.Divide => "/",
59 ExpressionType.Equal => "==",
60 ExpressionType.ExclusiveOr => "^",
61 ExpressionType.GreaterThan => ">",
62 ExpressionType.GreaterThanOrEqual => ">=",
63 ExpressionType.LeftShift => "<<",
64 ExpressionType.LessThan => "<",
65 ExpressionType.LessThanOrEqual => "<=",
66 ExpressionType.Modulo => "%",
67 ExpressionType.Multiply => "*",
68 ExpressionType.MultiplyChecked => "*",
69 ExpressionType.NotEqual => "!=",
70 ExpressionType.Or => "|", // bitwise
71 ExpressionType.OrElse => "||", // boolean
72 ExpressionType.Power => "**",
73 ExpressionType.RightShift => ">>",
74 ExpressionType.Subtract => "-",
75 ExpressionType.SubtractChecked => "-",
76 _ => throw IQuerySource.Fail(expr)
77 };
78
79 var lhs = Apply(expr.Left);
80 var rhs = Apply(expr.Right);
81
82 return QH.Parens(QH.Op(lhs, op, rhs));
83 }
84
85 protected override Query CallExpr(MethodCallExpression expr)
86 {
87 var (callee, args, ext) = Expressions.GetCalleeAndArgs(expr);
88 var name = _lookup.MethodLookup(expr.Method, callee)?.Name;
89 if (name is null) throw IQuerySource.Fail(expr);
90 return QH.MethodCall(Apply(callee), name, ApplyAll(args));
91 }
92
93 protected override Query MemberAccessExpr(MemberExpression expr)
94 {
95 var callee = expr.Expression;
96 if (callee is null)
97 {
98 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
99 return QH.Const(val);
100 }
101 else if (callee.Type.IsClosureType())
102 {
103 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
104 return QH.Const(val);
105 }
106
107 switch (Apply(callee))
108 {
109 case QueryVal v:
110 var c = Expression.Constant(v.Unwrap);
111 var access = Expression.PropertyOrField(c, expr.Member.Name);
112 var val = Expression.Lambda(access).Compile().DynamicInvoke();
113 return QH.Const(val);
114
115 case var q:
116 var name = expr.Member is PropertyInfo prop ?
117 _lookup.FieldLookup(prop, callee)?.Name :
118 null;
119
120 if (name is null) throw IQuerySource.Fail(expr);
121 return QH.FieldAccess(q, name);
122 }
123 }
124}
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:9