1 /* ****************************************************************************
3 * Copyright (c) Microsoft Corporation.
5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
6 * copy of the license can be found in the License.html file at the root of this distribution. If
7 * you cannot locate the Apache License, Version 2.0, please send an email to
8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
9 * by the terms of the Apache License, Version 2.0.
11 * You must not remove this notice, or any other, from this software.
14 * ***************************************************************************/
17 using System.Linq.Expressions;
19 using Microsoft.Scripting.Ast;
23 using BigInt = System.Numerics.BigInteger;
24 using Complex = System.Numerics.Complex;
28 using System.Reflection;
29 using Microsoft.Scripting.Generation;
30 using Microsoft.Scripting.Math;
31 using Microsoft.Scripting.Utils;
33 namespace Microsoft.Scripting.Ast {
34 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces")]
35 public static partial class Utils {
36 private static readonly ConstantExpression TrueLiteral = Expression.Constant(true, typeof(bool));
37 private static readonly ConstantExpression FalseLiteral = Expression.Constant(false, typeof(bool));
38 private static readonly ConstantExpression NullLiteral = Expression.Constant(null, typeof(object));
39 private static readonly ConstantExpression EmptyStringLiteral = Expression.Constant(String.Empty, typeof(string));
40 private static readonly ConstantExpression[] IntCache = new ConstantExpression[100];
43 /// Wraps the given value in a WeakReference and returns a tree that will retrieve
44 /// the value from the WeakReference.
46 public static MemberExpression WeakConstant(object value) {
47 System.Diagnostics.Debug.Assert(!(value is Expression));
48 return Expression.Property(
49 Constant(new WeakReference(value)),
50 typeof(WeakReference).GetDeclaredProperty("Target")
54 public static ConstantExpression Constant(object value, Type type) {
55 return Expression.Constant(value, type);
58 // The helper API should return ConstantExpression after SymbolConstantExpression goes away
59 public static Expression Constant(object value) {
65 BigInteger bi = value as BigInteger;
66 if ((object)bi != null) {
67 return BigIntegerConstant(bi);
72 return BigIntConstant((BigInt)value);
74 return ComplexConstant((Complex)value);
78 if (value is Complex64)
79 return Complex64Constant((Complex64)value);
82 return Expression.Constant(value, typeof(Type));
83 } else if (value is ConstructorInfo) {
84 return Expression.Constant(value, typeof(ConstructorInfo));
85 } else if (value is EventInfo) {
86 return Expression.Constant(value, typeof(EventInfo));
87 } else if (value is FieldInfo) {
88 return Expression.Constant(value, typeof(FieldInfo));
89 } else if (value is MethodInfo) {
90 return Expression.Constant(value, typeof(MethodInfo));
91 } else if (value is PropertyInfo) {
92 return Expression.Constant(value, typeof(PropertyInfo));
94 Type t = value.GetType();
95 if (!t.GetTypeInfo().IsEnum) {
96 switch (t.GetTypeCode()) {
97 case TypeCode.Boolean:
98 return (bool)value ? TrueLiteral : FalseLiteral;
101 int cacheIndex = x + 2;
102 if (cacheIndex >= 0 && cacheIndex < IntCache.Length) {
103 ConstantExpression res;
104 if ((res = IntCache[cacheIndex]) == null) {
105 IntCache[cacheIndex] = res = Constant(x, typeof(int));
110 case TypeCode.String:
111 if (String.IsNullOrEmpty((string)value)) {
112 return EmptyStringLiteral;
117 return Expression.Constant(value);
121 #if !MONO_INTERPRETER
122 private static Expression BigIntegerConstant(BigInteger value) {
124 if (value.AsInt32(out ival)) {
125 return Expression.Call(
126 new Func<int, BigInteger>(BigInteger.Create).GetMethodInfo(),
132 if (value.AsInt64(out lval)) {
133 return Expression.Call(
134 new Func<long, BigInteger>(BigInteger.Create).GetMethodInfo(),
139 #if !FEATURE_NUMERICS
140 return Expression.Call(
141 new Func<int, uint[], BigInteger>(CompilerHelpers.CreateBigInteger).Method,
142 Constant((int)value.Sign),
143 CreateArray<uint>(value.GetWords())
146 return Expression.Call(
147 new Func<bool, byte[], BigInteger>(CompilerHelpers.CreateBigInteger).GetMethodInfo(),
148 Constant(value.Sign < 0),
149 CreateArray<byte>(value.Abs().ToByteArray())
153 private static Expression BigIntConstant(BigInt value) {
155 if (value.AsInt32(out ival)) {
156 return Expression.Call(
157 new Func<int, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
163 if (value.AsInt64(out lval)) {
164 return Expression.Call(
165 new Func<long, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
170 return Expression.Call(
171 new Func<bool, byte[], BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
172 Constant(value.Sign < 0),
173 CreateArray<byte>(value.Abs().ToByteArray())
178 private static Expression CreateArray<T>(T[] array) {
179 // TODO: could we use blobs?
180 Expression[] init = new Expression[array.Length];
181 for (int i = 0; i < init.Length; i++) {
182 init[i] = Constant(array[i]);
184 return Expression.NewArrayInit(typeof(T), init);
188 private static Expression ComplexConstant(Complex value) {
189 if (value.Real != 0.0) {
190 if (value.Imaginary() != 0.0) {
191 return Expression.Call(
192 new Func<double, double, Complex>(MathUtils.MakeComplex).GetMethodInfo(),
193 Constant(value.Real),
194 Constant(value.Imaginary())
197 return Expression.Call(
198 new Func<double, Complex>(MathUtils.MakeReal).GetMethodInfo(),
203 return Expression.Call(
204 new Func<double, Complex>(MathUtils.MakeImaginary).GetMethodInfo(),
205 Constant(value.Imaginary())
211 #if !MONO_INTERPRETER
212 private static Expression Complex64Constant(Complex64 value) {
213 if (value.Real != 0.0) {
214 if (value.Imag != 0.0) {
215 return Expression.Call(
216 new Func<double, double, Complex64>(Complex64.Make).GetMethodInfo(),
217 Constant(value.Real),
221 return Expression.Call(
222 new Func<double, Complex64>(Complex64.MakeReal).GetMethodInfo(),
227 return Expression.Call(
228 new Func<double, Complex64>(Complex64.MakeImaginary).GetMethodInfo(),