Esempio n. 1
0
        /// <summary>
        /// Calls the specified function, supporting most cases. The called function must not yield.
        /// </summary>
        /// <param name="func">The function; it must be a Function or ClrFunction or have a call metamethod defined.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        /// <exception cref="ScriptRuntimeException">If the function yields, returns a tail call request with continuations/handlers or, of course, if it encounters errors.</exception>
        public DynValue Call(DynValue func, params DynValue[] args)
        {
            if (func.Type == DataType.Function)
            {
                return(this.GetScript().Call(func, args));
            }
            else if (func.Type == DataType.ClrFunction)
            {
                while (true)
                {
                    DynValue ret = func.Callback.Invoke(this, args, false);

                    if (ret.Type == DataType.YieldRequest)
                    {
                        throw ScriptRuntimeException.CannotYield();
                    }
                    else if (ret.Type == DataType.TailCallRequest)
                    {
                        var tail = ret.TailCallData;

                        if (tail.Continuation != null || tail.ErrorHandler != null)
                        {
                            throw new ScriptRuntimeException("the function passed cannot be called directly. wrap in a script function instead.");
                        }
                        else
                        {
                            args = tail.Args;
                            func = tail.Function;
                        }
                    }
                    else
                    {
                        return(ret);
                    }
                }
            }
            else
            {
                int maxloops = 10;

                while (maxloops > 0)
                {
                    DynValue v = this.GetMetamethod(func, "__call");

                    if (v == null && v.IsNil())
                    {
                        throw ScriptRuntimeException.AttemptToCallNonFunc(func.Type);
                    }

                    func = v;

                    if (func.Type == DataType.Function || func.Type == DataType.ClrFunction)
                    {
                        return(Call(func, args));
                    }
                }

                throw ScriptRuntimeException.LoopInCall();
            }
        }