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 BigInt = System.Numerics.BigInteger;
21 using System.Linq.Expressions;
25 using System.Collections;
26 using System.Collections.Generic;
27 using System.ComponentModel;
28 using System.Diagnostics;
31 using System.Reflection;
33 using System.Reflection.Emit;
35 using System.Runtime.CompilerServices;
36 using Microsoft.Scripting.Actions;
37 using Microsoft.Scripting.Ast;
38 using Microsoft.Scripting.Interpreter;
39 using Microsoft.Scripting.Math;
40 using Microsoft.Scripting.Runtime;
41 using Microsoft.Scripting.Utils;
42 using AstUtils = Microsoft.Scripting.Ast.Utils;
44 namespace Microsoft.Scripting.Generation {
46 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
47 public delegate void ActionRef<T0, T1>(ref T0 arg0, ref T1 arg1);
49 public static class CompilerHelpers {
50 public static readonly MethodAttributes PublicStatic = MethodAttributes.Public | MethodAttributes.Static;
51 private static readonly MethodInfo _CreateInstanceMethod = typeof(ScriptingRuntimeHelpers).GetMethod("CreateInstance");
53 private static int _Counter; // for generating unique names for lambda methods
55 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
56 public static object GetMissingValue(Type type) {
57 ContractUtils.RequiresNotNull(type, "type");
59 if (type.IsByRef) type = type.GetElementType();
60 if (type.IsEnum()) return Activator.CreateInstance(type);
62 switch (type.GetTypeCode()) {
66 if (type.IsSealed() && type.IsValueType()) {
67 return Activator.CreateInstance(type);
68 } else if (type == typeof(object)) {
69 // parameter of type object receives the actual Missing value
71 } else if (!type.IsValueType()) {
74 throw Error.CantCreateDefaultTypeFor(type);
81 case TypeCode.Boolean: return false;
82 case TypeCode.Char: return '\0';
83 case TypeCode.SByte: return (sbyte)0;
84 case TypeCode.Byte: return (byte)0;
85 case TypeCode.Int16: return (short)0;
86 case TypeCode.UInt16: return (ushort)0;
87 case TypeCode.Int32: return (int)0;
88 case TypeCode.UInt32: return (uint)0;
89 case TypeCode.Int64: return 0L;
90 case TypeCode.UInt64: return 0UL;
91 case TypeCode.Single: return 0.0f;
92 case TypeCode.Double: return 0.0D;
93 case TypeCode.Decimal: return (decimal)0;
94 case TypeCode.DateTime: return DateTime.MinValue;
98 public static bool IsStatic(MethodBase mi) {
99 return mi.IsConstructor || mi.IsStatic;
103 /// True if the MethodBase is method which is going to construct an object
105 public static bool IsConstructor(MethodBase mb) {
106 if (mb.IsConstructor) {
110 if (mb.IsGenericMethod) {
111 MethodInfo mi = mb as MethodInfo;
113 if (mi.GetGenericMethodDefinition() == _CreateInstanceMethod) {
121 public static T[] MakeRepeatedArray<T>(T item, int count) {
122 T[] ret = new T[count];
123 for (int i = 0; i < count; i++) ret[i] = item;
127 public static bool IsComparisonOperator(ExpressionType op) {
129 case ExpressionType.LessThan: return true;
130 case ExpressionType.LessThanOrEqual: return true;
131 case ExpressionType.GreaterThan: return true;
132 case ExpressionType.GreaterThanOrEqual: return true;
133 case ExpressionType.Equal: return true;
134 case ExpressionType.NotEqual: return true;
140 /// Returns the System.Type for any object, including null. The type of null
141 /// is represented by None.Type and all other objects just return the
142 /// result of Object.GetType
144 public static Type GetType(object obj) {
146 return typeof(DynamicNull);
149 return obj.GetType();
153 /// Simply returns a Type[] from calling GetType on each element of args.
155 public static Type[] GetTypes(object[] args) {
156 Type[] types = new Type[args.Length];
157 for (int i = 0; i < args.Length; i++) {
158 types[i] = GetType(args[i]);
165 /// Used by default method binder to check types of splatted arguments.
167 public static bool TypesEqual(IList args, int start, Type[] types) {
168 for (int i = 0; i < types.Length; i++) {
169 object arg = args[start + i];
170 if (types[i] != (arg != null ? arg.GetType() : null)) {
177 public static bool CanOptimizeMethod(MethodBase method) {
178 if (method.ContainsGenericParameters ||
179 method.IsProtected() ||
181 !method.DeclaringType.IsVisible()) {
188 /// Given a MethodInfo which may be declared on a non-public type this attempts to
189 /// return a MethodInfo which will dispatch to the original MethodInfo but is declared
190 /// on a public type.
192 /// Returns the original method if the method if a public version cannot be found.
194 public static MethodInfo TryGetCallableMethod(Type targetType, MethodInfo method) {
195 if (method.DeclaringType == null || method.DeclaringType.IsVisible()) {
199 // first try and get it from the base type we're overriding...
200 MethodInfo baseMethod = method.GetRuntimeBaseDefinition();
202 if (baseMethod.DeclaringType.IsVisible() || baseMethod.DeclaringType.IsInterface()) {
203 // We need to instantiate the method as GetBaseDefinition might return a generic definition of the base method:
204 if (baseMethod.IsGenericMethodDefinition) {
205 baseMethod = baseMethod.MakeGenericMethod(method.GetGenericArguments());
210 #if WIN8 // TODO: interface map, method handle
211 foreach (Type iface in targetType.GetImplementedInterfaces()) {
212 dynamic mapping = ((dynamic)targetType).GetInterfaceMap(iface);
213 for (int i = 0; i < mapping.TargetMethods.Length; i++) {
214 MethodInfo targetMethod = mapping.TargetMethods[i];
215 if (targetMethod != null && ((dynamic)targetMethod).MethodHandle == ((dynamic)method).MethodHandle) {
216 return mapping.InterfaceMethods[i];
221 // maybe we can get it from an interface on the type this
222 // method came from...
223 foreach (Type iface in targetType.GetImplementedInterfaces()) {
224 if (iface.IsPublic()) {
225 InterfaceMapping mapping = targetType.GetInterfaceMap(iface);
226 for (int i = 0; i < mapping.TargetMethods.Length; i++) {
227 MethodInfo targetMethod = mapping.TargetMethods[i];
228 if (targetMethod != null && targetMethod.MethodHandle == method.MethodHandle) {
229 return mapping.InterfaceMethods[i];
239 /// Non-public types can have public members that we find when calling type.GetMember(...). This
240 /// filters out the non-visible members by attempting to resolve them to the correct visible type.
242 /// If no correct visible type can be found then the member is not visible and we won't call it.
244 public static IEnumerable<MemberInfo> FilterNonVisibleMembers(Type targetType, IEnumerable<MemberInfo> members) {
245 if (targetType.IsVisible()) {
248 return FilterNonVisibleMembersIterator(targetType, members);
252 public static IEnumerable<MemberInfo> FilterNonVisibleMembersIterator(Type targetType, IEnumerable<MemberInfo> members) {
253 foreach (var member in members) {
254 MemberInfo visible = TryGetVisibleMember(targetType, member);
255 if (visible != null) {
256 yield return visible;
261 public static MemberInfo TryGetVisibleMember(Type targetType, MemberInfo member) {
263 PropertyInfo property;
267 MemberInfo visible = null;
269 if ((method = member as MethodInfo) != null) {
270 mi = TryGetCallableMethod(targetType, method);
271 if (CompilerHelpers.IsVisible(mi)) {
274 } else if ((property = member as PropertyInfo) != null) {
275 mi = TryGetCallableMethod(targetType, property.GetGetMethod() ?? property.GetSetMethod());
276 if (CompilerHelpers.IsVisible(mi)) {
277 visible = mi.DeclaringType.GetDeclaredProperty(property.Name);
279 } else if ((evnt = member as EventInfo) != null) {
280 mi = TryGetCallableMethod(targetType, evnt.GetAddMethod() ?? evnt.GetRemoveMethod() ?? evnt.GetRaiseMethod());
281 if (CompilerHelpers.IsVisible(mi)) {
282 visible = mi.DeclaringType.GetDeclaredEvent(evnt.Name);
286 // all others can't be exposed out this way
292 /// Sees if two MemberInfos point to the same underlying construct in IL. This
293 /// ignores the ReflectedType property which exists on MemberInfos which
294 /// causes direct comparisons to be false even if they are the same member.
296 public static bool MemberEquals(this MemberInfo self, MemberInfo other) {
297 if ((self == null) != (other == null)) {
298 // one null, the other isn't.
300 } else if (self == null) {
305 if (self.MemberType != other.MemberType) {
309 switch (self.MemberType) {
310 case MemberTypes.Field:
311 return ((FieldInfo)self).FieldHandle.Equals(((FieldInfo)other).FieldHandle);
312 case MemberTypes.Method:
313 return ((MethodInfo)self).MethodHandle.Equals(((MethodInfo)other).MethodHandle);
314 case MemberTypes.Constructor:
315 return ((ConstructorInfo)self).MethodHandle.Equals(((ConstructorInfo)other).MethodHandle);
316 case MemberTypes.NestedType:
317 case MemberTypes.TypeInfo:
318 return ((Type)self).TypeHandle.Equals(((Type)other).TypeHandle);
319 case MemberTypes.Event:
320 case MemberTypes.Property:
323 ((MemberInfo)self).Module == ((MemberInfo)other).Module &&
324 ((MemberInfo)self).MetadataToken == ((MemberInfo)other).MetadataToken;
329 public static bool IsVisible(MethodBase info) {
330 return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
333 public static bool IsVisible(FieldInfo info) {
334 return info.IsPublic && (info.DeclaringType == null || info.DeclaringType.IsVisible());
337 public static bool IsProtected(this MethodBase info) {
338 return info.IsFamily || info.IsFamilyOrAssembly;
341 public static bool IsProtected(this FieldInfo info) {
342 return info.IsFamily || info.IsFamilyOrAssembly;
345 public static bool IsProtected(this Type type) {
346 return type.GetTypeInfo().IsNestedFamily || type.GetTypeInfo().IsNestedFamORAssem;
349 public static Type GetVisibleType(object value) {
350 return GetVisibleType(GetType(value));
353 public static Type GetVisibleType(Type t) {
354 while (!t.IsVisible()) {
360 public static MethodBase[] GetConstructors(Type t, bool privateBinding) {
361 return GetConstructors(t, privateBinding, false);
364 public static MethodBase[] GetConstructors(Type t, bool privateBinding, bool includeProtected) {
366 // The JIT verifier doesn't like new int[](3) even though it appears as a ctor.
367 // We could do better and return newarr in the future.
368 return new MethodBase[] { GetArrayCtor(t) };
371 BindingFlags bf = BindingFlags.Instance | BindingFlags.Public;
372 if (privateBinding || includeProtected) {
373 bf |= BindingFlags.NonPublic;
376 IEnumerable<ConstructorInfo> ctors = t.GetDeclaredConstructors().WithBindingFlags(bf);
378 // leave in protected ctors, even if we're not in private binding mode.
379 if (!privateBinding && includeProtected) {
380 ctors = FilterConstructorsToPublicAndProtected(ctors);
384 #if !SILVERLIGHT && !WIN8 && !WP75
385 && t != typeof(ArgIterator)
388 // structs don't define a parameterless ctor, add a generic method for that.
389 List<MethodBase> result = new List<MethodBase>();
390 result.Add(GetStructDefaultCtor(t));
391 result.AddRange(ctors.Cast<ConstructorInfo, MethodBase>());
392 return result.ToArray();
394 return ctors.ToArray();
398 public static IEnumerable<ConstructorInfo> FilterConstructorsToPublicAndProtected(IEnumerable<ConstructorInfo> ctors) {
399 foreach (var ctor in ctors) {
400 if (ctor.IsPublic || ctor.IsProtected()) {
406 private static MethodBase GetStructDefaultCtor(Type t) {
407 return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateInstance").Single().MakeGenericMethod(t);
410 private static MethodBase GetArrayCtor(Type t) {
411 return typeof(ScriptingRuntimeHelpers).GetDeclaredMethods("CreateArray").Single().MakeGenericMethod(t.GetElementType());
414 #region Type Conversions
416 public static MethodInfo GetImplicitConverter(Type fromType, Type toType) {
417 return GetConverter(fromType, fromType, toType, "op_Implicit") ?? GetConverter(toType, fromType, toType, "op_Implicit");
420 public static MethodInfo GetExplicitConverter(Type fromType, Type toType) {
421 return GetConverter(fromType, fromType, toType, "op_Explicit") ?? GetConverter(toType, fromType, toType, "op_Explicit");
424 private static MethodInfo GetConverter(Type type, Type fromType, Type toType, string opMethodName) {
425 foreach (MethodInfo mi in type.GetInheritedMembers(opMethodName).WithBindingFlags(BindingFlags.Public | BindingFlags.Static)) {
426 if ((mi.DeclaringType == null || mi.DeclaringType.IsVisible()) && mi.IsPublic &&
427 mi.ReturnType == toType && mi.GetParameters()[0].ParameterType.IsAssignableFrom(fromType)) {
434 public static bool TryImplicitConversion(Object value, Type to, out object result) {
435 if (CompilerHelpers.TryImplicitConvert(value, to, to.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
439 Type curType = CompilerHelpers.GetType(value);
441 if (CompilerHelpers.TryImplicitConvert(value, to, curType.GetInheritedMethods("op_Implicit").WithBindingFlags(BindingFlags.Public | BindingFlags.Static), out result)) {
444 curType = curType.GetBaseType();
445 } while (curType != null);
450 private static bool TryImplicitConvert(Object value, Type to, IEnumerable<MethodInfo> implicitConv, out object result) {
451 foreach (MethodInfo mi in implicitConv) {
452 if (to.IsValueType() == mi.ReturnType.IsValueType() && to.IsAssignableFrom(mi.ReturnType)) {
454 result = mi.Invoke(null, new object[] { value });
456 result = mi.Invoke(value, ArrayUtils.EmptyObjects);
466 public static bool IsStrongBox(object target) {
467 Type t = CompilerHelpers.GetType(target);
469 return IsStrongBox(t);
472 public static bool IsStrongBox(Type t) {
473 return t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(StrongBox<>);
477 /// Returns a value which indicates failure when a OldConvertToAction of ImplicitTry or
480 public static Expression GetTryConvertReturnValue(Type type) {
482 var info = type.GetTypeInfo();
483 if (info.IsInterface || info.IsClass || (info.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))) {
484 res = AstUtils.Constant(null, type);
486 res = AstUtils.Constant(Activator.CreateInstance(type));
492 public static bool HasTypeConverter(Type fromType, Type toType) {
493 #if FEATURE_TYPECONVERTER
495 return TryGetTypeConverter(fromType, toType, out _);
501 public static bool TryApplyTypeConverter(object value, Type toType, out object result) {
502 #if FEATURE_TYPECONVERTER
503 TypeConverter converter;
504 if (value != null && CompilerHelpers.TryGetTypeConverter(value.GetType(), toType, out converter)) {
505 result = converter.ConvertFrom(value);
517 #if FEATURE_TYPECONVERTER
518 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
519 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
520 public static bool TryGetTypeConverter(Type fromType, Type toType, out TypeConverter converter) {
521 ContractUtils.RequiresNotNull(fromType, "fromType");
522 ContractUtils.RequiresNotNull(toType, "toType");
524 // try available type conversions...
525 foreach (TypeConverterAttribute tca in toType.GetCustomAttributes(typeof(TypeConverterAttribute), true)) {
527 converter = Activator.CreateInstance(Type.GetType(tca.ConverterTypeName)) as TypeConverter;
528 } catch (Exception) {
532 if (converter != null && converter.CanConvertFrom(fromType)) {
544 #if !MONO_INTERPRETER
545 public static MethodBase[] GetMethodTargets(object obj) {
546 Type t = CompilerHelpers.GetType(obj);
548 if (typeof(Delegate).IsAssignableFrom(t)) {
549 MethodInfo mi = t.GetMethod("Invoke");
550 return new MethodBase[] { mi };
551 } else if (typeof(BoundMemberTracker).IsAssignableFrom(t)) {
552 BoundMemberTracker bmt = obj as BoundMemberTracker;
553 if (bmt.BoundTo.MemberType == TrackerTypes.Method) {
555 } else if (typeof(MethodGroup).IsAssignableFrom(t)) {
556 } else if (typeof(MemberGroup).IsAssignableFrom(t)) {
558 return MakeCallSignatureForCallableObject(t);
565 private static MethodBase[] MakeCallSignatureForCallableObject(Type t) {
566 List<MethodBase> res = new List<MethodBase>();
567 foreach (MethodInfo method in t.GetInheritedMethods("Call")) {
568 if (method.IsSpecialName) {
572 return res.ToArray();
575 public static Type[] GetSiteTypes(IList<Expression> arguments, Type returnType) {
576 int count = arguments.Count;
578 Type[] ret = new Type[count + 1];
580 for (int i = 0; i < count; i++) {
581 ret[i] = arguments[i].Type;
584 ret[count] = returnType;
588 public static Type[] GetExpressionTypes(Expression[] expressions) {
589 ContractUtils.RequiresNotNull(expressions, "expressions");
591 Type[] res = new Type[expressions.Length];
592 for (int i = 0; i < res.Length; i++) {
593 ContractUtils.RequiresNotNull(expressions[i], "expressions[i]");
595 res[i] = expressions[i].Type;
601 public static Type MakeCallSiteType(params Type[] types) {
602 return typeof(CallSite<>).MakeGenericType(DelegateHelpers.MakeDelegate(types));
605 public static Type MakeCallSiteDelegateType(Type[] types) {
606 return DelegateHelpers.MakeDelegate(types);
610 /// Creates an interpreted delegate for the lambda.
612 /// <param name="lambda">The lambda to compile.</param>
613 /// <returns>A delegate which can interpret the lambda.</returns>
614 public static Delegate LightCompile(this LambdaExpression lambda) {
615 return new LightCompiler(-1).CompileTop(lambda).CreateDelegate();
619 /// Creates an interpreted delegate for the lambda.
621 /// <param name="lambda">The lambda to compile.</param>
622 /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
623 /// <returns>A delegate which can interpret the lambda.</returns>
624 public static Delegate LightCompile(this LambdaExpression lambda, int compilationThreshold) {
625 return new LightCompiler(compilationThreshold).CompileTop(lambda).CreateDelegate();
629 /// Creates an interpreted delegate for the lambda.
631 /// <typeparam name="T">The lambda's delegate type.</typeparam>
632 /// <param name="lambda">The lambda to compile.</param>
633 /// <returns>A delegate which can interpret the lambda.</returns>
634 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
635 public static T LightCompile<T>(this Expression<T> lambda) {
636 return (T)(object)LightCompile((LambdaExpression)lambda);
640 /// Creates an interpreted delegate for the lambda.
642 /// <param name="lambda">The lambda to compile.</param>
643 /// <param name="compilationThreshold">The number of iterations before the interpreter starts compiling</param>
644 /// <returns>A delegate which can interpret the lambda.</returns>
645 public static T LightCompile<T>(this Expression<T> lambda, int compilationThreshold) {
646 return (T)(object)LightCompile((LambdaExpression)lambda, compilationThreshold);
651 /// Compiles the lambda into a method definition.
653 /// <param name="lambda">the lambda to compile</param>
654 /// <param name="method">A <see cref="MethodBuilder"/> which will be used to hold the lambda's IL.</param>
655 /// <param name="emitDebugSymbols">A parameter that indicates if debugging information should be emitted to a PDB symbol store.</param>
656 public static void CompileToMethod(this LambdaExpression lambda, MethodBuilder method, bool emitDebugSymbols) {
658 if (emitDebugSymbols) {
659 var module = method.Module as ModuleBuilder;
660 ContractUtils.Requires(module != null, "method", "MethodBuilder does not have a valid ModuleBuilder");
661 lambda.CompileToMethod(method, DebugInfoGenerator.CreatePdbGenerator());
667 ((dynamic)lambda).CompileToMethod(method);
669 lambda.CompileToMethod(method);
675 /// Compiles the LambdaExpression.
677 /// If the lambda is compiled with emitDebugSymbols, it will be
678 /// generated into a TypeBuilder. Otherwise, this method is the same as
679 /// calling LambdaExpression.Compile()
681 /// This is a workaround for a CLR limitiation: DynamicMethods cannot
682 /// have debugging information.
684 /// <param name="lambda">the lambda to compile</param>
685 /// <param name="emitDebugSymbols">true to generate a debuggable method, false otherwise</param>
686 /// <returns>the compiled delegate</returns>
687 public static T Compile<T>(this Expression<T> lambda, bool emitDebugSymbols) {
688 #if FEATURE_PDBEMIT && FEATURE_REFEMIT
689 if (emitDebugSymbols) {
690 return CompileToMethod(lambda, DebugInfoGenerator.CreatePdbGenerator(), true);
693 return lambda.Compile();
698 /// Compiles the LambdaExpression, emitting it into a new type, and
699 /// optionally making it debuggable.
701 /// This is a workaround for a CLR limitiation: DynamicMethods cannot
702 /// have debugging information.
704 /// <param name="lambda">the lambda to compile</param>
705 /// <param name="debugInfoGenerator">Debugging information generator used by the compiler to mark sequence points and annotate local variables.</param>
706 /// <param name="emitDebugSymbols">True if debug symbols (PDBs) are emitted by the <paramref name="debugInfoGenerator"/>.</param>
707 /// <returns>the compiled delegate</returns>
708 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")]
709 public static T CompileToMethod<T>(Expression<T> lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
710 return (T)(object)CompileToMethod((LambdaExpression)lambda, debugInfoGenerator, emitDebugSymbols);
713 public static Delegate CompileToMethod(LambdaExpression lambda, DebugInfoGenerator debugInfoGenerator, bool emitDebugSymbols) {
714 string methodName = String.IsNullOrEmpty(lambda.Name) ? GetUniqueMethodName() : lambda.Name;
716 var type = Snippets.Shared.DefineType(methodName, typeof(object), false, emitDebugSymbols).TypeBuilder;
717 var rewriter = new DebuggableCodeRewriter(type);
718 lambda = (LambdaExpression)rewriter.Visit(lambda);
720 //Create a unique method name when the lambda doesn't have a name or the name is empty.
721 var method = type.DefineMethod(methodName, CompilerHelpers.PublicStatic);
723 lambda.CompileToMethod(method, debugInfoGenerator);
724 var finished = type.CreateType();
726 rewriter.InitializeFields(finished);
728 return finished.GetMethod(method.Name).CreateDelegate(lambda.Type);
732 /// Removes all live objects and places them in static fields of a type.
734 private sealed class DebuggableCodeRewriter : DynamicExpressionVisitor {
735 private readonly Dictionary<object, FieldBuilder> _fields = new Dictionary<object, FieldBuilder>(ReferenceEqualityComparer<object>.Instance);
736 private readonly TypeBuilder _type;
737 private readonly HashSet<string> _methodNames = new HashSet<string>();
739 internal DebuggableCodeRewriter(TypeBuilder type) {
743 internal void InitializeFields(Type type) {
744 foreach (var pair in _fields) {
745 type.GetInheritedFields(pair.Value.Name).First().SetValue(null, pair.Key);
749 protected override Expression VisitLambda<T>(Expression<T> node) {
750 if (_methodNames.Contains(node.Name)) {
751 int count = _methodNames.Count;
755 newName = node.Name + "$" + count++;
756 } while (_methodNames.Contains(newName));
758 _methodNames.Add(newName);
759 return Expression.Lambda<T>(
760 base.Visit(node.Body),
766 _methodNames.Add(node.Name);
767 return base.VisitLambda<T>(node);
771 protected override Expression VisitExtension(Expression node) {
772 // LightDynamicExpressions override Visit but we want to really reduce them
773 // because they reduce to DynamicExpressions.
774 LightDynamicExpression lightDyn = node as LightDynamicExpression;
775 if (lightDyn != null) {
776 return Visit(lightDyn.Reduce());
779 return Visit(node.Reduce());
782 protected override Expression VisitConstant(ConstantExpression node) {
783 if (CanEmitConstant(node.Value, node.Type)) {
788 if (!_fields.TryGetValue(node.Value, out field)) {
789 field = _type.DefineField(
790 "$constant" + _fields.Count,
791 GetVisibleType(node.Value.GetType()),
792 FieldAttributes.Public | FieldAttributes.Static
794 _fields.Add(node.Value, field);
797 Expression result = Expression.Field(null, field);
798 if (result.Type != node.Type) {
799 result = Expression.Convert(result, node.Type);
804 protected override Expression VisitDynamic(DynamicExpression node) {
805 return Visit(Reduce(node));
810 public static string GetUniqueMethodName() {
811 return "lambda_method" + "$" + System.Threading.Interlocked.Increment(ref _Counter);
815 // Matches ILGen.TryEmitConstant
816 public static bool CanEmitConstant(object value, Type type) {
817 if (value == null || CanEmitILConstant(type)) {
821 Type t = value as Type;
822 if (t != null && ILGen.ShouldLdtoken(t)) {
826 MethodBase mb = value as MethodBase;
827 if (mb != null && ILGen.ShouldLdtoken(mb)) {
834 // Matches ILGen.TryEmitILConstant
835 internal static bool CanEmitILConstant(Type type) {
836 switch (type.GetTypeCode()) {
837 case TypeCode.Boolean:
842 case TypeCode.Single:
843 case TypeCode.Double:
846 case TypeCode.UInt16:
847 case TypeCode.UInt32:
848 case TypeCode.UInt64:
849 case TypeCode.Decimal:
850 case TypeCode.String:
858 /// Reduces the provided DynamicExpression into site.Target(site, *args).
860 public static Expression Reduce(DynamicExpression node) {
861 // Store the callsite as a constant
862 var siteConstant = AstUtils.Constant(CallSite.Create(node.DelegateType, node.Binder));
864 // ($site = siteExpr).Target.Invoke($site, *args)
865 var site = Expression.Variable(siteConstant.Type, "$site");
866 return Expression.Block(
870 Expression.Assign(site, siteConstant),
871 siteConstant.Type.GetDeclaredField("Target")
873 node.DelegateType.GetMethod("Invoke"),
874 ArrayUtils.Insert(site, node.Arguments)
880 #if !FEATURE_NUMERICS
881 [CLSCompliant(false)]
882 public static BigInteger CreateBigInteger(int sign, uint[] data) {
883 return new BigInteger(sign, data);
886 public static BigInteger CreateBigInteger(bool isNegative, byte[] data) {
887 return new BigInteger(CreateBigInt(isNegative, data));
890 public static BigInt CreateBigInt(int value) {
891 return (BigInt)value;
894 public static BigInt CreateBigInt(long value) {
895 return (BigInt)value;
898 public static BigInt CreateBigInt(bool isNegative, byte[] data) {
899 BigInt res = new BigInt(data);
900 return isNegative ? -res : res;