public static BuiltinFunction MakeOrAdd(BuiltinFunction existing, string name, MethodBase mi, FunctionType funcType)
 {
     if (existing != null) {
         existing.AddMethod(mi);
         return existing;
     } else {
         return MakeMethod(name, mi, funcType);
     }
 }
        private void FindMatchingTargets(Type[] sig, MethodBase[] targets, BuiltinFunction rm)
        {
            int args = sig.Length;

            foreach (MethodBase mb in targets) {
                ParameterInfo[] pis = mb.GetParameters();
                if (pis.Length != args)
                    continue;

                // Check each parameter type for an exact match.
                bool match = true;
                for (int i = 0; i < args; i++)
                    if (pis[i].ParameterType != sig[i]) {
                        match = false;
                        break;
                    }
                if (!match)
                    continue;

                // Okay, we have a match, add it to the list.
                rm.AddMethod(mb);
            }
        }
        // Use indexing on generic methods to provide a new reflected method with targets bound with
        // the supplied type arguments.
        public object this[object key]
        {
            get {
                // Retrieve the list of type arguments from the index.
                Type[] types;
                Tuple typesTuple = key as Tuple;

                if (typesTuple != null) {
                    types = new Type[typesTuple.Count];
                    for (int i = 0; i < types.Length; i++) {
                        types[i] = Converter.ConvertToType(typesTuple[i]);
                    }
                } else {
                    types = new Type[] { Converter.ConvertToType(key) };
                }

                // Start building a new ReflectedMethod that will contain targets with bound type
                // arguments.
                BuiltinFunction rm = new BuiltinFunction();

                // Search for generic targets with the correct arity (number of type parameters).
                // Compatible targets must be MethodInfos by definition (constructors never take
                // type arguments).
                int arity = types.Length;
                foreach (MethodBase mb in targets) {
                    MethodInfo mi = mb as MethodInfo;
                    if (mi == null)
                        continue;
                    if (mi.ContainsGenericParameters && mi.GetGenericArguments().Length == arity)
                        rm.AddMethod(mi.MakeGenericMethod(types));
                }
                if (rm.Targets == null)
                    throw Ops.TypeError(string.Format("bad type args to this generic method {0}", this));

                rm.Name = Name;
                rm.FunctionType = FunctionType | FunctionType.OptimizeChecked;    // don't want to optimize & whack our dictionary.

                return rm;
            }
        }