Example #1
0
        internal MetaObject /*!*/ CreateMetaObject(MetaObjectBinder /*!*/ action, MetaObject /*!*/[] /*!*/ siteArgs)
        {
            var expr = _error ? Ast.Throw(_result) : _result;

            Restrictions restrictions;

            if (_condition != null)
            {
                var deferral = action.Defer(siteArgs);
                expr         = Ast.Condition(_condition, AstUtils.Convert(expr, typeof(object)), deferral.Expression);
                restrictions = deferral.Restrictions;
            }
            else
            {
                restrictions = Restrictions.Empty;
            }

            if (_temps != null)
            {
                expr = Ast.Block(_temps, expr);
            }

            if (_restriction != null)
            {
                restrictions = restrictions.Merge(Restrictions.GetExpressionRestriction(_restriction));
            }

            return(new MetaObject(expr, restrictions));
        }
Example #2
0
 internal MetaObject /*!*/ CreateMetaObject(MetaObjectBinder /*!*/ action, MetaObject /*!*/ context, MetaObject /*!*/[] /*!*/ args)
 {
     return(CreateMetaObject(action, ArrayUtils.Insert(context, args)));
 }
Example #3
0
 public BinderMappingInfo(MetaObjectBinder binder, params ParameterMappingInfo[] mappingInfos)
     : this(binder, (IList <ParameterMappingInfo>)mappingInfos)
 {
 }
        protected override Expression VisitDynamic(DynamicExpression node)
        {
            MetaObjectBinder metaBinder = node.Binder as MetaObjectBinder;

            if (metaBinder == null)
            {
                // don't rewrite non meta-binder nodes, we can't compose them
                return(node);
            }

            // gather the real arguments for the new dynamic site node
            var  args = node.Arguments;
            bool foundSideEffectingArgs = false;
            List <Expression> inputs    = new List <Expression>();

            // parameter mapping is 1 List<ComboParameterMappingInfo> for each meta binder, the inner list
            // contains the mapping info for each particular binder

            List <BinderMappingInfo>    binders = new List <BinderMappingInfo>();
            List <ParameterMappingInfo> myInfo  = new List <ParameterMappingInfo>();

            int actionCount = 0;

            for (int i = 0; i < args.Count; i++)
            {
                Expression e = args[i];

                if (!foundSideEffectingArgs)
                {
                    // attempt to combine the arguments...
                    Expression rewritten = Visit(e);

                    ComboDynamicSiteExpression combo = rewritten as ComboDynamicSiteExpression;
                    ConstantExpression         ce;
                    if (combo != null)
                    {
                        // an action expression we can combine with our own expression

                        // remember how many actions we have so far - if any of our children consume
                        // actions their offset is bumped up
                        int baseActionCount = actionCount;

                        foreach (BinderMappingInfo comboInfo in combo.Binders)
                        {
                            List <ParameterMappingInfo> newInfo = new List <ParameterMappingInfo>();

                            foreach (ParameterMappingInfo info in comboInfo.MappingInfo)
                            {
                                if (info.IsParameter)
                                {
                                    // all of the inputs from the child now become ours
                                    newInfo.Add(ParameterMappingInfo.Parameter(inputs.Count));
                                    inputs.Add(combo.Inputs[info.ParameterIndex]);
                                }
                                else if (info.IsAction)
                                {
                                    newInfo.Add(ParameterMappingInfo.Action(info.ActionIndex + baseActionCount));
                                    actionCount++;
                                }
                                else
                                {
                                    Debug.Assert(info.Constant != null);

                                    // constants can just flow through
                                    newInfo.Add(info);
                                }
                            }

                            binders.Add(new BinderMappingInfo(comboInfo.Binder, newInfo));
                        }

                        myInfo.Add(ParameterMappingInfo.Action(actionCount++));
                    }
                    else if ((ce = rewritten as ConstantExpression) != null)
                    {
                        // we can hoist the constant into the combo
                        myInfo.Add(ParameterMappingInfo.Fixed(ce));
                    }
                    else if (IsSideEffectFree(rewritten))
                    {
                        // we can treat this as an input parameter
                        myInfo.Add(ParameterMappingInfo.Parameter(inputs.Count));
                        inputs.Add(rewritten);
                    }
                    else
                    {
                        // this argument is doing something we don't understand - we have to leave
                        // it as is (an input we consume) and all the remaining arguments need to be
                        // evaluated normally as this could have side effects on them.
                        foundSideEffectingArgs = true;
                        myInfo.Add(ParameterMappingInfo.Parameter(inputs.Count));
                        inputs.Add(e);
                    }
                }
                else
                {
                    // we've already seen an argument which may have side effects, don't do
                    // any more combinations.
                    myInfo.Add(ParameterMappingInfo.Parameter(inputs.Count));
                    inputs.Add(e);
                }
            }
            binders.Add(new BinderMappingInfo(metaBinder, myInfo));
            // TODO: Remove any duplicate inputs (e.g. locals being fed in multiple times)
            return(new ComboDynamicSiteExpression(node.Type, binders, inputs.ToArray()));
        }
Example #5
0
 public BinderMappingInfo(MetaObjectBinder binder, IList <ParameterMappingInfo> mappingInfo)
 {
     Binder      = binder;
     MappingInfo = mappingInfo;
 }