2008-01-17 Miguel de Icaza <miguel@novell.com>
[mono.git] / mcs / class / System.Core / System.Linq.Expressions / ConstantExpression.cs
index 169f4961304271391781591b697340f576239230..f958329396ecc92217f82082d3c04e3ceef7174a 100644 (file)
@@ -3,8 +3,13 @@
 //
 // Author:
 //   Jb Evain (jbevain@novell.com)
+//   Miguel de Icaza (miguel@novell.com)
 //
-// (C) 2008 Novell, Inc. (http://www.novell.com)
+// Some code is based on the Mono C# compiler:
+//   Marek Safar (marek.safar@seznam.cz)
+//   Martin Baulig (martin@ximian.com)
+//
+// (C) 2001-2008 Novell, Inc. (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using System;
+using System.Reflection;
+using System.Reflection.Emit;
 
 namespace System.Linq.Expressions {
 
        public sealed class ConstantExpression : Expression {
-
                object value;
 
                public object Value {
@@ -43,5 +49,96 @@ namespace System.Linq.Expressions {
                {
                        this.value = value;
                }
+
+               internal override void Emit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       
+                       switch (Type.GetTypeCode (Type)){
+                       case TypeCode.Byte:
+                               ig.Emit (OpCodes.Ldc_I4, (int) ((byte)value));
+                               return;
+                                             
+                       case TypeCode.SByte:
+                               ig.Emit (OpCodes.Ldc_I4, (int) ((sbyte)value));
+                               return;
+                                       
+                       case TypeCode.Int16:
+                               ig.Emit (OpCodes.Ldc_I4, (int) ((short)value));
+                               return;
+                               
+                       case TypeCode.UInt16:
+                               ig.Emit (OpCodes.Ldc_I4, (int) ((ushort)value));
+                               return;
+                               
+                       case TypeCode.Int32:
+                               ig.Emit (OpCodes.Ldc_I4, (int) value);
+                               return;
+                               
+                       case TypeCode.UInt32:
+                               ig.Emit (OpCodes.Ldc_I4, unchecked ((int) ((uint)Value)));
+                               return;
+                               
+                       case TypeCode.Int64:
+                               ig.Emit (OpCodes.Ldc_I8, (long) value);
+                               return;
+                                       
+                       case TypeCode.UInt64:
+                               ig.Emit (OpCodes.Ldc_I8, unchecked ((long) ((ulong)value)));
+                               return;
+
+                       case TypeCode.Boolean:
+                               if ((bool) Value)
+                                       ig.Emit (OpCodes.Ldc_I4_1);
+                               else
+                                       ec.ig.Emit (OpCodes.Ldc_I4_0);
+                               return;
+                               
+                       case TypeCode.Char:
+                               ig.Emit (OpCodes.Ldc_I4, (int) ((char) value));
+                               return;
+                               
+                       case TypeCode.Single:
+                               ig.Emit (OpCodes.Ldc_R4, (float) value);
+                               return;
+                               
+                       case TypeCode.Double:
+                               ig.Emit (OpCodes.Ldc_R8, (double) value);
+                               return;
+                               
+                       case TypeCode.Decimal: {
+                               Decimal v = (decimal) value;
+                               int [] words = Decimal.GetBits (v);
+                               int power = (words [3] >> 16) & 0xff;
+                               Type ti = typeof (int);
+                               
+                               if (power == 0 && v <= int.MaxValue && v >= int.MinValue) {
+                                       ig.Emit (OpCodes.Ldc_I4, (int) v);
+                                       
+                                       ig.Emit (OpCodes.Newobj, typeof (Decimal).GetConstructor (new Type [1] { ti }));
+                                       return;
+                               }
+                               ig.Emit (OpCodes.Ldc_I4, words [0]);
+                               ig.Emit (OpCodes.Ldc_I4, words [1]);
+                               ig.Emit (OpCodes.Ldc_I4, words [2]);
+                               // sign
+                               ig.Emit (OpCodes.Ldc_I4, words [3] >> 31);
+
+                               // power
+                               ig.Emit (OpCodes.Ldc_I4, power);
+
+                               ig.Emit (OpCodes.Newobj, typeof (Decimal).GetConstructor (new Type [5] { ti, ti, ti, typeof(bool), typeof(byte) }));
+                               return;
+                        }
+
+                       case TypeCode.String:
+                               ig.Emit (OpCodes.Ldstr, (string) value);
+                               return;
+                       }
+
+                       // FIXME: complete the implementation
+                       
+                       throw new NotImplementedException (String.Format ("No support for constants of type {0} yet", Type));
+               }
        }
 }