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