/// <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); }
/// <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); }
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)); }
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)); } }