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) {
64 BigInteger bi = value as BigInteger;
65 if ((object)bi != null) {
66 return BigIntegerConstant(bi);
68 } else if (value is BigInt) {
69 return BigIntConstant((BigInt)value);
70 } else if (value is Complex) {
71 return ComplexConstant((Complex)value);
73 } else if (value is Complex64) {
74 return Complex64Constant((Complex64)value);
75 } else if (value is Type) {
76 return Expression.Constant(value, typeof(Type));
77 } else if (value is ConstructorInfo) {
78 return Expression.Constant(value, typeof(ConstructorInfo));
79 } else if (value is EventInfo) {
80 return Expression.Constant(value, typeof(EventInfo));
81 } else if (value is FieldInfo) {
82 return Expression.Constant(value, typeof(FieldInfo));
83 } else if (value is MethodInfo) {
84 return Expression.Constant(value, typeof(MethodInfo));
85 } else if (value is PropertyInfo) {
86 return Expression.Constant(value, typeof(PropertyInfo));
88 Type t = value.GetType();
89 if (!t.GetTypeInfo().IsEnum) {
90 switch (t.GetTypeCode()) {
91 case TypeCode.Boolean:
92 return (bool)value ? TrueLiteral : FalseLiteral;
95 int cacheIndex = x + 2;
96 if (cacheIndex >= 0 && cacheIndex < IntCache.Length) {
97 ConstantExpression res;
98 if ((res = IntCache[cacheIndex]) == null) {
99 IntCache[cacheIndex] = res = Constant(x, typeof(int));
104 case TypeCode.String:
105 if (String.IsNullOrEmpty((string)value)) {
106 return EmptyStringLiteral;
111 return Expression.Constant(value);
115 private static Expression BigIntegerConstant(BigInteger value) {
117 if (value.AsInt32(out ival)) {
118 return Expression.Call(
119 new Func<int, BigInteger>(BigInteger.Create).GetMethodInfo(),
125 if (value.AsInt64(out lval)) {
126 return Expression.Call(
127 new Func<long, BigInteger>(BigInteger.Create).GetMethodInfo(),
132 #if !FEATURE_NUMERICS
133 return Expression.Call(
134 new Func<int, uint[], BigInteger>(CompilerHelpers.CreateBigInteger).Method,
135 Constant((int)value.Sign),
136 CreateArray<uint>(value.GetWords())
139 return Expression.Call(
140 new Func<bool, byte[], BigInteger>(CompilerHelpers.CreateBigInteger).GetMethodInfo(),
141 Constant(value.Sign < 0),
142 CreateArray<byte>(value.Abs().ToByteArray())
146 private static Expression BigIntConstant(BigInt value) {
148 if (value.AsInt32(out ival)) {
149 return Expression.Call(
150 new Func<int, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
156 if (value.AsInt64(out lval)) {
157 return Expression.Call(
158 new Func<long, BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
163 return Expression.Call(
164 new Func<bool, byte[], BigInt>(CompilerHelpers.CreateBigInt).GetMethodInfo(),
165 Constant(value.Sign < 0),
166 CreateArray<byte>(value.Abs().ToByteArray())
171 private static Expression CreateArray<T>(T[] array) {
172 // TODO: could we use blobs?
173 Expression[] init = new Expression[array.Length];
174 for (int i = 0; i < init.Length; i++) {
175 init[i] = Constant(array[i]);
177 return Expression.NewArrayInit(typeof(T), init);
181 private static Expression ComplexConstant(Complex value) {
182 if (value.Real != 0.0) {
183 if (value.Imaginary() != 0.0) {
184 return Expression.Call(
185 new Func<double, double, Complex>(MathUtils.MakeComplex).GetMethodInfo(),
186 Constant(value.Real),
187 Constant(value.Imaginary())
190 return Expression.Call(
191 new Func<double, Complex>(MathUtils.MakeReal).GetMethodInfo(),
196 return Expression.Call(
197 new Func<double, Complex>(MathUtils.MakeImaginary).GetMethodInfo(),
198 Constant(value.Imaginary())
204 private static Expression Complex64Constant(Complex64 value) {
205 if (value.Real != 0.0) {
206 if (value.Imag != 0.0) {
207 return Expression.Call(
208 new Func<double, double, Complex64>(Complex64.Make).GetMethodInfo(),
209 Constant(value.Real),
213 return Expression.Call(
214 new Func<double, Complex64>(Complex64.MakeReal).GetMethodInfo(),
219 return Expression.Call(
220 new Func<double, Complex64>(Complex64.MakeImaginary).GetMethodInfo(),