예제 #1
0
        public static void resume(LuaInterop lua)
        {
            LuaThread co = lua.Argument <LuaThread>(0);

            co.BeginResume(lua.ArgumentCount - 1);
            for (int argument = 0; argument < lua.ArgumentCount - 1; ++argument)
            {
                co.ResumeArgument(argument, lua.Argument(argument));
            }

            int resultCount;

            try
            {
                resultCount = co.Resume(LuaThread.VarResult);
            }
            catch (Exception e)
            {
                lua.BeginReturn(2);
                lua.ReturnResult(0, false);
                lua.ReturnResult(1, e.Message);
                lua.EndReturn();
                return;
            }

            lua.BeginReturn(resultCount + 1);
            lua.ReturnResult(0, true);
            for (int result = 0; result < resultCount; ++result)
            {
                lua.ReturnResult(result + 1, co.ResumeResult(result));
            }
            co.EndResume();
            lua.EndReturn();
        }
예제 #2
0
        internal override void Call(LuaThread thread, int frameBase, int argumentCount, int resultCount)
        {
            LuaInterop lua = new LuaInterop(thread, frameBase, argumentCount, resultCount);

            action();
            lua.Return();
        }
예제 #3
0
            internal override void Resume(LuaThread thread)
            {
                // We should be the last function in the stack (at index 0).
                Frame frame = thread.UnwoundFrames[thread.UnwoundFrames.Count - 1];

                thread.UnwoundFrames.RemoveAt(thread.UnwoundFrames.Count - 1);

                // The resume code will have altered our arguments to correspond to the
                // arguments of the resume call (always the correct number of results).
                // The resume code can't simulate a return directly because that would
                // overwrite the value at the frame base, which references the yeild
                // function.

                // Find number of arguments/results.
                int resultCount;

                if (frame.ResultCount != -1)
                {
                    resultCount = frame.ResultCount;
                }
                else
                {
                    resultCount = thread.Top - frame.FrameBase;
                    thread.Top  = -1;
                    thread.Top  = frame.FrameBase + resultCount - 1;
                }

                // Copy down.
                for (int result = 0; result < resultCount; ++result)
                {
                    thread.Stack[frame.FrameBase + result] = thread.Stack[frame.FrameBase + 1 + result];
                }
            }
예제 #4
0
 internal LuaInterop(LuaThread thread, int frameBase, int argumentCount, int resultCount)
 {
     this.thread        = thread;
     this.frameBase     = frameBase;
     this.argumentCount = argumentCount;
     this.resultCount   = resultCount;
 }
예제 #5
0
    public static bool GetResult(out LuaThread res)
    {
        bool ret = false;

        if (s_ResIndex > s_ResNum)
        {
            res = null;
            return(ret);
        }
        int from = s_From + s_ResIndex;

        ++s_ResIndex;
        var L = s_Func.L;

        LuaTypes type = LuaDLL.lua_type(L, from);

        switch (type)
        {
        case LuaTypes.LUA_TTHREAD: {
            LuaThread lt;
            LuaObject.checkType(L, from, out lt);
            res = lt;
            ret = true;
            break;
        }

        default:
            res = null;
            break;
        }
        return(ret);
    }
예제 #6
0
        [TestMethod] public void Native()
        {
            using (var lua = new Lua())
            {
                var       calls  = new List <string>(4);
                LuaThread thread = null;
                lua.RegisterFunction("callback", new Action <string>(s => {
                    calls.Add(s);
                    Assert.AreEqual(LuaCoStatus.Running, thread.Status);
                }));
                using (var body = lua.LoadString(@"
					assert(... == 'start')
					callback('B')
					assert(coroutine.yield('yield') == 'resume')
					callback('D')
					return 'return'
				"                ))
                    thread = lua.NewThread(body);
                using (thread)
                {
                    Assert.AreEqual(LuaCoStatus.Suspended, thread.Status);
                    calls.Add("A");
                    CollectionAssert.AreEqual(new object[] { "yield" }, thread.Resume("start"));
                    Assert.AreEqual(LuaCoStatus.Suspended, thread.Status);
                    calls.Add("C");
                    CollectionAssert.AreEqual(new object[] { "return" }, thread.Resume("resume"));
                    Assert.AreEqual(LuaCoStatus.Dead, thread.Status);
                    calls.Add("E");
                }
                Assert.AreEqual("ABCDE", string.Concat(calls.ToArray()));
            }
        }
 private void CloseThread()
 {
     if (thread != null)
     {
         thread.Dispose();
         thread = null;
     }
 }
예제 #8
0
            public static void Spawn(MulticastDelegate f)
            {
                var sw = Stopwatch.StartNew();

                var e = new WaitExecution(CurrentScript, (LuaThread)LuaThread.running().Values[0], 0,
                                          () => f.FastDynamicInvoke(sw.Elapsed.TotalSeconds, Game.Workspace.DistributedGameTime));

                ExecutionQueue.Enqueue(e);
            }
예제 #9
0
    static int TimeoutAsync(IntPtr state)
    {
        IntPtr co   = LuaStack.GetThread(state, 1);
        float  time = (float)LuaStack.GetNumber(state, 2);

        Observable.Timer(TimeSpan.FromSeconds(time)).Subscribe(x => {
            LuaThread.ResumeSubthread(co, state, 0, out _);
        });
        return(0);
    }
예제 #10
0
 private void OnDestroy()
 {
     if (this.thread != null)
     {
         this.thread.Dispose();
         this.thread = null;
     }
     this.state.Dispose();
     this.state = null;
 }
예제 #11
0
        // Lifetime.

        public void Close()
        {
            if (thread == null)
            {
                throw new InvalidOperationException();
            }

            value      = thread.Stack[stackIndex];
            thread     = null;
            stackIndex = -1;
        }
예제 #12
0
    void OnDestroy()
    {
        if (thread != null)
        {
            thread.Dispose();
            thread = null;
        }

        state.Dispose();
        state = null;
    }
예제 #13
0
    void OnDestroy()
    {
        if (thread != null)
        {
            thread.Dispose();
            thread = null;
        }

        state.Dispose();
        state = null;
    }
예제 #14
0
    void OnApplicationQuit()
    {
        if (thread != null)
        {
            thread.Dispose();
            thread = null;
        }

        state.Dispose();
        state = null;
        Application.logMessageReceived -= ShowTips;
    }
예제 #15
0
 public static IEnumerator EnumLuaCoroutine(LuaFunc lfunc)
 {
     if (lfunc != null)
     {
         LuaThread lthd = new LuaThread(lfunc);
         return(EnumLuaCoroutine(lthd));
     }
     else
     {
         return(GetEmptyEnumerator());
     }
 }
예제 #16
0
            public void printidentity()
            {
                var identity = GetIdentity(LuaThread.running());

                if (identity.HasValue)
                {
                    OnPrint($"Current identity is {(byte)identity.Value} ({identity})");
                }
                else
                {
                    OnPrint("This thread has no identity.");
                }
            }
예제 #17
0
    // Update is called once per frame
    void Update()
    {
        if (!co.IsDead())
        {
            co.Resume();
        }
        else
        {
            print("Coroutine has exited.");

            // In order to destroy a coroutine (but not the function in lua, just the coroutine stack instance) simply allow C# to clean up the wrapped object
            co = null;
        }
    }
예제 #18
0
    // Update is called once per frame
    void Update()
    {
        if( !co.IsDead() )
        {
            co.Resume();
        }
        else
        {
            print("Coroutine has exited.");

            // In order to destroy a coroutine (but not the function in lua, just the coroutine stack instance) simply allow C# to clean up the wrapped object
            co = null;
        }
    }
예제 #19
0
            public static double Wait(double seconds)
            {
                seconds = Math.Max(seconds, LuaSettings.DefaultWaitTime);

                var sw = Stopwatch.StartNew();

                var e = new WaitExecution(CurrentScript, (LuaThread)LuaThread.running().Values[0], seconds);

                ExecutionQueue.Enqueue(e);

                YieldThread();

                return(sw.Elapsed.TotalSeconds);
            }
예제 #20
0
        public static string status(LuaThread co)
        {
            switch (co.Status)
            {
            case LuaThreadStatus.Running:   return("running");

            case LuaThreadStatus.Suspended: return("suspended");

            case LuaThreadStatus.Normal:    return("normal");

            case LuaThreadStatus.Dead:              return("dead");
            }

            throw new ArgumentException();
        }
예제 #21
0
    private void OnApplicationQuit()
    {
        if (thread != null)
        {
            thread.Dispose();
            thread = null;
        }
        state.Dispose();
        state = null;
#if UNITY_5 || UNITY_2017 || UNITY_2018
        Application.logMessageReceived -= ShowTips;
#else
        Application.RegisterLogCallback(null);
#endif
    }
예제 #22
0
    void Start()
    {
        LuaState l = new LuaState();

        // First run the script so the function is created
        l.DoString(Encoding.UTF8.GetBytes(script));

        // Get the function object
        LuaFunction f = l.GetFunction("myFunc");

        // Create a paused lua coroutine object from the parent state and a function
        co = new LuaThread(l, f);
        // The coroutine needs to be resumed each frame, since it is yielding each frame, alternatively you could only resume it on conditions in C# instead
        co.Start();
    }
예제 #23
0
	void Start () 
    {
        state = new LuaState();
        state.Start();
        state.DoString(script);

        LuaFunction func = state.GetFunction("Test");
        func.BeginPCall();
        func.PCall();
        thread = func.CheckLuaThread();
        func.EndPCall();
        func.Dispose();
        func = null;

        thread.Resume(10);
	}
예제 #24
0
    // Use this for initialization
    void Start()
    {
        LuaState l = new LuaState();
        LuaScriptMgr._translator = l.GetTranslator();

        // First run the script so the function is created
        l.DoString(script);

        // Get the function object
        LuaFunction f = l.GetFunction("myFunc");

        // Create a paused lua coroutine object from the parent state and a function
        co = new LuaThread(l, f);

        // The coroutine needs to be resumed each frame, since it is yielding each frame, alternatively you could only resume it on conditions in C# instead
        co.Start();
    }
예제 #25
0
    void Start()
    {
        state = new LuaState();
        state.Start();
        state.DoString(script);

        LuaFunction func = state.GetFunction("Test");

        func.BeginPCall();
        func.PCall();
        thread = func.CheckLuaThread();
        func.EndPCall();
        func.Dispose();
        func = null;

        thread.Resume(10);
    }
예제 #26
0
        public double wait()
        {
            var thread = (LuaThread)LuaThread.running().Values[0];
            var sw     = Stopwatch.StartNew();

            Action callback = null;

            callback = () =>
            {
                ScriptService.ResumeThread(thread);
                Disconnect(callback);
            };

            Connect(callback);
            ScriptService.YieldThread();
            return(sw.Elapsed.TotalSeconds);
        }
예제 #27
0
 private void OnGUI()
 {
     if (GUI.Button(new Rect(10f, 10f, 120f, 40f), "Resume Thead"))
     {
         if (this.thread != null && this.thread.Resume(new object[]
         {
             true
         }) == 1)
         {
             object[] result = this.thread.GetResult();
             Debugger.Log("lua yield: " + result[0]);
         }
     }
     else if (GUI.Button(new Rect(10f, 60f, 120f, 40f), "Close Thread") && this.thread != null)
     {
         this.thread.Dispose();
         this.thread = null;
     }
 }
예제 #28
0
    private void Start()
    {
        this.state = new LuaState();
        this.state.Start();
        this.state.LogGC = true;
        this.state.DoString(this.script, "LuaState.cs");
        LuaFunction function = this.state.GetFunction("Test", true);

        function.BeginPCall();
        function.PCall();
        this.thread      = function.CheckLuaThread();
        this.thread.name = "LuaThread";
        function.EndPCall();
        function.Dispose();
        this.thread.Resume(new object[]
        {
            10
        });
    }
예제 #29
0
 void OnGUI()
 {
     if (GUI.Button(new Rect(10, 10, 120, 40), "Resume Thead"))
     {
         if (thread != null && thread.Resume(true) == (int)LuaThreadStatus.LUA_YIELD)
         {
             object[] objs = thread.GetResult();
             Debugger.Log("lua yield: " + objs[0]);
         }
     }
     else if (GUI.Button(new Rect(10, 60, 120, 40), "Close Thread"))
     {
         if (thread != null)
         {
             thread.Dispose();
             thread = null;
         }
     }
 }
예제 #30
0
        /// <summary>
        /// Asserts that the calling thread has the required identity.
        /// </summary>
        /// <param name="target">The required identity.</param>
        /// <param name="condition">
        /// If true, an exception is thrown when the thread does not meet target identity.
        /// If false, an exception is thrown when the thread does the target identity.
        /// </param>
        internal static void AssertIdentity(ScriptIdentity target, bool condition = true)
        {
            var thread   = LuaThread.running();
            var identity = GetIdentity(thread);

            if (identity == null || (target.HasFlag(identity) == condition))
            {
                return;                                                              // threads with no identity are unrestricted
            }
#if DEBUG
            var frame  = new StackFrame(1);
            var method = frame.GetMethod();
            var type   = method.DeclaringType;
            var name   = method.Name;
            throw new SecurityException($"Method {type}.{name} requires identity level {target}. (Current: {identity})");
#else
            throw new SecurityException();
#endif
        }
예제 #31
0
        public Instance WaitForChild(string name, double?timeout = null)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException("Name parameter cannot be empty.");
            }

            foreach (var c in Children)
            {
                if (c.Name == name)
                {
                    return(c);
                }
            }

            var thread = (LuaThread)LuaThread.running().Values[0];

            lock (Locker)
            {
                List <LuaThread> threads;
                if (_waitForChildList.TryGetValue(name, out threads))
                {
                    threads.Add(thread);
                }
                else
                {
                    _waitForChildList.Add(name, new List <LuaThread>(new[] { thread }));
                }
            }

            Timer timer       = null;
            var   timerAction = new TimerCallback(obj =>
            {
                ScriptService.ResumeThread(thread);
                timer?.Dispose();
            });

            timer = timeout == null ? new Timer(timerAction) : new Timer(timerAction, null, (int)(timeout * 1000), -1);

            ScriptService.YieldThread();

            return(FindFirstChild(name));
        }
예제 #32
0
 void OnGUI()
 {
     if (GUI.Button(new Rect(10, 10, 120, 40), "Resume Thead"))
     {
         if (thread != null && thread.Resume(true) == (int)LuaThreadStatus.LUA_YIELD)
         {
             object[] objs = thread.GetResult();
             Debugger.Log("lua yield: " + objs[0]);
         }
     }
     else if (GUI.Button(new Rect(10, 60, 120, 40), "Close Thread"))
     {
         if (thread != null)
         {
             thread.Dispose();
             thread = null;
         }
     }
 }
예제 #33
0
    void OnGUI()
    {
        GUI.Label(new Rect(Screen.width / 2 - 300, Screen.height / 2 - 200, 600, 400), tips);

        if (GUI.Button(new Rect(10, 50, 120, 40), "Resume Thread"))
        {
            int ret = -1;
            if (thread != null && thread.Resume(true, out ret) == (int)LuaThreadStatus.LUA_YIELD)
            {
                Debugger.Log("lua yield:" + ret);
            }
        }
        else if (GUI.Button(new Rect(10, 150, 120, 40), "Close thread "))
        {
            if (thread != null)
            {
                thread.Dispose();
                thread = null;
            }
        }
    }
예제 #34
0
    void OnGUI()
    {
        GUI.Label(new Rect(Screen.width / 2 - 300, Screen.height / 2 - 200, 600, 400), tips);

        if (GUI.Button(new Rect(10, 50, 120, 40), "Resume Thead"))
        {
            if (thread != null && thread.Resume(true) == (int)LuaThreadStatus.LUA_YIELD)
            {
                object[] objs = thread.GetResult();
                Debugger.Log("lua yield: " + objs[0]);
            }
        }
        else if (GUI.Button(new Rect(10, 150, 120, 40), "Close Thread"))
        {
            if (thread != null)
            {
                thread.Dispose();
                thread = null;
            }
        }
    }
예제 #35
0
    void Start()
    {
        Application.logMessageReceived += ShowTips;
        new LuaResLoader();
        state = new LuaState();
        state.Start();
        state.LogGC = true;
        state.DoString(script);

        LuaFunction func = state.GetFunction("Test");

        func.BeginPCall();
        func.PCall();
        thread      = func.CheckLuaThread();
        thread.name = "LuaThread";
        func.EndPCall();
        func.Dispose();
        func = null;

        thread.Resume(10);
    }
예제 #36
0
        private object[] Run(LuaThread mainThread)
        {
            LuaThread thread = currentThread = mainThread;
            thread.Status = Thread.StatusType.Running;
            List<object> result = new List<object>();

            ThreadResult tResult;
            Dictionary<LuaThread, LuaThread> calledBy = new Dictionary<LuaThread, LuaThread>();
            do {
                EmptyFunc pushResults = delegate() {
                    if (thread.func.returnsSaved >= 1) {
                        thread.func.Top = thread.func.returnRegister + thread.func.returnsSaved - 1;
                        for (int i = 0; i < thread.func.returnsSaved-1; ++i) {
                            thread.func.stack[thread.func.returnRegister+i] = i < result.Count ? result[i] : Nil.Value;
                        }
                    }
                    else {
                        thread.func.Top = thread.func.returnRegister + result.Count;
                        for (int i = 0; i < result.Count; ++i) {
                            thread.func.stack[thread.func.returnRegister+i] = result[i];
                        }
                    }
                };

                do {
                    try {
                        tResult = thread.Run();
                    }
                    catch(Exception ex) {
                        tResult = new ThreadResult {
                            Type = ThreadResult.ResultType.Error,
                            Data = ex.ToString(),
                        };
                    }

                    if (tResult.Type == ThreadResult.ResultType.FunctionCall || tResult.Type == ThreadResult.ResultType.Error) {
                        if (tResult.Type == ThreadResult.ResultType.FunctionCall) {
                            try {
                                var tResultF = (InternalClosure)tResult.Data;
                                tResultF.Run();
                                currentThread = thread;

                                //Pop results
                                result = tResultF.GetResults();
                            }
                            catch (Exception ex) {
                                result = new List<object> { VMCommand.ERROR, ex.ToString() /*Error msg*/ };
                            }
                        }
                        else { //It was an error
                            result = new List<object> { VMCommand.ERROR, tResult.Data /*Error msg*/ };
                        }

                        if (result.Count != 0) {
                            if (result[0] is System.Enum) {
                                switch((VMCommand)result[0]) {
                                    //1: The closure
                                    case VMCommand.CO_CREATE:
                                        var newFunction = (FunctionClosure)((FunctionClosure)result[1]).CreateCallableInstance();
                                        LuaThread newThread = new LuaThread(thread.func.env, newFunction, this);
                                        result.Clear();
                                        result.Add(newThread);
                                        break;

                                    //1: the thread to resume
                                    //2+: args to the thread
                                    case VMCommand.CO_RESUME:
                                        calledBy.Add((LuaThread)result[1], thread);
                                        thread.Status = Thread.StatusType.Normal;
                                        thread = currentThread = (LuaThread)result[1];
                                        thread.Status = Thread.StatusType.Running;
                                        if (!thread.Running) {
                                            for (int i = 2; i < result.Count; ++i) {
                                                thread.func.AddParam(result[i]);
                                            }
                                            continue;
                                        }
                                        //Else just pass them as return values to yield
                                        result.RemoveRange(0, 2); // Remove the command and the thread
                                        break;

                                    case VMCommand.CO_RUNNING:
                                        result.Clear();
                                        if (calledBy.ContainsKey(thread)) {
                                            result.Add(thread);
                                        }
                                        else {
                                            result.Add(Nil.Value);
                                        }
                                        break;

                                    //1+: return values to resume
                                    case VMCommand.CO_YIELD:
                                        var caller = calledBy[thread];
                                        calledBy.Remove(thread);
                                        thread.Status = Thread.StatusType.Suspended;
                                        thread = currentThread = caller;
                                        thread.Status = Thread.StatusType.Running;
                                        result.RemoveAt(0); // Remove command
                                        break;

                                    case VMCommand.PCALL:
                                        thread.func.errorHandler = true;
                                        break;

                                    //1: error msg
                                    case VMCommand.ERROR:
                                        //Pop all stacks until an error handler is found
                                        var stackTrace = new List<string>();
                                        string errorMsg = string.Intern(thread.ErrorString + ": " + (string)result[1]);
                                        result[1] = errorMsg;
                                        FunctionClosure fc;
                                        do {
                                            fc = thread.PopFrame();
                                            if (fc == null) {
                                                //Thread finished without handling the error, start unwinding the calling thread
                                                if (calledBy.Count == 0) {
                                                    stackTrace.Add("\t" + thread.ErrorString + ": in main chunk");
                                                    //Last thread finished without handling the error, bailing out
                                                    throw new LuaScriptException(errorMsg, stackTrace.ToArray());
                                                }

                                                var callerThread = calledBy[thread];
                                                calledBy.Remove(thread);
                                                thread = currentThread = callerThread;
                                                stackTrace.Add("\t" + thread.ErrorString + ": in lua thread");
                                                continue;
                                            }
                                            else if (fc.errorHandler == true) break;
                                            stackTrace.Add("\t"+ thread.ErrorString +": in lua function");
                                        } while (true);
                                        result[0] = false;
                                        break;
                                }
                            }
                        }
                        pushResults();
                    }
                } while(tResult.Type != ThreadResult.ResultType.Dead);
                thread.Status = Thread.StatusType.Dead;

                if (calledBy.Count == 0) break;

                result = thread.func.GetResults();
                var prevThread = calledBy[thread];
                calledBy.Remove(thread);
                thread = currentThread = prevThread;
                pushResults();

            } while(true);
            return thread.func.stack.ToArray();
        }