Example #1
0
        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);
        }