internal ComInvokeBinder(
                CallInfo callInfo, 
                DynamicMetaObject[] args,
                bool[] isByRef,
                BindingRestrictions restrictions, 
                Expression method, 
                Expression dispatch, 
                ComMethodDesc methodDesc
                ) {

            Debug.Assert(callInfo != null, "arguments");
            Debug.Assert(args != null, "args");
            Debug.Assert(isByRef != null, "isByRef");
            Debug.Assert(method != null, "method");
            Debug.Assert(dispatch != null, "dispatch");

            Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(ComMethodDesc), method.Type), "method");
            Debug.Assert(TypeUtils.AreReferenceAssignable(typeof(IDispatch), dispatch.Type), "dispatch");

            _method = method;
            _dispatch = dispatch;
            _methodDesc = methodDesc;

            _callInfo = callInfo;
            _args = args;
            _isByRef = isByRef;
            _restrictions = restrictions;

            // Set Instance to some value so that CallBinderHelper has the right number of parameters to work with
            _instance = dispatch;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DynamicMetaObject"/> class.
        /// </summary>
        /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
        /// <param name="restrictions">The set of binding restrictions under which the binding is valid.</param>
        public DynamicMetaObject(Expression expression, BindingRestrictions restrictions) {
            ContractUtils.RequiresNotNull(expression, "expression");
            ContractUtils.RequiresNotNull(restrictions, "restrictions");

            _expression = expression;
            _restrictions = restrictions;
        }
 /// <summary>
 /// Merges the set of binding restrictions with the current binding restrictions.
 /// </summary>
 /// <param name="restrictions">The set of restrictions with which to merge the current binding restrictions.</param>
 /// <returns>The new set of binding restrictions.</returns>
 public BindingRestrictions Merge(BindingRestrictions restrictions) {
     ContractUtils.RequiresNotNull(restrictions, "restrictions");
     if (this == Empty) {
         return restrictions;
     }
     if (restrictions == Empty) {
         return this;
     }
     return new MergedRestriction(this, restrictions);
 }
Beispiel #4
0
 private static DynamicMetaObject NoThisParam(DynamicMetaObjectBinder binder, BindingRestrictions restrictions) {
     return new DynamicMetaObject(
         binder.Throw(
             Expression.Call(
                 typeof(PythonOps).GetMethod("ValueError"),
                 Expression.Constant("native com method call without 'this' parameter"),
                 Expression.NewArrayInit(typeof(object))
             ),
             typeof(object)
         ),
         restrictions
     );
 }
Beispiel #5
0
            DynamicMetaObject BindSetMember(object key, Expression value, DynamicMetaObjectBinder binder, BindingRestrictions additional, Func <DynamicMetaObject> fallback)
            {
                IForceMemberCreatable creatable = binder as IForceMemberCreatable;
                var v          = Expression.Variable(typeof(object));
                var accessible = binder as IDirectAccessible;
                var exp        = Expression.Block(new[] { v },
                                                  Expression.Assign(v, Expression.Convert(value, v.Type)),
                                                  Expression.Condition(
                                                      Expression.Call(
                                                          LimitedInstance,
                                                          (MethodInfo)Utils.GetMember(() => Value.TrySetValue(null, false, false, null)),
                                                          Expression.Constant(key, typeof(object)),
                                                          Expression.Constant(accessible != null && accessible.DirectAccess),
                                                          Expression.Constant(creatable == null || creatable.ForceCreate),
                                                          v
                                                          ),
                                                      v,
                                                      Expression.Convert(fallback().Expression, typeof(object))
                                                      )
                                                  );

                return(Restrict(exp, binder, additional));
            }
Beispiel #6
0
 public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
 {
     return(BindSetMember(indexes[0].Value, value.Expression, binder, BindingRestrictions.GetInstanceRestriction(indexes[0].Expression, indexes[0].Value), () => base.BindSetIndex(binder, indexes, value)));
 }
 public BindingRestrictionsProxy(BindingRestrictions node) {
     _node = node;
 }
Beispiel #8
0
		public DynamicMetaNode( Expression parameter, BindingRestrictions rest, object value )
			: base( parameter, rest, value ) { }
Beispiel #9
0
 private static DynamicMetaObject IncorrectArgCount(BindingRestrictions restrictions, int expected, int got) {
     return new DynamicMetaObject(
         Expression.Throw(
             Expression.Call(
                 typeof(PythonOps).GetMethod("TypeError"),
                 Expression.Constant(String.Format("this function takes {0} arguments ({1} given)", expected, got)),
                 Expression.NewArrayInit(typeof(object))                                    
             ),
             typeof(object)
         ),
         restrictions
     );
 }
 internal ComFallbackMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
     : base(expression, restrictions, arg) {
 }
        private DynamicMetaObject MakeArrayIndexRule(OverloadResolverFactory factory, IndexType oper, DynamicMetaObject[] args)
        {
            if (CanConvertFrom(GetArgType(args, 1), typeof(int), false, NarrowingLevel.All))
            {
                BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));

                if (oper == IndexType.Get)
                {
                    return(new DynamicMetaObject(
                               Ast.ArrayAccess(
                                   args[0].Expression,
                                   ConvertIfNeeded(factory, args[1].Expression, typeof(int))
                                   ),
                               restrictions
                               ));
                }
                else
                {
                    return(new DynamicMetaObject(
                               Ast.Assign(
                                   Ast.ArrayAccess(
                                       args[0].Expression,
                                       ConvertIfNeeded(factory, args[1].Expression, typeof(int))
                                       ),
                                   ConvertIfNeeded(factory, args[2].Expression, args[0].GetLimitType().GetElementType())
                                   ),
                               restrictions.Merge(args[1].Restrictions)
                               ));
                }
            }

            return(null);
        }
        private DynamicMetaObject TryMakeBindingTarget(OverloadResolverFactory resolverFactory, MethodInfo[] targets, DynamicMetaObject[] args, BindingRestrictions restrictions)
        {
            var           resolver = resolverFactory.CreateOverloadResolver(args, new CallSignature(args.Length), CallTypes.None);
            BindingTarget target   = resolver.ResolveOverload(targets[0].Name, targets, NarrowingLevel.None, NarrowingLevel.All);

            if (target.Success)
            {
                return(new DynamicMetaObject(
                           target.MakeExpression(),
                           restrictions.Merge(target.RestrictedArguments.GetAllRestrictions())
                           ));
            }

            return(null);
        }
        private static DynamicMetaObject TryPrimitiveCompare(OperatorInfo info, DynamicMetaObject[] args)
        {
            if (TypeUtils.GetNonNullableType(args[0].GetLimitType()) == TypeUtils.GetNonNullableType(args[1].GetLimitType()) &&
                TypeUtils.IsNumeric(args[0].GetLimitType()))
            {
                Expression arg0 = args[0].Expression;
                Expression arg1 = args[1].Expression;

                // TODO: Nullable<PrimitveType> Support
                Expression expr;
                switch (info.Operator)
                {
                case ExpressionType.Equal: expr = Ast.Equal(arg0, arg1); break;

                case ExpressionType.NotEqual: expr = Ast.NotEqual(arg0, arg1); break;

                case ExpressionType.GreaterThan: expr = Ast.GreaterThan(arg0, arg1); break;

                case ExpressionType.LessThan: expr = Ast.LessThan(arg0, arg1); break;

                case ExpressionType.GreaterThanOrEqual: expr = Ast.GreaterThanOrEqual(arg0, arg1); break;

                case ExpressionType.LessThanOrEqual: expr = Ast.LessThanOrEqual(arg0, arg1); break;

                default: throw new InvalidOperationException();
                }

                return(new DynamicMetaObject(
                           expr,
                           BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg0, args[0].GetLimitType()).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(arg1, args[0].GetLimitType())).Merge(BindingRestrictions.Combine(args))
                           ));
            }

            return(null);
        }
        private static DynamicMetaObject TryMakeDefaultUnaryRule(OperatorInfo info, DynamicMetaObject[] args)
        {
            if (args.Length == 1)
            {
                BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));
                switch (info.Operator)
                {
                case ExpressionType.IsTrue:
                    if (args[0].GetLimitType() == typeof(bool))
                    {
                        return(args[0]);
                    }
                    break;

                case ExpressionType.Negate:
                    if (TypeUtils.IsArithmetic(args[0].GetLimitType()))
                    {
                        return(new DynamicMetaObject(
                                   Ast.Negate(args[0].Expression),
                                   restrictions
                                   ));
                    }
                    break;

                case ExpressionType.Not:
                    if (TypeUtils.IsIntegerOrBool(args[0].GetLimitType()))
                    {
                        return(new DynamicMetaObject(
                                   Ast.Not(args[0].Expression),
                                   restrictions
                                   ));
                    }
                    break;
                }
            }
            return(null);
        }
        /// <summary>
        /// Produces a rule for comparing a value to null - supports comparing object references and nullable types.
        /// </summary>
        private static DynamicMetaObject TryNullComparisonRule(DynamicMetaObject[] args)
        {
            Type otherType = args[1].GetLimitType();

            BindingRestrictions restrictions = BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[0].Expression, args[0].GetLimitType()).Merge(BindingRestrictions.Combine(args));

            if (args[0].GetLimitType() == typeof(DynamicNull))
            {
                if (!otherType.IsValueType)
                {
                    return(new DynamicMetaObject(
                               Ast.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }
                else if (otherType.GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            else if (otherType == typeof(DynamicNull))
            {
                if (!args[0].GetLimitType().IsValueType)
                {
                    return(new DynamicMetaObject(
                               Ast.Equal(args[0].Expression, AstUtils.Constant(null)),
                               restrictions
                               ));
                }
                else if (args[0].GetLimitType().GetGenericTypeDefinition() == typeof(Nullable <>))
                {
                    return(new DynamicMetaObject(
                               Ast.Property(args[0].Expression, otherType.GetProperty("HasValue")),
                               restrictions
                               ));
                }
            }
            return(null);
        }
        private DynamicMetaObject TryToCharConversion(DynamicMetaObject /*!*/ self)
        {
            DynamicMetaObject res;
            // we have an implicit conversion to char if the
            // string length == 1, but we can only represent
            // this is implicit via a rule.
            string     strVal  = self.Value as string;
            Expression strExpr = self.Expression;

            if (strVal == null)
            {
                Extensible <string> extstr = self.Value as Extensible <string>;
                if (extstr != null)
                {
                    strVal  = extstr.Value;
                    strExpr =
                        Ast.Property(
                            AstUtils.Convert(
                                strExpr,
                                typeof(Extensible <string>)
                                ),
                            typeof(Extensible <string>).GetProperty("Value")
                            );
                }
            }

            // we can only produce a conversion if we have a string value...
            if (strVal != null)
            {
                self = self.Restrict(self.GetRuntimeType());

                Expression getLen = Ast.Property(
                    AstUtils.Convert(
                        strExpr,
                        typeof(string)
                        ),
                    typeof(string).GetProperty("Length")
                    );

                if (strVal.Length == 1)
                {
                    res = new DynamicMetaObject(
                        Ast.Call(
                            AstUtils.Convert(strExpr, typeof(string)),
                            typeof(string).GetMethod("get_Chars"),
                            AstUtils.Constant(0)
                            ),
                        self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.Equal(getLen, AstUtils.Constant(1))))
                        );
                }
                else
                {
                    res = new DynamicMetaObject(
                        this.Throw(
                            Ast.Call(
                                typeof(PythonOps).GetMethod(nameof(PythonOps.TypeError)),
                                AstUtils.Constant("expected string of length 1 when converting to char, got '{0}'"),
                                Ast.NewArrayInit(typeof(object), self.Expression)
                                ),
                            ReturnType
                            ),
                        self.Restrictions.Merge(BindingRestrictions.GetExpressionRestriction(Ast.NotEqual(getLen, AstUtils.Constant(1))))
                        );
                }
            }
            else
            {
                // let the base class produce the rule
                res = null;
            }

            return(res);
        }
        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:
                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)));
        }
        public override DynamicMetaObject FallbackSetMember(
            DynamicMetaObject targetMO, DynamicMetaObject value,
            DynamicMetaObject errorSuggestion)
        {
            // Defer if any object has no value so that we evaulate their
            // Expressions and nest a CallSite for the InvokeMember.
            if (!targetMO.HasValue)
            {
                return(Defer(targetMO));
            }
            // Find our own binding.
            const BindingFlags flags = BindingFlags.IgnoreCase | BindingFlags.Static |
                                       BindingFlags.Instance | BindingFlags.Public;
            var members = targetMO.LimitType.GetMember(Name, flags);

            if (members.Length == 1)
            {
                MemberInfo mem = members[0];
                Expression val;
                // Should check for member domain type being Type and value being
                // TypeModel, similar to ConvertArguments, and building an
                // expression like GetRuntimeTypeMoFromModel.
                if (mem.MemberType == MemberTypes.Property)
                {
                    val = Expression.Convert(value.Expression,
                                             ((PropertyInfo)mem).PropertyType);
                }
                else if (mem.MemberType == MemberTypes.Field)
                {
                    val = Expression.Convert(value.Expression,
                                             ((FieldInfo)mem).FieldType);
                }
                else
                {
                    return(errorSuggestion ??
                           RuntimeHelpers.CreateThrow(
                               targetMO, null,
                               BindingRestrictions.GetTypeRestriction(
                                   targetMO.Expression,
                                   targetMO.LimitType),
                               typeof(InvalidOperationException),
                               "Crispy only supports setting Properties and " +
                               "fields at this time."));
                }
                return(new DynamicMetaObject(
                           // Assign returns the stored value, so we're good for Crispy.
                           RuntimeHelpers.EnsureObjectResult(
                               Expression.Assign(
                                   Expression.MakeMemberAccess(
                                       Expression.Convert(targetMO.Expression,
                                                          members[0].DeclaringType),
                                       members[0]),
                                   val)),
                           // Don't need restriction test for name since this
                           // rule is only used where binder is used, which is
                           // only used in sites with this binder.Name.
                           BindingRestrictions.GetTypeRestriction(targetMO.Expression,
                                                                  targetMO.LimitType)));
            }
            return(errorSuggestion ??
                   RuntimeHelpers.CreateThrow(
                       targetMO, null,
                       BindingRestrictions.GetTypeRestriction(targetMO.Expression,
                                                              targetMO.LimitType),
                       typeof(MissingMemberException),
                       "IDynObj member name conflict."));
        }
Beispiel #19
0
 public DynamicMetaObject GetMetaObject(Expression parameter)
 {
     return(new Meta(parameter, BindingRestrictions.GetTypeRestriction(parameter, typeof(Function)), this));
 }
        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
                       ));
        }
Beispiel #21
0
 public Meta(Expression expression, BindingRestrictions restrictions, Function value) : base(expression, restrictions, value)
 {
 }
Beispiel #22
0
        private readonly DynamicMetaObject _baseMetaObject;            // if we're a subtype of MetaObject this is the base class MO

        public MetaUserObject(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, DynamicMetaObject baseMetaObject, IPythonObject value)
            : base(expression, restrictions, value) {
            _baseMetaObject = baseMetaObject;
        }
Beispiel #23
0
 public override BindingRestrictions GetRestrictions()
 {
     return(BindingRestrictions.GetTypeRestriction(ArgumentExpression, typeof(NativeArgument)));
 }
            internal void Append(BindingRestrictions restrictions) {
                if (_unique.Contains(restrictions)) {
                    return;
                }
                _unique.Add(restrictions);

                Push(restrictions.GetExpression(), 0);
            }
Beispiel #25
0
                public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
                {
                    CodeContext context = PythonContext.GetPythonContext(binder).SharedContext;

                    ArgumentMarshaller[] signature = GetArgumentMarshallers(args);

                    BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(
                        Expression,
                        Value.GetType()
                        ).Merge(
                        BindingRestrictions.GetExpressionRestriction(
                            Expression.Call(
                                typeof(ModuleOps).GetMethod("CheckFunctionId"),
                                Expression.Convert(Expression, typeof(_CFuncPtr)),
                                Expression.Constant(Value.Id)
                                )
                            )
                        );

                    foreach (var arg in signature)
                    {
                        restrictions = restrictions.Merge(arg.GetRestrictions());
                    }

                    int argCount = args.Length;

                    if (Value._comInterfaceIndex != -1)
                    {
                        argCount--;
                    }
                    // need to verify we have the correct # of args
                    if (Value._argtypes != null)
                    {
                        if (argCount < Value._argtypes.Count || (Value.CallingConvention != CallingConvention.Cdecl && argCount > Value._argtypes.Count))
                        {
                            return(IncorrectArgCount(binder, restrictions, Value._argtypes.Count, argCount));
                        }
                    }
                    else
                    {
                        CFuncPtrType funcType = ((CFuncPtrType)Value.NativeType);
                        if (funcType._argtypes != null &&
                            (argCount < funcType._argtypes.Length || (Value.CallingConvention != CallingConvention.Cdecl && argCount > funcType._argtypes.Length)))
                        {
                            return(IncorrectArgCount(binder, restrictions, funcType._argtypes.Length, argCount));
                        }
                    }

                    if (Value._comInterfaceIndex != -1 && args.Length == 0)
                    {
                        return(NoThisParam(binder, restrictions));
                    }

                    Expression        call  = MakeCall(signature, GetNativeReturnType(), Value.Getrestype() == null, GetFunctionAddress(args));
                    List <Expression> block = new List <Expression>();
                    Expression        res;

                    if (call.Type != typeof(void))
                    {
                        ParameterExpression tmp = Expression.Parameter(call.Type, "ret");
                        block.Add(Expression.Assign(tmp, call));
                        AddKeepAlives(signature, block);
                        block.Add(tmp);
                        res = Expression.Block(new[] { tmp }, block);
                    }
                    else
                    {
                        block.Add(call);
                        AddKeepAlives(signature, block);
                        res = Expression.Block(block);
                    }

                    res = AddReturnChecks(context, args, res);

                    return(new DynamicMetaObject(Utils.Convert(res, typeof(object)), restrictions));
                }
 public MetaPythonFunction(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, PythonFunction/*!*/ value)
     : base(expression, BindingRestrictions.Empty, value) {
     Assert.NotNull(value);
 }
Beispiel #27
0
 private static DynamicMetaObject IncorrectArgCount(DynamicMetaObjectBinder binder, BindingRestrictions restrictions, int expected, int got)
 {
     return(new DynamicMetaObject(
                binder.Throw(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("TypeError"),
                        Expression.Constant(String.Format("this function takes {0} arguments ({1} given)", expected, got)),
                        Expression.NewArrayInit(typeof(object))
                        ),
                    typeof(object)
                    ),
                restrictions
                ));
 }
Beispiel #28
0
            DynamicMetaObject BindGetMember(object key, DynamicMetaObjectBinder binder, BindingRestrictions additional, Func <DynamicMetaObject> fallback)
            {
                var v          = Expression.Variable(typeof(object));
                var accessible = binder as IDirectAccessible;
                var exp        = Expression.Block(new[] { v },
                                                  Expression.Condition(
                                                      Expression.Call(
                                                          LimitedInstance,
                                                          (MethodInfo)Utils.GetMember <object>(x => Value.TryGetValue(null, false, out x)),
                                                          Expression.Constant(key, typeof(object)), Expression.Constant(accessible != null && accessible.DirectAccess), v
                                                          ),
                                                      v,
                                                      Expression.Convert(fallback().Expression, typeof(object))
                                                      )
                                                  );

                return(Restrict(exp, binder, additional));
            }
 /// <summary>
 /// Initializes a new instance of the <see cref="DynamicMetaObject"/> class.
 /// </summary>
 /// <param name="expression">The expression representing this <see cref="DynamicMetaObject"/> during the dynamic binding process.</param>
 /// <param name="restrictions">The set of binding restrictions under which the binding is valid.</param>
 /// <param name="value">The runtime value represented by the <see cref="DynamicMetaObject"/>.</param>
 public DynamicMetaObject(Expression expression, BindingRestrictions restrictions, object value)
     : this(expression, restrictions) {
     _value = value;
     _hasValue = true;
 }
Beispiel #30
0
 public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes)
 {
     return(BindDeleteMember(indexes[0].Value, binder, BindingRestrictions.GetInstanceRestriction(indexes[0].Expression, indexes[0].Value), () => base.BindDeleteIndex(binder, indexes)));
 }
 public MetaBuiltinMethodDescriptor(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, BuiltinMethodDescriptor/*!*/ value)
     : base(expression, BindingRestrictions.Empty, value) {
     Assert.NotNull(value);
 }
Beispiel #32
0
        /// <summary>
        /// Translates our CallSignature into a DLR Argument list and gives the simple MetaObject's which are extracted
        /// from the tuple or dictionary parameters being splatted.
        /// </summary>
        private void TranslateArguments(DynamicMetaObject target, DynamicMetaObject/*!*/[]/*!*/ args, out List<ArgumentInfo/*!*/>/*!*/ newArgs, out List<Expression/*!*/>/*!*/ metaArgs, out Expression test, out BindingRestrictions restrictions) {
            Argument[] argInfo = _signature.GetArgumentInfos();

            newArgs = new List<ArgumentInfo>();
            metaArgs = new List<Expression>();
            metaArgs.Add(target.Expression);
            Expression splatArgTest = null;
            Expression splatKwArgTest = null;
            restrictions = BindingRestrictions.Empty;

            for (int i = 0; i < argInfo.Length; i++) {
                Argument ai = argInfo[i];

                switch (ai.Kind) {
                    case ArgumentType.Dictionary:
                        IAttributesCollection iac = (IAttributesCollection)args[i].Value;
                        List<string> argNames = new List<string>();

                        foreach (KeyValuePair<object, object> kvp in iac) {
                            string key = (string)kvp.Key;
                            newArgs.Add(Expression.NamedArg(key));
                            argNames.Add(key);

                            metaArgs.Add(
                                Expression.Call(
                                    AstUtils.Convert(args[i].Expression, typeof(IAttributesCollection)),
                                    typeof(IAttributesCollection).GetMethod("get_Item"),
                                    AstUtils.Constant(SymbolTable.StringToId(key))
                                )
                            );
                        }

                        restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[i].Expression, args[i].GetLimitType()));
                        splatKwArgTest = Expression.Call(
                            typeof(PythonOps).GetMethod("CheckDictionaryMembers"),
                            AstUtils.Convert(args[i].Expression, typeof(IAttributesCollection)),
                            Expression.Constant(argNames.ToArray())
                        );
                        break;
                    case ArgumentType.List:
                        IList<object> splattedArgs = (IList<object>)args[i].Value;
                        splatArgTest = Expression.Equal(
                            Expression.Property(AstUtils.Convert(args[i].Expression, args[i].GetLimitType()), typeof(ICollection<object>).GetProperty("Count")),
                            Expression.Constant(splattedArgs.Count)
                        );

                        for (int splattedArg = 0; splattedArg < splattedArgs.Count; splattedArg++) {
                            newArgs.Add(Expression.PositionalArg(splattedArg + i));
                            metaArgs.Add(
                                Expression.Call(
                                    AstUtils.Convert(args[i].Expression, typeof(IList<object>)),
                                    typeof(IList<object>).GetMethod("get_Item"),
                                    Expression.Constant(splattedArg)
                                )
                            );
                        }

                        restrictions = restrictions.Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(args[i].Expression, args[i].GetLimitType()));
                        break;
                    case ArgumentType.Named:
                        newArgs.Add(Expression.NamedArg(SymbolTable.IdToString(ai.Name)));
                        metaArgs.Add(args[i].Expression);
                        break;
                    case ArgumentType.Simple:
                        newArgs.Add(Expression.PositionalArg(i));
                        metaArgs.Add(args[i].Expression);
                        break;
                    default:
                        throw new InvalidOperationException();
                }
            }

            test = splatArgTest;
            if (splatKwArgTest != null) {
                if (test != null) {
                    test = Expression.AndAlso(test, splatKwArgTest);
                } else {
                    test = splatKwArgTest;
                }
            }
        }
        private DynamicMetaObject MakeDeferred(BindingRestrictions rs, params DynamicMetaObject[] args) {
            var exprs = DynamicMetaObject.GetExpressions(args);

            Type delegateType = DelegateHelpers.MakeDeferredSiteDelegate(args, ReturnType);

            // Because we know the arguments match the delegate type (we just created the argument types)
            // we go directly to DynamicExpression.Make to avoid a bunch of unnecessary argument validation
            return new DynamicMetaObject(
                DynamicExpression.Make(ReturnType, delegateType, this, new TrueReadOnlyCollection<Expression>(exprs)),
                rs
            );
        }
Beispiel #34
0
 private static DynamicMetaObject NoThisParam(DynamicMetaObjectBinder binder, BindingRestrictions restrictions)
 {
     return(new DynamicMetaObject(
                binder.Throw(
                    Expression.Call(
                        typeof(PythonOps).GetMethod("ValueError"),
                        Expression.Constant("native com method call without 'this' parameter"),
                        Expression.NewArrayInit(typeof(object))
                        ),
                    typeof(object)
                    ),
                restrictions
                ));
 }
 public MetaBuiltinFunction(Expression /*!*/ expression, BindingRestrictions /*!*/ restrictions, BuiltinFunction /*!*/ value)
     : base(expression, BindingRestrictions.Empty, value)
 {
     Assert.NotNull(value);
 }
 public MetaTotemFunction(Expression expression, BindingRestrictions restrictions, TotemFunction value)
     : base(expression, restrictions, value)
 {
     Assert.Equals(restrictions, BindingRestrictions.Empty);
     Assert.NotNull(value);
 }
 public MetaPythonObject(Expression /*!*/ expression, BindingRestrictions /*!*/ restrictions, object value)
     : base(expression, restrictions, value)
 {
 }
        private static BindingRestrictions AddRemoteObjectRestrictions(BindingRestrictions restrictions, object[] args, ReadOnlyCollection<ParameterExpression> parameters) {
#if !SILVERLIGHT

            for (int i = 0; i < parameters.Count; i++) {
                var expr = parameters[i];
                var value = args[i] as MarshalByRefObject;

                // special case for MBR objects.
                // when MBR objects are remoted they can have different conversion behavior
                // so bindings created for local and remote objects should not be mixed.
                if (value != null && !IsComObject(value)) {
                    BindingRestrictions remotedRestriction;
                    if (RemotingServices.IsObjectOutOfAppDomain(value)) {
                        remotedRestriction = BindingRestrictions.GetExpressionRestriction(
                            Expression.AndAlso(
                                Expression.NotEqual(expr, Expression.Constant(null)),
                                Expression.Call(
                                    typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"),
                                    expr
                                )
                            )
                        );
                    } else {
                        remotedRestriction = BindingRestrictions.GetExpressionRestriction(
                            Expression.AndAlso(
                                Expression.NotEqual(expr, Expression.Constant(null)),
                                Expression.Not(
                                    Expression.Call(
                                        typeof(RemotingServices).GetMethod("IsObjectOutOfAppDomain"),
                                        expr
                                    )
                                )
                            )
                        );
                    }
                    restrictions = restrictions.Merge(remotedRestriction);
                }
            }

#endif
            return restrictions;
        }
 public MetaPythonType(Expression /*!*/ expression, BindingRestrictions /*!*/ restrictions, PythonType /*!*/ value)
     : base(expression, BindingRestrictions.Empty, value)
 {
     Assert.NotNull(value);
 }
        internal DynamicMetaObject Invoke() {
            _keywordArgNames = _callInfo.ArgumentNames.ToArray();
            _totalExplicitArgs = _args.Length;
            
            Type[] marshalArgTypes = new Type[_args.Length];

            // We already tested the instance, so no need to test it again
            for (int i = 0; i < _args.Length; i++) {
                DynamicMetaObject curMo = _args[i];
                _restrictions = _restrictions.Merge(ComBinderHelpers.GetTypeRestrictionForDynamicMetaObject(curMo));
                marshalArgTypes[i] = MarshalType(curMo, _isByRef[i]);
            }

            _varEnumSelector = new VarEnumSelector(marshalArgTypes);

            return new DynamicMetaObject(
                CreateScope(MakeIDispatchInvokeTarget()),
                BindingRestrictions.Combine(_args).Merge(_restrictions)
            );
        }
Beispiel #41
0
        /// <summary>
        /// Creating a Python type involves calling __new__ and __init__.  We resolve them
        /// and generate calls to either the builtin funcions directly or embed sites which
        /// call the slots at runtime.
        /// </summary>
        private DynamicMetaObject /*!*/ MakePythonTypeCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/[] /*!*/ args)
        {
            ValidationInfo valInfo = MakeVersionCheck();

            DynamicMetaObject self = new RestrictedMetaObject(
                AstUtils.Convert(Expression, LimitType),
                BindingRestrictionsHelpers.GetRuntimeTypeRestriction(Expression, LimitType),
                Value
                );
            CallSignature  sig = BindingHelpers.GetCallSignature(call);
            ArgumentValues ai  = new ArgumentValues(sig, self, args);
            NewAdapter     newAdapter;
            InitAdapter    initAdapter;

            if (TooManyArgsForDefaultNew(call, args))
            {
                return(MakeIncorrectArgumentsForCallError(call, ai, valInfo));
            }
            else if (Value.UnderlyingSystemType.IsGenericTypeDefinition())
            {
                return(MakeGenericTypeDefinitionError(call, ai, valInfo));
            }
            else if (Value.HasAbstractMethods(PythonContext.GetPythonContext(call).SharedContext))
            {
                return(MakeAbstractInstantiationError(call, ai, valInfo));
            }

            DynamicMetaObject translated = BuiltinFunction.TranslateArguments(call, codeContext, self, args, false, Value.Name);

            if (translated != null)
            {
                return(translated);
            }

            GetAdapters(ai, call, codeContext, out newAdapter, out initAdapter);
            PythonContext state = PythonContext.GetPythonContext(call);

            // get the expression for calling __new__
            DynamicMetaObject createExpr = newAdapter.GetExpression(state.Binder);

            if (createExpr.Expression.Type == typeof(void))
            {
                return(BindingHelpers.AddDynamicTestAndDefer(
                           call,
                           createExpr,
                           args,
                           valInfo
                           ));
            }

            Expression          res;
            BindingRestrictions additionalRestrictions = BindingRestrictions.Empty;

            if (!Value.IsSystemType && (!(newAdapter is DefaultNewAdapter) || HasFinalizer(call)))
            {
                // we need to dynamically check the return value to see if it's a subtype of
                // the type that we are calling.  If it is then we need to call __init__/__del__
                // for the actual returned type.
                res = DynamicExpression.Dynamic(
                    Value.GetLateBoundInitBinder(sig),
                    typeof(object),
                    ArrayUtils.Insert(
                        codeContext,
                        Expression.Convert(createExpr.Expression, typeof(object)),
                        DynamicUtils.GetExpressions(args)
                        )
                    );
                additionalRestrictions = createExpr.Restrictions;
            }
            else
            {
                // just call the __init__ method, built-in types currently have
                // no wacky return values which don't return the derived type.

                // then get the statement for calling __init__
                ParameterExpression allocatedInst = Ast.Variable(createExpr.GetLimitType(), "newInst");
                Expression          tmpRead       = allocatedInst;
                DynamicMetaObject   initCall      = initAdapter.MakeInitCall(
                    state.Binder,
                    new RestrictedMetaObject(
                        AstUtils.Convert(allocatedInst, Value.UnderlyingSystemType),
                        createExpr.Restrictions
                        )
                    );

                List <Expression> body = new List <Expression>();
                Debug.Assert(!HasFinalizer(call));

                // add the call to init if we need to
                if (initCall.Expression != tmpRead)
                {
                    // init can fail but if __new__ returns a different type
                    // no exception is raised.
                    DynamicMetaObject initStmt = initCall;

                    if (body.Count == 0)
                    {
                        body.Add(
                            Ast.Assign(allocatedInst, createExpr.Expression)
                            );
                    }

                    if (!Value.UnderlyingSystemType.IsAssignableFrom(createExpr.Expression.Type))
                    {
                        // return type of object, we need to check the return type before calling __init__.
                        body.Add(
                            AstUtils.IfThen(
                                Ast.TypeIs(allocatedInst, Value.UnderlyingSystemType),
                                initStmt.Expression
                                )
                            );
                    }
                    else
                    {
                        // just call the __init__ method, no type check necessary (TODO: need null check?)
                        body.Add(initStmt.Expression);
                    }
                }

                // and build the target from everything we have
                if (body.Count == 0)
                {
                    res = createExpr.Expression;
                }
                else
                {
                    body.Add(allocatedInst);
                    res = Ast.Block(body);
                }
                res = Ast.Block(new ParameterExpression[] { allocatedInst }, res);

                additionalRestrictions = initCall.Restrictions;
            }

            return(BindingHelpers.AddDynamicTestAndDefer(
                       call,
                       new DynamicMetaObject(
                           res,
                           self.Restrictions.Merge(additionalRestrictions)
                           ),
                       ArrayUtils.Insert(this, args),
                       valInfo
                       ));
        }
 public CallAdapter(ArgumentValues/*!*/ ai, PythonContext/*!*/ state, Expression/*!*/ codeContext) {
     _argInfo = ai;
     _state = state;
     _restrictions = BindingRestrictions.Empty;
     _context = codeContext;
 }
Beispiel #43
0
 private static BindingRestrictions GetInstanceRestriction(ArgumentValues ai)
 {
     return(BindingRestrictions.GetInstanceRestriction(ai.Self.Expression, ai.Self.Value));
 }
Beispiel #44
0
 internal static DynamicMetaObject/*!*/ TypeErrorGenericMethod(Type/*!*/ type, string/*!*/ name, BindingRestrictions/*!*/ restrictions) {
     return new DynamicMetaObject(
         Ast.Throw(
             Ast.Call(
                 typeof(PythonOps).GetMethod("TypeErrorForGenericMethod"),
                 AstUtils.Constant(type),
                 AstUtils.Constant(name)
             ),
             typeof(object)
         ),
         restrictions
     );
 }
        /// <summary>
        /// Helper for generating the call to a builtin function.  This is used for calls from built-in method
        /// descriptors and built-in functions w/ and w/o a bound instance.
        ///
        /// This provides all sorts of common checks on top of the call while the caller provides a delegate
        /// to do the actual call.  The common checks include:
        ///     check for generic-only methods
        ///     reversed operator support
        ///     transforming arguments so the default binder can understand them (currently user defined mapping types to PythonDictionary)
        ///     returning NotImplemented from binary operators
        ///     Warning when calling certain built-in functions
        ///
        /// </summary>
        /// <param name="call">The call binder we're doing the call for</param>
        /// <param name="codeContext">An expression which points to the code context</param>
        /// <param name="function">the meta object for the built in function</param>
        /// <param name="hasSelf">true if we're calling with an instance</param>
        /// <param name="args">The arguments being passed to the function</param>
        /// <param name="functionRestriction">A restriction for the built-in function, method desc, etc...</param>
        /// <param name="bind">A delegate to perform the actual call to the method.</param>
        internal DynamicMetaObject /*!*/ MakeBuiltinFunctionCall(DynamicMetaObjectBinder /*!*/ call, Expression /*!*/ codeContext, DynamicMetaObject /*!*/ function, DynamicMetaObject /*!*/[] args, bool hasSelf, BindingRestrictions /*!*/ functionRestriction, Func <DynamicMetaObject /*!*/[] /*!*/, BindingResult /*!*/> bind)
        {
            DynamicMetaObject res = null;

            // if we have a user defined operator for **args then transform it into a PythonDictionary
            DynamicMetaObject translated = TranslateArguments(call, codeContext, new DynamicMetaObject(function.Expression, functionRestriction, function.Value), args, hasSelf, Name);

            if (translated != null)
            {
                return(translated);
            }

            // swap the arguments if we have a reversed operator
            if (IsReversedOperator)
            {
                ArrayUtils.SwapLastTwo(args);
            }

            // do the appropriate calling logic
            BindingResult result = bind(args);

            // validate the result
            BindingTarget target = result.Target;

            res = result.MetaObject;

            if (target.Overload != null && target.Overload.IsProtected)
            {
                // report an error when calling a protected member
                res = new DynamicMetaObject(
                    BindingHelpers.TypeErrorForProtectedMember(
                        target.Overload.DeclaringType,
                        target.Overload.Name
                        ),
                    res.Restrictions
                    );
            }
            else if (IsBinaryOperator && args.Length == 2 && IsThrowException(res.Expression))
            {
                // Binary Operators return NotImplemented on failure.
                res = new DynamicMetaObject(
                    Ast.Property(null, typeof(PythonOps), "NotImplemented"),
                    res.Restrictions
                    );
            }
            else if (target.Overload != null)
            {
                // Add profiling information for this builtin function, if applicable
                IPythonSite pythonSite = (call as IPythonSite);
                if (pythonSite != null)
                {
                    var pc = pythonSite.Context;
                    var po = pc.Options as PythonOptions;
                    if (po != null && po.EnableProfiler)
                    {
                        Profiler profiler = Profiler.GetProfiler(pc);
                        res = new DynamicMetaObject(
                            profiler.AddProfiling(res.Expression, target.Overload.ReflectionInfo),
                            res.Restrictions
                            );
                    }
                }
            }

            // add any warnings that are applicable for calling this function
            WarningInfo info;

            if (target.Overload != null && BindingWarnings.ShouldWarn(PythonContext.GetPythonContext(call), target.Overload, out info))
            {
                res = info.AddWarning(codeContext, res);
            }

            // finally add the restrictions for the built-in function and return the result.
            res = new DynamicMetaObject(
                res.Expression,
                functionRestriction.Merge(res.Restrictions)
                );

            // The function can return something typed to boolean or int.
            // If that happens, we need to apply Python's boxing rules.
            if (res.Expression.Type.IsValueType())
            {
                res = BindingHelpers.AddPythonBoxing(res);
            }
            else if (res.Expression.Type == typeof(void))
            {
                res = new DynamicMetaObject(
                    Expression.Block(
                        res.Expression,
                        Expression.Constant(null)
                        ),
                    res.Restrictions
                    );
            }

            return(res);
        }
Beispiel #46
0
 public MetaMethod(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, Method/*!*/ value)
     : base(expression, BindingRestrictions.Empty, value) {
     Assert.NotNull(value);
 }
        internal static DynamicMetaObject TranslateArguments(DynamicMetaObjectBinder call, Expression codeContext, DynamicMetaObject function, DynamicMetaObject /*!*/[] args, bool hasSelf, string name)
        {
            if (hasSelf)
            {
                args = ArrayUtils.RemoveFirst(args);
            }

            CallSignature sig = BindingHelpers.GetCallSignature(call);

            if (sig.HasDictionaryArgument())
            {
                int index = sig.IndexOf(ArgumentType.Dictionary);

                DynamicMetaObject dict = args[index];

                if (!(dict.Value is IDictionary) && dict.Value != null)
                {
                    // The DefaultBinder only handles types that implement IDictionary.  Here we have an
                    // arbitrary user-defined mapping type.  We'll convert it into a PythonDictionary
                    // and then have an embedded dynamic site pass that dictionary through to the default
                    // binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.UserMappingToPythonDictionary)),
                            codeContext,
                            args[index].Expression,
                            AstUtils.Constant(name)
                            ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()),
                        PythonOps.UserMappingToPythonDictionary(PythonContext.GetPythonContext(call).SharedContext, dict.Value, name)
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()))
                               ));
                }
            }

            if (sig.HasListArgument())
            {
                int index             = sig.IndexOf(ArgumentType.List);
                DynamicMetaObject str = args[index];

                // TODO: ANything w/ __iter__ that's not an IList<object>
                if (!(str.Value is IList <object>) && str.Value is IEnumerable)
                {
                    // The DefaultBinder only handles types that implement IList<object>.  Here we have a
                    // string.  We'll convert it into a tuple
                    // and then have an embedded dynamic site pass that tuple through to the default
                    // binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                            typeof(PythonOps).GetMethod(nameof(PythonOps.MakeTupleFromSequence)),
                            Expression.Convert(args[index].Expression, typeof(object))
                            ),
                        BindingRestrictions.Empty
                        );

                    if (call is IPythonSite)
                    {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                            );
                    }

                    return(new DynamicMetaObject(
                               DynamicExpression.Dynamic(
                                   call,
                                   typeof(object),
                                   DynamicUtils.GetExpressions(dynamicArgs)
                                   ),
                               function.Restrictions.Merge(
                                   BindingRestrictions.Combine(args).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(str.Expression, str.GetLimitType()))
                                   )
                               ));
                }
            }
            return(null);
        }
 internal ComUnwrappedMetaObject(Expression expression, BindingRestrictions restrictions, object value)
     : base(expression, restrictions, value) {
 }
Beispiel #49
0
 /// <summary>
 /// Returns a Restrictions object which includes our current restrictions merged
 /// with a restriction limiting our type
 /// </summary>
 private BindingRestrictions GetRestrictions()
 {
     return((Value == null && HasValue)
         ? BindingRestrictions.GetInstanceRestriction(Expression, null)
         : BindingRestrictions.GetTypeRestriction(Expression, LimitType));
 }
 internal MergedRestriction(BindingRestrictions left, BindingRestrictions right) {
     Left = left;
     Right = right;
 }
Beispiel #51
0
 public void FinishCondition(DynamicMetaObject body)
 {
     _restrictions = _restrictions.Merge(body.Restrictions);
     FinishCondition(body.Expression);
 }
Beispiel #52
0
 internal ComFallbackMetaObject(Expression expression, BindingRestrictions restrictions, object arg)
     : base(expression, restrictions, arg)
 {
 }
Beispiel #53
0
 internal ComUnwrappedMetaObject(Expression expression, BindingRestrictions restrictions, object value)
     : base(expression, restrictions, value)
 {
 }
Beispiel #54
0
 public MetaOldInstance(Expression/*!*/ expression, BindingRestrictions/*!*/ restrictions, OldInstance/*!*/ value)
     : base(expression, BindingRestrictions.Empty, value) {
     Assert.NotNull(value);
 }
Beispiel #55
0
        /// <summary>
        /// Helper for generating the call to a builtin function.  This is used for calls from built-in method
        /// descriptors and built-in functions w/ and w/o a bound instance.  
        /// 
        /// This provides all sorts of common checks on top of the call while the caller provides a delegate
        /// to do the actual call.  The common checks include:
        ///     check for generic-only methods
        ///     reversed operator support
        ///     transforming arguments so the default binder can understand them (currently user defined mapping types to PythonDictionary)
        ///     returning NotImplemented from binary operators
        ///     Warning when calling certain built-in functions
        ///     
        /// </summary>
        /// <param name="call">The call binder we're doing the call for</param>
        /// <param name="codeContext">An expression which points to the code context</param>
        /// <param name="args">The arguments being passed to the function</param>
        /// <param name="functionRestriction">A restriction for the built-in function, method desc, etc...</param>
        /// <param name="bind">A delegate to perform the actual call to the method.</param>
        internal DynamicMetaObject/*!*/ MakeBuiltinFunctionCall(DynamicMetaObjectBinder/*!*/ call, Expression/*!*/ codeContext, DynamicMetaObject/*!*/ function, DynamicMetaObject/*!*/[] args, bool hasSelf, bool enforceProtected, BindingRestrictions/*!*/ functionRestriction, Func<DynamicMetaObject/*!*/[]/*!*/, BindingResult/*!*/> bind) {
            DynamicMetaObject res = null;

            // produce an error if all overloads are generic
            if (IsOnlyGeneric) {
                return BindingHelpers.TypeErrorGenericMethod(DeclaringType, Name, functionRestriction);
            }

            // swap the arguments if we have a reversed operator
            if (IsReversedOperator) {
                ArrayUtils.SwapLastTwo(args);
            }

            // if we have a user defined operator for **args then transform it into a PythonDictionary
            CallSignature sig = BindingHelpers.GetCallSignature(call);
            if (sig.HasDictionaryArgument()) {
                int index = sig.IndexOf(ArgumentType.Dictionary);
                if (hasSelf) {
                    index++;
                }

                DynamicMetaObject dict = args[index];
                
                if (!(dict.Value is IDictionary)) {
                    // The DefaultBinder only handles types that implement IDictionary.  Here we have an
                    // arbitrary user-defined mapping type.  We'll convert it into a PythonDictionary
                    // and then have an embedded dynamic site pass that dictionary through to the default
                    // binder.
                    DynamicMetaObject[] dynamicArgs = ArrayUtils.Insert(function, args);

                    dynamicArgs[index + 1] = new DynamicMetaObject(
                        Expression.Call(
                           typeof(PythonOps).GetMethod("UserMappingToPythonDictionary"),
                           codeContext,
                           args[index].Expression,
                           Ast.Constant(Name)
                        ),
                        BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()),
                        PythonOps.UserMappingToPythonDictionary(BinderState.GetBinderState(call).Context, dict.Value, Name)
                    );

                    if (call is IPythonSite) {
                        dynamicArgs = ArrayUtils.Insert(
                            new DynamicMetaObject(codeContext, BindingRestrictions.Empty),
                            dynamicArgs
                        );
                    }

                    return new DynamicMetaObject(
                        Ast.Dynamic(
                            call,
                            typeof(object),
                            DynamicUtils.GetExpressions(dynamicArgs)
                        ),
                        BindingRestrictions.Combine(dynamicArgs).Merge(BindingRestrictionsHelpers.GetRuntimeTypeRestriction(dict.Expression, dict.GetLimitType()))
                    );
                }
            }

            // do the appropriate calling logic
            BindingResult result = bind(args);

            // validate the result
            BindingTarget target = result.Target;
            res = result.MetaObject;

            // BUG: enforceProtected should alwyas be enforced, but we have some tests that depend upon it not being enforced.
            if (enforceProtected && target.Method != null && (target.Method.IsFamily || target.Method.IsFamilyOrAssembly)) {
                // report an error when calling a protected member
                res = new DynamicMetaObject(
                    BindingHelpers.TypeErrorForProtectedMember(
                        target.Method.DeclaringType,
                        target.Method.Name
                    ),
                    res.Restrictions
                );
            } else if (IsBinaryOperator && args.Length == 2 && res.Expression.NodeType == ExpressionType.Throw) {
                // Binary Operators return NotImplemented on failure.
                res = new DynamicMetaObject(
                    Ast.Property(null, typeof(PythonOps), "NotImplemented"),
                    res.Restrictions
                );
            }

            // add any warnings that are applicable for calling this function
            WarningInfo info;

            if (target.Method != null && BindingWarnings.ShouldWarn(BinderState.GetBinderState(call).Binder, target.Method, out info)) {
                res = info.AddWarning(codeContext, res);
            }            

            // finally add the restrictions for the built-in function and return the result.
            res = new DynamicMetaObject(
                res.Expression,
                functionRestriction.Merge(res.Restrictions)
            );

            // The function can return something typed to boolean or int.
            // If that happens, we need to apply Python's boxing rules.
            if (res.Expression.Type == typeof(bool) || res.Expression.Type == typeof(int)) {
                res = new DynamicMetaObject(
                    AstUtils.Convert(res.Expression, typeof(object)),
                    res.Restrictions
                );
            }

            return res;
        }