コード例 #1
0
ファイル: VirtualMachine.cs プロジェクト: rgunczer/QAB
        private void HandleQuit(ActionBase action)
        {
            if (m_bQuitIsHandled)
            {
                return;
            }

            if (0 == m_listOnQuit.Count)
            {
                return;
            }

            m_bQuitIsHandled = true;

            int pos = m_script.Actions.IndexOf(action) + 1; // insert before

            foreach (string funcName in m_listOnQuit)
            {
                if (m_FnNameStack.Count > 0)
                {
                    string fn = m_FnNameStack.Peek();

                    if (fn == funcName) // do not insert calls inside our function
                    {
                        continue;
                    }
                }

                Actioncall call = new Actioncall();
                call.FunctionName = funcName;

                m_script.Actions.Insert(pos, call);
                ++pos;
            }

            Actionsys actSys = new Actionsys();

            actSys.AddParams(new List <string>()
            {
                "sys.quit"
            });
            m_script.Actions.Insert(pos, actSys);

            m_Status = VMStatus.IN_PLAYBACK;
        }
コード例 #2
0
ファイル: VirtualMachine.cs プロジェクト: rgunczer/QAB
        private int StepFlow(ActionBase action)
        {
// function
            if (action is Actionfunction)
            {
                return(++m_IP);
            }

// return
            if (action is Actionreturn)
            {
                m_IP = m_InstrStack.Pop();
                m_CallStack.Pop();
                m_variables.RemoveLocals(m_FnNameStack.Pop());

                return(++m_IP);
            }

// call
            if (action is Actioncall)
            {
                Actioncall call = (Actioncall)action;
                Debug.Assert(null != call);

                m_InstrStack.Push(m_IP);
                m_IP = m_script.GetFuncEntryIndex(call.FunctionName);
                m_CallStack.Push(m_IP);

                if (-1 == m_IP)
                {
                    string errMsg = "Function: '" + call.FunctionName + "' NOT found.";

                    m_Status = VMStatus.ERROR;

                    m_ErrStack.Push(errMsg);
                    host.MarkCurrentLine(m_IP, action.LineNumber, Color.Red, action.Path2Script);
                    action.Result = EnumActionResult.ERROR;

                    throw new Exception(errMsg);
                }

                Actionfunction fn = (Actionfunction)m_script.GetAction(m_IP);
                Debug.Assert(null != fn);

                Dictionary <string, string> vars = new Dictionary <string, string>();

                if (call.Parameters.Count > 0)
                {
                    for (int i = 0; i < call.Parameters.Count; ++i)
                    {
                        string key   = fn.Parameters[i];
                        string value = m_variables.Get(call.Parameters[i]);

                        vars.Add(key, value);
                    }
                }

                m_variables.AddLocals(fn.Name, vars); // create a new scope as well

                m_FnNameStack.Push(fn.Name);

                return(m_IP);
            }

// Label
            if (action is ActionLabel)
            {
                return(++m_IP);
            }

// goto
            if (action is ActionGoto)
            {
                ActionGoto actGoto = (ActionGoto)action;

                int jump2Index = -1;
                int i          = 0;

                foreach (ActionBase item in m_script.Actions) // locate position where to goto
                {
                    if (item is ActionLabel)
                    {
                        ActionLabel actLabel = (ActionLabel)item;

                        if (actLabel.GetLabel == actGoto.label)
                        {
                            jump2Index = i;
                            break;
                        }
                    }
                    ++i;
                }

                if (-1 == jump2Index)
                {
                    throw new Exception("Error locating label '" + actGoto.label + "' for GOTO command.");
                }

                if ("0" != actGoto.jumpCount) // not a FOR-EVER kind of goto
                {
                    if (!m_dicGotoCounts.ContainsKey(actGoto.label))
                    {
                        m_dicGotoCounts.Add(actGoto.label, Convert.ToInt32(actGoto.jumpCount)); // init
                    }
                    if (m_dicGotoCounts[actGoto.label] > 0)
                    {
                        --m_dicGotoCounts[actGoto.label];
                    }
                    else
                    {
                        m_dicGotoCounts.Remove(actGoto.label);
                        m_script.Actions.IndexOf(actGoto);
                        return(m_IP);
                    }
                }
                m_IP = jump2Index;

                return(m_IP);
            }

// foreach
// for
// while
            if (action is ActionFlowIterator)
            {
                ActionFlowIterator act = (ActionFlowIterator)action;

                Debug.Assert(null != act);

                if (0 == m_LoopStack.Count)
                {
                    m_LoopStack.Push(m_IP);
                }
                else if (m_LoopStack.Peek() != m_IP)
                {
                    m_LoopStack.Push(m_IP);
                }

                if (act.IsDone)
                {
                    m_LoopStack.Pop();
                    m_IP = GetMatchingLoopStatement(m_IP);
                }

                return(++m_IP);
            }

// break
            if (action is Actionbreak)
            {
                int ip = m_LoopStack.Pop();

                ActionFlowIterator act = (ActionFlowIterator)m_script.Actions[ip];

                act.Done(); // probably it will cleanup itself from the vm

                m_IP = GetClosestLoopStatement(m_IP);

                return(++m_IP);
            }

// loop
// continue
            if (action is Actionloop || action is Actioncontinue)
            {
                m_IP = m_LoopStack.Peek();
                return(m_IP);
            }

// if
            if (action is Actionif)
            {
                Actionif actIF = (Actionif)action;
                m_IfStack.Push(m_IP);

                if (actIF.result == true)
                {
                    return(++m_IP);  // go inside if block
                }
                else // bypass if block (find else or endif statement (matching! nested if satetement are skipped as well)
                {
                    m_IP = GetMatchingIfStatement(m_IP);
                    return(m_IP);
                }
            }

// endif
            if (action is Actionendif)
            {
                m_IfStack.Pop();
                return(++m_IP);
            }

// else
            if (action is Actionelse)
            {
                int      index = m_IfStack.Peek();
                Actionif actIF = (Actionif)script.Actions[index];

                if (actIF.result == true) // then skip the else part
                {
                    m_IP = GetMatchingIfStatement(m_IP);
                    return(m_IP);
                }
                else
                {
                    return(++m_IP);
                }
            }

            // unknown command
            throw new Exception("Player::StepFlow Unknown FlowCommand [" + action.RawCmdLine.Trim() + "]");
        }
コード例 #3
0
ファイル: VirtualMachine.cs プロジェクト: rgunczer/QAB
        private bool HandleError(ActionBase action)
        {
            if (null == m_actionError)
            {
                m_actionError = action;
            }

            m_variables.UpdateSystem("$ERROR", "True");

            int tmpInstPtr = m_IP;

            ++tmpInstPtr;

            if (tmpInstPtr < script.Actions.Count) // peek ahead one instruction is it a if statement?
            {
                ActionBase actTmp = m_script.GetAction(tmpInstPtr);;

                if (actTmp is Actionif)
                {
                    Actionif actIF = (Actionif)actTmp;
                    Debug.Assert(null != actIF);

                    if (actIF.Params[1] == "$ERROR" || actIF.Params[3] == "$ERROR")
                    {
                        return(true); // error is handled (do not let the playback to be stopped)
                    }
                }
            }

            // unhandled error...
            if (!m_bErrorIsHandled && m_listOnError.Count > 0)
            {
                m_bErrorIsHandled = true;

                int pos = m_script.Actions.IndexOf(action) + 1;

                foreach (string funcName in m_listOnError)
                {
                    if (m_FnNameStack.Count > 0)
                    {
                        string fn = m_FnNameStack.Peek();

                        if (fn == funcName) // do not insert calls inside our function
                        {
                            continue;
                        }
                    }

                    Actioncall call = new Actioncall();
                    call.FunctionName = funcName;

                    m_script.Actions.Insert(pos, call);
                    ++pos;
                }

                ActionError err = new ActionError();

                m_script.Actions.Insert(pos, err);

                return(true); // show must go on
            }
            else
            {
                m_Status = VMStatus.ERROR;
                return(false); // we stop the playback
            }
        }