Пример #1
0
        public override object Call(object[] args, string[] names)
        {
            KwArgBinder argBinder = new KwArgBinder(args, names);

            object[] defaults = this.defaults;
            if (defaults.Length != argNames.Length)
            {
                // we need a 1<->1 mapping here for kwarg binder.
                object[] newDefs = new object[argNames.Length];

                for (int i = 0; i < (nparams - defaults.Length); i++)
                {
                    newDefs[i] = DBNull.Value;
                }

                Array.Copy(defaults, 0, newDefs, (nparams - defaults.Length), defaults.Length);
                defaults = newDefs;
            }

            object[] realArgs = argBinder.DoBind(Name, argNames, defaults, kwDictPos, argListPos);

            if (realArgs != null)
            {
                if (!EnforceRecursion)
                {
                    return(target(realArgs));
                }
                PushFrame();
                try {
                    return(target(realArgs));
                } finally {
                    PopFrame();
                }
            }
            else if (argBinder.GetError() != null)
            {
                throw argBinder.GetError();
            }
            else
            {
                throw BadArgumentError(args.Length);
            }
        }
Пример #2
0
        public virtual object Call(object[] args, string[] names)
        {
            // we allow kw-arg binding to ctor's of arbitrary CLS types, but
            // NOT Python built-in types.  After the ctor succeeds we'll set the kw args as
            // arbitrary properties on the CLS type.  If this ends up being a built-in type we'll
            // do the check when we're going to set the kw-args.  This accomplishes 2 things:
            //      1. Our error messages match CPython more closely
            //      2. The attribute lookup is done lazily only if kw-args are supplied to a ctor

            KwArgBinder            kwArgBinder     = new KwArgBinder(args, names, targets[0].IsConstructor);
            MethodBinding          bestBinding     = new MethodBinding();
            List <UnboundArgument> bestUnboundArgs = null;

            for (int i = 0; i < targets.Length; i++)
            {
                object[] realArgs = kwArgBinder.DoBind(targets[i], Name);

                if (realArgs != null)
                {
                    MethodBinding mb = new MethodBinding();
                    mb.method = targets[i];

                    if (!(targets[i].IsStatic || targets[i].IsConstructor))
                    {
                        if (!HasInstance)
                        {
                            if (realArgs.Length == 0)
                            {
                                throw Ops.TypeError("bad number of arguments for function {0}", targets[0].Name);
                            }
                            mb.instance  = realArgs[0];
                            mb.arguments = new object[realArgs.Length - 1];
                            Array.Copy(realArgs, mb.arguments, realArgs.Length - 1);
                        }
                        else
                        {
                            mb.instance  = Instance;
                            mb.arguments = realArgs;
                        }
                    }
                    else
                    {
                        mb.arguments = realArgs;
                    }

                    if (!kwArgBinder.AllowUnboundArgs)
                    {
                        // we can have no better bindings!
                        bestBinding = mb;
                        break;
                    }

                    if (bestBinding.method == null ||
                        (kwArgBinder.UnboundArgs == null ||
                         (bestUnboundArgs != null && bestUnboundArgs.Count > kwArgBinder.UnboundArgs.Count)))
                    {
                        bestBinding     = mb;
                        bestUnboundArgs = kwArgBinder.UnboundArgs;
                    }
                }
            }

            if (bestBinding.method != null)
            {
                // we've bound the arguments to a real method,
                // finally we're going to dispatch back to the
                // optimized version of the calls.
                object ret = Call(bestBinding.arguments);

                // any unbound arguments left over we assume the user
                // wants to do a property set with.  We'll go ahead and try
                // that - if they fail we'll throw.
                if (bestUnboundArgs != null)
                {
                    ///!!! if we had a constructor w/ a ref param then we'll try
                    // updating the Tuple here instead of the user's object.

                    if (targets[0].DeclaringType.IsDefined(typeof(PythonTypeAttribute), false))
                    {
                        throw Ops.TypeError("'{0}' is an invalid keyword argument for this function",
                                            bestUnboundArgs[0].Name,
                                            Name);
                    }

                    for (int j = 0; j < bestUnboundArgs.Count; j++)
                    {
                        Ops.SetAttr(DefaultContext.Default, ret,
                                    SymbolTable.StringToId(bestUnboundArgs[j].Name),
                                    bestUnboundArgs[j].Value);
                    }
                }

                return(ret);
            }

            if (kwArgBinder.GetError() != null)
            {
                throw kwArgBinder.GetError();
            }

            throw Ops.TypeError("bad number of arguments for function {0}", FriendlyName);
        }