263578e504655df7ad1f1396c02e73e9d3fb3909
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / Expression.cs
1 //
2 // Expression.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //   Miguel de Icaza (miguel@novell.com)
7 //
8 // (C) 2008 Novell, Inc. (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Collections.ObjectModel;
33 using System.Linq;
34 using System.Reflection;
35
36 namespace System.Linq.Expressions {
37
38         public abstract class Expression {
39
40                 ExpressionType node_type;
41                 Type type;
42
43                 static BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance;
44                 static BindingFlags PublicStatic = BindingFlags.Public | BindingFlags.Static;
45
46                 public ExpressionType NodeType {
47                         get { return node_type; }
48                 }
49
50                 public Type Type {
51                         get { return type; }
52                 }
53
54                 // TODO: remove when all Expression subtypes
55                 // have their constructor implemented
56                 protected Expression ()
57                 {
58                 }
59
60                 protected Expression (ExpressionType node_type, Type type)
61                 {
62                         this.node_type = node_type;
63                         this.type = type;
64                 }
65
66                 public override string ToString ()
67                 {
68                         return ExpressionPrinter.ToString (this);
69                 }
70
71                 static void CheckMethod (MethodInfo m)
72                 {
73                 }
74
75 #region Binary Expressions
76                 static bool IsInt (Type t)
77                 {
78                         return t == typeof (byte) || t == typeof (sbyte) ||
79                                 t == typeof (short) || t == typeof (ushort) ||
80                                 t == typeof (int) || t == typeof (uint) ||
81                                 t == typeof (long) || t == typeof (ulong);
82                 }
83
84                 static bool IsNumber (Type t)
85                 {
86                         if (IsInt (t))
87                                 return true;
88
89                         return t == typeof (float) || t == typeof (double) || t == typeof (decimal);
90                 }
91
92                 static MethodInfo GetUnaryOperator (string oper_name, Type on_type, Expression expression)
93                 {
94                         var methods = on_type.GetMethods (PublicStatic);
95
96                         foreach (var method in methods) {
97                                 if (method.Name != oper_name)
98                                         continue;
99
100                                 var parameters = method.GetParameters ();
101                                 if (parameters.Length != 1)
102                                         continue;
103
104                                 if (!parameters [0].ParameterType.IsAssignableFrom (expression.Type))
105                                         continue;
106
107                                 return method;
108                         }
109
110                         return null;
111                 }
112
113                 static MethodInfo UnaryCoreCheck (string oper_name, Expression expression, MethodInfo method)
114                 {
115                         if (expression == null)
116                                 throw new ArgumentNullException ("expression");
117
118                         if (method != null) {
119                                 if (method.ReturnType == typeof (void))
120                                         throw new ArgumentException ("Specified method must return a value", "method");
121
122                                 if (!method.IsStatic)
123                                         throw new ArgumentException ("Method must be static", "method");
124
125                                 var parameters = method.GetParameters ();
126
127                                 if (parameters.Length != 1)
128                                         throw new ArgumentException ("Must have only one parameters", "method");
129
130                                 if (!parameters [0].ParameterType.IsAssignableFrom (expression.Type))
131                                         throw new InvalidOperationException ("left-side argument type does not match left expression type");
132
133                                 return method;
134                         } else {
135                                 if (IsNumber (expression.Type))
136                                         return null;
137
138                                 if (oper_name != null) {
139                                         method = GetUnaryOperator (oper_name, expression.Type, expression);
140                                         if (method != null)
141                                                 return method;
142                                 }
143
144                                 throw new InvalidOperationException (
145                                         String.Format ("Operation {0} not defined for {1}", oper_name != null ? oper_name.Substring (3) : "is", expression.Type));
146                         }
147                 }
148
149                 static MethodInfo GetBinaryOperator (string oper_name, Type on_type, Expression left, Expression right)
150                 {
151                         MethodInfo [] methods = on_type.GetMethods (PublicStatic);
152
153                         foreach (MethodInfo m in methods){
154                                 if (m.Name != oper_name)
155                                         continue;
156
157                                 ParameterInfo [] pi = m.GetParameters ();
158                                 if (pi.Length != 2)
159                                         continue;
160
161                                 if (!pi [0].ParameterType.IsAssignableFrom (left.Type))
162                                         continue;
163
164                                 if (!pi [1].ParameterType.IsAssignableFrom (right.Type))
165                                         continue;
166
167                                 // Method has papers in order.
168                                 return m;
169                         }
170
171                         return null;
172                 }
173
174                 //
175                 // Performs basic checks on the incoming expressions for binary expressions
176                 // and any provided MethodInfo.
177                 //
178                 static MethodInfo BinaryCoreCheck (string oper_name, Expression left, Expression right, MethodInfo method)
179                 {
180                         if (left == null)
181                                 throw new ArgumentNullException ("left");
182                         if (right == null)
183                                 throw new ArgumentNullException ("right");
184
185                         if (method != null){
186                                 if (method.ReturnType == typeof (void))
187                                         throw new ArgumentException ("Specified method must return a value", "method");
188
189                                 if (!method.IsStatic)
190                                         throw new ArgumentException ("Method must be static", "method");
191                                 ParameterInfo [] pi = method.GetParameters ();
192
193                                 if (pi.Length != 2)
194                                         throw new ArgumentException ("Must have only two parameters", "method");
195
196                                 Type ltype = left.Type.IsValueType && IsNullable (left.Type) ? GetNullableOf(left.Type) : left.Type;
197                                 Type rtype = left.Type.IsValueType && IsNullable (right.Type) ? GetNullableOf(right.Type) :right.Type;
198                                         
199                                 if (ltype != pi [0].ParameterType)
200                                         throw new InvalidOperationException ("left-side argument type does not match left expression type");
201
202                                 if (rtype != pi [1].ParameterType)
203                                         throw new InvalidOperationException ("right-side argument type does not match right expression type");
204
205                                 return method;
206                         } else {
207                                 Type ltype = left.Type;
208                                 Type rtype = right.Type;
209                                 Type ultype = left.Type;
210                                 Type urtype = right.Type;
211
212                                 if (IsNullable (ltype))
213                                         ultype = GetNullableOf (ltype);
214
215                                 if (IsNullable (rtype))
216                                         urtype = GetNullableOf (rtype);
217
218                                 if (oper_name == "op_BitwiseOr" || oper_name == "op_BitwiseAnd"){
219                                         if (ultype == typeof (bool)){
220                                                 if (ultype == urtype && ltype == rtype)
221                                                         return null;
222                                         }
223                                 }
224                                 
225                                 if (oper_name == "op_LogicalAnd" || oper_name == "op_LogicalOr"){
226                                         if (ultype == typeof (bool)){
227                                                 if (ultype == urtype && ltype == rtype)
228                                                         return null;
229
230                                                 method = GetBinaryOperator (oper_name, rtype, left, right);
231                                                 if (method != null)
232                                                         return method;
233                                         }
234                                 } else {
235                                         // Use IsNumber to avoid expensive reflection.
236                                         if (IsNumber (ultype)){
237                                                 if (ultype == urtype && ltype == rtype)
238                                                         return method;
239                                                 
240                                                 if (oper_name != null){
241                                                         method = GetBinaryOperator (oper_name, rtype, left, right);
242                                                         if (method != null)
243                                                                 return method;
244                                                 }
245                                         }
246                                 }
247                                 
248                                 if (oper_name != null){
249                                         method = GetBinaryOperator (oper_name, ltype, left, right);
250                                         if (method != null)
251                                                 return method;
252                                 }
253
254                                 //
255                                 // == and != allow reference types without operators defined.
256                                 //
257                                 if (!ltype.IsValueType && !rtype.IsValueType &&
258                                     (oper_name == "op_Equality" || oper_name == "op_Inequality"))
259                                         return null;
260                                 
261                                 throw new InvalidOperationException (
262                                         String.Format ("Operation {0} not defined for {1} and {2}", oper_name != null ? oper_name.Substring (3) : "is", ltype, rtype));
263                         }
264                 }
265
266                 //
267                 // This is like BinaryCoreCheck, but if no method is used adds the restriction that
268                 // only ints and bools are allowed
269                 //
270                 static MethodInfo BinaryBitwiseCoreCheck (string oper_name, Expression left, Expression right, MethodInfo method)
271                 {
272                         if (left == null)
273                                 throw new ArgumentNullException ("left");
274                         if (right == null)
275                                 throw new ArgumentNullException ("right");
276
277                         if (method == null){
278                                 // avoid reflection shortcut and catches Ints/bools before we check Numbers in general
279                                 if (left.Type == right.Type && (left.Type == typeof (bool) || IsInt (left.Type)))
280                                         return method;
281                         }
282
283                         method = BinaryCoreCheck (oper_name, left, right, method);
284                         if (method == null){
285                                 //
286                                 // The check in BinaryCoreCheck allows a bit more than we do
287                                 // (floats and doubles).  Catch this here
288                                 //
289                                 if (left.Type == typeof(double) || left.Type == typeof(float))
290                                         throw new InvalidOperationException ("Types not supported");
291                         }
292                         return method;
293                 }
294
295                 static BinaryExpression MakeSimpleBinary (ExpressionType et, Expression left, Expression right, MethodInfo method)
296                 {
297                         Type result = method == null ? left.Type : method.ReturnType;
298                         bool is_lifted;
299                         
300                         if (method == null){
301                                 if (IsNullable (left.Type)){
302                                         if (!IsNullable (right.Type))
303                                                 throw new Exception ("Assertion, internal error: left is nullable, requires right to be as well");
304                                         is_lifted = true;
305                                 } else
306                                         is_lifted = false;
307                         } else {
308                                 //
309                                 // FIXME: implement
310                                 //
311                                 is_lifted = false;
312                         }
313                         
314                         return new BinaryExpression (et, result, left, right, false, is_lifted, method, null);
315                 }
316
317                 static UnaryExpression MakeSimpleUnary (ExpressionType et, Expression expression, MethodInfo method)
318                 {
319                         Type result = method == null ? expression.Type : method.ReturnType;
320
321                         return new UnaryExpression (et, expression, result, method);
322                 }
323
324                 static BinaryExpression MakeBoolBinary (ExpressionType et, Expression left, Expression right, bool liftToNull, MethodInfo method)
325                 {
326                         Type result;
327                         Type ltype = left.Type;
328                         Type rtype = right.Type;
329                         bool lnullable = IsNullable (ltype);
330                         bool rnullable = IsNullable (rtype);
331                         bool is_lifted;
332
333                         //
334                         // Implement the rules as described in "Expression.Equal" method.  
335                         //
336                         if (method == null){
337                                 if (lnullable == false && rnullable == false){
338                                         is_lifted = false;
339                                         result = typeof (bool);
340                                 } else if (lnullable && rnullable){
341                                         is_lifted = true;
342                                         result = liftToNull ? typeof(bool?) : typeof (bool);
343                                 } else
344                                         throw new Exception ("Internal error: this should have been caught in BinaryCoreCheck");
345                         } else {
346                                 ParameterInfo [] pi = method.GetParameters ();
347                                 Type mltype = pi [0].ParameterType;
348                                 Type mrtype = pi [1].ParameterType;
349                                 
350                                 if (ltype == mltype && rtype == mrtype){
351                                         is_lifted = false;
352                                         result = method.ReturnType;
353                                 }
354                                 else if (ltype.IsValueType && rtype.IsValueType &&
355                                            ((lnullable && GetNullableOf (ltype) == mltype) ||
356                                             (rnullable && GetNullableOf (rtype) == mrtype))){
357                                         is_lifted = true;
358                                         if (method.ReturnType == typeof(bool)){
359                                                 result = liftToNull ? typeof(bool?) : typeof(bool);
360                                         } else {
361                                                 //
362                                                 // This behavior is not documented: what
363                                                 // happens if the result is not typeof(bool), but
364                                                 // the parameters are nullable: the result
365                                                 // becomes nullable<returntype>
366                                                 //
367                                                 // See:
368                                                 // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=323139
369                                                 result = typeof (Nullable<>).MakeGenericType (method.ReturnType);
370                                                         //Type.GetType ("System.Nullable`1[" + method.ReturnType.ToString () + "]");
371                                         }
372                                 } else {
373                                         is_lifted = false;
374                                         result = method.ReturnType;
375                                 }
376                         }
377
378                         return new BinaryExpression (et, result, left, right, liftToNull, is_lifted, method, null);
379                 }
380
381                 //
382                 // Arithmetic
383                 //
384                 public static BinaryExpression Add (Expression left, Expression right)
385                 {
386                         return Add (left, right, null);
387                 }
388
389                 public static BinaryExpression Add (Expression left, Expression right, MethodInfo method)
390                 {
391                         method = BinaryCoreCheck ("op_Addition", left, right, method);
392
393                         return MakeSimpleBinary (ExpressionType.Add, left, right, method);
394                 }
395
396                 public static BinaryExpression AddChecked (Expression left, Expression right)
397                 {
398                         return AddChecked (left, right, null);
399                 }
400
401                 public static BinaryExpression AddChecked (Expression left, Expression right, MethodInfo method)
402                 {
403                         method = BinaryCoreCheck ("op_Addition", left, right, method);
404
405                         //
406                         // The check in BinaryCoreCheck allows a bit more than we do
407                         // (byte, sbyte).  Catch that here
408                         //
409                         
410                         if (method == null){
411                                 Type ltype = left.Type;
412
413                                 if (ltype == typeof (byte) || ltype == typeof (sbyte))
414                                         throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
415                         }
416
417                         return MakeSimpleBinary (ExpressionType.AddChecked, left, right, method);
418                 }
419
420                 public static BinaryExpression Subtract (Expression left, Expression right)
421                 {
422                         return Subtract (left, right, null);
423                 }
424
425                 public static BinaryExpression Subtract (Expression left, Expression right, MethodInfo method)
426                 {
427                         method = BinaryCoreCheck ("op_Subtraction", left, right, method);
428                         return MakeSimpleBinary (ExpressionType.Subtract, left, right, method);
429                 }
430
431                 public static BinaryExpression SubtractChecked (Expression left, Expression right)
432                 {
433                         return SubtractChecked (left, right, null);
434                 }
435
436                 public static BinaryExpression SubtractChecked (Expression left, Expression right, MethodInfo method)
437                 {
438                         method = BinaryCoreCheck ("op_Subtraction", left, right, method);
439
440                         //
441                         // The check in BinaryCoreCheck allows a bit more than we do
442                         // (byte, sbyte).  Catch that here
443                         //
444
445                         if (method == null){
446                                 Type ltype = left.Type;
447
448                                 if (ltype == typeof (byte) || ltype == typeof (sbyte))
449                                         throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
450                         }
451                         return MakeSimpleBinary (ExpressionType.SubtractChecked, left, right, method);
452                 }
453
454                 public static BinaryExpression Modulo (Expression left, Expression right)
455                 {
456                         return Modulo (left, right, null);
457                 }
458
459                 public static BinaryExpression Modulo (Expression left, Expression right, MethodInfo method)
460                 {
461                         method = BinaryCoreCheck ("op_Modulus", left, right, method);
462
463                         return MakeSimpleBinary (ExpressionType.Modulo, left, right, method);
464                 }
465
466                 public static BinaryExpression Multiply (Expression left, Expression right)
467                 {
468                         return Multiply (left, right, null);
469                 }
470
471                 public static BinaryExpression Multiply (Expression left, Expression right, MethodInfo method)
472                 {
473                         method = BinaryCoreCheck ("op_Multiply", left, right, method);
474
475                         return MakeSimpleBinary (ExpressionType.Multiply, left, right, method);
476                 }
477
478                 public static BinaryExpression MultiplyChecked (Expression left, Expression right)
479                 {
480                         return MultiplyChecked (left, right, null);
481                 }
482
483                 public static BinaryExpression MultiplyChecked (Expression left, Expression right, MethodInfo method)
484                 {
485                         method = BinaryCoreCheck ("op_Multiply", left, right, method);
486
487                         return MakeSimpleBinary (ExpressionType.MultiplyChecked, left, right, method);
488                 }
489
490                 public static BinaryExpression Divide (Expression left, Expression right)
491                 {
492                         return Divide (left, right, null);
493                 }
494
495                 public static BinaryExpression Divide (Expression left, Expression right, MethodInfo method)
496                 {
497                         method = BinaryCoreCheck ("op_Division", left, right, method);
498
499                         return MakeSimpleBinary (ExpressionType.Divide, left, right, method);
500                 }
501
502                 public static BinaryExpression Power (Expression left, Expression right)
503                 {
504                         return Power (left, right, null);
505                 }
506
507                 public static BinaryExpression Power (Expression left, Expression right, MethodInfo method)
508                 {
509                         method = BinaryCoreCheck (null, left, right, method);
510
511                         if (left.Type != typeof (double))
512                                 throw new InvalidOperationException ("Power only supports double arguments");
513
514                         return MakeSimpleBinary (ExpressionType.Power, left, right, method);
515                 }
516
517                 //
518                 // Bitwise
519                 //
520                 public static BinaryExpression And (Expression left, Expression right)
521                 {
522                         return And (left, right, null);
523                 }
524
525                 public static BinaryExpression And (Expression left, Expression right, MethodInfo method)
526                 {
527                         method = BinaryBitwiseCoreCheck ("op_BitwiseAnd", left, right, method);
528
529                         return MakeSimpleBinary (ExpressionType.And, left, right, method);
530                 }
531
532                 public static BinaryExpression Or (Expression left, Expression right)
533                 {
534                         return Or (left, right, null);
535                 }
536
537                 public static BinaryExpression Or (Expression left, Expression right, MethodInfo method)
538                 {
539                         method = BinaryBitwiseCoreCheck ("op_BitwiseOr", left, right, method);
540
541                         return MakeSimpleBinary (ExpressionType.Or, left, right, method);
542                 }
543
544                 public static BinaryExpression ExclusiveOr (Expression left, Expression right)
545                 {
546                         return ExclusiveOr (left, right, null);
547                 }
548
549                 public static BinaryExpression ExclusiveOr (Expression left, Expression right, MethodInfo method)
550                 {
551                         method = BinaryBitwiseCoreCheck ("op_ExclusiveOr", left, right, method);
552
553                         return MakeSimpleBinary (ExpressionType.ExclusiveOr, left, right, method);
554                 }
555
556                 public static BinaryExpression LeftShift (Expression left, Expression right)
557                 {
558                         return LeftShift (left, right, null);
559                 }
560
561                 public static BinaryExpression LeftShift (Expression left, Expression right, MethodInfo method)
562                 {
563                         method = BinaryBitwiseCoreCheck ("op_LeftShift", left, right, method);
564
565                         return MakeSimpleBinary (ExpressionType.LeftShift, left, right, method);
566                 }
567
568                 public static BinaryExpression RightShift (Expression left, Expression right)
569                 {
570                         return RightShift (left, right, null);
571                 }
572
573                 public static BinaryExpression RightShift (Expression left, Expression right, MethodInfo method)
574                 {
575                         method = BinaryCoreCheck ("op_RightShift", left, right, method);
576
577                         return MakeSimpleBinary (ExpressionType.RightShift, left, right, method);
578                 }
579
580                 //
581                 // Short-circuit
582                 //
583                 public static BinaryExpression AndAlso (Expression left, Expression right)
584                 {
585                         return AndAlso (left, right, null);
586                 }
587
588                 public static BinaryExpression AndAlso (Expression left, Expression right, MethodInfo method)
589                 {
590                         method = BinaryCoreCheck ("op_LogicalAnd", left, right, method);
591
592                         return MakeBoolBinary (ExpressionType.AndAlso, left, right, false, method);
593                 }
594
595                 public static BinaryExpression OrElse (Expression left, Expression right)
596                 {
597                         return OrElse (left, right, null);
598                 }
599
600                 public static BinaryExpression OrElse (Expression left, Expression right, MethodInfo method)
601                 {
602                         method = BinaryCoreCheck ("op_LogicalOr", left, right, method);
603
604                         return MakeBoolBinary (ExpressionType.OrElse, left, right, false, method);
605                 }
606
607                 //
608                 // Comparison
609                 //
610                 public static BinaryExpression Equal (Expression left, Expression right)
611                 {
612                         return Equal (left, right, false, null);
613                 }
614
615                 public static BinaryExpression Equal (Expression left, Expression right, bool liftToNull, MethodInfo method)
616                 {
617                         method = BinaryCoreCheck ("op_Equality", left, right, method);
618
619                         return MakeBoolBinary (ExpressionType.Equal, left, right, liftToNull, method);
620                 }
621
622                 public static BinaryExpression NotEqual (Expression left, Expression right)
623                 {
624                         return NotEqual (left, right, false, null);
625                 }
626
627
628                 public static BinaryExpression NotEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
629                 {
630                         method = BinaryCoreCheck ("op_Inequality", left, right, method);
631
632                         return MakeBoolBinary (ExpressionType.NotEqual, left, right, liftToNull, method);
633                 }
634
635                 public static BinaryExpression GreaterThan (Expression left, Expression right)
636                 {
637                         return GreaterThan (left, right, false, null);
638                 }
639
640                 public static BinaryExpression GreaterThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
641                 {
642                         method = BinaryCoreCheck ("op_GreaterThan", left, right, method);
643
644                         return MakeBoolBinary (ExpressionType.GreaterThan, left, right, liftToNull, method);
645                 }
646
647                 public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right)
648                 {
649                         return GreaterThanOrEqual (left, right, false, null);
650                 }
651
652
653                 public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
654                 {
655                         method = BinaryCoreCheck ("op_GreaterThanOrEqual", left, right, method);
656
657                         return MakeBoolBinary (ExpressionType.GreaterThanOrEqual, left, right, liftToNull, method);
658                 }
659
660                 public static BinaryExpression LessThan (Expression left, Expression right)
661                 {
662                         return LessThan (left, right, false, null);
663                 }
664
665                 public static BinaryExpression LessThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
666                 {
667                         method = BinaryCoreCheck ("op_LessThan", left, right, method);
668
669                         return MakeBoolBinary (ExpressionType.LessThan, left, right, liftToNull, method);
670                 }
671
672                 public static BinaryExpression LessThanOrEqual (Expression left, Expression right)
673                 {
674                         return LessThanOrEqual (left, right, false, null);
675                 }
676
677                 public static BinaryExpression LessThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
678                 {
679                         method = BinaryCoreCheck ("op_LessThanOrEqual", left, right, method);
680
681                         return MakeBoolBinary (ExpressionType.LessThanOrEqual, left, right, liftToNull, method);
682                 }
683
684                 //
685                 // Miscelaneous
686                 //
687
688                 static void ArrayCheck (Expression array)
689                 {
690                         if (array == null)
691                                 throw new ArgumentNullException ("array");
692                         if (!array.Type.IsArray)
693                                 throw new ArgumentException ("The array argument must be of type array");
694                 }
695
696                 public static BinaryExpression ArrayIndex (Expression array, Expression index)
697                 {
698                         ArrayCheck (array);
699                         if (index == null)
700                                 throw new ArgumentNullException ("index");
701                         if (array.Type.GetArrayRank () != 1)
702                                 throw new ArgumentException ("The array argument must be a single dimensional array");
703                         if (index.Type != typeof (int))
704                                 throw new ArgumentException ("The index must be of type int");
705
706                         return new BinaryExpression (ExpressionType.ArrayIndex, array.Type.GetElementType (), array, index);
707                 }
708
709                 public static BinaryExpression Coalesce (Expression left, Expression right)
710                 {
711                         return Coalesce (left, right, null);
712                 }
713
714                 public static BinaryExpression Coalesce (Expression left, Expression right, LambdaExpression conversion)
715                 {
716                         if (left == null)
717                                 throw new ArgumentNullException ("left");
718                         if (right == null)
719                                 throw new ArgumentNullException ("right");
720
721                         //
722                         // First arg must ne nullable (either Nullable<T> or a reference type
723                         //
724                         if (left.Type.IsValueType && !IsNullable (left.Type))
725                                 throw new InvalidOperationException ("Left expression can never be null");
726                         
727                         Type result = null;
728
729                         if (IsNullable (left.Type)){
730                                 Type lbase = GetNullableOf (left.Type);
731                                 
732                                 if (!IsNullable (right.Type) && lbase.IsAssignableFrom (right.Type))
733                                         result = lbase;
734                         }
735
736                         if (result == null && left.Type.IsAssignableFrom (right.Type))
737                                 result = left.Type;
738
739                         if (result == null){
740                                 if (IsNullable (left.Type) && right.Type.IsAssignableFrom (GetNullableOf (left.Type))){
741                                         result = right.Type;
742                                 }
743                         }
744
745                         if (result == null)
746                                 throw new ArgumentException ("Incompatible argument types");
747
748                         //
749                         // FIXME: What do we do with "conversion"?
750                         //
751                         return new BinaryExpression (ExpressionType.Coalesce, result, left, right, false, false, null, conversion);
752                 }
753
754                 //
755                 // MakeBinary constructors
756                 //
757                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right)
758                 {
759                         return MakeBinary (binaryType, left, right, false, null);
760                 }
761
762                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method)
763                 {
764                         return MakeBinary (binaryType, left, right, liftToNull, method, null);
765                 }
766
767                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion)
768                 {
769                         switch (binaryType) {
770                         case ExpressionType.Add:
771                                 return Add (left, right, method);
772                         case ExpressionType.AddChecked:
773                                 return AddChecked (left, right, method);
774                         case ExpressionType.AndAlso:
775                                 return AndAlso (left, right);
776                         case ExpressionType.Coalesce:
777                                 return Coalesce (left, right, conversion);
778                         case ExpressionType.Divide:
779                                 return Divide (left, right, method);
780                         case ExpressionType.Equal:
781                                 return Equal (left, right, liftToNull, method);
782                         case ExpressionType.ExclusiveOr:
783                                 return ExclusiveOr (left, right, method);
784                         case ExpressionType.GreaterThan:
785                                 return GreaterThan (left, right, liftToNull, method);
786                         case ExpressionType.GreaterThanOrEqual:
787                                 return GreaterThanOrEqual (left, right, liftToNull, method);
788                         case ExpressionType.LeftShift:
789                                 return LeftShift (left, right, method);
790                         case ExpressionType.LessThan:
791                                 return LessThan (left, right, liftToNull, method);
792                         case ExpressionType.LessThanOrEqual:
793                                 return LessThanOrEqual (left, right, liftToNull, method);
794                         case ExpressionType.Modulo:
795                                 return Modulo (left, right, method);
796                         case ExpressionType.Multiply:
797                                 return Multiply (left, right, method);
798                         case ExpressionType.MultiplyChecked:
799                                 return MultiplyChecked (left, right, method);
800                         case ExpressionType.NotEqual:
801                                 return NotEqual (left, right, liftToNull, method);
802                         case ExpressionType.OrElse:
803                                 return OrElse (left, right);
804                         case ExpressionType.Power:
805                                 return Power (left, right, method);
806                         case ExpressionType.RightShift:
807                                 return RightShift (left, right, method);
808                         case ExpressionType.Subtract:
809                                 return Subtract (left, right, method);
810                         case ExpressionType.SubtractChecked:
811                                 return SubtractChecked (left, right, method);
812                         case ExpressionType.And:
813                                 return And (left, right, method);
814                         case ExpressionType.Or:
815                                 return Or (left, right, method);
816                         }
817
818                         throw new ArgumentException ("MakeBinary expect a binary node type");
819                 }
820
821 #endregion
822
823                 public static MethodCallExpression ArrayIndex (Expression array, params Expression [] indexes)
824                 {
825                         return ArrayIndex (array, indexes as IEnumerable<Expression>);
826                 }
827
828                 public static MethodCallExpression ArrayIndex (Expression array, IEnumerable<Expression> indexes)
829                 {
830                         ArrayCheck (array);
831
832                         if (indexes == null)
833                                 throw new ArgumentNullException ("indexes");
834
835                         var args = indexes.ToReadOnlyCollection ();
836                         if (array.Type.GetArrayRank () != args.Count)
837                                 throw new ArgumentException ("The number of arguments doesn't match the rank of the array");
838
839                         foreach (var arg in args)
840                                 if (arg.Type != typeof (int))
841                                         throw new ArgumentException ("The index must be of type int");
842
843                         return Call (array, array.Type.GetMethod ("Get", PublicInstance), args);
844                 }
845
846                 public static UnaryExpression ArrayLength (Expression array)
847                 {
848                         if (array == null)
849                                 throw new ArgumentNullException ("array");
850                         if (!array.Type.IsArray)
851                                 throw new ArgumentException ("The type of the expression must me Array");
852                         if (array.Type.GetArrayRank () != 1)
853                                 throw new ArgumentException ("The array must be a single dimensional array");
854
855                         return new UnaryExpression (ExpressionType.ArrayLength, array, typeof (int));
856                 }
857
858                 [MonoTODO]
859                 public static MemberAssignment Bind (MemberInfo member, Expression expression)
860                 {
861                         throw new NotImplementedException ();
862                 }
863
864                 [MonoTODO]
865                 public static MemberAssignment Bind (MethodInfo propertyAccessor, Expression expression)
866                 {
867                         throw new NotImplementedException ();
868                 }
869
870                 public static MethodCallExpression Call (Expression instance, MethodInfo method)
871                 {
872                         return Call (instance, method, null as IEnumerable<Expression>);
873                 }
874
875                 public static MethodCallExpression Call (MethodInfo method, params Expression [] arguments)
876                 {
877                         return Call (null, method, arguments as IEnumerable<Expression>);
878                 }
879
880                 public static MethodCallExpression Call (Expression instance, MethodInfo method, params Expression [] arguments)
881                 {
882                         return Call (instance, method, arguments as IEnumerable<Expression>);
883                 }
884
885                 public static MethodCallExpression Call (Expression instance, MethodInfo method, IEnumerable<Expression> arguments)
886                 {
887                         if (method == null)
888                                 throw new ArgumentNullException ("method");
889                         if (instance == null && !method.IsStatic)
890                                 throw new ArgumentNullException ("instance");
891                         if (instance != null && !method.DeclaringType.IsAssignableFrom (instance.Type))
892                                 throw new ArgumentException ("Type is not assignable to the declaring type of the method");
893
894                         var args = arguments.ToReadOnlyCollection ();
895                         var parameters = method.GetParameters ();
896
897                         if (args.Count != parameters.Length)
898                                 throw new ArgumentException ("The number of arguments doesn't match the number of parameters");
899
900                         // TODO: check for assignability of the arguments on the parameters
901
902                         return new MethodCallExpression (instance, method, args);
903                 }
904
905                 [MonoTODO]
906                 public static MethodCallExpression Call (Expression instance, string methodName, Type [] typeArguments, params Expression [] arguments)
907                 {
908                         throw new NotImplementedException ();
909                 }
910
911                 [MonoTODO]
912                 public static MethodCallExpression Call (Type type, string methodName, Type [] typeArguments, params Expression [] arguments)
913                 {
914                         throw new NotImplementedException ();
915                 }
916
917                 public static ConditionalExpression Condition (Expression test, Expression ifTrue, Expression ifFalse)
918                 {
919                         if (test == null)
920                                 throw new ArgumentNullException ("test");
921                         if (ifTrue == null)
922                                 throw new ArgumentNullException ("ifTrue");
923                         if (ifFalse == null)
924                                 throw new ArgumentNullException ("ifFalse");
925                         if (test.Type != typeof (bool))
926                                 throw new ArgumentException ("Test expression should be of type bool");
927                         if (ifTrue.Type != ifFalse.Type)
928                                 throw new ArgumentException ("The ifTrue and ifFalse type do not match");
929
930                         return new ConditionalExpression (test, ifTrue, ifFalse);
931                 }
932
933                 public static ConstantExpression Constant (object value)
934                 {
935                         if (value == null)
936                                 return new ConstantExpression (null, typeof (object));
937
938                         return Constant (value, value.GetType ());
939                 }
940
941                 public static ConstantExpression Constant (object value, Type type)
942                 {
943                         if (type == null)
944                                 throw new ArgumentNullException ("type");
945
946                         //
947                         // value must be compatible with type, no conversions
948                         // are allowed
949                         //
950                         if (value == null){
951                                 if (type.IsValueType && !IsNullable (type))
952                                         throw new ArgumentException ();
953                         } else {
954                                 if (!(type.IsValueType && IsNullable (type)) && value.GetType () != type)
955                                         throw new ArgumentException ();
956
957                         }
958
959                         return new ConstantExpression (value, type);
960                 }
961
962                 [MonoTODO]
963                 public static UnaryExpression Convert (Expression expression, Type type)
964                 {
965                         throw new NotImplementedException ();
966                 }
967
968                 [MonoTODO]
969                 public static UnaryExpression Convert (Expression expression, Type type, MethodInfo method)
970                 {
971                         throw new NotImplementedException ();
972                 }
973
974                 [MonoTODO]
975                 public static UnaryExpression ConvertChecked (Expression expression, Type type)
976                 {
977                         throw new NotImplementedException ();
978                 }
979
980                 [MonoTODO]
981                 public static UnaryExpression ConvertChecked (Expression expression, Type type, MethodInfo method)
982                 {
983                         throw new NotImplementedException ();
984                 }
985
986                 [MonoTODO]
987                 public static ElementInit ElementInit (MethodInfo addMethod, params Expression [] arguments)
988                 {
989                         throw new NotImplementedException ();
990                 }
991
992                 [MonoTODO]
993                 public static ElementInit ElementInit (MethodInfo addMethod, IEnumerable<Expression> arguments)
994                 {
995                         throw new NotImplementedException ();
996                 }
997
998                 [MonoTODO]
999                 public static MemberExpression Field (Expression expression, FieldInfo field)
1000                 {
1001                         throw new NotImplementedException ();
1002                 }
1003
1004                 [MonoTODO]
1005                 public static MemberExpression Field (Expression expression, string fieldName)
1006                 {
1007                         throw new NotImplementedException ();
1008                 }
1009
1010                 public static Type GetActionType (params Type [] typeArgs)
1011                 {
1012                         if (typeArgs == null)
1013                                 throw new ArgumentNullException ("typeArgs");
1014
1015                         if (typeArgs.Length > 4)
1016                                 throw new ArgumentException ("No Action type of this arity");
1017
1018                         if (typeArgs.Length == 0)
1019                                 return typeof (Action);
1020
1021                         Type action = null;
1022                         switch (typeArgs.Length) {
1023                         case 1:
1024                                 action = typeof (Action<>);
1025                                 break;
1026                         case 2:
1027                                 action = typeof (Action<,>);
1028                                 break;
1029                         case 3:
1030                                 action = typeof (Action<,,>);
1031                                 break;
1032                         case 4:
1033                                 action = typeof (Action<,,,>);
1034                                 break;
1035                         }
1036
1037                         return action.MakeGenericType (typeArgs);
1038                 }
1039
1040                 public static Type GetFuncType (params Type [] typeArgs)
1041                 {
1042                         if (typeArgs == null)
1043                                 throw new ArgumentNullException ("typeArgs");
1044
1045                         if (typeArgs.Length < 1 || typeArgs.Length > 5)
1046                                 throw new ArgumentException ("No Func type of this arity");
1047
1048                         Type func = null;
1049                         switch (typeArgs.Length) {
1050                         case 1:
1051                                 func = typeof (Func<>);
1052                                 break;
1053                         case 2:
1054                                 func = typeof (Func<,>);
1055                                 break;
1056                         case 3:
1057                                 func = typeof (Func<,,>);
1058                                 break;
1059                         case 4:
1060                                 func = typeof (Func<,,,>);
1061                                 break;
1062                         case 5:
1063                                 func = typeof (Func<,,,,>);
1064                                 break;
1065                         }
1066
1067                         return func.MakeGenericType (typeArgs);
1068                 }
1069
1070                 [MonoTODO]
1071                 public static InvocationExpression Invoke (Expression expression, params Expression [] arguments)
1072                 {
1073                         throw new NotImplementedException ();
1074                 }
1075
1076                 [MonoTODO]
1077                 public static InvocationExpression Invoke (Expression expression, IEnumerable<Expression> arguments)
1078                 {
1079                         throw new NotImplementedException ();
1080                 }
1081
1082                 public static Expression<TDelegate> Lambda<TDelegate> (Expression body, params ParameterExpression [] parameters)
1083                 {
1084                         if (body == null)
1085                                 throw new ArgumentNullException ("body");
1086
1087                         return new Expression<TDelegate> (body, parameters);
1088                 }
1089
1090                 [MonoTODO]
1091                 public static Expression<TDelegate> Lambda<TDelegate> (Expression body, IEnumerable<ParameterExpression> parameters)
1092                 {
1093                         throw new NotImplementedException ();
1094                 }
1095
1096                 [MonoTODO]
1097                 public static LambdaExpression Lambda (Expression body, params ParameterExpression [] parameters)
1098                 {
1099                         throw new NotImplementedException ();
1100                 }
1101
1102                 public static LambdaExpression Lambda (Type delegateType, Expression body, params ParameterExpression [] parameters)
1103                 {
1104                         return Lambda (delegateType, body, parameters as IEnumerable<ParameterExpression>);
1105                 }
1106
1107                 [MonoTODO]
1108                 public static LambdaExpression Lambda (Type delegateType, Expression body, IEnumerable<ParameterExpression> parameters)
1109                 {
1110                         if (delegateType == null)
1111                                 throw new ArgumentNullException ("delegateType");
1112                         if (body == null)
1113                                 throw new ArgumentNullException ("body");
1114
1115                         return new LambdaExpression (delegateType, body, parameters.ToReadOnlyCollection ());
1116                 }
1117
1118                 public static MemberListBinding ListBind (MemberInfo member, params ElementInit [] initializers)
1119                 {
1120                         throw new NotImplementedException ();
1121                 }
1122
1123                 [MonoTODO]
1124                 public static MemberListBinding ListBind (MemberInfo member, IEnumerable<ElementInit> initializers)
1125                 {
1126                         throw new NotImplementedException ();
1127                 }
1128
1129                 [MonoTODO]
1130                 public static MemberListBinding ListBind (MethodInfo propertyAccessor, params ElementInit [] initializers)
1131                 {
1132                         throw new NotImplementedException ();
1133                 }
1134
1135                 [MonoTODO]
1136                 public static MemberListBinding ListBind (MethodInfo propertyAccessor, IEnumerable<ElementInit> initializers)
1137                 {
1138                         throw new NotImplementedException ();
1139                 }
1140
1141                 [MonoTODO]
1142                 public static ListInitExpression ListInit (NewExpression newExpression, params ElementInit [] initializers)
1143                 {
1144                         throw new NotImplementedException ();
1145                 }
1146
1147                 [MonoTODO]
1148                 public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<ElementInit> initializers)
1149                 {
1150                         throw new NotImplementedException ();
1151                 }
1152
1153                 [MonoTODO]
1154                 public static ListInitExpression ListInit (NewExpression newExpression, params Expression [] initializers)
1155                 {
1156                         throw new NotImplementedException ();
1157                 }
1158
1159                 [MonoTODO]
1160                 public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<Expression> initializers)
1161                 {
1162                         throw new NotImplementedException ();
1163                 }
1164
1165                 [MonoTODO]
1166                 public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, params Expression [] initializers)
1167                 {
1168                         throw new NotImplementedException ();
1169                 }
1170
1171                 [MonoTODO]
1172                 public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, IEnumerable<Expression> initializers)
1173                 {
1174                         throw new NotImplementedException ();
1175                 }
1176
1177                 public static MemberExpression MakeMemberAccess (Expression expression, MemberInfo member)
1178                 {
1179                         if (expression == null)
1180                                 throw new ArgumentNullException ("expression");
1181                         if (member == null)
1182                                 throw new ArgumentNullException ("member");
1183
1184                         var field = member as FieldInfo;
1185                         if (field != null)
1186                                 return Field (expression, field);
1187
1188                         var property = member as PropertyInfo;
1189                         if (property != null)
1190                                 return Property (expression, property);
1191
1192                         throw new ArgumentException ("Member should either be a field or a property");
1193                 }
1194
1195                 public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type)
1196                 {
1197                         return MakeUnary (unaryType, operand, type, null);
1198                 }
1199
1200                 public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type, MethodInfo method)
1201                 {
1202                         switch (unaryType) {
1203                         case ExpressionType.ArrayLength:
1204                                 return ArrayLength (operand);
1205                         case ExpressionType.Convert:
1206                                 return Convert (operand, type, method);
1207                         case ExpressionType.ConvertChecked:
1208                                 return ConvertChecked (operand, type, method);
1209                         case ExpressionType.Negate:
1210                                 return Negate (operand, method);
1211                         case ExpressionType.NegateChecked:
1212                                 return NegateChecked (operand, method);
1213                         case ExpressionType.Not:
1214                                 return Not (operand, method);
1215                         case ExpressionType.Quote:
1216                                 return Quote (operand);
1217                         case ExpressionType.TypeAs:
1218                                 return TypeAs (operand, type);
1219                         case ExpressionType.UnaryPlus:
1220                                 return UnaryPlus (operand, method);
1221                         }
1222
1223                         throw new ArgumentException ("MakeUnary expect an unary operator");
1224                 }
1225
1226                 [MonoTODO]
1227                 public static MemberMemberBinding MemberBind (MemberInfo member, params MemberBinding [] binding)
1228                 {
1229                         throw new NotImplementedException ();
1230                 }
1231
1232                 [MonoTODO]
1233                 public static MemberMemberBinding MemberBind (MemberInfo member, IEnumerable<MemberBinding> binding)
1234                 {
1235                         throw new NotImplementedException ();
1236                 }
1237
1238                 [MonoTODO]
1239                 public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, params MemberBinding [] binding)
1240                 {
1241                         throw new NotImplementedException ();
1242                 }
1243
1244                 [MonoTODO]
1245                 public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, IEnumerable<MemberBinding> binding)
1246                 {
1247                         throw new NotImplementedException ();
1248                 }
1249
1250                 [MonoTODO]
1251                 public static MemberInitExpression MemberInit (NewExpression newExpression, params MemberBinding [] binding)
1252                 {
1253                         throw new NotImplementedException ();
1254                 }
1255
1256                 [MonoTODO]
1257                 public static MemberInitExpression MemberInit (NewExpression newExpression, IEnumerable<MemberBinding> binding)
1258                 {
1259                         throw new NotImplementedException ();
1260                 }
1261
1262                 public static UnaryExpression Negate (Expression expression)
1263                 {
1264                         return Negate (expression, null);
1265                 }
1266
1267                 public static UnaryExpression Negate (Expression expression, MethodInfo method)
1268                 {
1269                         method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
1270
1271                         return MakeSimpleUnary (ExpressionType.Negate, expression, method);
1272                 }
1273
1274                 public static UnaryExpression NegateChecked (Expression expression)
1275                 {
1276                         return NegateChecked (expression, null);
1277                 }
1278
1279                 public static UnaryExpression NegateChecked (Expression expression, MethodInfo method)
1280                 {
1281                         method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
1282
1283                         return MakeSimpleUnary (ExpressionType.Negate, expression, method);
1284                 }
1285
1286                 [MonoTODO]
1287                 public static NewExpression New (ConstructorInfo constructor)
1288                 {
1289                         throw new NotImplementedException ();
1290                 }
1291
1292                 [MonoTODO]
1293                 public static NewExpression New (Type type)
1294                 {
1295                         throw new NotImplementedException ();
1296                 }
1297
1298                 [MonoTODO]
1299                 public static NewExpression New (ConstructorInfo constructor, params Expression [] arguments)
1300                 {
1301                         throw new NotImplementedException ();
1302                 }
1303
1304                 [MonoTODO]
1305                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments)
1306                 {
1307                         throw new NotImplementedException ();
1308                 }
1309
1310                 [MonoTODO]
1311                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, params MemberInfo [] members)
1312                 {
1313                         throw new NotImplementedException ();
1314                 }
1315
1316                 [MonoTODO]
1317                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, IEnumerable<MemberInfo> members)
1318                 {
1319                         throw new NotImplementedException ();
1320                 }
1321
1322                 public static NewArrayExpression NewArrayBounds (Type type, params Expression [] bounds)
1323                 {
1324                         return NewArrayBounds (type, bounds as IEnumerable<Expression>);
1325                 }
1326
1327                 public static NewArrayExpression NewArrayBounds (Type type, IEnumerable<Expression> bounds)
1328                 {
1329                         if (type == null)
1330                                 throw new ArgumentNullException ("type");
1331                         if (bounds == null)
1332                                 throw new ArgumentNullException ("bounds");
1333
1334                         var array_bounds = bounds.ToReadOnlyCollection ();
1335                         foreach (var expression in array_bounds)
1336                                 if (!IsInt (expression.Type))
1337                                         throw new ArgumentException ("The bounds collection can only contain expression of integers types");
1338
1339                         return new NewArrayExpression (ExpressionType.NewArrayBounds, type.MakeArrayType (array_bounds.Count), array_bounds);
1340                 }
1341
1342                 public static NewArrayExpression NewArrayInit (Type type, params Expression [] initializers)
1343                 {
1344                         return NewArrayInit (type, initializers as IEnumerable<Expression>);
1345                 }
1346
1347                 public static NewArrayExpression NewArrayInit (Type type, IEnumerable<Expression> initializers)
1348                 {
1349                         if (type == null)
1350                                 throw new ArgumentNullException ("type");
1351                         if (initializers == null)
1352                                 throw new ArgumentNullException ("initializers");
1353
1354                         var array_initializers = initializers.ToReadOnlyCollection ();
1355
1356                         foreach (var expression in initializers) {
1357                                 if (expression == null)
1358                                         throw new ArgumentNullException ("initializers");
1359
1360                                 if (!type.IsAssignableFrom (expression.Type))
1361                                         throw new InvalidOperationException ();
1362
1363                                 // TODO: Quote elements if type == typeof (Expression)
1364                         }
1365
1366                         return new NewArrayExpression (ExpressionType.NewArrayInit, type.MakeArrayType (), array_initializers);
1367                 }
1368
1369                 public static UnaryExpression Not (Expression expression)
1370                 {
1371                         return Not (expression, null);
1372                 }
1373
1374                 public static UnaryExpression Not (Expression expression, MethodInfo method)
1375                 {
1376                         method = UnaryCoreCheck ("op_LogicalNot", expression, method);
1377
1378                         return MakeSimpleUnary (ExpressionType.Not, expression, method);
1379                 }
1380
1381                 public static ParameterExpression Parameter (Type type, string name)
1382                 {
1383                         if (type == null)
1384                                 throw new ArgumentNullException ("type");
1385
1386                         return new ParameterExpression (type, name);
1387                 }
1388
1389                 [MonoTODO]
1390                 public static MemberExpression Property (Expression expression, MethodInfo propertyAccessor)
1391                 {
1392                         throw new NotImplementedException ();
1393                 }
1394
1395                 [MonoTODO]
1396                 public static MemberExpression Property (Expression expression, PropertyInfo property)
1397                 {
1398                         throw new NotImplementedException ();
1399                 }
1400
1401                 [MonoTODO]
1402                 public static MemberExpression Property (Expression expression, string propertyName)
1403                 {
1404                         throw new NotImplementedException ();
1405                 }
1406
1407                 [MonoTODO]
1408                 public static MemberExpression PropertyOrField (Expression expression, string propertyOrFieldName)
1409                 {
1410                         throw new NotImplementedException ();
1411                 }
1412
1413                 public static UnaryExpression Quote (Expression expression)
1414                 {
1415                         if (expression == null)
1416                                 throw new ArgumentNullException ("expression");
1417
1418                         return new UnaryExpression (ExpressionType.Quote, expression, expression.GetType ());
1419                 }
1420
1421                 public static UnaryExpression TypeAs (Expression expression, Type type)
1422                 {
1423                         if (expression == null)
1424                                 throw new ArgumentNullException ("expression");
1425                         if (type == null)
1426                                 throw new ArgumentNullException ("type");
1427                         if (type.IsValueType && !IsNullable (type))
1428                                 throw new ArgumentException ("TypeAs expect a reference or a nullable type");
1429
1430                         return new UnaryExpression (ExpressionType.TypeAs, expression, type);
1431                 }
1432
1433                 public static TypeBinaryExpression TypeIs (Expression expression, Type type)
1434                 {
1435                         if (expression == null)
1436                                 throw new ArgumentNullException ("expression");
1437                         if (type == null)
1438                                 throw new ArgumentNullException ("type");
1439
1440                         return new TypeBinaryExpression (ExpressionType.TypeIs, expression, type, typeof (bool));
1441                 }
1442
1443                 public static UnaryExpression UnaryPlus (Expression expression)
1444                 {
1445                         return UnaryPlus (expression, null);
1446                 }
1447
1448                 public static UnaryExpression UnaryPlus (Expression expression, MethodInfo method)
1449                 {
1450                         method = UnaryCoreCheck ("op_UnaryPlus", expression, method);
1451
1452                         return MakeSimpleUnary (ExpressionType.UnaryPlus, expression, method);
1453                 }
1454
1455                 internal static bool IsNullable (Type type)
1456                 {
1457                         return type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>);
1458                 }
1459
1460                 internal static bool IsUnsigned (Type t)
1461                 {
1462                         if (t.IsPointer)
1463                                 return IsUnsigned (t.GetElementType ());
1464
1465                         return t == typeof (ushort) || t == typeof (uint) || t == typeof (ulong) || t == typeof (byte);
1466                 }
1467
1468                 //
1469                 // returns the T in a a Nullable<T> type.
1470                 //
1471                 internal static Type GetNullableOf (Type type)
1472                 {
1473                         return type.GetGenericArguments () [0];
1474                 }
1475                 
1476                 //
1477                 // This method must be overwritten by derived classes to
1478                 // compile the expression
1479                 //
1480                 internal abstract void Emit (EmitContext ec);
1481         }
1482 }