DeveelDB  20151217
complete SQL database system, primarly developed for .NET/Mono frameworks
ExpressionVisitor.cs
Go to the documentation of this file.
1 //
2 // Copyright 2010-2015 Deveel
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #if !NET40
18 using System;
19 using System.Collections.Generic;
20 using System.Collections.ObjectModel;
21 using System.Linq.Expressions;
22 
23 namespace Deveel.Data.Linq {
24  abstract class ExpressionVisitor {
25  protected ExpressionVisitor() {
26  }
27 
28  public virtual Expression Visit(Expression exp) {
29  if (exp == null)
30  return exp;
31  switch (exp.NodeType) {
32  case ExpressionType.Negate:
33  case ExpressionType.NegateChecked:
34  case ExpressionType.Not:
35  case ExpressionType.Convert:
36  case ExpressionType.ConvertChecked:
37  case ExpressionType.ArrayLength:
38  case ExpressionType.Quote:
39  case ExpressionType.TypeAs:
40  return this.VisitUnary((UnaryExpression)exp);
41  case ExpressionType.Add:
42  case ExpressionType.AddChecked:
43  case ExpressionType.Subtract:
44  case ExpressionType.SubtractChecked:
45  case ExpressionType.Multiply:
46  case ExpressionType.MultiplyChecked:
47  case ExpressionType.Divide:
48  case ExpressionType.Modulo:
49  case ExpressionType.And:
50  case ExpressionType.AndAlso:
51  case ExpressionType.Or:
52  case ExpressionType.OrElse:
53  case ExpressionType.LessThan:
54  case ExpressionType.LessThanOrEqual:
55  case ExpressionType.GreaterThan:
56  case ExpressionType.GreaterThanOrEqual:
57  case ExpressionType.Equal:
58  case ExpressionType.NotEqual:
59  case ExpressionType.Coalesce:
60  case ExpressionType.ArrayIndex:
61  case ExpressionType.RightShift:
62  case ExpressionType.LeftShift:
63  case ExpressionType.ExclusiveOr:
64  return VisitBinary((BinaryExpression)exp);
65  case ExpressionType.TypeIs:
66  return VisitTypeIs((TypeBinaryExpression)exp);
67  case ExpressionType.Conditional:
68  return VisitConditional((ConditionalExpression)exp);
69  case ExpressionType.Constant:
70  return VisitConstant((ConstantExpression)exp);
71  case ExpressionType.Parameter:
72  return VisitParameter((ParameterExpression)exp);
73  case ExpressionType.MemberAccess:
74  return VisitMemberAccess((MemberExpression)exp);
75  case ExpressionType.Call:
76  return VisitMethodCall((MethodCallExpression)exp);
77  case ExpressionType.Lambda:
78  return VisitLambda((LambdaExpression)exp);
79  case ExpressionType.New:
80  return VisitNew((NewExpression)exp);
81  case ExpressionType.NewArrayInit:
82  case ExpressionType.NewArrayBounds:
83  return VisitNewArray((NewArrayExpression)exp);
84  case ExpressionType.Invoke:
85  return VisitInvocation((InvocationExpression)exp);
86  case ExpressionType.MemberInit:
87  return VisitMemberInit((MemberInitExpression)exp);
88  case ExpressionType.ListInit:
89  return VisitListInit((ListInitExpression)exp);
90  default:
91  throw new Exception(string.Format("Unhandled expression type: '{0}'", exp.NodeType));
92  }
93  }
94 
95  protected virtual MemberBinding VisitBinding(MemberBinding binding) {
96  switch (binding.BindingType) {
97  case MemberBindingType.Assignment:
98  return VisitMemberAssignment((MemberAssignment)binding);
99  case MemberBindingType.MemberBinding:
100  return VisitMemberMemberBinding((MemberMemberBinding)binding);
101  case MemberBindingType.ListBinding:
102  return VisitMemberListBinding((MemberListBinding)binding);
103  default:
104  throw new Exception(string.Format("Unhandled binding type '{0}'", binding.BindingType));
105  }
106  }
107 
108  protected virtual ElementInit VisitElementInitializer(ElementInit initializer) {
109  ReadOnlyCollection<Expression> arguments = VisitExpressionList(initializer.Arguments);
110  if (arguments != initializer.Arguments) {
111  return Expression.ElementInit(initializer.AddMethod, arguments);
112  }
113  return initializer;
114  }
115 
116  protected virtual Expression VisitUnary(UnaryExpression u) {
117  Expression operand = Visit(u.Operand);
118  if (operand != u.Operand) {
119  return Expression.MakeUnary(u.NodeType, operand, u.Type, u.Method);
120  }
121  return u;
122  }
123 
124  protected virtual Expression VisitBinary(BinaryExpression b) {
125  Expression left = Visit(b.Left);
126  Expression right = Visit(b.Right);
127  Expression conversion = Visit(b.Conversion);
128  if (left != b.Left || right != b.Right || conversion != b.Conversion) {
129  if (b.NodeType == ExpressionType.Coalesce && b.Conversion != null)
130  return Expression.Coalesce(left, right, conversion as LambdaExpression);
131 
132  return Expression.MakeBinary(b.NodeType, left, right, b.IsLiftedToNull, b.Method);
133  }
134  return b;
135  }
136 
137  protected virtual Expression VisitTypeIs(TypeBinaryExpression b) {
138  Expression expr = Visit(b.Expression);
139  if (expr != b.Expression) {
140  return Expression.TypeIs(expr, b.TypeOperand);
141  }
142  return b;
143  }
144 
145  protected virtual Expression VisitConstant(ConstantExpression c) {
146  return c;
147  }
148 
149  protected virtual Expression VisitConditional(ConditionalExpression c) {
150  Expression test = Visit(c.Test);
151  Expression ifTrue = Visit(c.IfTrue);
152  Expression ifFalse = Visit(c.IfFalse);
153  if (test != c.Test || ifTrue != c.IfTrue || ifFalse != c.IfFalse) {
154  return Expression.Condition(test, ifTrue, ifFalse);
155  }
156  return c;
157  }
158 
159  protected virtual Expression VisitParameter(ParameterExpression p) {
160  return p;
161  }
162 
163  protected virtual Expression VisitMemberAccess(MemberExpression m) {
164  Expression exp = this.Visit(m.Expression);
165  if (exp != m.Expression) {
166  return Expression.MakeMemberAccess(exp, m.Member);
167  }
168  return m;
169  }
170 
171  protected virtual Expression VisitMethodCall(MethodCallExpression m) {
172  Expression obj = this.Visit(m.Object);
173  IEnumerable<Expression> args = this.VisitExpressionList(m.Arguments);
174  if (obj != m.Object || args != m.Arguments) {
175  return Expression.Call(obj, m.Method, args);
176  }
177  return m;
178  }
179 
180  protected virtual ReadOnlyCollection<Expression> VisitExpressionList(ReadOnlyCollection<Expression> original) {
181  List<Expression> list = null;
182  for (int i = 0, n = original.Count; i < n; i++) {
183  Expression p = this.Visit(original[i]);
184  if (list != null) {
185  list.Add(p);
186  } else if (p != original[i]) {
187  list = new List<Expression>(n);
188  for (int j = 0; j < i; j++) {
189  list.Add(original[j]);
190  }
191  list.Add(p);
192  }
193  }
194  if (list != null) {
195  return list.AsReadOnly();
196  }
197  return original;
198  }
199 
200  protected virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment) {
201  Expression e = this.Visit(assignment.Expression);
202  if (e != assignment.Expression) {
203  return Expression.Bind(assignment.Member, e);
204  }
205  return assignment;
206  }
207 
208  protected virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding) {
209  IEnumerable<MemberBinding> bindings = this.VisitBindingList(binding.Bindings);
210  if (bindings != binding.Bindings) {
211  return Expression.MemberBind(binding.Member, bindings);
212  }
213  return binding;
214  }
215 
216  protected virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding) {
217  IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(binding.Initializers);
218  if (initializers != binding.Initializers) {
219  return Expression.ListBind(binding.Member, initializers);
220  }
221  return binding;
222  }
223 
224  protected virtual IEnumerable<MemberBinding> VisitBindingList(ReadOnlyCollection<MemberBinding> original) {
225  List<MemberBinding> list = null;
226  for (int i = 0, n = original.Count; i < n; i++) {
227  MemberBinding b = this.VisitBinding(original[i]);
228  if (list != null) {
229  list.Add(b);
230  } else if (b != original[i]) {
231  list = new List<MemberBinding>(n);
232  for (int j = 0; j < i; j++) {
233  list.Add(original[j]);
234  }
235  list.Add(b);
236  }
237  }
238  if (list != null)
239  return list;
240  return original;
241  }
242 
243  protected virtual IEnumerable<ElementInit> VisitElementInitializerList(ReadOnlyCollection<ElementInit> original) {
244  List<ElementInit> list = null;
245  for (int i = 0, n = original.Count; i < n; i++) {
246  ElementInit init = this.VisitElementInitializer(original[i]);
247  if (list != null) {
248  list.Add(init);
249  } else if (init != original[i]) {
250  list = new List<ElementInit>(n);
251  for (int j = 0; j < i; j++) {
252  list.Add(original[j]);
253  }
254  list.Add(init);
255  }
256  }
257  if (list != null)
258  return list;
259  return original;
260  }
261 
262  protected virtual Expression VisitLambda(LambdaExpression lambda) {
263  Expression body = this.Visit(lambda.Body);
264  if (body != lambda.Body) {
265  return Expression.Lambda(lambda.Type, body, lambda.Parameters);
266  }
267  return lambda;
268  }
269 
270  protected virtual NewExpression VisitNew(NewExpression nex) {
271  IEnumerable<Expression> args = this.VisitExpressionList(nex.Arguments);
272  if (args != nex.Arguments) {
273  if (nex.Members != null)
274  return Expression.New(nex.Constructor, args, nex.Members);
275  else
276  return Expression.New(nex.Constructor, args);
277  }
278  return nex;
279  }
280 
281  protected virtual Expression VisitMemberInit(MemberInitExpression init) {
282  NewExpression n = this.VisitNew(init.NewExpression);
283  IEnumerable<MemberBinding> bindings = this.VisitBindingList(init.Bindings);
284  if (n != init.NewExpression || bindings != init.Bindings) {
285  return Expression.MemberInit(n, bindings);
286  }
287  return init;
288  }
289 
290  protected virtual Expression VisitListInit(ListInitExpression init) {
291  NewExpression n = this.VisitNew(init.NewExpression);
292  IEnumerable<ElementInit> initializers = this.VisitElementInitializerList(init.Initializers);
293  if (n != init.NewExpression || initializers != init.Initializers) {
294  return Expression.ListInit(n, initializers);
295  }
296  return init;
297  }
298 
299  protected virtual Expression VisitNewArray(NewArrayExpression na) {
300  IEnumerable<Expression> exprs = this.VisitExpressionList(na.Expressions);
301  if (exprs != na.Expressions) {
302  if (na.NodeType == ExpressionType.NewArrayInit) {
303  return Expression.NewArrayInit(na.Type.GetElementType(), exprs);
304  } else {
305  return Expression.NewArrayBounds(na.Type.GetElementType(), exprs);
306  }
307  }
308  return na;
309  }
310 
311  protected virtual Expression VisitInvocation(InvocationExpression iv) {
312  IEnumerable<Expression> args = this.VisitExpressionList(iv.Arguments);
313  Expression expr = this.Visit(iv.Expression);
314  if (args != iv.Arguments || expr != iv.Expression) {
315  return Expression.Invoke(expr, args);
316  }
317  return iv;
318  }
319  }
320 }
321 #endif
virtual IEnumerable< MemberBinding > VisitBindingList(ReadOnlyCollection< MemberBinding > original)
virtual Expression VisitTypeIs(TypeBinaryExpression b)
virtual Expression VisitParameter(ParameterExpression p)
virtual MemberBinding VisitBinding(MemberBinding binding)
virtual MemberAssignment VisitMemberAssignment(MemberAssignment assignment)
virtual Expression VisitBinary(BinaryExpression b)
virtual MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding binding)
virtual IEnumerable< ElementInit > VisitElementInitializerList(ReadOnlyCollection< ElementInit > original)
virtual Expression VisitNewArray(NewArrayExpression na)
virtual Expression VisitListInit(ListInitExpression init)
virtual MemberListBinding VisitMemberListBinding(MemberListBinding binding)
virtual Expression VisitMethodCall(MethodCallExpression m)
virtual Expression VisitMemberInit(MemberInitExpression init)
virtual Expression VisitConditional(ConditionalExpression c)
virtual NewExpression VisitNew(NewExpression nex)
virtual Expression VisitInvocation(InvocationExpression iv)
virtual Expression Visit(Expression exp)
virtual Expression VisitMemberAccess(MemberExpression m)
virtual Expression VisitUnary(UnaryExpression u)
virtual Expression VisitLambda(LambdaExpression lambda)
virtual Expression VisitConstant(ConstantExpression c)
virtual ElementInit VisitElementInitializer(ElementInit initializer)
virtual ReadOnlyCollection< Expression > VisitExpressionList(ReadOnlyCollection< Expression > original)