private MethodInfo[] GetApplicableMembers(OperatorInfo info)
 {
     return(GetApplicableMembers(CompilerHelpers.GetType(_args[0]), info));
 }
Ejemplo n.º 2
0
        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)));
        }
Ejemplo n.º 3
0
 [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)));
 }
Ejemplo n.º 4
0
        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
                       ));
        }
Ejemplo n.º 5
0
        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));
        }
Ejemplo n.º 9
0
            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;
            }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
 /// <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));
 }
Ejemplo n.º 13
0
 public static AbstractValue Constant(object value, Expression expression)
 {
     return(new AbstractValue(value, CompilerHelpers.GetType(value), AbstractKind.Constant, expression));
 }
Ejemplo n.º 14
0
 public void MakeRule()
 {
     Rule.MakeTest(StrongBoxType ?? CompilerHelpers.GetType(Target));
     Rule.Target = MakeDeleteMemberTarget();
 }
Ejemplo n.º 15
0
        /// <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);
            }
        }
Ejemplo n.º 16
0
        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);
            }
        }
Ejemplo n.º 17
0
 public static Exception MakeIncorrectBoxTypeError(Type type, object received)
 {
     return(Error.UnexpectedType("StrongBox<" + type.Name + ">", CompilerHelpers.GetType(received).Name));
 }
Ejemplo n.º 18
0
        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));
        }
Ejemplo n.º 20
0
        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);
        }
Ejemplo n.º 21
0
        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);
            }
                       ));
        }
Ejemplo n.º 22
0
 public Argument[] GetArgumentInfos()
 {
     return((_infos != null) ? ArrayUtils.Copy(_infos) : CompilerHelpers.MakeRepeatedArray(Argument.Simple, _argumentCount));
 }
Ejemplo n.º 23
0
        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)
                        )
                    );
            }
        }
Ejemplo n.º 24
0
 public virtual string GetObjectTypeName(object arg)
 {
     return(GetTypeName(CompilerHelpers.GetType(arg)));
 }
Ejemplo n.º 25
0
 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));
        }
Ejemplo n.º 27
0
        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));
        }
Ejemplo n.º 28
0
 public DynamicMetaObject GetCallSignatures(DynamicMetaObject target)
 {
     return(MakeCallSignatureResult(CompilerHelpers.GetMethodTargets(target.LimitType), target));
 }
Ejemplo n.º 29
0
 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);
        }