2 // ConstantExpression.cs
5 // Jb Evain (jbevain@novell.com)
6 // Miguel de Icaza (miguel@novell.com)
8 // Some code is based on the Mono C# compiler:
9 // Marek Safar (marek.safar@seznam.cz)
10 // Martin Baulig (martin@ximian.com)
12 // (C) 2001-2008 Novell, Inc. (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System
.Reflection
;
36 using System
.Reflection
.Emit
;
38 namespace System
.Linq
.Expressions
{
40 public sealed class ConstantExpression
: Expression
{
47 internal ConstantExpression (object value, Type type
)
48 : base (ExpressionType
.Constant
, type
)
53 internal override void Emit (EmitContext ec
)
55 if (Type
.IsNullable ()) {
56 EmitNullableConstant (ec
, Type
, value);
60 EmitConstant (ec
, Type
, value);
63 void EmitNullableConstant (EmitContext ec
, Type type
, object value)
67 var local
= ig
.DeclareLocal (type
);
68 ig
.Emit (OpCodes
.Ldloca
, local
);
69 ig
.Emit (OpCodes
.Initobj
, type
);
70 ig
.Emit (OpCodes
.Ldloc
, local
);
72 EmitConstant (ec
, type
.GetFirstGenericArgument (), value);
73 ec
.EmitNullableNew (type
);
77 void EmitConstant (EmitContext ec
, Type type
, object value)
81 switch (Type
.GetTypeCode (type
)){
83 ig
.Emit (OpCodes
.Ldc_I4
, (int) ((byte)value));
87 ig
.Emit (OpCodes
.Ldc_I4
, (int) ((sbyte)value));
91 ig
.Emit (OpCodes
.Ldc_I4
, (int) ((short)value));
95 ig
.Emit (OpCodes
.Ldc_I4
, (int) ((ushort)value));
99 ig
.Emit (OpCodes
.Ldc_I4
, (int) value);
102 case TypeCode
.UInt32
:
103 ig
.Emit (OpCodes
.Ldc_I4
, unchecked ((int) ((uint)Value
)));
107 ig
.Emit (OpCodes
.Ldc_I8
, (long) value);
110 case TypeCode
.UInt64
:
111 ig
.Emit (OpCodes
.Ldc_I8
, unchecked ((long) ((ulong)value)));
114 case TypeCode
.Boolean
:
116 ig
.Emit (OpCodes
.Ldc_I4_1
);
118 ec
.ig
.Emit (OpCodes
.Ldc_I4_0
);
122 ig
.Emit (OpCodes
.Ldc_I4
, (int) ((char) value));
125 case TypeCode
.Single
:
126 ig
.Emit (OpCodes
.Ldc_R4
, (float) value);
129 case TypeCode
.Double
:
130 ig
.Emit (OpCodes
.Ldc_R8
, (double) value);
133 case TypeCode
.Decimal
: {
134 Decimal v
= (decimal) value;
135 int [] words
= Decimal
.GetBits (v
);
136 int power
= (words
[3] >> 16) & 0xff;
137 Type ti
= typeof (int);
139 if (power
== 0 && v
<= int.MaxValue
&& v
>= int.MinValue
) {
140 ig
.Emit (OpCodes
.Ldc_I4
, (int) v
);
142 ig
.Emit (OpCodes
.Newobj
, typeof (Decimal
).GetConstructor (new Type
[1] { ti }
));
145 ig
.Emit (OpCodes
.Ldc_I4
, words
[0]);
146 ig
.Emit (OpCodes
.Ldc_I4
, words
[1]);
147 ig
.Emit (OpCodes
.Ldc_I4
, words
[2]);
149 ig
.Emit (OpCodes
.Ldc_I4
, words
[3] >> 31);
152 ig
.Emit (OpCodes
.Ldc_I4
, power
);
154 ig
.Emit (OpCodes
.Newobj
, typeof (Decimal
).GetConstructor (new Type
[5] { ti, ti, ti, typeof(bool), typeof(byte) }
));
158 case TypeCode
.DateTime
: {
159 var date
= (DateTime
) value;
160 var local
= ig
.DeclareLocal (typeof (DateTime
));
162 ig
.Emit (OpCodes
.Ldloca
, local
);
163 ig
.Emit (OpCodes
.Ldc_I8
, date
.Ticks
);
164 ig
.Emit (OpCodes
.Ldc_I4
, (int) date
.Kind
);
165 ig
.Emit (OpCodes
.Call
, typeof (DateTime
).GetConstructor (new [] { typeof (long), typeof (DateTimeKind) }
));
166 ig
.Emit (OpCodes
.Ldloc
, local
);
171 case TypeCode
.DBNull
:
172 ig
.Emit (OpCodes
.Ldsfld
, typeof (DBNull
).GetField ("Value", BindingFlags
.Public
| BindingFlags
.Static
));
175 case TypeCode
.String
:
176 EmitIfNotNull (ec
, c
=> c
.ig
.Emit (OpCodes
.Ldstr
, (string) value));
179 case TypeCode
.Object
:
180 EmitIfNotNull (ec
, c
=> c
.EmitReadGlobal (value));
184 throw new NotImplementedException (String
.Format ("No support for constants of type {0} yet", Type
));
187 void EmitIfNotNull (EmitContext ec
, Action
<EmitContext
> emit
)
190 ec
.ig
.Emit (OpCodes
.Ldnull
);