1using System.Linq.Expressions;
2using System.Reflection;
9internal class SubQuerySwitch : DefaultExpressionSwitch<Query>
11 private readonly LookupTable _lookup;
13 public SubQuerySwitch(LookupTable lookup)
18 protected override Query ApplyDefault(Expression? expr) =>
19 throw IQuerySource.Fail(expr);
21 protected override Query ConstantExpr(ConstantExpression expr)
23 return expr.Value
switch
25 DataContext.ICollection col =>
QH.CollectionAll(col),
26 DataContext.IIndex idx =>
QH.CollectionIndex(idx),
27 _ =>
QH.Const(expr.Value)
31 protected override Query LambdaExpr(LambdaExpression expr)
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} =>");
38 return arrow.Concat(
QH.Parens(Apply(expr.Body)));
41 protected override Query ParameterExpr(ParameterExpression expr) =>
QH.Expr(expr.Name!);
43 protected override Query BinaryExpr(BinaryExpression expr)
45 var op = expr.NodeType
switch
47 ExpressionType.Add =>
"+",
48 ExpressionType.AddChecked =>
"+",
49 ExpressionType.And =>
"&",
50 ExpressionType.AndAlso =>
"&&",
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 =>
"|",
66 ExpressionType.OrElse =>
"||",
67 ExpressionType.Power =>
"**",
68 ExpressionType.RightShift =>
">>",
69 ExpressionType.Subtract =>
"-",
70 ExpressionType.SubtractChecked =>
"-",
71 _ =>
throw IQuerySource.Fail(expr)
74 var lhs = Apply(expr.Left);
75 var rhs = Apply(expr.Right);
77 return QH.Parens(
QH.Op(lhs, op, rhs));
80 protected override Query CallExpr(MethodCallExpression expr)
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));
88 protected override Query MemberAccessExpr(MemberExpression expr)
90 var callee = expr.Expression;
93 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
96 else if (callee.Type.IsClosureType())
98 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
102 switch (Apply(callee))
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);
111 var name = expr.Member is PropertyInfo prop ?
112 _lookup.FieldLookup(prop, callee)?.Name :
115 if (name is
null)
throw IQuerySource.Fail(expr);
116 return QH.FieldAccess(q, name);
Fauna.Linq.IntermediateQueryHelpers QH
Represents the abstract base class for constructing FQL queries.
Represents a generic value holder for FQL queries. This class allows embedding values of various type...