Esempio n. 1
0
        private void DoExecute()    // MAIN thread only..
        {
            executing = true;

            System.Diagnostics.Stopwatch timetaken = new System.Diagnostics.Stopwatch();
            timetaken.Start();

            while (true)
            {
                if (progcurrent != null)
                {
                    if (progcurrent.GetErrorList != null)       // any errors pending, handle
                    {
                        actioncontroller.LogLine("Error: " + progcurrent.GetErrorList + Environment.NewLine + StackTrace());
                        TerminateToCloseAtEnd();            // terminate up to a close at end entry, which would have started this stack
                    }
                    else if (progcurrent.IsProgramFinished) // if current program ran out, cancel it
                    {
                        // this catches a LOOP without a statement at the end..  or a DO without a WHILE at the end..
                        if (progcurrent.ExecLevel > 0 && progcurrent.LevelUp(progcurrent.ExecLevel, null)) // see if we have any pending LOOP (or a DO without a while) and continue..
                        {
                            continue;                                                                      // errors or movement causes it to go back.. errors will be picked up above
                        }
                        TerminateCurrent();
                    }
                }

                while (progcurrent == null && progqueue.Count > 0)    // if no program,but something in queue
                {
                    progcurrent = progqueue[0];
                    progqueue.RemoveAt(0);

                    if (progcurrent.variables != null)                         // if not null, its because its just been restarted after a call.. reset globals
                    {
                        progcurrent.Add(actioncontroller.Globals);             // in case they have been updated...
                        progcurrent.Add(progcurrent.ActionFile.FileVariables); // in case they have been updated...
                    }
                    else
                    {
                        progcurrent.PrepareToRun(
                            new Variables(progcurrent.inputvariables, actioncontroller.Globals, progcurrent.ActionFile.FileVariables),
                            new FunctionPersistentData(),
                            new Dictionary <string, ExtendedControls.ConfigurableForm>(), true);    // with new file handles and close at end..
                    }

                    if (progcurrent.IsProgramFinished)          // reject empty programs..
                    {
                        TerminateCurrent();
                        continue;       // and try again
                    }
                }

                if (progcurrent == null)        // Still nothing, game over
                {
                    break;
                }

                ActionBase ac = progcurrent.GetNextStep();      // get the step. move PC on.

                //    System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " " + timetaken.ElapsedMilliseconds + " @ " + progcurrent.Location + " Lv " + progcurrent.ExecLevel + " e " + (progcurrent.IsExecuteOn ? "1" : "0") + " up " + ac.LevelUp + " " + progcurrent.PushPos + " " + ac.Name);

                if (ac.LevelUp > 0 && progcurrent.LevelUp(ac.LevelUp, ac))         // level up..
                {
                    //System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " Abort Lv" + progcurrent.ExecLevel + " e " + (progcurrent.IsExecuteOn ? "1" : "0") + " up " + ac.LevelUp + ": " + progcurrent.StepNumber + " " + ac.Name + " " + ac.DisplayedUserData);
                    continue;
                }

                if (logtologline || logger != null)
                {
                    string t     = (Environment.TickCount % 10000).ToString("00000") + " ";
                    string index = string.Concat(Enumerable.Repeat(". ", progcurrent.ExecLevel));
                    string s     = progcurrent.GetLastStep().LineNumber.ToString() + (progcurrent.IsExecuteOn ? "+" : "-") + ":" + index + ac.Name + " " + ac.DisplayedUserData;
                    System.Diagnostics.Debug.WriteLine(t + s);
                    if (logtologline)
                    {
                        actioncontroller.LogLine(t + s);
                    }
                    if (logger != null)
                    {
                        logger.WriteLine(s);
                    }
                }

                if (progcurrent.DoExecute(ac))                 // execute is on..
                {
                    if (ac.Type == ActionBase.ActionType.Call) // Call needs to pass info back up thru to us, need a different call
                    {
                        ActionCall acall = ac as ActionCall;
                        string     prog;
                        Variables  paravars;
                        if (acall.ExecuteCallAction(progcurrent, out prog, out paravars)) // if execute ok
                        {
                            //System.Diagnostics.Debug.WriteLine("Call " + prog + " with " + paravars.ToString());

                            Tuple <ActionFile, ActionProgram> ap = actionfilelist.FindProgram(prog, progcurrent.ActionFile);          // find program using this name, prefer this action file first

                            if (ap != null)
                            {
                                Run(true, ap.Item1, ap.Item2, paravars, progcurrent.Functions.persistentdata, progcurrent.Dialogs, false);   // run now with these para vars
                            }
                            else
                            {
                                progcurrent.ReportError("Call cannot find " + prog);
                            }
                        }
                    }
                    else if (ac.Type == ActionBase.ActionType.Return)     // Return needs to pass info back up thru to us, need a different call
                    {
                        ActionReturn ar = ac as ActionReturn;
                        string       retstr;
                        if (ar.ExecuteActionReturn(progcurrent, out retstr))
                        {
                            TerminateCurrent();

                            // if a new program is queued, but not prepared, and this program returns to finish, make sure we don't
                            // screw up since the variables are not preparred yet - they will be above in PrepareToRun

                            if (progqueue.Count > 0 && progqueue[0].variables != null)         // pass return value if program is there AND its prepared
                            {
                                progqueue[0]["ReturnValue"] = retstr;
                            }

                            continue;       // back to top, next action from returned function.
                        }
                    }
                    else if (!ac.ExecuteAction(progcurrent)) // if execute says, stop, i'm waiting for something
                    {
                        return;                              // exit, with executing set true.  ResumeAfterPause will restart it.
                    }
                }

                if (AsyncMode && timetaken.ElapsedMilliseconds > 150)  // no more than ms per go to stop the main thread being blocked
                {
                    System.Diagnostics.Debug.WriteLine((Environment.TickCount % 10000).ToString("00000") + " *** SUSPEND Actions at " + timetaken.ElapsedMilliseconds);
                    restarttick.Start();
                    break;
                }
            }

            executing = false;
        }