Exemplo n.º 1
0
        protected override ActualArguments CreateActualArguments(IList <DynamicMetaObject> namedArgs, IList <string> argNames, int preSplatLimit, int postSplatLimit)
        {
            var res = new List <DynamicMetaObject>();

            if (CallType == CallTypes.ImplicitInstance)
            {
                res.Add(_args[0]);
            }

            for (int i = 0; i < _signature.ArgumentCount; i++)
            {
                var arg = GetArgument(i);

                switch (_signature.GetArgumentKind(i))
                {
                case ArgumentType.Simple:
                case ArgumentType.Instance:
                    res.Add(arg);
                    break;

                case ArgumentType.List:
                    // TODO: lazy splat
                    IList <object> list = arg.Value as IList <object>;
                    if (list == null)
                    {
                        _invalidSplattee = arg;
                        return(null);
                    }

                    for (int j = 0; j < list.Count; j++)
                    {
                        res.Add(
                            DynamicMetaObject.Create(
                                list[j],
                                Ast.Call(
                                    Ast.Convert(
                                        arg.Expression,
                                        typeof(IList <object>)
                                        ),
                                    typeof(IList <object>).GetMethod("get_Item"),
                                    AstUtils.Constant(j)
                                    )
                                )
                            );
                    }
                    break;

                case ArgumentType.Named:
                case ArgumentType.Dictionary:
                    // already processed
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            res.TrimExcess();
            return(new ActualArguments(res, namedArgs, argNames, _callType == CallTypes.ImplicitInstance ? 1 : 0, 0, -1, -1));
        }
Exemplo n.º 2
0
        private void SplatDictionaryArgument(IList <string> splattedNames, IList <DynamicMetaObject> splattedArgs)
        {
            Assert.NotNull(splattedNames, splattedArgs);

            DynamicMetaObject     dictMo   = GetArgument(_signature.ArgumentCount - 1);
            IDictionary           dict     = (IDictionary)dictMo.Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            while (dictEnum.MoveNext())
            {
                DictionaryEntry de = dictEnum.Entry;

                if (de.Key is string)
                {
                    splattedNames.Add((string)de.Key);
                    splattedArgs.Add(
                        DynamicMetaObject.Create(
                            de.Value,
                            Ast.Call(
                                AstUtils.Convert(dictMo.Expression, typeof(IDictionary)),
                                typeof(IDictionary).GetMethod("get_Item"),
                                AstUtils.Constant(de.Key as string)
                                )
                            )
                        );
                }
            }
        }
Exemplo n.º 3
0
        private void SplatDictionaryArgument(IList <string> splattedNames, IList <DynamicMetaObject> splattedArgs)
        {
            Assert.NotNull(splattedNames, splattedArgs);
            Debug.Assert(_signature.HasDictionaryArgument());

            DynamicMetaObject     dictMo   = GetArgument(_signature.IndexOf(ArgumentType.Dictionary));
            IDictionary           dict     = (IDictionary)dictMo.Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            while (dictEnum.MoveNext())
            {
                DictionaryEntry de = dictEnum.Entry;

                string strKey = de.Key is string s ? s : de.Key is Extensible <string> es ? es.Value : null;
                if (strKey != null)
                {
                    splattedNames.Add(strKey);
                    splattedArgs.Add(
                        DynamicMetaObject.Create(
                            de.Value,
                            Ast.Call(
                                AstUtils.Convert(dictMo.Expression, typeof(IDictionary)),
                                typeof(IDictionary).GetMethod("get_Item"),
                                AstUtils.Constant(strKey)
                                )
                            )
                        );
                }
            }
        }
 internal static DynamicMetaObject /*!*/ MakeSplattedItem(IList /*!*/ list, Expression /*!*/ listVariable, int index)
 {
     return(DynamicMetaObject.Create(
                list[index],
                Ast.Call(listVariable, typeof(IList).GetMethod("get_Item"), AstUtils.Constant(index))
                ));
 }
Exemplo n.º 5
0
        public static Expression ApplyBinder(DynamicMetaObjectBinder binder, bool throwException, params Expression[] expressions)
        {
            var result = binder.Bind(DynamicMetaObject.Create(null, expressions[0]),
                                     expressions.Skip(1).Select(e =>
                                                                DynamicMetaObject.Create(null, e)).ToArray()
                                     );

            if (result.Expression.NodeType == ExpressionType.Convert)
            {
                var convert = (UnaryExpression)result.Expression;
                return(convert.Operand);
            }
            if (result.Expression.NodeType == ExpressionType.Throw)
            {
                if (throwException)
                {
                    // throw the exception
                    Expression.Lambda(result.Expression).Compile().DynamicInvoke();
                }
                else
                {
                    return(null);
                }
            }
            return(result.Expression);
        }
Exemplo n.º 6
0
            public T /*!*/ Bind(DynamicMetaObjectBinder /*!*/ binder, int compilationThreshold, object[] args)
            {
                if (CachedBindingInfo <T> .LastInterpretedFailure != null && CachedBindingInfo <T> .LastInterpretedFailure.Binder == binder)
                {
                    // we failed the rule because we have a compiled target available, return the compiled target
                    Debug.Assert(CachedBindingInfo <T> .LastInterpretedFailure.CompiledTarget != null);
                    var res = CachedBindingInfo <T> .LastInterpretedFailure.CompiledTarget;
                    CachedBindingInfo <T> .LastInterpretedFailure = null;
                    return(res);
                }

                // we haven't produced a rule yet....
                var bindingInfo = new CachedBindingInfo <T>(binder, compilationThreshold);

                var targetMO = DynamicMetaObject.Create(args[0], _parameters[1]); // 1 is skipping CallSite

                DynamicMetaObject[] argsMO = new DynamicMetaObject[args.Length - 1];
                for (int i = 0; i < argsMO.Length; i++)
                {
                    argsMO[i] = DynamicMetaObject.Create(args[i + 1], _parameters[i + 2]);
                }
                var binding = binder.Bind(targetMO, argsMO);

                return(CreateDelegate(binding, bindingInfo));
            }
Exemplo n.º 7
0
            public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
            {
                // get the default binding the language would return if we weren't involved
                // This will either access a property on MyDynamicObject or it will report
                // an error in a language appropriate manner.
                DynamicMetaObject errorSuggestion = binder.FallbackInvokeMember(this, args);

                // run through the plugins and replace our current rule.  Running through
                // the list forward means the last plugin has the highest precedence because
                // it may throw away the previous rules if it succeeds.
                for (int i = 0; i < Value._plugins.Length; i++)
                {
                    var pluginDo = DynamicMetaObject.Create(Value._plugins[i],
                                                            Expression.Call(
                                                                typeof(MyDynamicObjectOps).GetMethod("GetPlugin"),
                                                                Expression,
                                                                Expression.Constant(i)
                                                                )
                                                            );

                    errorSuggestion = binder.FallbackInvokeMember(pluginDo, args, errorSuggestion);
                }

                // Do we want DynamicMetaObject to have precedence?  If so then we can do
                // one more bind passing what we've produced so far as the rule.  Or if the
                // plugins have precedence we could just return the value.  We'll do that
                // here based upon the member name.

                if (binder.Name == "Foo")
                {
                    return(binder.FallbackInvokeMember(this, args, errorSuggestion));
                }

                return(errorSuggestion);
            }
Exemplo n.º 8
0
        private static MethodCallExpression TryFindMethod(Type context, string name, params Expression[] parameters)
        {
            var binder = (DynamicMetaObjectBinder)Microsoft.CSharp.RuntimeBinder.Binder.InvokeMember(
                CSharpBinderFlags.None, name, null, context,
                new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null) }
                .Concat(ExpressionHelper.GetBinderArguments(parameters.Length)));
            var result = binder.Bind(DynamicMetaObject.Create(context, Expression.Constant(context)), parameters.Select(e => DynamicMetaObject.Create(null, e)).ToArray());

            if (result.Expression.NodeType == ExpressionType.Throw)
            {
                return(null);
            }
            Expression expr = result.Expression;

            if (expr.NodeType == ExpressionType.Convert)
            {
                expr = expr.CastTo <UnaryExpression>().Operand;
            }
            var methodCall = expr as MethodCallExpression;

            if (methodCall != null && methodCall.Arguments.SequenceEqual(parameters))
            {
                return(methodCall);
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 9
0
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            var instance = Expression.Call(
                DynamicGetMemberMethod,
                target.Expression,
                Expression.Constant(Name),
                Expression.Constant(IgnoreCase));

            return(DynamicMetaObject.Create(target.Value, instance));
        }
Exemplo n.º 10
0
 public DynamicMetaObject GetMetaObject(Expression parameter, int index)
 {
     return(DynamicMetaObject.Create(
                GetArgument(index),
                Expression.Call(
                    s_getArgMethod,
                    AstUtils.Convert(parameter, typeof(ArgumentArray)),
                    AstUtils.Constant(index)
                    )
                ));
 }
Exemplo n.º 11
0
        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            IDictionary <string, object> dictionary = target.Value as IDictionary <string, object>;

            if (dictionary == null)
            {
                throw new InvalidOperationException("Target object is not an ExpandoObject");
            }

            return(DynamicMetaObject.Create(dictionary, Expression.MakeIndex(Expression.Constant(dictionary), Indexer, new Expression[] { Expression.Constant(Name) })));
        }
Exemplo n.º 12
0
 private static DynamicMetaObject[] CreateArgumentMetaObjects(object[] args, ReadOnlyCollection <ParameterExpression> parameters)
 {
     DynamicMetaObject[] mos;
     if (args.Length != 1)
     {
         mos = new DynamicMetaObject[args.Length - 1];
         for (int i = 1; i < args.Length; i++)
         {
             mos[i - 1] = DynamicMetaObject.Create(args[i], parameters[i]);
         }
     }
     else
     {
         mos = DynamicMetaObject.EmptyMetaObjects;
     }
     return(mos);
 }
Exemplo n.º 13
0
        // Original function receives a MethodBase (either a method or a constructor) and
        // builds an Expression object that calls it with supplied parameters. BabelShellfish
        // uses this behavior to add another call to its own inspection method before the
        // requested method is called.
        static Expression InvokeMethod(
            MethodBase mi,
            DynamicMetaObject target,
            DynamicMetaObject[] originalArgs,
            bool expandParameters,
            MethodInvocationType invocationType)
        {
            Expression exprOriginal = InvokeMethodDummy(mi, target, originalArgs, expandParameters, invocationType);

            if (GetInstance().BabelShellfishInspectInvoke.Count <= originalArgs.Length)
            {
                return(exprOriginal);
            }

            List <DynamicMetaObject> inspectArgs = new List <DynamicMetaObject>();

            inspectArgs.Add(DynamicMetaObject.Create(mi, Expression.Constant(mi)));

            if (false == mi.IsStatic)
            {
                inspectArgs.Add(target);
            }

            for (int i = 0; i < originalArgs.Length; i++)
            {
                inspectArgs.Add(originalArgs[i]);
            }

            Expression exprInpect = InvokeMethodDummy(
                GetInstance().BabelShellfishInspectInvoke[inspectArgs.Count - 1],
                target,
                inspectArgs.ToArray(),
                expandParameters,
                MethodInvocationType.Ordinary);

            return(Expression.Block(exprInpect, exprOriginal));
        }
Exemplo n.º 14
0
 private static DynamicMetaObject DMO(dynamic val)
 {
     return(DynamicMetaObject.Create(val, Expression.Constant(val)));
 }
Exemplo n.º 15
0
        /// <summary>
        /// Performs the runtime binding of the dynamic operation on a set of arguments.
        /// </summary>
        /// <param name="args">An array of arguments to the dynamic operation.</param>
        /// <param name="parameters">The array of <see cref="ParameterExpression"/> instances that represent the parameters of the call site in the binding process.</param>
        /// <param name="returnLabel">A LabelTarget used to return the result of the dynamic binding.</param>
        /// <returns>
        /// An Expression that performs tests on the dynamic operation arguments, and
        /// performs the dynamic operation if hte tests are valid. If the tests fail on
        /// subsequent occurrences of the dynamic operation, Bind will be called again
        /// to produce a new <see cref="Expression"/> for the new argument types.
        /// </returns>
        public sealed override Expression Bind(object[] args, ReadOnlyCollection <ParameterExpression> parameters, LabelTarget returnLabel)
        {
            ContractUtils.RequiresNotNull(args, "args");
            ContractUtils.RequiresNotNull(parameters, "parameters");
            ContractUtils.RequiresNotNull(returnLabel, "returnLabel");
            if (args.Length == 0)
            {
                throw Error.OutOfRange("args.Length", 1);
            }
            if (parameters.Count == 0)
            {
                throw Error.OutOfRange("parameters.Count", 1);
            }
            if (args.Length != parameters.Count)
            {
                throw new ArgumentOutOfRangeException("args");
            }

            // Ensure that the binder's ReturnType matches CallSite's return
            // type. We do this so meta objects and language binders can
            // compose trees together without needing to insert converts.
            Type expectedResult;

            if (IsStandardBinder)
            {
                expectedResult = ReturnType;

                if (returnLabel.Type != typeof(void) &&
                    !TypeUtils.AreReferenceAssignable(returnLabel.Type, expectedResult))
                {
                    throw Error.BinderNotCompatibleWithCallSite(expectedResult, this, returnLabel.Type);
                }
            }
            else
            {
                // Even for non-standard binders, we have to at least make sure
                // it works with the CallSite's type to build the return.
                expectedResult = returnLabel.Type;
            }

            DynamicMetaObject target = DynamicMetaObject.Create(args[0], parameters[0]);

            DynamicMetaObject[] metaArgs = CreateArgumentMetaObjects(args, parameters);

            DynamicMetaObject binding = Bind(target, metaArgs);

            if (binding == null)
            {
                throw Error.BindingCannotBeNull();
            }

            Expression          body         = binding.Expression;
            BindingRestrictions restrictions = binding.Restrictions;

            // Ensure the result matches the expected result type.
            if (expectedResult != typeof(void) &&
                !TypeUtils.AreReferenceAssignable(expectedResult, body.Type))
            {
                //
                // Blame the last person that handled the result: assume it's
                // the dynamic object (if any), otherwise blame the language.
                //
                if (target.Value is IDynamicMetaObjectProvider)
                {
                    throw Error.DynamicObjectResultNotAssignable(body.Type, target.Value.GetType(), this, expectedResult);
                }
                else
                {
                    throw Error.DynamicBinderResultNotAssignable(body.Type, this, expectedResult);
                }
            }

            // if the target is IDO, standard binders ask it to bind the rule so we may have a target-specific binding.
            // it makes sense to restrict on the target's type in such cases.
            // ideally IDO metaobjects should do this, but they often miss that type of "this" is significant.
            if (IsStandardBinder && args[0] as IDynamicMetaObjectProvider != null)
            {
                if (restrictions == BindingRestrictions.Empty)
                {
                    throw Error.DynamicBindingNeedsRestrictions(target.Value.GetType(), this);
                }
            }

            restrictions = AddRemoteObjectRestrictions(restrictions, args, parameters);

            // Add the return
            if (body.NodeType != ExpressionType.Goto)
            {
                body = Expression.Return(returnLabel, body);
            }

            // Finally, add restrictions
            if (restrictions != BindingRestrictions.Empty)
            {
                body = Expression.IfThen(restrictions.ToExpression(), body);
            }

            return(body);
        }