/// <summary>
        /// Builds the restrictions for calling with keyword arguments.  The restrictions include
        /// tests on the individual keys of the dictionary to ensure they have the same names.
        /// </summary>
        private static BindingRestrictions MakeParamsDictionaryTest(IList <DynamicMetaObject> args, bool testTypes)
        {
            IDictionary           dict     = (IDictionary)args[args.Count - 1].Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            // verify the dictionary has the same count and arguments.

            string[] names = new string[dict.Count];
            Type[]   types = testTypes ? new Type[dict.Count] : null;
            int      index = 0;

            while (dictEnum.MoveNext())
            {
                if (dictEnum.Entry.Key is string name)
                {
                    names[index] = name;
                }
                else if (dictEnum.Entry.Key is Extensible <string> ename)
                {
                    names[index] = ename.Value;
                }
                else
                {
                    throw ScriptingRuntimeHelpers.SimpleTypeError(
                              $"expected string for dictionary argument, got {dictEnum.Entry.Key}");
                }
                if (types != null)
                {
                    types[index] = CompilerHelpers.GetType(dictEnum.Entry.Value);
                }
                index++;
            }

            return(BindingRestrictions.GetExpressionRestriction(
                       Expression.AndAlso(
                           Expression.TypeIs(args[args.Count - 1].Expression, typeof(IDictionary)),
                           Expression.Call(
                               typeof(BinderOps).GetMethod(nameof(BinderOps.CheckDictionaryMembers)),
                               Expression.Convert(args[args.Count - 1].Expression, typeof(IDictionary)),
                               AstUtils.Constant(names),
                               testTypes ? AstUtils.Constant(types) : AstUtils.Constant(null, typeof(Type[]))
                               )
                           )
                       ));
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Throws a formatted exception if no overload matchs.
        /// </summary>
        /// <param name="sig">Passed signature which should be used</param>
        /// <param name="targets">Given targets, which does not fit to the signature</param>
        /// <example>
        /// <code language="cs" title="Cause overload exceptiob"><![CDATA[
        /// # Will cause an exception:
        /// from System import Convert, Double
        /// Convert.ToInt32.Overloads[Double, Double](24)
        /// ]]></code>
        /// </example>
        public void ThrowOverloadException(Type[] sig, IList <MethodBase> targets)
        {
            // Create info for given signature
            System.Text.StringBuilder sigInfo = new System.Text.StringBuilder();
            sigInfo.Append((targets.Count > 0 ? targets[0].Name : "") + "[");
            foreach (var type in sig)
            {
                if (!sigInfo.ToString().endswith("["))
                {
                    sigInfo.Append(", ");
                }

                sigInfo.Append(type.Name);
            }
            sigInfo.Append("]");

            // Get possible overloads.
            System.Text.StringBuilder possibleOverloads = new System.Text.StringBuilder();

            foreach (var overload in targets)
            {
                if (possibleOverloads.Length > 0)
                {
                    possibleOverloads.Append(", ");
                }

                possibleOverloads.Append("[");
                foreach (var param in overload.GetParameters())
                {
                    if (!possibleOverloads.ToString().endswith("["))
                    {
                        possibleOverloads.Append(", ");
                    }
                    possibleOverloads.Append(param.ParameterType.Name);
                }
                possibleOverloads.Append("]");
            }

            throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}. Expected {1}", sigInfo.ToString(),
                                                                        possibleOverloads.ToString()));
        }
Ejemplo n.º 3
0
        private object GetOverload(Type[] sig, IList <MethodBase> targets, bool wrapCtors)
        {
            // We can still end up with more than one target since generic and non-generic
            // methods can share the same name and signature. So we'll build up a new
            // reflected method with all the candidate targets. A caller can then index this
            // reflected method if necessary in order to provide generic type arguments and
            // fully disambiguate the target.

            // Search for targets with the right number of arguments.
            BuiltinFunction bf;

            BuiltinFunction.TypeList tl = new BuiltinFunction.TypeList(sig);
            lock (_function.OverloadDictionary) {
                if (!_function.OverloadDictionary.TryGetValue(tl, out bf))
                {
                    MethodBase[] newTargets = FindMatchingTargets(sig, targets);

                    if (targets == null)
                    {
                        throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("No match found for the method signature {0}", sig));    // TODO: Sig to usable display
                    }
                    _function.OverloadDictionary[tl] = bf = new BuiltinFunction(_function.Name, newTargets, Function.DeclaringType, _function.FunctionType);
                }
            }

            if (_instance != null)
            {
                return(bf.BindToInstance(_instance));
            }
            else if (wrapCtors)
            {
                return(GetTargetFunction(bf));
            }
            else
            {
                return(bf);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Builds the restrictions for calling with keyword arguments.  The restrictions include
        /// tests on the individual keys of the dictionary to ensure they have the same names.
        /// </summary>
        private static Restrictions MakeParamsDictionaryTest(IList <MetaObject> args, bool testTypes)
        {
            IDictionary           dict     = (IDictionary)args[args.Count - 1].Value;
            IDictionaryEnumerator dictEnum = dict.GetEnumerator();

            // verify the dictionary has the same count and arguments.

            string[] names = new string[dict.Count];
            Type[]   types = testTypes ? new Type[dict.Count] : null;
            int      index = 0;

            while (dictEnum.MoveNext())
            {
                string name = dictEnum.Entry.Key as string;
                if (name == null)
                {
                    throw ScriptingRuntimeHelpers.SimpleTypeError(String.Format("expected string for dictionary argument got {0}", dictEnum.Entry.Key));
                }
                names[index] = name;
                if (types != null)
                {
                    types[index] = CompilerHelpers.GetType(dictEnum.Entry.Value);
                }
                index++;
            }

            return(Restrictions.GetExpressionRestriction(
                       Ast.AndAlso(
                           Ast.TypeIs(args[args.Count - 1].Expression, typeof(IDictionary)),
                           Ast.Call(
                               typeof(BinderOps).GetMethod("CheckDictionaryMembers"),
                               Ast.Convert(args[args.Count - 1].Expression, typeof(IDictionary)),
                               Ast.Constant(names),
                               testTypes ? Ast.Constant(types) : Ast.Constant(null, typeof(Type[]))
                               )
                           )
                       ));
        }