예제 #1
0
        public virtual StandardRule <T> MakeRule()
        {
            CallAction callAction = CallAction.Make(Action.Signature);

            // TODO: First try to make a rule for get-member and see if we get back a constant method to call
            //GetMemberAction getAction = GetMemberAction.Make(Action.Name);
            //StandardRule<T> getRule = Binder.GetRule<T>(Context, getAction, new object[] { _args[0] });

            // otherwise, make a generic rule with embedded dynamic sites
            StandardRule <T> rule = new StandardRule <T>();

            rule.SetTest(Ast.True());
            Expression getExpr = Ast.Action.GetMember(Action.Name, typeof(object), rule.Parameters[0]);

            Expression[] callArgs = new Expression[rule.ParameterCount];
            callArgs[0] = getExpr;
            for (int i = 1; i < callArgs.Length; i++)
            {
                callArgs[i] = rule.Parameters[i];
            }

            //TODO support non-object return types
            Expression callExpr = Ast.Action.Call(callAction, typeof(object), callArgs);

            rule.SetTarget(Ast.Return(callExpr));

            return(rule);
        }
예제 #2
0
        /// <summary>
        /// Given a CallAction and its arguments gets the number by which the parameter count should
        /// be adjusted due to the params array to get the logical number of parameters.
        /// </summary>
        protected static int GetParamsArgumentCountAdjust(CallAction action, object[] args)
        {
            int paramsCount  = 0;
            int listArgIndex = action.Signature.IndexOf(ArgumentKind.List);

            if (listArgIndex > -1)
            {
                paramsCount--;
                IList <object> paramArgs = args[listArgIndex + 1] as IList <object>;
                if (paramArgs != null)
                {
                    paramsCount += paramArgs.Count;
                }
            }
            return(paramsCount);
        }
예제 #3
0
        public static Type[] GetArgumentTypes(CallAction action, object[] args)
        {
            List <Type> res = new List <Type>();

            for (int i = 1; i < args.Length; i++)
            {
                switch (action.Signature.GetArgumentKind(i - 1))
                {
                case ArgumentKind.Simple:
                case ArgumentKind.Instance:
                case ArgumentKind.Named:
                    res.Add(CompilerHelpers.GetType(args[i]));
                    continue;

                case ArgumentKind.List:
                    IList <object> list = args[i] as IList <object>;
                    if (list == null)
                    {
                        return(null);
                    }

                    for (int j = 0; j < list.Count; j++)
                    {
                        res.Add(CompilerHelpers.GetType(list[j]));
                    }
                    break;

                case ArgumentKind.Dictionary:
                    // caller needs to process these...
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
            return(res.ToArray());
        }
예제 #4
0
 public static CallAction Call(int argumentCount)
 {
     return(CallAction.Make(argumentCount));
 }
예제 #5
0
        public virtual Statement MakeInvalidParametersError(MethodBinder binder, DynamicAction action, CallType callType, IList <MethodBase> targets, StandardRule rule, object [] args)
        {
            int  minArgs = Int32.MaxValue;
            int  maxArgs = Int32.MinValue;
            int  maxDflt = Int32.MinValue;
            int  argsProvided = args.Length - 1; // -1 to remove the object we're calling
            bool hasArgList = false, hasNamedArgument = false;
            Dictionary <string, bool> namedArgs = new Dictionary <string, bool>();

            CallAction ca = action as CallAction;

            if (ca != null)
            {
                hasNamedArgument = ca.Signature.HasNamedArgument();
                int dictArgIndex = ca.Signature.IndexOf(ArgumentKind.Dictionary);

                if (dictArgIndex > -1)
                {
                    argsProvided--;
                    IAttributesCollection iac = args[dictArgIndex + 1] as IAttributesCollection;
                    if (iac != null)
                    {
                        foreach (KeyValuePair <object, object> kvp in iac)
                        {
                            namedArgs[(string)kvp.Key] = false;
                        }
                    }
                }

                argsProvided += GetParamsArgumentCountAdjust(ca, args);
                foreach (SymbolId si in ca.Signature.GetArgumentNames())
                {
                    namedArgs[SymbolTable.IdToString(si)] = false;
                }
            }
            else
            {
                maxArgs = minArgs = rule.Parameters.Length;
                maxDflt = 0;
            }

            foreach (MethodBase mb in targets)
            {
                if (callType == CallType.ImplicitInstance && CompilerHelpers.IsStatic(mb))
                {
                    continue;
                }

                ParameterInfo[] pis  = mb.GetParameters();
                int             cnt  = pis.Length;
                int             dflt = 0;

                if (!CompilerHelpers.IsStatic(mb) && callType == CallType.None)
                {
                    cnt++;
                }

                foreach (ParameterInfo pi in pis)
                {
                    if (pi.ParameterType == typeof(CodeContext))
                    {
                        cnt--;
                    }
                    else if (CompilerHelpers.IsParamArray(pi))
                    {
                        cnt--;
                        hasArgList = true;
                    }
                    else if (CompilerHelpers.IsParamDictionary(pi))
                    {
                        cnt--;
                    }
                    else if (!CompilerHelpers.IsMandatoryParameter(pi))
                    {
                        dflt++;
                        cnt--;
                    }

                    namedArgs[pi.Name] = true;
                }

                minArgs = System.Math.Min(cnt, minArgs);
                maxArgs = System.Math.Max(cnt, maxArgs);
                maxDflt = System.Math.Max(dflt, maxDflt);
            }

            foreach (KeyValuePair <string, bool> kvp in namedArgs)
            {
                if (kvp.Value == false)
                {
                    // unbound named argument.
                    return(rule.MakeError(
                               Ast.Ast.Call(
                                   typeof(RuntimeHelpers).GetMethod("TypeErrorForExtraKeywordArgument"),
                                   Ast.Ast.Constant(binder._name, typeof(string)),
                                   Ast.Ast.Constant(kvp.Key, typeof(string))
                                   )
                               ));
                }
            }

            return(rule.MakeError(
                       Ast.Ast.Call(
                           typeof(RuntimeHelpers).GetMethod("TypeErrorForIncorrectArgumentCount", new Type[] {
                typeof(string), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)
            }),
                           Ast.Ast.Constant(binder._name, typeof(string)), // name
                           Ast.Ast.Constant(minArgs),                      // min formal normal arg cnt
                           Ast.Ast.Constant(maxArgs),                      // max formal normal arg cnt
                           Ast.Ast.Constant(maxDflt),                      // default cnt
                           Ast.Ast.Constant(argsProvided),                 // args provided
                           Ast.Ast.Constant(hasArgList),                   // hasArgList
                           Ast.Ast.Constant(hasNamedArgument)              // kwargs provided
                           )
                       ));
        }