c71ce40940b67848a73f51cb03ad2f69ee11d46f
[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_LogicalAnd" || oper_name == "op_LogicalOr"){
219                                         if (ultype == typeof (bool)){
220                                                 if (ultype == urtype && ltype == rtype)
221                                                         return null;
222
223                                                 method = GetBinaryOperator (oper_name, rtype, left, right);
224                                                 if (method != null)
225                                                         return method;
226                                         }
227                                 } else {
228                                         // Use IsNumber to avoid expensive reflection.
229                                         if (IsNumber (ultype)){
230                                                 if (ultype == urtype && ltype == rtype)
231                                                         return method;
232                                                 
233                                                 if (oper_name != null){
234                                                         method = GetBinaryOperator (oper_name, rtype, left, right);
235                                                         if (method != null)
236                                                                 return method;
237                                                 }
238                                         }
239                                 }
240                                 
241                                 if (oper_name != null){
242                                         method = GetBinaryOperator (oper_name, ltype, left, right);
243                                         if (method != null)
244                                                 return method;
245                                 }
246
247                                 //
248                                 // == and != allow reference types without operators defined.
249                                 //
250                                 if (!ltype.IsValueType && !rtype.IsValueType &&
251                                     (oper_name == "op_Equality" || oper_name == "op_Inequality"))
252                                         return null;
253                                 
254                                 throw new InvalidOperationException (
255                                         String.Format ("Operation {0} not defined for {1} and {2}", oper_name != null ? oper_name.Substring (3) : "is", ltype, rtype));
256                         }
257                 }
258
259                 //
260                 // This is like BinaryCoreCheck, but if no method is used adds the restriction that
261                 // only ints and bools are allowed
262                 //
263                 static MethodInfo BinaryBitwiseCoreCheck (string oper_name, Expression left, Expression right, MethodInfo method)
264                 {
265                         if (left == null)
266                                 throw new ArgumentNullException ("left");
267                         if (right == null)
268                                 throw new ArgumentNullException ("right");
269
270                         if (method == null){
271                                 // avoid reflection shortcut and catches Ints/bools before we check Numbers in general
272                                 if (left.Type == right.Type && (left.Type == typeof (bool) || IsInt (left.Type)))
273                                         return method;
274
275                         }
276
277                         method = BinaryCoreCheck (oper_name, left, right, method);
278                         if (method == null){
279                                 //
280                                 // The check in BinaryCoreCheck allows a bit more than we do
281                                 // (floats and doubles).  Catch this here
282                                 //
283                                 throw new InvalidOperationException ("Types not supported");
284                         }
285                         return method;
286                 }
287
288                 static BinaryExpression MakeSimpleBinary (ExpressionType et, Expression left, Expression right, MethodInfo method)
289                 {
290                         Type result = method == null ? left.Type : method.ReturnType;
291                         bool is_lifted;
292                         
293                         if (method == null){
294                                 if (IsNullable (left.Type)){
295                                         if (!IsNullable (right.Type))
296                                                 throw new Exception ("Assertion, internal error: left is nullable, requires right to be as well");
297                                         is_lifted = true;
298                                 } else
299                                         is_lifted = false;
300                         } else {
301                                 //
302                                 // FIXME: implement
303                                 //
304                                 is_lifted = false;
305                         }
306                         
307                         return new BinaryExpression (et, result, left, right, false, is_lifted, method, null);
308                 }
309
310                 static UnaryExpression MakeSimpleUnary (ExpressionType et, Expression expression, MethodInfo method)
311                 {
312                         Type result = method == null ? expression.Type : method.ReturnType;
313
314                         return new UnaryExpression (et, expression, result, method);
315                 }
316
317                 static BinaryExpression MakeBoolBinary (ExpressionType et, Expression left, Expression right, bool liftToNull, MethodInfo method)
318                 {
319                         Type result;
320                         Type ltype = left.Type;
321                         Type rtype = right.Type;
322                         bool lnullable = IsNullable (ltype);
323                         bool rnullable = IsNullable (rtype);
324                         bool is_lifted;
325
326                         //
327                         // Implement the rules as described in "Expression.Equal" method.  
328                         //
329                         if (method == null){
330                                 if (lnullable == false && rnullable == false){
331                                         is_lifted = false;
332                                         result = typeof (bool);
333                                 } else if (lnullable && rnullable){
334                                         is_lifted = true;
335                                         result = liftToNull ? typeof(bool?) : typeof (bool);
336                                 } else
337                                         throw new Exception ("Internal error: this should have been caught in BinaryCoreCheck");
338                         } else {
339                                 ParameterInfo [] pi = method.GetParameters ();
340                                 Type mltype = pi [0].ParameterType;
341                                 Type mrtype = pi [1].ParameterType;
342                                 
343                                 if (ltype == mltype && rtype == mrtype){
344                                         is_lifted = false;
345                                         result = method.ReturnType;
346                                 }
347                                 else if (ltype.IsValueType && rtype.IsValueType &&
348                                            ((lnullable && GetNullableOf (ltype) == mltype) ||
349                                             (rnullable && GetNullableOf (rtype) == mrtype))){
350                                         is_lifted = true;
351                                         if (method.ReturnType == typeof(bool)){
352                                                 result = liftToNull ? typeof(bool?) : typeof(bool);
353                                         } else {
354                                                 //
355                                                 // This behavior is not documented: what
356                                                 // happens if the result is not typeof(bool), but
357                                                 // the parameters are nullable: the result
358                                                 // becomes nullable<returntype>
359                                                 //
360                                                 // See:
361                                                 // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=323139
362                                                 result = typeof (Nullable<>).MakeGenericType (method.ReturnType);
363                                                         //Type.GetType ("System.Nullable`1[" + method.ReturnType.ToString () + "]");
364                                         }
365                                 } else {
366                                         is_lifted = false;
367                                         result = method.ReturnType;
368                                 }
369                         }
370
371                         return new BinaryExpression (et, result, left, right, liftToNull, is_lifted, method, null);
372                 }
373
374                 //
375                 // Arithmetic
376                 //
377                 public static BinaryExpression Add (Expression left, Expression right)
378                 {
379                         return Add (left, right, null);
380                 }
381
382                 public static BinaryExpression Add (Expression left, Expression right, MethodInfo method)
383                 {
384                         method = BinaryCoreCheck ("op_Addition", left, right, method);
385
386                         return MakeSimpleBinary (ExpressionType.Add, left, right, method);
387                 }
388
389                 public static BinaryExpression AddChecked (Expression left, Expression right)
390                 {
391                         return AddChecked (left, right, null);
392                 }
393
394                 public static BinaryExpression AddChecked (Expression left, Expression right, MethodInfo method)
395                 {
396                         method = BinaryCoreCheck ("op_Addition", left, right, method);
397
398                         //
399                         // The check in BinaryCoreCheck allows a bit more than we do
400                         // (byte, sbyte).  Catch that here
401                         //
402                         
403                         if (method == null){
404                                 Type ltype = left.Type;
405
406                                 if (ltype == typeof (byte) || ltype == typeof (sbyte))
407                                         throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
408                         }
409
410                         return MakeSimpleBinary (ExpressionType.AddChecked, left, right, method);
411                 }
412
413                 public static BinaryExpression Subtract (Expression left, Expression right)
414                 {
415                         return Subtract (left, right, null);
416                 }
417
418                 public static BinaryExpression Subtract (Expression left, Expression right, MethodInfo method)
419                 {
420                         method = BinaryCoreCheck ("op_Subtraction", left, right, method);
421                         return MakeSimpleBinary (ExpressionType.Subtract, left, right, method);
422                 }
423
424                 public static BinaryExpression SubtractChecked (Expression left, Expression right)
425                 {
426                         return SubtractChecked (left, right, null);
427                 }
428
429                 public static BinaryExpression SubtractChecked (Expression left, Expression right, MethodInfo method)
430                 {
431                         method = BinaryCoreCheck ("op_Subtraction", left, right, method);
432
433                         //
434                         // The check in BinaryCoreCheck allows a bit more than we do
435                         // (byte, sbyte).  Catch that here
436                         //
437
438                         if (method == null){
439                                 Type ltype = left.Type;
440
441                                 if (ltype == typeof (byte) || ltype == typeof (sbyte))
442                                         throw new InvalidOperationException (String.Format ("SubtractChecked not defined for {0} and {1}", left.Type, right.Type));
443                         }
444                         return MakeSimpleBinary (ExpressionType.SubtractChecked, left, right, method);
445                 }
446
447                 public static BinaryExpression Modulo (Expression left, Expression right)
448                 {
449                         return Modulo (left, right, null);
450                 }
451
452                 public static BinaryExpression Modulo (Expression left, Expression right, MethodInfo method)
453                 {
454                         method = BinaryCoreCheck ("op_Modulus", left, right, method);
455
456                         return MakeSimpleBinary (ExpressionType.Modulo, left, right, method);
457                 }
458
459                 public static BinaryExpression Multiply (Expression left, Expression right)
460                 {
461                         return Multiply (left, right, null);
462                 }
463
464                 public static BinaryExpression Multiply (Expression left, Expression right, MethodInfo method)
465                 {
466                         method = BinaryCoreCheck ("op_Multiply", left, right, method);
467
468                         return MakeSimpleBinary (ExpressionType.Multiply, left, right, method);
469                 }
470
471                 public static BinaryExpression MultiplyChecked (Expression left, Expression right)
472                 {
473                         return MultiplyChecked (left, right, null);
474                 }
475
476                 public static BinaryExpression MultiplyChecked (Expression left, Expression right, MethodInfo method)
477                 {
478                         method = BinaryCoreCheck ("op_Multiply", left, right, method);
479
480                         return MakeSimpleBinary (ExpressionType.MultiplyChecked, left, right, method);
481                 }
482
483                 public static BinaryExpression Divide (Expression left, Expression right)
484                 {
485                         return Divide (left, right, null);
486                 }
487
488                 public static BinaryExpression Divide (Expression left, Expression right, MethodInfo method)
489                 {
490                         method = BinaryCoreCheck ("op_Division", left, right, method);
491
492                         return MakeSimpleBinary (ExpressionType.Divide, left, right, method);
493                 }
494
495                 public static BinaryExpression Power (Expression left, Expression right)
496                 {
497                         return Power (left, right, null);
498                 }
499
500                 public static BinaryExpression Power (Expression left, Expression right, MethodInfo method)
501                 {
502                         method = BinaryCoreCheck (null, left, right, method);
503
504                         if (left.Type != typeof (double))
505                                 throw new InvalidOperationException ("Power only supports double arguments");
506
507                         return MakeSimpleBinary (ExpressionType.Power, left, right, method);
508                 }
509
510                 //
511                 // Bitwise
512                 //
513                 public static BinaryExpression And (Expression left, Expression right)
514                 {
515                         return And (left, right, null);
516                 }
517
518                 public static BinaryExpression And (Expression left, Expression right, MethodInfo method)
519                 {
520                         method = BinaryBitwiseCoreCheck ("op_BitwiseAnd", left, right, method);
521
522                         return MakeSimpleBinary (ExpressionType.And, left, right, method);
523                 }
524
525                 public static BinaryExpression Or (Expression left, Expression right)
526                 {
527                         return Or (left, right, null);
528                 }
529
530                 public static BinaryExpression Or (Expression left, Expression right, MethodInfo method)
531                 {
532                         method = BinaryBitwiseCoreCheck ("op_BitwiseOr", left, right, method);
533
534                         return MakeSimpleBinary (ExpressionType.Or, left, right, method);
535                 }
536
537                 public static BinaryExpression ExclusiveOr (Expression left, Expression right)
538                 {
539                         return ExclusiveOr (left, right, null);
540                 }
541
542                 public static BinaryExpression ExclusiveOr (Expression left, Expression right, MethodInfo method)
543                 {
544                         method = BinaryBitwiseCoreCheck ("op_ExclusiveOr", left, right, method);
545
546                         return MakeSimpleBinary (ExpressionType.ExclusiveOr, left, right, method);
547                 }
548
549                 public static BinaryExpression LeftShift (Expression left, Expression right)
550                 {
551                         return LeftShift (left, right, null);
552                 }
553
554                 public static BinaryExpression LeftShift (Expression left, Expression right, MethodInfo method)
555                 {
556                         method = BinaryBitwiseCoreCheck ("op_LeftShift", left, right, method);
557
558                         return MakeSimpleBinary (ExpressionType.LeftShift, left, right, method);
559                 }
560
561                 public static BinaryExpression RightShift (Expression left, Expression right)
562                 {
563                         return RightShift (left, right, null);
564                 }
565
566                 public static BinaryExpression RightShift (Expression left, Expression right, MethodInfo method)
567                 {
568                         method = BinaryCoreCheck ("op_RightShift", left, right, method);
569
570                         return MakeSimpleBinary (ExpressionType.RightShift, left, right, method);
571                 }
572
573                 //
574                 // Short-circuit
575                 //
576                 public static BinaryExpression AndAlso (Expression left, Expression right)
577                 {
578                         return AndAlso (left, right, null);
579                 }
580
581                 public static BinaryExpression AndAlso (Expression left, Expression right, MethodInfo method)
582                 {
583                         method = BinaryCoreCheck ("op_LogicalAnd", left, right, method);
584
585                         return MakeBoolBinary (ExpressionType.AndAlso, left, right, false, method);
586                 }
587
588                 public static BinaryExpression OrElse (Expression left, Expression right)
589                 {
590                         return OrElse (left, right, null);
591                 }
592
593                 public static BinaryExpression OrElse (Expression left, Expression right, MethodInfo method)
594                 {
595                         method = BinaryCoreCheck ("op_LogicalOr", left, right, method);
596
597                         return MakeBoolBinary (ExpressionType.OrElse, left, right, false, method);
598                 }
599
600                 //
601                 // Comparison
602                 //
603                 public static BinaryExpression Equal (Expression left, Expression right)
604                 {
605                         return Equal (left, right, false, null);
606                 }
607
608                 public static BinaryExpression Equal (Expression left, Expression right, bool liftToNull, MethodInfo method)
609                 {
610                         method = BinaryCoreCheck ("op_Equality", left, right, method);
611
612                         return MakeBoolBinary (ExpressionType.Equal, left, right, liftToNull, method);
613                 }
614
615                 public static BinaryExpression NotEqual (Expression left, Expression right)
616                 {
617                         return NotEqual (left, right, false, null);
618                 }
619
620
621                 public static BinaryExpression NotEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
622                 {
623                         method = BinaryCoreCheck ("op_Inequality", left, right, method);
624
625                         return MakeBoolBinary (ExpressionType.NotEqual, left, right, liftToNull, method);
626                 }
627
628                 public static BinaryExpression GreaterThan (Expression left, Expression right)
629                 {
630                         return GreaterThan (left, right, false, null);
631                 }
632
633                 public static BinaryExpression GreaterThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
634                 {
635                         method = BinaryCoreCheck ("op_GreaterThan", left, right, method);
636
637                         return MakeBoolBinary (ExpressionType.GreaterThan, left, right, liftToNull, method);
638                 }
639
640                 public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right)
641                 {
642                         return GreaterThanOrEqual (left, right, false, null);
643                 }
644
645
646                 public static BinaryExpression GreaterThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
647                 {
648                         method = BinaryCoreCheck ("op_GreaterThanOrEqual", left, right, method);
649
650                         return MakeBoolBinary (ExpressionType.GreaterThanOrEqual, left, right, liftToNull, method);
651                 }
652
653                 public static BinaryExpression LessThan (Expression left, Expression right)
654                 {
655                         return LessThan (left, right, false, null);
656                 }
657
658                 public static BinaryExpression LessThan (Expression left, Expression right, bool liftToNull, MethodInfo method)
659                 {
660                         method = BinaryCoreCheck ("op_LessThan", left, right, method);
661
662                         return MakeBoolBinary (ExpressionType.LessThan, left, right, liftToNull, method);
663                 }
664
665                 public static BinaryExpression LessThanOrEqual (Expression left, Expression right)
666                 {
667                         return LessThanOrEqual (left, right, false, null);
668                 }
669
670                 public static BinaryExpression LessThanOrEqual (Expression left, Expression right, bool liftToNull, MethodInfo method)
671                 {
672                         method = BinaryCoreCheck ("op_LessThanOrEqual", left, right, method);
673
674                         return MakeBoolBinary (ExpressionType.LessThanOrEqual, left, right, liftToNull, method);
675                 }
676
677                 //
678                 // Miscelaneous
679                 //
680
681                 static void ArrayCheck (Expression array)
682                 {
683                         if (array == null)
684                                 throw new ArgumentNullException ("array");
685                         if (!array.Type.IsArray)
686                                 throw new ArgumentException ("The array argument must be of type array");
687                 }
688
689                 public static BinaryExpression ArrayIndex (Expression array, Expression index)
690                 {
691                         ArrayCheck (array);
692                         if (index == null)
693                                 throw new ArgumentNullException ("index");
694                         if (array.Type.GetArrayRank () != 1)
695                                 throw new ArgumentException ("The array argument must be a single dimensional array");
696                         if (index.Type != typeof (int))
697                                 throw new ArgumentException ("The index must be of type int");
698
699                         return new BinaryExpression (ExpressionType.ArrayIndex, array.Type.GetElementType (), array, index);
700                 }
701
702                 public static BinaryExpression Coalesce (Expression left, Expression right)
703                 {
704                         return Coalesce (left, right, null);
705                 }
706
707                 [MonoTODO]
708                 public static BinaryExpression Coalesce (Expression left, Expression right, LambdaExpression conversion)
709                 {
710                         BinaryCoreCheck (null, left, right, null);
711
712                         throw new NotImplementedException ();
713                 }
714
715                 //
716                 // MakeBinary constructors
717                 //
718                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right)
719                 {
720                         return MakeBinary (binaryType, left, right, false, null);
721                 }
722
723                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method)
724                 {
725                         return MakeBinary (binaryType, left, right, liftToNull, method, null);
726                 }
727
728                 public static BinaryExpression MakeBinary (ExpressionType binaryType, Expression left, Expression right, bool liftToNull, MethodInfo method, LambdaExpression conversion)
729                 {
730                         switch (binaryType) {
731                         case ExpressionType.Add:
732                                 return Add (left, right, method);
733                         case ExpressionType.AddChecked:
734                                 return AddChecked (left, right, method);
735                         case ExpressionType.AndAlso:
736                                 return AndAlso (left, right);
737                         case ExpressionType.Coalesce:
738                                 return Coalesce (left, right, conversion);
739                         case ExpressionType.Divide:
740                                 return Divide (left, right, method);
741                         case ExpressionType.Equal:
742                                 return Equal (left, right, liftToNull, method);
743                         case ExpressionType.ExclusiveOr:
744                                 return ExclusiveOr (left, right, method);
745                         case ExpressionType.GreaterThan:
746                                 return GreaterThan (left, right, liftToNull, method);
747                         case ExpressionType.GreaterThanOrEqual:
748                                 return GreaterThanOrEqual (left, right, liftToNull, method);
749                         case ExpressionType.LeftShift:
750                                 return LeftShift (left, right, method);
751                         case ExpressionType.LessThan:
752                                 return LessThan (left, right, liftToNull, method);
753                         case ExpressionType.LessThanOrEqual:
754                                 return LessThanOrEqual (left, right, liftToNull, method);
755                         case ExpressionType.Modulo:
756                                 return Modulo (left, right, method);
757                         case ExpressionType.Multiply:
758                                 return Multiply (left, right, method);
759                         case ExpressionType.MultiplyChecked:
760                                 return MultiplyChecked (left, right, method);
761                         case ExpressionType.NotEqual:
762                                 return NotEqual (left, right, liftToNull, method);
763                         case ExpressionType.OrElse:
764                                 return OrElse (left, right);
765                         case ExpressionType.Power:
766                                 return Power (left, right, method);
767                         case ExpressionType.RightShift:
768                                 return RightShift (left, right, method);
769                         case ExpressionType.Subtract:
770                                 return Subtract (left, right, method);
771                         case ExpressionType.SubtractChecked:
772                                 return SubtractChecked (left, right, method);
773                         case ExpressionType.And:
774                                 return And (left, right, method);
775                         case ExpressionType.Or:
776                                 return Or (left, right, method);
777                         }
778
779                         throw new ArgumentException ("MakeBinary expect a binary node type");
780                 }
781
782 #endregion
783
784                 public static MethodCallExpression ArrayIndex (Expression array, params Expression [] indexes)
785                 {
786                         return ArrayIndex (array, indexes as IEnumerable<Expression>);
787                 }
788
789                 public static MethodCallExpression ArrayIndex (Expression array, IEnumerable<Expression> indexes)
790                 {
791                         ArrayCheck (array);
792
793                         if (indexes == null)
794                                 throw new ArgumentNullException ("indexes");
795
796                         var args = indexes.ToReadOnlyCollection ();
797                         if (array.Type.GetArrayRank () != args.Count)
798                                 throw new ArgumentException ("The number of arguments doesn't match the rank of the array");
799
800                         foreach (var arg in args)
801                                 if (arg.Type != typeof (int))
802                                         throw new ArgumentException ("The index must be of type int");
803
804                         return Call (array, array.Type.GetMethod ("Get", PublicInstance), args);
805                 }
806
807                 public static UnaryExpression ArrayLength (Expression array)
808                 {
809                         if (array == null)
810                                 throw new ArgumentNullException ("array");
811                         if (!array.Type.IsArray)
812                                 throw new ArgumentException ("The type of the expression must me Array");
813                         if (array.Type.GetArrayRank () != 1)
814                                 throw new ArgumentException ("The array must be a single dimensional array");
815
816                         return new UnaryExpression (ExpressionType.ArrayLength, array, typeof (int));
817                 }
818
819                 [MonoTODO]
820                 public static MemberAssignment Bind (MemberInfo member, Expression expression)
821                 {
822                         throw new NotImplementedException ();
823                 }
824
825                 [MonoTODO]
826                 public static MemberAssignment Bind (MethodInfo propertyAccessor, Expression expression)
827                 {
828                         throw new NotImplementedException ();
829                 }
830
831                 public static MethodCallExpression Call (Expression instance, MethodInfo method)
832                 {
833                         return Call (instance, method, null as IEnumerable<Expression>);
834                 }
835
836                 public static MethodCallExpression Call (MethodInfo method, params Expression [] arguments)
837                 {
838                         return Call (null, method, arguments as IEnumerable<Expression>);
839                 }
840
841                 public static MethodCallExpression Call (Expression instance, MethodInfo method, params Expression [] arguments)
842                 {
843                         return Call (instance, method, arguments as IEnumerable<Expression>);
844                 }
845
846                 public static MethodCallExpression Call (Expression instance, MethodInfo method, IEnumerable<Expression> arguments)
847                 {
848                         if (method == null)
849                                 throw new ArgumentNullException ("method");
850                         if (instance == null && !method.IsStatic)
851                                 throw new ArgumentNullException ("instance");
852                         if (instance != null && !method.DeclaringType.IsAssignableFrom (instance.Type))
853                                 throw new ArgumentException ("Type is not assignable to the declaring type of the method");
854
855                         var args = arguments.ToReadOnlyCollection ();
856                         var parameters = method.GetParameters ();
857
858                         if (args.Count != parameters.Length)
859                                 throw new ArgumentException ("The number of arguments doesn't match the number of parameters");
860
861                         // TODO: check for assignability of the arguments on the parameters
862
863                         return new MethodCallExpression (instance, method, args);
864                 }
865
866                 [MonoTODO]
867                 public static MethodCallExpression Call (Expression instance, string methodName, Type [] typeArguments, params Expression [] arguments)
868                 {
869                         throw new NotImplementedException ();
870                 }
871
872                 [MonoTODO]
873                 public static MethodCallExpression Call (Type type, string methodName, Type [] typeArguments, params Expression [] arguments)
874                 {
875                         throw new NotImplementedException ();
876                 }
877
878                 public static ConditionalExpression Condition (Expression test, Expression ifTrue, Expression ifFalse)
879                 {
880                         if (test == null)
881                                 throw new ArgumentNullException ("test");
882                         if (ifTrue == null)
883                                 throw new ArgumentNullException ("ifTrue");
884                         if (ifFalse == null)
885                                 throw new ArgumentNullException ("ifFalse");
886                         if (test.Type != typeof (bool))
887                                 throw new ArgumentException ("Test expression should be of type bool");
888                         if (ifTrue.Type != ifFalse.Type)
889                                 throw new ArgumentException ("The ifTrue and ifFalse type do not match");
890
891                         return new ConditionalExpression (test, ifTrue, ifFalse);
892                 }
893
894                 public static ConstantExpression Constant (object value)
895                 {
896                         if (value == null)
897                                 return new ConstantExpression (null, typeof (object));
898
899                         return Constant (value, value.GetType ());
900                 }
901
902                 public static ConstantExpression Constant (object value, Type type)
903                 {
904                         if (type == null)
905                                 throw new ArgumentNullException ("type");
906
907                         //
908                         // value must be compatible with type, no conversions
909                         // are allowed
910                         //
911                         if (value == null){
912                                 if (type.IsValueType && !IsNullable (type))
913                                         throw new ArgumentException ();
914                         } else {
915                                 if (!(type.IsValueType && IsNullable (type)) && value.GetType () != type)
916                                         throw new ArgumentException ();
917
918                         }
919
920                         return new ConstantExpression (value, type);
921                 }
922
923                 [MonoTODO]
924                 public static UnaryExpression Convert (Expression expression, Type type)
925                 {
926                         throw new NotImplementedException ();
927                 }
928
929                 [MonoTODO]
930                 public static UnaryExpression Convert (Expression expression, Type type, MethodInfo method)
931                 {
932                         throw new NotImplementedException ();
933                 }
934
935                 [MonoTODO]
936                 public static UnaryExpression ConvertChecked (Expression expression, Type type)
937                 {
938                         throw new NotImplementedException ();
939                 }
940
941                 [MonoTODO]
942                 public static UnaryExpression ConvertChecked (Expression expression, Type type, MethodInfo method)
943                 {
944                         throw new NotImplementedException ();
945                 }
946
947                 [MonoTODO]
948                 public static ElementInit ElementInit (MethodInfo addMethod, params Expression [] arguments)
949                 {
950                         throw new NotImplementedException ();
951                 }
952
953                 [MonoTODO]
954                 public static ElementInit ElementInit (MethodInfo addMethod, IEnumerable<Expression> arguments)
955                 {
956                         throw new NotImplementedException ();
957                 }
958
959                 [MonoTODO]
960                 public static MemberExpression Field (Expression expression, FieldInfo field)
961                 {
962                         throw new NotImplementedException ();
963                 }
964
965                 [MonoTODO]
966                 public static MemberExpression Field (Expression expression, string fieldName)
967                 {
968                         throw new NotImplementedException ();
969                 }
970
971                 public static Type GetActionType (params Type [] typeArgs)
972                 {
973                         if (typeArgs == null)
974                                 throw new ArgumentNullException ("typeArgs");
975
976                         if (typeArgs.Length > 4)
977                                 throw new ArgumentException ("No Action type of this arity");
978
979                         if (typeArgs.Length == 0)
980                                 return typeof (Action);
981
982                         Type action = null;
983                         switch (typeArgs.Length) {
984                         case 1:
985                                 action = typeof (Action<>);
986                                 break;
987                         case 2:
988                                 action = typeof (Action<,>);
989                                 break;
990                         case 3:
991                                 action = typeof (Action<,,>);
992                                 break;
993                         case 4:
994                                 action = typeof (Action<,,,>);
995                                 break;
996                         }
997
998                         return action.MakeGenericType (typeArgs);
999                 }
1000
1001                 public static Type GetFuncType (params Type [] typeArgs)
1002                 {
1003                         if (typeArgs == null)
1004                                 throw new ArgumentNullException ("typeArgs");
1005
1006                         if (typeArgs.Length < 1 || typeArgs.Length > 5)
1007                                 throw new ArgumentException ("No Func type of this arity");
1008
1009                         Type func = null;
1010                         switch (typeArgs.Length) {
1011                         case 1:
1012                                 func = typeof (Func<>);
1013                                 break;
1014                         case 2:
1015                                 func = typeof (Func<,>);
1016                                 break;
1017                         case 3:
1018                                 func = typeof (Func<,,>);
1019                                 break;
1020                         case 4:
1021                                 func = typeof (Func<,,,>);
1022                                 break;
1023                         case 5:
1024                                 func = typeof (Func<,,,,>);
1025                                 break;
1026                         }
1027
1028                         return func.MakeGenericType (typeArgs);
1029                 }
1030
1031                 [MonoTODO]
1032                 public static InvocationExpression Invoke (Expression expression, params Expression [] arguments)
1033                 {
1034                         throw new NotImplementedException ();
1035                 }
1036
1037                 [MonoTODO]
1038                 public static InvocationExpression Invoke (Expression expression, IEnumerable<Expression> arguments)
1039                 {
1040                         throw new NotImplementedException ();
1041                 }
1042
1043                 public static Expression<TDelegate> Lambda<TDelegate> (Expression body, params ParameterExpression [] parameters)
1044                 {
1045                         if (body == null)
1046                                 throw new ArgumentNullException ("body");
1047
1048                         return new Expression<TDelegate> (body, parameters);
1049                 }
1050
1051                 [MonoTODO]
1052                 public static Expression<TDelegate> Lambda<TDelegate> (Expression body, IEnumerable<ParameterExpression> parameters)
1053                 {
1054                         throw new NotImplementedException ();
1055                 }
1056
1057                 [MonoTODO]
1058                 public static LambdaExpression Lambda (Expression body, params ParameterExpression [] parameters)
1059                 {
1060                         throw new NotImplementedException ();
1061                 }
1062
1063                 public static LambdaExpression Lambda (Type delegateType, Expression body, params ParameterExpression [] parameters)
1064                 {
1065                         return Lambda (delegateType, body, parameters as IEnumerable<ParameterExpression>);
1066                 }
1067
1068                 [MonoTODO]
1069                 public static LambdaExpression Lambda (Type delegateType, Expression body, IEnumerable<ParameterExpression> parameters)
1070                 {
1071                         if (delegateType == null)
1072                                 throw new ArgumentNullException ("delegateType");
1073                         if (body == null)
1074                                 throw new ArgumentNullException ("body");
1075
1076                         return new LambdaExpression (delegateType, body, parameters.ToReadOnlyCollection ());
1077                 }
1078
1079                 public static MemberListBinding ListBind (MemberInfo member, params ElementInit [] initializers)
1080                 {
1081                         throw new NotImplementedException ();
1082                 }
1083
1084                 [MonoTODO]
1085                 public static MemberListBinding ListBind (MemberInfo member, IEnumerable<ElementInit> initializers)
1086                 {
1087                         throw new NotImplementedException ();
1088                 }
1089
1090                 [MonoTODO]
1091                 public static MemberListBinding ListBind (MethodInfo propertyAccessor, params ElementInit [] initializers)
1092                 {
1093                         throw new NotImplementedException ();
1094                 }
1095
1096                 [MonoTODO]
1097                 public static MemberListBinding ListBind (MethodInfo propertyAccessor, IEnumerable<ElementInit> initializers)
1098                 {
1099                         throw new NotImplementedException ();
1100                 }
1101
1102                 [MonoTODO]
1103                 public static ListInitExpression ListInit (NewExpression newExpression, params ElementInit [] initializers)
1104                 {
1105                         throw new NotImplementedException ();
1106                 }
1107
1108                 [MonoTODO]
1109                 public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<ElementInit> initializers)
1110                 {
1111                         throw new NotImplementedException ();
1112                 }
1113
1114                 [MonoTODO]
1115                 public static ListInitExpression ListInit (NewExpression newExpression, params Expression [] initializers)
1116                 {
1117                         throw new NotImplementedException ();
1118                 }
1119
1120                 [MonoTODO]
1121                 public static ListInitExpression ListInit (NewExpression newExpression, IEnumerable<Expression> initializers)
1122                 {
1123                         throw new NotImplementedException ();
1124                 }
1125
1126                 [MonoTODO]
1127                 public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, params Expression [] initializers)
1128                 {
1129                         throw new NotImplementedException ();
1130                 }
1131
1132                 [MonoTODO]
1133                 public static ListInitExpression ListInit (NewExpression newExpression, MethodInfo addMethod, IEnumerable<Expression> initializers)
1134                 {
1135                         throw new NotImplementedException ();
1136                 }
1137
1138                 public static MemberExpression MakeMemberAccess (Expression expression, MemberInfo member)
1139                 {
1140                         if (expression == null)
1141                                 throw new ArgumentNullException ("expression");
1142                         if (member == null)
1143                                 throw new ArgumentNullException ("member");
1144
1145                         var field = member as FieldInfo;
1146                         if (field != null)
1147                                 return Field (expression, field);
1148
1149                         var property = member as PropertyInfo;
1150                         if (property != null)
1151                                 return Property (expression, property);
1152
1153                         throw new ArgumentException ("Member should either be a field or a property");
1154                 }
1155
1156                 public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type)
1157                 {
1158                         return MakeUnary (unaryType, operand, type, null);
1159                 }
1160
1161                 public static UnaryExpression MakeUnary (ExpressionType unaryType, Expression operand, Type type, MethodInfo method)
1162                 {
1163                         switch (unaryType) {
1164                         case ExpressionType.ArrayLength:
1165                                 return ArrayLength (operand);
1166                         case ExpressionType.Convert:
1167                                 return Convert (operand, type, method);
1168                         case ExpressionType.ConvertChecked:
1169                                 return ConvertChecked (operand, type, method);
1170                         case ExpressionType.Negate:
1171                                 return Negate (operand, method);
1172                         case ExpressionType.NegateChecked:
1173                                 return NegateChecked (operand, method);
1174                         case ExpressionType.Not:
1175                                 return Not (operand, method);
1176                         case ExpressionType.Quote:
1177                                 return Quote (operand);
1178                         case ExpressionType.TypeAs:
1179                                 return TypeAs (operand, type);
1180                         case ExpressionType.UnaryPlus:
1181                                 return UnaryPlus (operand, method);
1182                         }
1183
1184                         throw new ArgumentException ("MakeUnary expect an unary operator");
1185                 }
1186
1187                 [MonoTODO]
1188                 public static MemberMemberBinding MemberBind (MemberInfo member, params MemberBinding [] binding)
1189                 {
1190                         throw new NotImplementedException ();
1191                 }
1192
1193                 [MonoTODO]
1194                 public static MemberMemberBinding MemberBind (MemberInfo member, IEnumerable<MemberBinding> binding)
1195                 {
1196                         throw new NotImplementedException ();
1197                 }
1198
1199                 [MonoTODO]
1200                 public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, params MemberBinding [] binding)
1201                 {
1202                         throw new NotImplementedException ();
1203                 }
1204
1205                 [MonoTODO]
1206                 public static MemberMemberBinding MemberBind (MethodInfo propertyAccessor, IEnumerable<MemberBinding> binding)
1207                 {
1208                         throw new NotImplementedException ();
1209                 }
1210
1211                 [MonoTODO]
1212                 public static MemberInitExpression MemberInit (NewExpression newExpression, params MemberBinding [] binding)
1213                 {
1214                         throw new NotImplementedException ();
1215                 }
1216
1217                 [MonoTODO]
1218                 public static MemberInitExpression MemberInit (NewExpression newExpression, IEnumerable<MemberBinding> binding)
1219                 {
1220                         throw new NotImplementedException ();
1221                 }
1222
1223                 public static UnaryExpression Negate (Expression expression)
1224                 {
1225                         return Negate (expression, null);
1226                 }
1227
1228                 public static UnaryExpression Negate (Expression expression, MethodInfo method)
1229                 {
1230                         method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
1231
1232                         return MakeSimpleUnary (ExpressionType.Negate, expression, method);
1233                 }
1234
1235                 public static UnaryExpression NegateChecked (Expression expression)
1236                 {
1237                         return NegateChecked (expression, null);
1238                 }
1239
1240                 public static UnaryExpression NegateChecked (Expression expression, MethodInfo method)
1241                 {
1242                         method = UnaryCoreCheck ("op_UnaryNegation", expression, method);
1243
1244                         return MakeSimpleUnary (ExpressionType.Negate, expression, method);
1245                 }
1246
1247                 [MonoTODO]
1248                 public static NewExpression New (ConstructorInfo constructor)
1249                 {
1250                         throw new NotImplementedException ();
1251                 }
1252
1253                 [MonoTODO]
1254                 public static NewExpression New (Type type)
1255                 {
1256                         throw new NotImplementedException ();
1257                 }
1258
1259                 [MonoTODO]
1260                 public static NewExpression New (ConstructorInfo constructor, params Expression [] arguments)
1261                 {
1262                         throw new NotImplementedException ();
1263                 }
1264
1265                 [MonoTODO]
1266                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments)
1267                 {
1268                         throw new NotImplementedException ();
1269                 }
1270
1271                 [MonoTODO]
1272                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, params MemberInfo [] members)
1273                 {
1274                         throw new NotImplementedException ();
1275                 }
1276
1277                 [MonoTODO]
1278                 public static NewExpression New (ConstructorInfo constructor, IEnumerable<Expression> arguments, IEnumerable<MemberInfo> members)
1279                 {
1280                         throw new NotImplementedException ();
1281                 }
1282
1283                 [MonoTODO]
1284                 public static NewArrayExpression NewArrayBounds (Type type, params Expression [] bounds)
1285                 {
1286                         throw new NotImplementedException ();
1287                 }
1288
1289                 [MonoTODO]
1290                 public static NewArrayExpression NewArrayBounds (Type type, IEnumerable<Expression> bounds)
1291                 {
1292                         throw new NotImplementedException ();
1293                 }
1294
1295                 [MonoTODO]
1296                 public static NewArrayExpression NewArrayInit (Type type, params Expression [] bounds)
1297                 {
1298                         throw new NotImplementedException ();
1299                 }
1300
1301                 [MonoTODO]
1302                 public static NewArrayExpression NewArrayInit (Type type, IEnumerable<Expression> bounds)
1303                 {
1304                         throw new NotImplementedException ();
1305                 }
1306
1307                 public static UnaryExpression Not (Expression expression)
1308                 {
1309                         return Not (expression, null);
1310                 }
1311
1312                 public static UnaryExpression Not (Expression expression, MethodInfo method)
1313                 {
1314                         method = UnaryCoreCheck ("op_LogicalNot", expression, method);
1315
1316                         return MakeSimpleUnary (ExpressionType.Not, expression, method);
1317                 }
1318
1319                 public static ParameterExpression Parameter (Type type, string name)
1320                 {
1321                         if (type == null)
1322                                 throw new ArgumentNullException ("type");
1323
1324                         return new ParameterExpression (type, name);
1325                 }
1326
1327                 [MonoTODO]
1328                 public static MemberExpression Property (Expression expression, MethodInfo propertyAccessor)
1329                 {
1330                         throw new NotImplementedException ();
1331                 }
1332
1333                 [MonoTODO]
1334                 public static MemberExpression Property (Expression expression, PropertyInfo property)
1335                 {
1336                         throw new NotImplementedException ();
1337                 }
1338
1339                 [MonoTODO]
1340                 public static MemberExpression Property (Expression expression, string propertyName)
1341                 {
1342                         throw new NotImplementedException ();
1343                 }
1344
1345                 [MonoTODO]
1346                 public static MemberExpression PropertyOrField (Expression expression, string propertyOrFieldName)
1347                 {
1348                         throw new NotImplementedException ();
1349                 }
1350
1351                 public static UnaryExpression Quote (Expression expression)
1352                 {
1353                         if (expression == null)
1354                                 throw new ArgumentNullException ("expression");
1355
1356                         return new UnaryExpression (ExpressionType.Quote, expression, expression.GetType ());
1357                 }
1358
1359                 public static UnaryExpression TypeAs (Expression expression, Type type)
1360                 {
1361                         if (expression == null)
1362                                 throw new ArgumentNullException ("expression");
1363                         if (type == null)
1364                                 throw new ArgumentNullException ("type");
1365                         if (type.IsValueType && !IsNullable (type))
1366                                 throw new ArgumentException ("TypeAs expect a reference or a nullable type");
1367
1368                         return new UnaryExpression (ExpressionType.TypeAs, expression, type);
1369                 }
1370
1371                 public static TypeBinaryExpression TypeIs (Expression expression, Type type)
1372                 {
1373                         if (expression == null)
1374                                 throw new ArgumentNullException ("expression");
1375                         if (type == null)
1376                                 throw new ArgumentNullException ("type");
1377
1378                         return new TypeBinaryExpression (ExpressionType.TypeIs, expression, type, typeof (bool));
1379                 }
1380
1381                 public static UnaryExpression UnaryPlus (Expression expression)
1382                 {
1383                         return UnaryPlus (expression, null);
1384                 }
1385
1386                 public static UnaryExpression UnaryPlus (Expression expression, MethodInfo method)
1387                 {
1388                         method = UnaryCoreCheck ("op_UnaryPlus", expression, method);
1389
1390                         return MakeSimpleUnary (ExpressionType.UnaryPlus, expression, method);
1391                 }
1392
1393                 static bool IsNullable (Type type)
1394                 {
1395                         return type.IsGenericType && type.GetGenericTypeDefinition () == typeof (Nullable<>);
1396                 }
1397
1398                 protected static bool IsUnsigned (Type t)
1399                 {
1400                         if (t.IsPointer)
1401                                 return IsUnsigned (t.GetElementType ());
1402
1403                         return t == typeof (ushort) || t == typeof (uint) || t == typeof (ulong) || t == typeof (byte);
1404                 }
1405
1406                 //
1407                 // returns the T in a a Nullable<T> type.
1408                 //
1409                 static Type GetNullableOf (Type type)
1410                 {
1411                         return type.GetGenericArguments () [0];
1412                 }
1413                 
1414                 //
1415                 // This method must be overwritten by derived classes to
1416                 // compile the expression
1417                 //
1418                 internal abstract void Emit (EmitContext ec);
1419         }
1420 }