1using System.Linq.Expressions;
2using System.Reflection;
8internal class SubQuerySwitch : DefaultExpressionSwitch<Query>
10 private readonly LookupTable _lookup;
12 public SubQuerySwitch(LookupTable lookup)
17 protected override Query ApplyDefault(Expression? expr) =>
18 throw IQuerySource.Fail(expr);
20 protected override Query ConstantExpr(ConstantExpression expr)
22 return expr.Value
switch
26 _ =>
QH.Const(expr.Value)
30 protected override Query LambdaExpr(LambdaExpression expr)
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} =>");
37 return arrow.Concat(
QH.Parens(Apply(expr.Body)));
40 protected override Query ParameterExpr(ParameterExpression expr) =>
QH.Expr(expr.Name!);
42 protected override Query BinaryExpr(BinaryExpression expr)
44 var op = expr.NodeType
switch
46 ExpressionType.Add =>
"+",
47 ExpressionType.AddChecked =>
"+",
48 ExpressionType.And =>
"&",
49 ExpressionType.AndAlso =>
"&&",
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 =>
"|",
65 ExpressionType.OrElse =>
"||",
66 ExpressionType.Power =>
"**",
67 ExpressionType.RightShift =>
">>",
68 ExpressionType.Subtract =>
"-",
69 ExpressionType.SubtractChecked =>
"-",
70 _ =>
throw IQuerySource.Fail(expr)
73 var lhs = Apply(expr.Left);
74 var rhs = Apply(expr.Right);
76 return QH.Parens(
QH.Op(lhs, op, rhs));
79 protected override Query CallExpr(MethodCallExpression expr)
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));
87 protected override Query MemberAccessExpr(MemberExpression expr)
89 var callee = expr.Expression;
92 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
95 else if (callee.Type.IsClosureType())
97 var val = Expression.Lambda(expr).Compile().DynamicInvoke();
101 switch (Apply(callee))
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);
110 var name = expr.Member is PropertyInfo prop ?
111 _lookup.FieldLookup(prop, callee)?.Name :
114 if (name is
null)
throw IQuerySource.Fail(expr);
115 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...