/// <summary> /// Creates a delegate with a given signature that could be used to invoke this object from non-dynamic code (w/o code context). /// A stub is created that makes appropriate conversions/boxing and calls the object. /// The stub should be executed within a context of this object's language. /// </summary> /// <returns>The delegate or a <c>null</c> reference if the object is not callable.</returns> public static Delegate GetDelegate(object callableObject, Type delegateType) { Contract.RequiresNotNull(delegateType, "delegateType"); Delegate result = callableObject as Delegate; if (result != null) { if (!delegateType.IsAssignableFrom(result.GetType())) { throw RuntimeHelpers.SimpleTypeError(String.Format("Cannot cast {0} to {1}.", result.GetType(), delegateType)); } return(result); } #if FULL IDynamicObject dynamicObject = callableObject as IDynamicObject; if (dynamicObject != null) { MethodInfo invoke; if (!typeof(Delegate).IsAssignableFrom(delegateType) || (invoke = delegateType.GetMethod("Invoke")) == null) { throw RuntimeHelpers.SimpleTypeError("A specific delegate type is required."); } // using IDynamicObject.LanguageContext for now, we need todo better Debug.Assert(dynamicObject.LanguageContext != null, "Invalid implementation"); ParameterInfo[] parameters = invoke.GetParameters(); dynamicObject.LanguageContext.CheckCallable(dynamicObject, parameters.Length); DelegateSignatureInfo signatureInfo = new DelegateSignatureInfo( dynamicObject.LanguageContext.Binder, invoke.ReturnType, parameters ); DelegateInfo delegateInfo = _dynamicDelegateCache.GetOrCreateValue(signatureInfo, delegate() { // creation code return(signatureInfo.GenerateDelegateStub()); }); result = delegateInfo.CreateDelegate(delegateType, dynamicObject); if (result != null) { return(result); } } #endif throw RuntimeHelpers.SimpleTypeError("Object is not callable."); }
private bool BindKWArgs(string[] argNames, int kwDictIndex, int paramArray) { bool fHasDict = false; IAttributesCollection kwDict = null; if (kwDictIndex != -1) { // append kw value to dictionary _realArgs[kwDictIndex] = kwDict = new SymbolDictionary(); _haveArg[kwDictIndex] = true; fHasDict = true; } for (int i = 0; i < _kwNames.Length; i++) { int index = FindParamIndex(argNames, _kwNames[i]); int argumentsIndex = i + _arguments.Length - _kwNames.Length; if (index != -1 && index != kwDictIndex && index != paramArray) { // attempt to bind to a real arg if (_haveArg[index]) { if (index == paramArray) { _error = RuntimeHelpers.SimpleTypeError(String.Format("{0}() got an unexpected keyword argument '{1}'", _methodName, _kwNames[i])); } else { _error = RuntimeHelpers.SimpleTypeError(String.Format("got multiple values for keyword argument {0}", _kwNames[i])); } return(false); } _haveArg[index] = true; _realArgs[index] = _arguments[argumentsIndex]; } else if (fHasDict) { // append kw value to dictionary kwDict[SymbolTable.StringToId(_kwNames[i])] = _arguments[argumentsIndex]; } else if (AllowUnboundArgs) { if (_unboundArgs == null) { _unboundArgs = new List <UnboundArgument>(); } _unboundArgs.Add(new UnboundArgument(_kwNames[i], _arguments[argumentsIndex])); } else { _error = RuntimeHelpers.SimpleTypeError(String.Format("{0}() got an unexpected keyword argument '{1}'", _methodName, _kwNames[i])); return(false); } } return(true); }
// used by DynamicHelpers.GetDelegate /// <summary> /// Checks whether the target is callable with given number of arguments. /// </summary> public void CheckCallable(object target, int argumentCount) { int min, max; if (!IsCallable(target, argumentCount, out min, out max)) { if (min == max) { throw RuntimeHelpers.SimpleTypeError(String.Format("expected compatible function, but got parameter count mismatch (expected {0} args, target takes {1})", argumentCount, min)); } else { throw RuntimeHelpers.SimpleTypeError(String.Format("expected compatible function, but got parameter count mismatch (expected {0} args, target takes at least {1} and at most {2})", argumentCount, min, max)); } } }
/// <summary> /// Creates a delegate with a given signature that could be used to invoke this object from non-dynamic code (w/o code context). /// A stub is created that makes appropriate conversions/boxing and calls the object. /// The stub should be executed within a context of this object's language. /// </summary> /// <returns>The delegate or a <c>null</c> reference if the object is not callable.</returns> public static Delegate GetDelegate(object callableObject, Type delegateType) { Contract.RequiresNotNull(delegateType, "delegateType"); Delegate result = callableObject as Delegate; if (result != null) { if (!delegateType.IsAssignableFrom(result.GetType())) { throw RuntimeHelpers.SimpleTypeError(String.Format("Cannot cast {0} to {1}.", result.GetType(), delegateType)); } return(result); } throw RuntimeHelpers.SimpleTypeError("Object is not callable."); }
public static ArgumentTypeException TypeErrorForIncorrectArgumentCount( string methodName, int minFormalNormalArgumentCount, int maxFormalNormalArgumentCount, int defaultArgumentCount, int providedArgumentCount, bool hasArgList, bool keywordArgumentsProvided) { int formalCount; string formalCountQualifier; string nonKeyword = keywordArgumentsProvided ? "non-keyword " : ""; if (defaultArgumentCount > 0 || hasArgList || minFormalNormalArgumentCount != maxFormalNormalArgumentCount) { if (providedArgumentCount < minFormalNormalArgumentCount) { formalCountQualifier = "at least"; formalCount = minFormalNormalArgumentCount - defaultArgumentCount; } else { formalCountQualifier = "at most"; formalCount = maxFormalNormalArgumentCount; } } else { formalCountQualifier = "exactly"; formalCount = minFormalNormalArgumentCount; } return(RuntimeHelpers.SimpleTypeError(string.Format( "{0}() takes {1} {2} {3}argument{4} ({5} given)", methodName, // 0 formalCountQualifier, // 1 formalCount, // 2 nonKeyword, // 3 formalCount == 1 ? "" : "s", // 4 providedArgumentCount))); // 5 }
private bool BindNormalArgs(int kwDict, int paramArrayIndex) { int maxNormalArgs = _arguments.Length - _kwNames.Length; for (int i = 0; i < maxNormalArgs; i++) { if (i == paramArrayIndex || (i == kwDict && paramArrayIndex != -1)) { _haveArg[paramArrayIndex] = true; object[] paramArray = new object[maxNormalArgs - i]; for (int j = i; j < maxNormalArgs; j++) { paramArray[j - i] = _arguments[j]; } _realArgs[paramArrayIndex] = _targetsCls ? (object)paramArray : (object)_ctx.LanguageContext.Binder.GetByRefArray(paramArray); return(true); } else if (i == kwDict) { // we shouldn't bind to the kwDict during normal arg binding _error = RuntimeHelpers.SimpleTypeError(String.Format("{0}() takes exactly {1} argument ({2} given)", _methodName, i, maxNormalArgs)); return(false); } else if (i >= _realArgs.Length) { _error = RuntimeHelpers.SimpleTypeError(String.Format("{0}() takes exactly {1} argument ({2} given)", _methodName, i, maxNormalArgs)); return(false); } _haveArg[i] = true; _realArgs[i] = _arguments[i]; } if (paramArrayIndex != -1 && !_haveArg[paramArrayIndex]) { _realArgs[paramArrayIndex] = _targetsCls ? (object)ArrayUtils.EmptyObjects : (object)_ctx.LanguageContext.Binder.GetByRefArray(ArrayUtils.EmptyObjects); _haveArg[paramArrayIndex] = true; } return(true); }