예제 #1
0
        /// <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.");
        }
예제 #2
0
        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);
        }
예제 #3
0
        // 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));
                }
            }
        }
예제 #4
0
        /// <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.");
        }
예제 #5
0
        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
        }
예제 #6
0
        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);
        }