Exemple #1
0
        private static Expression <T> Stitch <T>(Expression binding, LambdaSignature <T> signature) where T : class
        {
            Type targetType = typeof(T);
            Type siteType   = typeof(CallSite <T>);

            var body = new ReadOnlyCollectionBuilder <Expression>(3);

            body.Add(binding);

            var site    = Expression.Parameter(typeof(CallSite), "$site");
            var @params = signature.Parameters.AddFirst(site);

            Expression updLabel = Expression.Label(CallSiteBinder.UpdateLabel);

#if DEBUG
            // put the AST into the constant pool for debugging purposes
            updLabel = Expression.Block(
                Expression.Constant(binding, typeof(Expression)),
                updLabel
                );
#endif

            body.Add(updLabel);
            body.Add(
                Expression.Label(
                    signature.ReturnLabel,
                    Expression.Condition(
                        Expression.Call(
                            typeof(CallSiteOps).GetMethod("SetNotMatched"),
                            @params.First()
                            ),
                        Expression.Default(signature.ReturnLabel.Type),
                        Expression.Invoke(
                            Expression.Property(
                                Expression.Convert(site, siteType),
                                typeof(CallSite <T>).GetProperty("Update")
                                ),
                            new TrueReadOnlyCollection <Expression>(@params)
                            )
                        )
                    )
                );

            return(new Expression <T>(
                       Expression.Block(body),
                       "CallSite.Target",
                       true, // always compile the rules with tail call optimization
                       new TrueReadOnlyCollection <ParameterExpression>(@params)
                       ));
        }
        private static Expression <T> Stitch <T>(Expression binding, LambdaSignature <T> signature) where T : class
        {
            ParameterExpression expression;
            Type type = typeof(CallSite <T>);
            ReadOnlyCollectionBuilder <Expression> expressions = new ReadOnlyCollectionBuilder <Expression>(3)
            {
                binding
            };

            ParameterExpression[] source = signature.Parameters.AddFirst <ParameterExpression>(expression = Expression.Parameter(typeof(CallSite), "$site"));
            Expression            item   = Expression.Label(UpdateLabel);

            expressions.Add(item);
            expressions.Add(Expression.Label(signature.ReturnLabel, Expression.Condition(Expression.Call(typeof(CallSiteOps).GetMethod("SetNotMatched"), source.First <ParameterExpression>()), Expression.Default(signature.ReturnLabel.Type), Expression.Invoke(Expression.Property(Expression.Convert(expression, type), typeof(CallSite <T>).GetProperty("Update")), new TrueReadOnlyCollection <Expression>(source)))));
            return(new Expression <T>(Expression.Block(expressions), "CallSite.Target", true, new TrueReadOnlyCollection <ParameterExpression>(source)));
        }
        internal T BindCore <T>(CallSite <T> site, object[] args) where T : class
        {
            T local = this.BindDelegate <T>(site, args);

            if (local != null)
            {
                return(local);
            }
            LambdaSignature <T> instance = LambdaSignature <T> .Instance;
            Expression          binding  = this.Bind(args, instance.Parameters, instance.ReturnLabel);

            if (binding == null)
            {
                throw Error.NoOrInvalidRuleProduced();
            }
            if (!AppDomain.CurrentDomain.IsHomogenous)
            {
                throw Error.HomogenousAppDomainRequired();
            }
            T target = Stitch <T>(binding, instance).Compile();

            this.CacheTarget <T>(target);
            return(target);
        }
Exemple #4
0
        // TODO: This should be merged into CallSiteBinder.
        private static LambdaExpression /*!*/ Stitch <T>(Expression binding, LambdaSignature <T> signature, LabelTarget returnLabel) where T : class
        {
            Expression updLabel = Expression.Label(CallSiteBinder.UpdateLabel);

            var site    = Expression.Parameter(typeof(CallSite), "$site");
            var @params = ArrayUtils.Insert(site, signature.Parameters);

            Expression body;

            if (returnLabel != signature.ReturnLabel)
            {
                // TODO:
                // This allows the binder to produce a strongly typed binding expression that gets boxed
                // if the call site's return value is of type object.
                // The current implementation of CallSiteBinder is too strict as it requires the two types to be reference-assignable.

                var tmp = Expression.Parameter(typeof(object));
                body = Expression.Convert(
                    Expression.Block(new[] { tmp },
                                     binding,
                                     updLabel,
                                     Expression.Label(
                                         returnLabel,
                                         Expression.Condition(
                                             Expression.NotEqual(
                                                 Expression.Assign(
                                                     tmp,
                                                     Expression.Invoke(
                                                         Expression.Property(
                                                             Expression.Convert(site, typeof(CallSite <T>)),
                                                             typeof(CallSite <T>).GetProperty("Update")
                                                             ),
                                                         @params
                                                         )
                                                     ),
                                                 AstUtils.Constant(null)
                                                 ),
                                             Expression.Convert(tmp, returnLabel.Type),
                                             Expression.Default(returnLabel.Type)
                                             )
                                         )
                                     ),
                    typeof(object)
                    );
            }
            else
            {
                body = Expression.Block(
                    binding,
                    updLabel,
                    Expression.Label(
                        returnLabel,
                        Expression.Invoke(
                            Expression.Property(
                                Expression.Convert(site, typeof(CallSite <T>)),
                                typeof(CallSite <T>).GetProperty("Update")
                                ),
                            @params
                            )
                        )
                    );
            }

            return(Expression.Lambda <T>(
                       body,
                       "CallSite.Target",
                       true, // always compile the rules with tail call optimization
                       @params
                       ));
        }