Пример #1
0
            /// <summary>
            /// Gets expression representing cost of argument binding operation.
            /// The expression can be constant.
            /// </summary>
            public virtual Expression BindCostOf(int srcarg, Type ptype, bool ismandatory, bool ignorecost)
            {
                var key = new TmpVarKey()
                {
                    Priority = 100, ArgIndex = srcarg, TargetTypeOpt = ptype, Prefix = "costOf" + (ismandatory ? "" : "Opt")
                };

                // lookup cache
                TmpVarValue value;

                if (!_tmpvars.TryGetValue(key, out value))
                {
                    // bind cost expression
                    value = new TmpVarValue();

                    var expr_cost = ignorecost ? Expression.Constant(ConversionCost.Pass) : ConvertExpression.BindCost(BindArgument(srcarg), ptype);
                    if (expr_cost is ConstantExpression)
                    {
                        value.Expression = expr_cost;
                    }
                    else
                    {
                        value.TrueInitializer  = expr_cost;
                        value.FalseInitializer = Expression.Constant(ismandatory ? ConversionCost.MissingArgs : ConversionCost.DefaultValue);
                        value.Expression       = Expression.Variable(typeof(ConversionCost), key.VariableName);
                    }

                    _tmpvars[key] = value;
                }

                //
                return(value.Expression);
            }
Пример #2
0
            /// <summary>
            /// Gets expression resulting in <see cref="ConversionCost.Pass"/> or <see cref="ConversionCost.TooManyArgs"/> based on actual arguments count.
            /// </summary>
            public virtual Expression BindCostOfTooManyArgs(int expectedargs)
            {
                var key = new TmpVarKey()
                {
                    Priority = 100, ArgIndex = expectedargs, Prefix = "istoomany"
                };

                // lookup cache
                TmpVarValue value;

                if (!_tmpvars.TryGetValue(key, out value))
                {
                    // bind cost expression
                    value = new TmpVarValue();

                    var expr_argc = BindArgsCount();
                    if (expr_argc is ConstantExpression)
                    {
                        var argc = (int)((ConstantExpression)expr_argc).Value;
                        value.Expression = Expression.Constant((argc > expectedargs) ? ConversionCost.TooManyArgs : ConversionCost.Pass);
                    }
                    else
                    {
                        // istoomanyX = TooManyArgs;  in case we endup in this condition
                        value.TrueInitializer  = Expression.Constant(ConversionCost.TooManyArgs);
                        value.FalseInitializer = Expression.Constant(ConversionCost.Pass);
                        value.Expression       = Expression.Variable(typeof(ConversionCost), key.VariableName);
                    }

                    _tmpvars[key] = value;
                }

                //
                return(value.Expression);
            }
Пример #3
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    // cache the argument value

                    var key = new TmpVarKey()
                    {
                        Priority = 0 /*first*/, ArgIndex = srcarg, Prefix = "arg"
                    };
                    TmpVarValue value;

                    if (!_tmpvars.TryGetValue(key, out value))
                    {
                        value = new TmpVarValue();

                        value.TrueInitializer  = Expression.ArrayIndex(_argsarray, Expression.Constant(srcarg));
                        value.FalseInitializer = ConvertExpression.BindDefault(value.TrueInitializer.Type); // ~ default(_argsarray.Type.GetElementType())
                        value.Expression       = Expression.Variable(value.TrueInitializer.Type, "arg_" + srcarg);

                        //
                        _tmpvars[key] = value;
                    }

                    if (targetparam != null)
                    {
                        // create specialized variable with default value
                        if (targetparam.HasDefaultValue)
                        {
                            var @default         = targetparam.DefaultValue;
                            var defaultValueExpr = Expression.Constant(@default);
                            var defaultValueStr  = (@default != null) ? @default.ToString() : "NULL";

                            //
                            var key2 = new TmpVarKey()
                            {
                                Priority = 1 /*after key*/, ArgIndex = srcarg, Prefix = "arg(" + defaultValueStr + ")"
                            };
                            TmpVarValue value2;
                            if (!_tmpvars.TryGetValue(key2, out value2))
                            {
                                value2 = new TmpVarValue();

                                value2.TrueInitializer  = ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx);   // reuse the value already obtained from argv
                                value2.FalseInitializer = ConvertExpression.Bind(defaultValueExpr, value2.TrueInitializer.Type, _ctx); // ~ default(targetparam)
                                value2.Expression       = Expression.Variable(value2.TrueInitializer.Type, "arg_" + srcarg + "_" + defaultValueStr);

                                //
                                _tmpvars[key2] = value2;
                            }

                            return(value2.Expression);   // already converted to targetparam.ParameterType
                        }
                    }

                    return((targetparam == null)
                        ? value.Expression
                        : ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx));
                }
Пример #4
0
                public override Expression BindArgument(int srcarg, ParameterInfo targetparam = null)
                {
                    Debug.Assert(srcarg >= 0);

                    // cache the argument value

                    var key = new TmpVarKey()
                    {
                        Priority = 0 /*first*/, ArgIndex = srcarg, Prefix = "arg"
                    };
                    TmpVarValue value;

                    if (!_tmpvars.TryGetValue(key, out value))
                    {
                        value = new TmpVarValue();

                        value.TrueInitializer  = Expression.ArrayIndex(_argsarray, Expression.Constant(srcarg));
                        value.FalseInitializer = ConvertExpression.BindDefault(value.TrueInitializer.Type); // ~ default(_argsarray.Type.GetElementType())
                        value.Expression       = Expression.Variable(value.TrueInitializer.Type, "arg_" + srcarg);

                        //
                        _tmpvars[key] = value;
                    }

                    if (targetparam != null)
                    {
                        DefaultValueAttribute defaultValueAttr = null;

                        // create specialized variable with default value
                        if (targetparam.HasDefaultValue || (defaultValueAttr = targetparam.GetCustomAttribute <DefaultValueAttribute>()) != null)
                        {
                            Debug.Assert(!targetparam.ParameterType.IsByRef);   // parameter with a default value cannot be byref (at least we don't expect it)

                            // just for debugging purposes:
                            var defaultValueStr = defaultValueAttr != null
                                ? defaultValueAttr.FieldName
                                : targetparam.DefaultValue?.ToString() ?? "NULL";

                            // the default value expression
                            var defaultValueExpr = defaultValueAttr != null
                                ? BindDefaultValue(targetparam.Member.DeclaringType, defaultValueAttr)
                                : Expression.Constant(targetparam.DefaultValue);

                            //
                            var key2 = new TmpVarKey()
                            {
                                Priority = 1 /*after key*/, ArgIndex = srcarg, Prefix = "default(" + defaultValueStr + ")"
                            };
                            TmpVarValue value2;
                            if (!_tmpvars.TryGetValue(key2, out value2))
                            {
                                value2 = new TmpVarValue();

                                value2.TrueInitializer  = ConvertExpression.Bind(value.Expression, targetparam.ParameterType, _ctx);   // reuse the value already obtained from argv
                                value2.FalseInitializer = ConvertExpression.Bind(defaultValueExpr, value2.TrueInitializer.Type, _ctx); // ~ default(targetparam)
                                value2.Expression       = Expression.Variable(value2.TrueInitializer.Type, "default_" + srcarg + "_" + defaultValueStr);

                                //
                                _tmpvars[key2] = value2;
                            }

                            return(value2.Expression);   // already converted to targetparam.ParameterType
                        }
                    }

                    if (targetparam == null)
                    {
                        return(value.Expression);
                    }
                    else
                    {
                        var ptype = targetparam.ParameterType;

                        // TODO: ptype.IsByRef -> implement write-back after the invocation
                        if (ptype.IsByRef)
                        {
                            ptype = ptype.GetElementType(); // LINQ will create a local variable for it implicitly
                        }

                        return(ConvertExpression.Bind(value.Expression, ptype, _ctx));
                    }
                }