private MethodInfo[] GetApplicableMembers(OperatorInfo info) { return(GetApplicableMembers(CompilerHelpers.GetType(_args[0]), info)); }
internal DynamicMetaObject FallbackConvert(Type returnType, DynamicMetaObject self, DynamicMetaObject errorSuggestion) { Type type = Type; DynamicMetaObject res = null; switch (type.GetTypeCode()) { case TypeCode.Boolean: res = MakeToBoolConversion(self); break; case TypeCode.Char: res = TryToCharConversion(self); break; case TypeCode.String: var limitType = self.GetLimitType(); if ((limitType == typeof(Bytes) || limitType == typeof(PythonBuffer) || limitType == typeof(ByteArray)) && !_context.PythonOptions.Python30) { res = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeString)), AstUtils.Convert(self.Expression, typeof(IList <byte>)) ), BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, limitType) ); } break; case TypeCode.Object: // !!! Deferral? if (type.IsArray && self.Value is PythonTuple && type.GetArrayRank() == 1) { res = MakeToArrayConversion(self, type); } else if (type.IsGenericType && !type.IsAssignableFrom(CompilerHelpers.GetType(self.Value))) { Type genTo = type.GetGenericTypeDefinition(); // Interface conversion helpers... if (genTo == typeof(IList <>)) { if (self.LimitType == typeof(string)) { res = new DynamicMetaObject( Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.MakeByteArray)), AstUtils.Convert(self.Expression, typeof(string)) ), BindingRestrictions.GetTypeRestriction( self.Expression, typeof(string) ) ); } else { res = TryToGenericInterfaceConversion(self, type, typeof(IList <object>), typeof(ListGenericWrapper <>)); } } else if (genTo == typeof(IDictionary <,>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IDictionary <object, object>), typeof(DictionaryGenericWrapper <,>)); } else if (genTo == typeof(IEnumerable <>)) { res = TryToGenericInterfaceConversion(self, type, typeof(IEnumerable), typeof(IEnumerableOfTWrapper <>)); } } else if (type == typeof(IEnumerable)) { if (!typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) { res = ConvertToIEnumerable(this, self.Restrict(self.GetLimitType())); } } else if (type == typeof(IEnumerator)) { if (!typeof(IEnumerator).IsAssignableFrom(self.GetLimitType()) && !typeof(IEnumerable).IsAssignableFrom(self.GetLimitType())) { res = ConvertToIEnumerator(this, self.Restrict(self.GetLimitType())); } } break; } if (type.IsEnum() && Enum.GetUnderlyingType(type) == self.GetLimitType()) { // numeric type to enum, this is ok if the value is zero object value = Activator.CreateInstance(type); return(new DynamicMetaObject( Ast.Condition( Ast.Equal( AstUtils.Convert(self.Expression, Enum.GetUnderlyingType(type)), AstUtils.Constant(Activator.CreateInstance(self.GetLimitType())) ), AstUtils.Constant(value), Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.TypeErrorForBadEnumConversion)).MakeGenericMethod(type), AstUtils.Convert(self.Expression, typeof(object)) ) ), self.Restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(self.Expression, self.GetLimitType())), value )); } return(res ?? EnsureReturnType(returnType, Context.Binder.ConvertTo(Type, ResultKind, self, _context.SharedOverloadResolverFactory, errorSuggestion))); }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters")] // TODO: fix public static Exception CannotConvertError(Type toType, object value) { return(SimpleTypeError(String.Format("Cannot convert {0}({1}) to {2}", CompilerHelpers.GetType(value).Name, value, toType.Name))); }
private DynamicMetaObject /*!*/ GetInstance(Expression /*!*/ instance, Type /*!*/ testType) { Assert.NotNull(instance, testType); object instanceValue = Value.BindingSelf; BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(instance, testType); // cast the instance to the correct type if (CompilerHelpers.IsStrongBox(instanceValue)) { instance = ReadStrongBoxValue(instance); instanceValue = ((IStrongBox)instanceValue).Value; } else if (!testType.IsEnum()) { // We need to deal w/ wierd types like MarshalByRefObject. // We could have an MBRO whos DeclaringType is completely different. // Therefore we special case it here and cast to the declaring type Type selfType = CompilerHelpers.GetType(Value.BindingSelf); selfType = CompilerHelpers.GetVisibleType(selfType); if (selfType == typeof(object) && Value.DeclaringType.IsInterface()) { selfType = Value.DeclaringType; Type genericTypeDefinition = null; // the behavior is different on Mono, it sets FullName for the DeclaringType if (Value.DeclaringType.IsGenericType() && (ClrModule.IsMono || Value.DeclaringType.FullName == null) && Value.DeclaringType.ContainsGenericParameters() && !Value.DeclaringType.IsGenericTypeDefinition()) { // from MSDN: If the current type contains generic type parameters that have not been replaced by // specific types (that is, the ContainsGenericParameters property returns true), but the type // is not a generic type definition (that is, the IsGenericTypeDefinition property returns false), // this property returns Nothing. For example, consider the classes Base and Derived in the following code. // if this type is completely generic (no type arguments specified) then we'll go ahead and get the // generic type definition for the this parameter - that'll let us successfully type infer on it later. var genericArgs = Value.DeclaringType.GetGenericArguments(); bool hasOnlyGenerics = genericArgs.Length > 0; foreach (var genericParam in genericArgs) { if (!genericParam.IsGenericParameter) { hasOnlyGenerics = false; break; } } if (hasOnlyGenerics) { genericTypeDefinition = Value.DeclaringType.GetGenericTypeDefinition(); } } else if (Value.DeclaringType.IsGenericTypeDefinition()) { genericTypeDefinition = Value.DeclaringType; } if (genericTypeDefinition != null) { // we're a generic interface method on a non-public type. // We need to see if we can match any types implemented on // the concrete selfType. var interfaces = CompilerHelpers.GetType(Value.BindingSelf).GetInterfaces(); foreach (var iface in interfaces) { if (iface.IsGenericType() && iface.GetGenericTypeDefinition() == genericTypeDefinition) { selfType = iface; break; } } } } if (Value.DeclaringType.IsInterface() && selfType.IsValueType()) { // explicit interface implementation dispatch on a value type, don't // unbox the value type before the dispatch. instance = AstUtils.Convert(instance, Value.DeclaringType); } else if (selfType.IsValueType()) { // We might be calling a a mutating method (like // Rectangle.Intersect). If so, we want it to mutate // the boxed value directly instance = Ast.Unbox(instance, selfType); } else { #if FEATURE_REMOTING Type convType = selfType == typeof(MarshalByRefObject) ? CompilerHelpers.GetVisibleType(Value.DeclaringType) : selfType; instance = AstUtils.Convert(instance, convType); #else instance = AstUtils.Convert(instance, selfType); #endif } } else { // we don't want to cast the enum to its real type, it will unbox it // and turn it into its underlying type. We presumably want to call // a method on the Enum class though - so we cast to Enum instead. instance = AstUtils.Convert(instance, typeof(Enum)); } return(new DynamicMetaObject( instance, restrictions, instanceValue )); }
public override T BindDelegate <T>(CallSite <T> site, object[] args) { switch (_operation) { case PythonOperationKind.Hash: if (CompilerHelpers.GetType(args[0]) == typeof(PythonType)) { if (typeof(T) == typeof(Func <CallSite, object, int>)) { return((T)(object)new Func <CallSite, object, int>(HashPythonType)); } } else if (args[0] is OldClass) { if (typeof(T) == typeof(Func <CallSite, object, int>)) { return((T)(object)new Func <CallSite, object, int>(HashOldClass)); } } break; case PythonOperationKind.Compare: if (CompilerHelpers.GetType(args[0]) == typeof(string) && CompilerHelpers.GetType(args[1]) == typeof(string)) { if (typeof(T) == typeof(Func <CallSite, object, object, int>)) { return((T)(object)new Func <CallSite, object, object, int>(CompareStrings)); } } break; case PythonOperationKind.GetEnumeratorForIteration: if (CompilerHelpers.GetType(args[0]) == typeof(List)) { if (typeof(T) == typeof(Func <CallSite, List, KeyValuePair <IEnumerator, IDisposable> >)) { return((T)(object)new Func <CallSite, List, KeyValuePair <IEnumerator, IDisposable> >(GetListEnumerator)); } return((T)(object)new Func <CallSite, object, KeyValuePair <IEnumerator, IDisposable> >(GetListEnumerator)); } else if (CompilerHelpers.GetType(args[0]) == typeof(PythonTuple)) { if (typeof(T) == typeof(Func <CallSite, PythonTuple, KeyValuePair <IEnumerator, IDisposable> >)) { return((T)(object)new Func <CallSite, PythonTuple, KeyValuePair <IEnumerator, IDisposable> >(GetTupleEnumerator)); } return((T)(object)new Func <CallSite, object, KeyValuePair <IEnumerator, IDisposable> >(GetTupleEnumerator)); } break; case PythonOperationKind.Contains: if (CompilerHelpers.GetType(args[1]) == typeof(List)) { Type tType = typeof(T); if (tType == typeof(Func <CallSite, object, object, bool>)) { return((T)(object)new Func <CallSite, object, object, bool>(ListContains <object>)); } else if (tType == typeof(Func <CallSite, object, List, bool>)) { return((T)(object)new Func <CallSite, object, List, bool>(ListContains)); } else if (tType == typeof(Func <CallSite, int, object, bool>)) { return((T)(object)new Func <CallSite, int, object, bool>(ListContains <int>)); } else if (tType == typeof(Func <CallSite, string, object, bool>)) { return((T)(object)new Func <CallSite, string, object, bool>(ListContains <string>)); } else if (tType == typeof(Func <CallSite, double, object, bool>)) { return((T)(object)new Func <CallSite, double, object, bool>(ListContains <double>)); } else if (tType == typeof(Func <CallSite, PythonTuple, object, bool>)) { return((T)(object)new Func <CallSite, PythonTuple, object, bool>(ListContains <PythonTuple>)); } } else if (CompilerHelpers.GetType(args[1]) == typeof(PythonTuple)) { Type tType = typeof(T); if (tType == typeof(Func <CallSite, object, object, bool>)) { return((T)(object)new Func <CallSite, object, object, bool>(TupleContains <object>)); } else if (tType == typeof(Func <CallSite, object, PythonTuple, bool>)) { return((T)(object)new Func <CallSite, object, PythonTuple, bool>(TupleContains)); } else if (tType == typeof(Func <CallSite, int, object, bool>)) { return((T)(object)new Func <CallSite, int, object, bool>(TupleContains <int>)); } else if (tType == typeof(Func <CallSite, string, object, bool>)) { return((T)(object)new Func <CallSite, string, object, bool>(TupleContains <string>)); } else if (tType == typeof(Func <CallSite, double, object, bool>)) { return((T)(object)new Func <CallSite, double, object, bool>(TupleContains <double>)); } else if (tType == typeof(Func <CallSite, PythonTuple, object, bool>)) { return((T)(object)new Func <CallSite, PythonTuple, object, bool>(TupleContains <PythonTuple>)); } } else if (CompilerHelpers.GetType(args[0]) == typeof(string) && CompilerHelpers.GetType(args[1]) == typeof(string)) { Type tType = typeof(T); if (tType == typeof(Func <CallSite, object, object, bool>)) { return((T)(object)new Func <CallSite, object, object, bool>(StringContains)); } else if (tType == typeof(Func <CallSite, string, object, bool>)) { return((T)(object)new Func <CallSite, string, object, bool>(StringContains)); } else if (tType == typeof(Func <CallSite, object, string, bool>)) { return((T)(object)new Func <CallSite, object, string, bool>(StringContains)); } else if (tType == typeof(Func <CallSite, string, string, bool>)) { return((T)(object)new Func <CallSite, string, string, bool>(StringContains)); } } else if (CompilerHelpers.GetType(args[1]) == typeof(SetCollection)) { if (typeof(T) == typeof(Func <CallSite, object, object, bool>)) { return((T)(object)new Func <CallSite, object, object, bool>(SetContains)); } } break; } return(base.BindDelegate <T>(site, args)); }
private Func <CallSite, TSelfType, CodeContext, object> MakeGetMemberTarget <TSelfType>(string name, object target, CodeContext context) { Type type = CompilerHelpers.GetType(target); // needed for GetMember call until DynamicAction goes away if (typeof(TypeTracker).IsAssignableFrom(type)) { // no fast path for TypeTrackers PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast TypeTracker"); return(null); } MemberGroup members = Context.Binder.GetMember(MemberRequestKind.Get, type, name); if (members.Count == 0 && type.IsInterface()) { // all interfaces have object members type = typeof(object); members = Context.Binder.GetMember(MemberRequestKind.Get, type, name); } if (members.Count == 0 && typeof(IStrongBox).IsAssignableFrom(type)) { // no fast path for strong box access PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast StrongBox"); return(null); } MethodInfo getMem = Context.Binder.GetMethod(type, "GetCustomMember"); if (getMem != null && getMem.IsSpecialName) { // no fast path for custom member access PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetCustomMember " + type); return(null); } Expression error; TrackerTypes memberType = Context.Binder.GetMemberType(members, out error); if (error == null) { PythonType argType = DynamicHelpers.GetPythonTypeFromType(type); bool isHidden = argType.IsHiddenMember(name); if (isHidden) { PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast FilteredMember " + memberType); return(null); } switch (memberType) { case TrackerTypes.TypeGroup: case TrackerTypes.Type: object typeObj; if (members.Count == 1) { typeObj = DynamicHelpers.GetPythonTypeFromType(((TypeTracker)members[0]).Type); } else { TypeTracker typeTracker = (TypeTracker)members[0]; for (int i = 1; i < members.Count; i++) { typeTracker = TypeGroup.UpdateTypeEntity(typeTracker, (TypeTracker)members[i]); } typeObj = typeTracker; } return(new FastTypeGet <TSelfType>(type, typeObj).GetTypeObject); case TrackerTypes.Method: PythonTypeSlot slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding); if (slot is BuiltinMethodDescriptor) { return(new FastMethodGet <TSelfType>(type, (BuiltinMethodDescriptor)slot).GetMethod); } else if (slot is BuiltinFunction) { return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetRetSlot); } return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(type)).GetBindSlot); case TrackerTypes.Event: if (members.Count == 1 && !((EventTracker)members[0]).IsStatic) { slot = PythonTypeOps.GetSlot(members, name, _context.DomainManager.Configuration.PrivateBinding); return(new FastSlotGet <TSelfType>(type, slot, DynamicHelpers.GetPythonTypeFromType(((EventTracker)members[0]).DeclaringType)).GetBindSlot); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Event " + members.Count + " " + ((EventTracker)members[0]).IsStatic); return(null); case TrackerTypes.Property: if (members.Count == 1) { PropertyTracker pt = (PropertyTracker)members[0]; if (!pt.IsStatic && pt.GetIndexParameters().Length == 0) { MethodInfo prop = pt.GetGetMethod(); ParameterInfo[] parameters; if (prop != null && (parameters = prop.GetParameters()).Length == 0) { if (prop.ReturnType == typeof(bool)) { return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyBool); } else if (prop.ReturnType == typeof(int)) { return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetPropertyInt); } else { return(new FastPropertyGet <TSelfType>(type, CallInstruction.Create(prop, parameters).Invoke).GetProperty); } } } } PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast Property " + members.Count + " " + ((PropertyTracker)members[0]).IsStatic); return(null); case TrackerTypes.All: getMem = Context.Binder.GetMethod(type, "GetBoundMember"); if (getMem != null && getMem.IsSpecialName) { PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast GetBoundMember " + type); return(null); } if (members.Count == 0) { // we don't yet support fast bindings to extension methods members = context.ModuleContext.ExtensionMethods.GetBinder(_context).GetMember(MemberRequestKind.Get, type, name); if (members.Count == 0) { if (IsNoThrow) { return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorNoThrow); } else if (SupportsLightThrow) { return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetErrorLightThrow); } else { return(new FastErrorGet <TSelfType>(type, name, context.ModuleContext.ExtensionMethods).GetError); } } } return(null); default: PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast " + memberType); return(null); } } else { StringBuilder sb = new StringBuilder(); foreach (MemberTracker mi in members) { if (sb.Length != 0) { sb.Append(", "); } sb.Append(mi.MemberType); sb.Append(" : "); sb.Append(mi.ToString()); } return(new FastErrorGet <TSelfType>(type, sb.ToString(), context.ModuleContext.ExtensionMethods).GetAmbiguous); } }
public override Expression /*!*/ Convert(DynamicMetaObject /*!*/ metaObject, Type restrictedType, ParameterInfo info, Type /*!*/ toType) { Expression expr = metaObject.Expression; Type fromType = restrictedType ?? expr.Type; // block: if (fromType == typeof(MissingBlockParam)) { Debug.Assert(toType == typeof(BlockParam) || toType == typeof(MissingBlockParam)); return(AstUtils.Constant(null)); } if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) { return(AstUtils.Constant(null)); } // protocol conversions: if (info != null && info.IsDefined(typeof(DefaultProtocolAttribute), false)) { var action = RubyConversionAction.TryGetDefaultConversionAction(Context, toType); if (action != null) { // TODO: inline implicit conversions: return(AstUtils.LightDynamic(action, toType, expr)); } // Do not throw an exception here to allow generic type parameters to be used with D.P. attribute. // The semantics should be to use DP if available for the current instantiation and ignore it otherwise. } if (restrictedType != null) { if (restrictedType == typeof(DynamicNull)) { if (!toType.IsValueType || toType.IsGenericType && toType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(AstUtils.Constant(null, toType)); } else if (toType == typeof(bool)) { return(AstUtils.Constant(false)); } } if (toType.IsAssignableFrom(restrictedType)) { // expr can be converted to restrictedType, which can be converted toType => we can convert expr to toType: return(AstUtils.Convert(expr, CompilerHelpers.GetVisibleType(toType))); } // if there is a simple conversion from restricted type, convert the expression to the restricted type and use that conversion: Type visibleRestrictedType = CompilerHelpers.GetVisibleType(restrictedType); if (Converter.CanConvertFrom(metaObject, visibleRestrictedType, toType, false, NarrowingLevel.None, false, false).IsConvertible) { expr = AstUtils.Convert(expr, visibleRestrictedType); } } return(Converter.ConvertExpression(expr, toType, _args.RubyContext, _args.MetaContext.Expression, _implicitProtocolConversions)); }
public override T BindDelegate <T>(CallSite <T> site, object[] args) { switch (Operation) { case ExpressionType.Negate: if (CompilerHelpers.GetType(args[0]) == typeof(int)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(IntNegate)); } } break; case ExpressionType.IsFalse: if (args[0] == null) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(NoneIsFalse)); } } else if (args[0].GetType() == typeof(string)) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(StringIsFalse)); } } else if (args[0].GetType() == typeof(bool)) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(BoolIsFalse)); } } else if (args[0].GetType() == typeof(List)) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(ListIsFalse)); } } else if (args[0].GetType() == typeof(PythonTuple)) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(TupleIsFalse)); } } else if (args[0].GetType() == typeof(int)) { if (typeof(T) == typeof(Func <CallSite, object, bool>)) { return((T)(object)new Func <CallSite, object, bool>(IntIsFalse)); } } break; case ExpressionType.Not: if (args[0] == null) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(NoneNot)); } } else if (args[0].GetType() == typeof(string)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(StringNot)); } } else if (args[0].GetType() == typeof(bool)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(BoolNot)); } } else if (args[0].GetType() == typeof(List)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(ListNot)); } } else if (args[0].GetType() == typeof(PythonTuple)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(TupleNot)); } } else if (args[0].GetType() == typeof(int)) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { return((T)(object)new Func <CallSite, object, object>(IntNot)); } } break; } return(base.BindDelegate(site, args)); }
private void MakeReverseDelegateWorker(CodeContext context) { Type[] sigTypes; Type[] callSiteType; Type retType; GetSignatureInfo(out sigTypes, out callSiteType, out retType); DynamicMethod dm = new DynamicMethod("ReverseInteropInvoker", retType, ArrayUtils.RemoveLast(sigTypes), DynamicModule); ILGenerator ilGen = dm.GetILGenerator(); PythonContext pc = context.LanguageContext; Type callDelegateSiteType = CompilerHelpers.MakeCallSiteDelegateType(callSiteType); CallSite site = CallSite.Create(callDelegateSiteType, pc.Invoke(new CallSignature(_argtypes.Length))); List <object> constantPool = new List <object>(); constantPool.Add(null); // 1st item is the target object, will be put in later. constantPool.Add(site); ilGen.BeginExceptionBlock(); //CallSite<Func<CallSite, object, object>> mySite; //mySite.Target(mySite, target, ...); LocalBuilder siteLocal = ilGen.DeclareLocal(site.GetType()); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, constantPool.Count - 1); ilGen.Emit(OpCodes.Ldelem_Ref); ilGen.Emit(OpCodes.Castclass, site.GetType()); ilGen.Emit(OpCodes.Stloc, siteLocal); ilGen.Emit(OpCodes.Ldloc, siteLocal); ilGen.Emit(OpCodes.Ldfld, site.GetType().GetField("Target")); ilGen.Emit(OpCodes.Ldloc, siteLocal); // load code context int contextIndex = constantPool.Count; Debug.Assert(pc.SharedContext != null); constantPool.Add(pc.SharedContext); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, contextIndex); ilGen.Emit(OpCodes.Ldelem_Ref); // load function target, in constant pool slot 0 ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4_0); ilGen.Emit(OpCodes.Ldelem_Ref); // load arguments for (int i = 0; i < _argtypes.Length; i++) { INativeType nativeType = _argtypes[i]; nativeType.EmitReverseMarshalling(ilGen, new Arg(i + 1, sigTypes[i + 1]), constantPool, 0); } ilGen.Emit(OpCodes.Call, callDelegateSiteType.GetMethod("Invoke")); LocalBuilder finalRes = null; // emit forward marshaling for return value if (_restype != null) { LocalBuilder tmpRes = ilGen.DeclareLocal(typeof(object)); ilGen.Emit(OpCodes.Stloc, tmpRes); finalRes = ilGen.DeclareLocal(retType); ((INativeType)_restype).EmitMarshalling(ilGen, new Local(tmpRes), constantPool, 0); ilGen.Emit(OpCodes.Stloc, finalRes); } else { ilGen.Emit(OpCodes.Pop); } // } catch(Exception e) { // emit the cleanup code ilGen.BeginCatchBlock(typeof(Exception)); ilGen.Emit(OpCodes.Ldarg_0); ilGen.Emit(OpCodes.Ldc_I4, contextIndex); ilGen.Emit(OpCodes.Ldelem_Ref); ilGen.Emit(OpCodes.Call, typeof(ModuleOps).GetMethod(nameof(ModuleOps.CallbackException))); ilGen.EndExceptionBlock(); if (_restype != null) { ilGen.Emit(OpCodes.Ldloc, finalRes); } ilGen.Emit(OpCodes.Ret); _reverseDelegateConstants = constantPool; _reverseDelegateType = GetReverseDelegateType(ArrayUtils.RemoveFirst(sigTypes), CallingConvention); _reverseDelegate = dm; }
/// <summary> /// Gets the extension members of the given name from the provided type. Subclasses of the /// type and their extension members are not searched. /// </summary> public MemberGroup GetExtensionMembers(Type declaringType, string name) { IList <Type> extTypes = GetExtensionTypes(declaringType); List <MemberTracker> members = new List <MemberTracker>(); foreach (Type ext in extTypes) { foreach (MemberInfo mi in ext.GetMember(name, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) { MemberInfo newMember = mi; if (PrivateBinding || (newMember = CompilerHelpers.TryGetVisibleMember(mi)) != null) { if (IncludeExtensionMember(newMember)) { if (ext != declaringType) { members.Add(MemberTracker.FromMemberInfo(newMember, declaringType)); } else { members.Add(MemberTracker.FromMemberInfo(newMember)); } } } } // TODO: Support indexed getters/setters w/ multiple methods MethodInfo getter = null, setter = null, deleter = null; foreach (MemberInfo mi in ext.GetMember("Get" + name, MemberTypes.Method, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { if (!mi.IsDefined(typeof(PropertyMethodAttribute), false)) { continue; } Debug.Assert(getter == null); getter = (MethodInfo)mi; } foreach (MemberInfo mi in ext.GetMember("Set" + name, MemberTypes.Method, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { if (!mi.IsDefined(typeof(PropertyMethodAttribute), false)) { continue; } Debug.Assert(setter == null); setter = (MethodInfo)mi; } foreach (MemberInfo mi in ext.GetMember("Delete" + name, MemberTypes.Method, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { if (!mi.IsDefined(typeof(PropertyMethodAttribute), false)) { continue; } Debug.Assert(deleter == null); deleter = (MethodInfo)mi; } if (getter != null || setter != null || deleter != null) { members.Add(new ExtensionPropertyTracker(name, getter, setter, deleter, declaringType)); } } if (members.Count != 0) { return(MemberGroup.CreateInternal(members.ToArray())); } return(MemberGroup.EmptyGroup); }
internal static Convertibility CanConvertFrom(DynamicMetaObject fromArg, Type /*!*/ fromType, Type /*!*/ toType, bool toNotNullable, NarrowingLevel level, bool explicitProtocolConversions, bool implicitProtocolConversions) { ContractUtils.RequiresNotNull(fromType, "fromType"); ContractUtils.RequiresNotNull(toType, "toType"); var metaConvertible = fromArg as IConvertibleMetaObject; var rubyMetaConvertible = fromArg as IConvertibleRubyMetaObject; // // narrowing level 0: // if (toType == fromType) { return(Convertibility.AlwaysConvertible); } if (fromType == typeof(DynamicNull)) { if (toNotNullable) { return(Convertibility.NotConvertible); } if (toType.IsGenericType() && toType.GetGenericTypeDefinition() == typeof(Nullable <>)) { return(Convertibility.AlwaysConvertible); } if (!toType.IsValueType()) { // null convertible to any reference type: return(Convertibility.AlwaysConvertible); } else if (toType == typeof(bool)) { return(Convertibility.AlwaysConvertible); } else if (!ProtocolConversionAction.HasDefaultConversion(toType)) { // null not convertible to a value type unless a protocol conversion is allowed: return(Convertibility.NotConvertible); } } // blocks: if (fromType == typeof(MissingBlockParam)) { return(new Convertibility(toType == typeof(BlockParam) && !toNotNullable, null)); } if (fromType == typeof(BlockParam) && toType == typeof(MissingBlockParam)) { return(Convertibility.AlwaysConvertible); } if (toType.IsAssignableFrom(fromType)) { return(Convertibility.AlwaysConvertible); } if (HasImplicitNumericConversion(fromType, toType)) { return(Convertibility.AlwaysConvertible); } if (CompilerHelpers.GetImplicitConverter(fromType, toType) != null) { return(Convertibility.AlwaysConvertible); } if (rubyMetaConvertible != null) { return(rubyMetaConvertible.IsConvertibleTo(toType, false)); } else if (metaConvertible != null) { return(new Convertibility(metaConvertible.CanConvertTo(toType, false), null)); } // // narrowing level 1: // if (level < NarrowingLevel.One) { return(Convertibility.NotConvertible); } if (explicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return(Convertibility.AlwaysConvertible); } // // narrowing level 2: // if (level < NarrowingLevel.Two) { return(Convertibility.NotConvertible); } if (HasExplicitNumericConversion(fromType, toType)) { return(Convertibility.AlwaysConvertible); } if (CompilerHelpers.GetExplicitConverter(fromType, toType) != null) { return(Convertibility.AlwaysConvertible); } if (CompilerHelpers.HasTypeConverter(fromType, toType)) { return(Convertibility.AlwaysConvertible); } if (fromType == typeof(char) && toType == typeof(string)) { return(Convertibility.AlwaysConvertible); } if (toType == typeof(bool)) { return(Convertibility.AlwaysConvertible); } if (rubyMetaConvertible != null) { return(rubyMetaConvertible.IsConvertibleTo(toType, true)); } else if (metaConvertible != null) { return(new Convertibility(metaConvertible.CanConvertTo(toType, true), null)); } // // narrowing level 3: // if (level < NarrowingLevel.Three) { return(Convertibility.NotConvertible); } if (implicitProtocolConversions && ProtocolConversionAction.HasDefaultConversion(toType)) { return(Convertibility.AlwaysConvertible); } // A COM object can potentially be converted to the given interface, but might also be not so use this only as the last resort: if (TypeUtils.IsComObjectType(fromType) && toType.IsInterface()) { return(Convertibility.AlwaysConvertible); } return(Convertibility.NotConvertible); }
/// <summary> /// Checks to see if the language allows keyword arguments to be bound to instance fields or /// properties and turned into sets. By default this is only allowed on contructors. /// </summary> protected internal virtual bool AllowKeywordArgumentSetting(MethodBase method) { return(CompilerHelpers.IsConstructor(method)); }
public static AbstractValue Constant(object value, Expression expression) { return(new AbstractValue(value, CompilerHelpers.GetType(value), AbstractKind.Constant, expression)); }
public void MakeRule() { Rule.MakeTest(StrongBoxType ?? CompilerHelpers.GetType(Target)); Rule.Target = MakeDeleteMemberTarget(); }
/// <summary> /// Generates stub to receive the CLR call and then call the dynamic language code. /// This code is similar to that in DelegateSignatureInfo.cs in the Microsoft.Scripting. /// </summary> internal void EmitClrCallStub(ILGen /*!*/ il, MethodInfo /*!*/ mi, string /*!*/ name) { int firstArg = 0; bool list = false; // The list calling convention bool context = false; // Context is an argument ParameterInfo[] pis = mi.GetParameters(); if (pis.Length > 0) { if (pis[0].ParameterType == ContextType) { firstArg = 1; context = true; } if (pis[pis.Length - 1].IsDefined(typeof(ParamArrayAttribute), false)) { list = true; } } ParameterInfo[] args = pis; int nargs = args.Length - firstArg; // Create the action ILGen cctor = GetCCtor(); EmitMakeCallAction(name, nargs, list); // Create the dynamic site Type siteType = CompilerHelpers.MakeCallSiteType(MakeSiteSignature(nargs)); FieldBuilder site = _tb.DefineField("site$" + _site++, siteType, FieldAttributes.Private | FieldAttributes.Static); cctor.EmitCall(siteType.GetMethod("Create")); cctor.EmitFieldSet(site); // // Emit the site invoke // il.EmitFieldGet(site); FieldInfo target = siteType.GetField("Target"); il.EmitFieldGet(target); il.EmitFieldGet(site); // Emit the code context EmitContext(il, context); il.Emit(OpCodes.Ldarg_0); List <ReturnFixer> fixers = new List <ReturnFixer>(0); for (int i = firstArg; i < args.Length; i++) { ReturnFixer rf = ReturnFixer.EmitArgument(il, args[i], i + 1); if (rf != null) { fixers.Add(rf); } } il.EmitCall(target.FieldType, "Invoke"); foreach (ReturnFixer rf in fixers) { rf.FixReturn(il); } }
public static void RunTests() { var param = Expression.Parameter(typeof(Exception), "foo"); var lambdax = Expression.Lambda <Func <object> >( Expression.Block( LightExceptions.RewriteExternal( Expression.TryCatch( Expression.Default(typeof(object)), Expression.Catch(param, Expression.Default(typeof(object))) ) ), LightExceptions.RewriteExternal( Expression.TryCatch( Expression.Default(typeof(object)), Expression.Catch(param, Expression.Default(typeof(object))) ) ) ) ); lambdax.Compile()(); CompilerHelpers.LightCompile(lambdax)(); var builder = new LightExceptionTests(); List <string> record = new List <string>(); List <string> rewriteRecord = new List <string>(); int testCount = 0; try { foreach (var lambda in builder.MakeLambda()) { // run each test in normal and lightweight exception modes, make sure they have the same result try { object res = lambda.Compile()(record); if (res != null) { record.Add(res.ToString()); } } catch (Exception e) { record.Add(String.Format("EXCEPTION {0}", e.GetType())); } try { object res = ((Expression <Func <List <string>, object> >)LightExceptions.Rewrite(lambda)).Compile()(rewriteRecord); Exception e = LightExceptions.GetLightException(res); if (e != null) { rewriteRecord.Add(String.Format("EXCEPTION {0}", e.GetType())); } else if (res != null) { rewriteRecord.Add(res.ToString()); } } catch (Exception e) { rewriteRecord.Add(String.Format("EXCEPTION {0}", e.GetType())); } if (record.Count != rewriteRecord.Count) { PrintLambda(lambda, record, rewriteRecord); throw new Exception("Records differ in length"); } for (int i = 0; i < record.Count; i++) { if (record[i] != rewriteRecord[i]) { PrintLambda(lambda, record, rewriteRecord); throw new Exception("Records differ"); } } record.Clear(); rewriteRecord.Clear(); testCount++; } } finally { Console.Write("Ran {0} tests", testCount); } }
public static Exception MakeIncorrectBoxTypeError(Type type, object received) { return(Error.UnexpectedType("StrongBox<" + type.Name + ">", CompilerHelpers.GetType(received).Name)); }
internal Expression MakeExpression(RestrictedArguments restrictedArgs) { bool[] usageMarkers; Expression[] spilledArgs; Expression[] callArgs = GetArgumentExpressions(restrictedArgs, out usageMarkers, out spilledArgs); Expression call; MethodBase mb = _overload.ReflectionInfo; // TODO: make MakeExpression virtual on OverloadInfo? if (mb == null) { throw new InvalidOperationException("Cannot generate an expression for an overload w/o MethodBase"); } MethodInfo mi = mb as MethodInfo; if (mi != null) { Expression instance; if (mi.IsStatic) { instance = null; } else { Debug.Assert(mi != null); instance = _instanceBuilder.ToExpression(ref mi, _resolver, restrictedArgs, usageMarkers); Debug.Assert(instance != null, "Can't skip instance expression"); } if (CompilerHelpers.IsVisible(mi)) { call = AstUtils.SimpleCallHelper(instance, mi, callArgs); } else { call = Ast.Call( typeof(BinderOps).GetMethod("InvokeMethod"), AstUtils.Constant(mi), instance != null ? AstUtils.Convert(instance, typeof(object)) : AstUtils.Constant(null), AstUtils.NewArrayHelper(typeof(object), callArgs) ); } } else { ConstructorInfo ci = (ConstructorInfo)mb; if (CompilerHelpers.IsVisible(ci)) { call = AstUtils.SimpleNewHelper(ci, callArgs); } else { call = Ast.Call( typeof(BinderOps).GetMethod("InvokeConstructor"), AstUtils.Constant(ci), AstUtils.NewArrayHelper(typeof(object), callArgs) ); } } if (spilledArgs != null) { call = Expression.Block(spilledArgs.AddLast(call)); } Expression ret = _returnBuilder.ToExpression(_resolver, _argBuilders, restrictedArgs, call); List <Expression> updates = null; for (int i = 0; i < _argBuilders.Count; i++) { Expression next = _argBuilders[i].UpdateFromReturn(_resolver, restrictedArgs); if (next != null) { if (updates == null) { updates = new List <Expression>(); } updates.Add(next); } } if (updates != null) { if (ret.Type != typeof(void)) { ParameterExpression temp = Ast.Variable(ret.Type, "$ret"); updates.Insert(0, Ast.Assign(temp, ret)); updates.Add(temp); ret = Ast.Block(new[] { temp }, updates.ToArray()); } else { updates.Insert(0, ret); ret = Ast.Block(typeof(void), updates.ToArray()); } } if (_resolver.Temps != null) { ret = Ast.Block(_resolver.Temps, ret); } return(ret); }
public override T BindDelegate <T>(CallSite <T> site, object[] args) { Debug.Assert(args[1].GetType() == typeof(CodeContext)); IFastGettable fastGet = args[0] as IFastGettable; if (fastGet != null) { T res = fastGet.MakeGetBinding <T>(site, this, (CodeContext)args[1], Name); if (res != null) { PerfTrack.NoteEvent(PerfTrack.Categories.BindingFast, "IFastGettable"); return(res); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "IFastGettable"); return(base.BindDelegate <T>(site, args)); } IPythonObject pyObj = args[0] as IPythonObject; if (pyObj != null && !(args[0] is IProxyObject)) { FastBindResult <T> res = UserTypeOps.MakeGetBinding <T>((CodeContext)args[1], site, pyObj, this); if (res.Target != null) { PerfTrack.NoteEvent(PerfTrack.Categories.BindingFast, "IPythonObject"); if (res.ShouldCache) { CacheTarget(res.Target); } return(res.Target); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "IPythonObject Get"); return(base.BindDelegate <T>(site, args)); } if (args[0] != null) { if (args[0].GetType() == typeof(PythonModule)) { if (SupportsLightThrow) { return((T)(object)new Func <CallSite, object, CodeContext, object>(new PythonModuleDelegate(_name).LightThrowTarget)); } else if (!IsNoThrow) { return((T)(object)new Func <CallSite, object, CodeContext, object>(new PythonModuleDelegate(_name).Target)); } else { return((T)(object)new Func <CallSite, object, CodeContext, object>(new PythonModuleDelegate(_name).NoThrowTarget)); } } else if (args[0].GetType() == typeof(NamespaceTracker)) { switch (Name) { case "__str__": case "__repr__": case "__doc__": // need to return the built in method descriptor for these... break; case "__file__": return((T)(object)new Func <CallSite, object, CodeContext, object>(new NamespaceTrackerDelegate(_name).GetFile)); case "__dict__": return((T)(object)new Func <CallSite, object, CodeContext, object>(new NamespaceTrackerDelegate(_name).GetDict)); case "__name__": return((T)(object)new Func <CallSite, object, CodeContext, object>(new NamespaceTrackerDelegate(_name).GetName)); default: if (IsNoThrow) { return((T)(object)new Func <CallSite, object, CodeContext, object>(new NamespaceTrackerDelegate(_name).NoThrowTarget)); } else { return((T)(object)new Func <CallSite, object, CodeContext, object>(new NamespaceTrackerDelegate(_name).Target)); } } } } if (args[0] != null && #if FEATURE_COM !Microsoft.Scripting.ComInterop.ComBinder.IsComObject(args[0]) && #endif !(args[0] is IDynamicMetaObjectProvider)) { Type selfType = typeof(T).GetMethod("Invoke").GetParameters()[1].ParameterType; CodeContext context = (CodeContext)args[1]; T res = null; if (selfType == typeof(object)) { res = (T)(object)MakeGetMemberTarget <object>(Name, args[0], context); } else if (selfType == typeof(PythonList)) { res = (T)(object)MakeGetMemberTarget <PythonList>(Name, args[0], context); } else if (selfType == typeof(string)) { res = (T)(object)MakeGetMemberTarget <string>(Name, args[0], context); } if (res != null) { return((T)(object)res); } return(base.BindDelegate <T>(site, args)); } PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "GetNoFast " + IsNoThrow + " " + CompilerHelpers.GetType(args[0])); return(this.LightBind <T>(args, Context.Options.CompilationThreshold)); }
public override T BindDelegate <T>(CallSite <T> site, object[] args) { if (args[1] is IFastInvokable ifi) { FastBindResult <T> res = ifi.MakeInvokeBinding(site, this, (CodeContext)args[0], ArrayUtils.ShiftLeft(args, 2)); if (res.Target != null) { if (res.ShouldCache) { base.CacheTarget(res.Target); } return(res.Target); } } if (args[1] is Types.PythonType) { PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "InvokeNoFast " + ((Types.PythonType)args[1]).Name); } else { PerfTrack.NoteEvent(PerfTrack.Categories.BindingSlow, "InvokeNoFast " + CompilerHelpers.GetType(args[1])); } var target = this.LightBind <T>(args, Context.Options.CompilationThreshold); base.CacheTarget(target); return(target); }
private DynamicMetaObject /*!*/ MakeSelfCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args) { BindingRestrictions selfRestrict = Restrictions.Merge( BindingRestrictionsHelpers.GetRuntimeTypeRestriction( Expression, LimitType ) ).Merge( BindingRestrictions.GetExpressionRestriction( Value.MakeBoundFunctionTest( AstUtils.Convert(Expression, typeof(BuiltinFunction)) ) ) ); Expression instance = Ast.Call( typeof(PythonOps).GetMethod(nameof(PythonOps.GetBuiltinFunctionSelf)), AstUtils.Convert( Expression, typeof(BuiltinFunction) ) ); DynamicMetaObject self = GetInstance(instance, CompilerHelpers.GetType(Value.BindingSelf)); return(Value.MakeBuiltinFunctionCall( call, codeContext, this, ArrayUtils.Insert(self, args), true, // has self selfRestrict, (newArgs) => { CallSignature signature = BindingHelpers.GetCallSignature(call); DynamicMetaObject res; PythonContext state = PythonContext.GetPythonContext(call); BindingTarget target; PythonOverloadResolver resolver; if (Value.IsReversedOperator) { resolver = new PythonOverloadResolver( state.Binder, newArgs, GetReversedSignature(signature), codeContext ); } else { resolver = new PythonOverloadResolver( state.Binder, self, args, signature, codeContext ); } res = state.Binder.CallMethod( resolver, Value.Targets, self.Restrictions, Value.Name, NarrowingLevel.None, Value.IsBinaryOperator ? PythonNarrowing.BinaryOperator : NarrowingLevel.All, out target ); return BindingHelpers.CheckLightThrow(call, res, target); } )); }
public Argument[] GetArgumentInfos() { return((_infos != null) ? ArrayUtils.Copy(_infos) : CompilerHelpers.MakeRepeatedArray(Argument.Simple, _argumentCount)); }
private void MakePropertyRule(SetOrDeleteMemberInfo memInfo, DynamicMetaObject instance, DynamicMetaObject target, Type targetType, MemberGroup properties, DynamicMetaObject errorSuggestion) { PropertyTracker info = (PropertyTracker)properties[0]; MethodInfo setter = info.GetSetMethod(true); // Allow access to protected getters TODO: this should go, it supports IronPython semantics. if (setter != null && !setter.IsPublic && !setter.IsProtected()) { if (!PrivateBinding) { setter = null; } } if (setter != null) { // TODO (tomat): this used to use setter.ReflectedType, is it still correct? setter = CompilerHelpers.TryGetCallableMethod(targetType, setter); if (!PrivateBinding && !CompilerHelpers.IsVisible(setter)) { setter = null; } } if (setter != null) { if (info.IsStatic != (instance == null)) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeStaticPropertyInstanceAccessError( info, true, instance, target ), typeof(object) ) ); } else if (info.IsStatic && info.DeclaringType != targetType) { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeStaticAssignFromDerivedTypeError(targetType, instance, info, target, memInfo.ResolutionFactory), typeof(object) ) ); } else if (setter.ContainsGenericParameters) { memInfo.Body.FinishCondition( MakeGenericPropertyExpression(memInfo) ); } else if (setter.IsPublic && !setter.DeclaringType.IsValueType()) { if (instance == null) { memInfo.Body.FinishCondition( Ast.Block( AstUtils.SimpleCallHelper( setter, ConvertExpression( target.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory ) ), Ast.Constant(null) ) ); } else { memInfo.Body.FinishCondition( MakeReturnValue( MakeCallExpression(memInfo.ResolutionFactory, setter, instance, target), target ) ); } } else { // TODO: Should be able to do better w/ value types. memInfo.Body.FinishCondition( MakeReturnValue( Ast.Call( AstUtils.Constant(((ReflectedPropertyTracker)info).Property), // TODO: Private binding on extension properties typeof(PropertyInfo).GetMethod("SetValue", new Type[] { typeof(object), typeof(object), typeof(object[]) }), instance == null ? AstUtils.Constant(null) : AstUtils.Convert(instance.Expression, typeof(object)), AstUtils.Convert( ConvertExpression( target.Expression, setter.GetParameters()[0].ParameterType, ConversionResultKind.ExplicitCast, memInfo.ResolutionFactory ), typeof(object) ), Ast.NewArrayInit(typeof(object)) ), target ) ); } } else { memInfo.Body.FinishError( errorSuggestion ?? MakeError( MakeMissingMemberErrorForAssignReadOnlyProperty(targetType, instance, memInfo.Name), typeof(object) ) ); } }
public virtual string GetObjectTypeName(object arg) { return(GetTypeName(CompilerHelpers.GetType(arg))); }
internal static Expression ExplicitConvert(Type /*!*/ toType, CallArguments /*!*/ args) { return(Converter.ExplicitConvert(args.TargetExpression, CompilerHelpers.GetType(args.Target), toType)); }
//private static Func<CallSite, object, object, object> DoubleAddSite = new Func<CallSite, object, object, object>(DoubleAdd); public override T BindDelegate <T>(CallSite <T> site, object[] args) { if (args[0] != null && CompilerHelpers.GetType(args[0]) == CompilerHelpers.GetType(args[1])) { switch (Operation) { case ExpressionType.Add: case ExpressionType.AddAssign: return(BindAdd <T>(site, args)); case ExpressionType.And: case ExpressionType.AndAssign: return(BindAnd <T>(site, args)); case ExpressionType.Or: case ExpressionType.OrAssign: return(BindOr <T>(site, args)); case ExpressionType.Subtract: case ExpressionType.SubtractAssign: return(BindSubtract <T>(site, args)); case ExpressionType.Equal: return(BindEqual <T>(site, args)); case ExpressionType.NotEqual: return(BindNotEqual <T>(site, args)); case ExpressionType.GreaterThan: return(BindGreaterThan <T>(site, args)); case ExpressionType.LessThan: return(BindLessThan <T>(site, args)); case ExpressionType.LessThanOrEqual: return(BindLessThanOrEqual <T>(site, args)); case ExpressionType.GreaterThanOrEqual: return(BindGreaterThanOrEqual <T>(site, args)); case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: return(BindMultiply <T>(site, args)); case ExpressionType.Divide: case ExpressionType.DivideAssign: return(BindDivide <T>(site, args)); case ExpressionType.Modulo: return(BindModulo <T>(site, args)); } } else { switch (Operation) { case ExpressionType.Modulo: return(BindModulo <T>(site, args)); case ExpressionType.Multiply: return(BindMultiplyDifferentTypes <T>(site, args)); } } return(base.BindDelegate <T>(site, args)); }
public override T BindDelegate <T>(CallSite <T> site, object[] args) { //Debug.Assert(typeof(T).GetMethod("Invoke").ReturnType == Type); object target = args[0]; T res = null; if (typeof(T) == typeof(Func <CallSite, object, string>) && target is string) { res = (T)(object)new Func <CallSite, object, string>(StringConversion); } else if (typeof(T) == typeof(Func <CallSite, object, int>)) { if (target is int) { res = (T)(object)new Func <CallSite, object, int>(IntConversion); } else if (target is bool) { res = (T)(object)new Func <CallSite, object, int>(BoolToIntConversion); } } else if (typeof(T) == typeof(Func <CallSite, bool, int>)) { res = (T)(object)new Func <CallSite, bool, int>(BoolToIntConversion); } else if (typeof(T) == typeof(Func <CallSite, object, bool>)) { if (target is bool) { res = (T)(object)new Func <CallSite, object, bool>(BoolConversion); } else if (target is string) { res = (T)(object)new Func <CallSite, object, bool>(StringToBoolConversion); } else if (target is int) { res = (T)(object)new Func <CallSite, object, bool>(IntToBoolConversion); } else if (target == null) { res = (T)(object)new Func <CallSite, object, bool>(NullToBoolConversion); } else if (target.GetType() == typeof(object)) { res = (T)(object)new Func <CallSite, object, bool>(ObjectToBoolConversion); } else if (target.GetType() == typeof(List)) { res = (T)(object)new Func <CallSite, object, bool>(ListToBoolConversion); } else if (target.GetType() == typeof(PythonTuple)) { res = (T)(object)new Func <CallSite, object, bool>(TupleToBoolConversion); } } else if (target != null) { // Special cases: // - string or bytes to IEnumerable or IEnumerator // - CLR 4 only: BigInteger -> Complex if (target is BigInteger) { if (typeof(T) == typeof(Func <CallSite, BigInteger, Complex>)) { res = (T)(object)new Func <CallSite, BigInteger, Complex>(BigIntegerToComplexConversion); } else if (typeof(T) == typeof(Func <CallSite, object, Complex>)) { res = (T)(object)new Func <CallSite, object, Complex>(BigIntegerObjectToComplexConversion); } else if (typeof(T) == typeof(Func <CallSite, BigInteger, object>)) { res = (T)(object)new Func <CallSite, BigInteger, object>(BigIntegerToComplexObjectConversion); } } else if (target is string) { if (typeof(T) == typeof(Func <CallSite, string, IEnumerable>)) { res = (T)(object)new Func <CallSite, string, IEnumerable>(StringToIEnumerableConversion); } else if (typeof(T) == typeof(Func <CallSite, string, IEnumerator>)) { res = (T)(object)new Func <CallSite, string, IEnumerator>(StringToIEnumeratorConversion); } else if (typeof(T) == typeof(Func <CallSite, object, IEnumerable>)) { res = (T)(object)new Func <CallSite, object, IEnumerable>(ObjectToIEnumerableConversion); } else if (typeof(T) == typeof(Func <CallSite, object, IEnumerator>)) { res = (T)(object)new Func <CallSite, object, IEnumerator>(ObjectToIEnumeratorConversion); } } else if (target.GetType() == typeof(Bytes)) { if (typeof(T) == typeof(Func <CallSite, Bytes, IEnumerable>)) { res = (T)(object)new Func <CallSite, Bytes, IEnumerable>(BytesToIEnumerableConversion); } else if (typeof(T) == typeof(Func <CallSite, Bytes, IEnumerator>)) { res = (T)(object)new Func <CallSite, Bytes, IEnumerator>(BytesToIEnumeratorConversion); } else if (typeof(T) == typeof(Func <CallSite, object, IEnumerable>)) { res = (T)(object)new Func <CallSite, object, IEnumerable>(ObjectToIEnumerableConversion); } else if (typeof(T) == typeof(Func <CallSite, object, IEnumerator>)) { res = (T)(object)new Func <CallSite, object, IEnumerator>(ObjectToIEnumeratorConversion); } } if (res == null && (target.GetType() == Type || Type.IsAssignableFrom(target.GetType()))) { if (typeof(T) == typeof(Func <CallSite, object, object>)) { // called via a helper call site in the runtime (e.g. Converter.Convert) res = (T)(object)new Func <CallSite, object, object>(new IdentityConversion(target.GetType()).Convert); } else { // called via an embedded call site Debug.Assert(typeof(T).GetMethod("Invoke").ReturnType == Type); if (typeof(T).GetMethod("Invoke").GetParameters()[1].ParameterType == typeof(object)) { object identityConversion = Activator.CreateInstance(typeof(IdentityConversion <>).MakeGenericType(Type), target.GetType()); res = (T)(object)identityConversion.GetType().GetMethod("Convert").CreateDelegate(typeof(T), identityConversion); } } } } if (res != null) { CacheTarget(res); return(res); } PerfTrack.NoteEvent(PerfTrack.Categories.Binding, "Convert " + Type.FullName + " " + CompilerHelpers.GetType(args[0]) + " " + typeof(T)); return(base.BindDelegate(site, args)); }
public DynamicMetaObject GetCallSignatures(DynamicMetaObject target) { return(MakeCallSignatureResult(CompilerHelpers.GetMethodTargets(target.LimitType), target)); }
public static T IncorrectBoxType <T>(object received) { throw Error.UnexpectedType("StrongBox<" + typeof(T).Name + ">", CompilerHelpers.GetType(received).Name); }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")] // TODO: fix private StandardRule <T> MakeOperatorRule(OperatorInfo info) { MethodInfo[] targets = GetApplicableMembers(info); if (targets.Length == 0) { targets = GetFallbackMembers(_types[0], info); } if (targets.Length > 0 && TryMakeBindingTarget(targets)) { return(_rule); } if (_types.Length > 1) { targets = GetApplicableMembers(_types[1], info); if (targets.Length > 0 && TryMakeBindingTarget(targets)) { return(_rule); } } Operators op = CompilerHelpers.InPlaceOperatorToOperator(info.Operator); if (op != Operators.None) { // recurse to try and get the non-inplace action... return(MakeOperatorRule(GetOperatorInfo(op))); } if (_types.Length == 2 && TypeUtils.GetNonNullableType(_types[0]) == TypeUtils.GetNonNullableType(_types[1]) && TypeUtils.IsArithmetic(_types[0])) { // TODO: Nullable<PrimitveType> Support Expression expr; switch (info.Operator) { case Operators.Add: expr = Ast.Add(Param0, Param1); break; case Operators.Subtract: expr = Ast.Subtract(Param0, Param1); break; case Operators.Divide: expr = Ast.Divide(Param0, Param1); break; case Operators.Mod: expr = Ast.Modulo(Param0, Param1); break; case Operators.Multiply: expr = Ast.Multiply(Param0, Param1); break; case Operators.LeftShift: expr = Ast.LeftShift(Param0, Param1); break; case Operators.RightShift: expr = Ast.RightShift(Param0, Param1); break; case Operators.BitwiseAnd: expr = Ast.And(Param0, Param1); break; case Operators.BitwiseOr: expr = Ast.Or(Param0, Param1); break; case Operators.Xor: expr = Ast.ExclusiveOr(Param0, Param1); break; default: throw new InvalidOperationException(); } _rule.SetTarget(_rule.MakeReturn(Binder, expr)); return(_rule); } else if (_types.Length == 1) { if (info.Operator == Operators.Negate && TypeUtils.IsArithmetic(_types[0])) { _rule.SetTarget(_rule.MakeReturn(Binder, Ast.Negate(Param0))); return(_rule); } else if (info.Operator == Operators.Not && TypeUtils.IsIntegerOrBool(_types[0])) { _rule.SetTarget(_rule.MakeReturn(Binder, Ast.Not(Param0))); return(_rule); } } if (info.Operator == Operators.IsTrue) { if (_types[0] == typeof(bool)) { _rule.SetTarget(_rule.MakeReturn(Binder, Param0)); return(_rule); } } SetErrorTarget(info); return(_rule); }