示例#1
0
        public override void PrtEnqueueEvent(PrtValue e, PrtValue arg, PrtMachine source, PrtMachineValue target = null)
        {
            int numOfStepsTaken = 0;

            // set the currentTrigger and currentPayload fields
            // so that we can reuse the common functions
            currentPayload = arg.Clone();
            currentTrigger = e;

            PrtValue currEventValue;
            PrtFun   currAction;
            bool     hasMoreWork = false;

            try
            {
Start:
                switch (nextSMOperation)
                {
                case PrtNextStatemachineOperation.ExecuteFunctionOperation:
                    goto DoExecuteFunction;

                case PrtNextStatemachineOperation.HandleEventOperation:
                    goto DoHandleEvent;
                }

DoExecuteFunction:
                if (invertedFunStack.TopOfStack == null)
                {
                    //Trace: entered state
                    PrtFun entryFun = CurrentState.entryFun;
                    if (entryFun.IsAnonFun)
                    {
                        PrtPushFunStackFrame(entryFun, entryFun.CreateLocals(currentPayload));
                    }
                    else
                    {
                        PrtPushFunStackFrame(entryFun, entryFun.CreateLocals());
                    }
                }
                //invoke the function
                invertedFunStack.TopOfStack.fun.Execute(stateImpl, this);
                goto CheckFunLastOperation;

DoAction:
                currAction = PrtFindActionHandler(eventValue);
                if (currAction == PrtFun.IgnoreFun)
                {
                    //Trace: Performed ignore action for the event
                    currentTrigger = PrtValue.@null;
                    currentPayload = PrtValue.@null;
                }
                else
                {
                    if (invertedFunStack.TopOfStack == null)
                    {
                        //Trace: executed the action handler for event
                        if (currAction.IsAnonFun)
                        {
                            PrtPushFunStackFrame(currAction, currAction.CreateLocals(currentPayload));
                        }
                        else
                        {
                            PrtPushFunStackFrame(currAction, currAction.CreateLocals());
                        }
                    }
                    //invoke the action handler
                    invertedFunStack.TopOfStack.fun.Execute(stateImpl, this);
                }
                goto CheckFunLastOperation;

CheckFunLastOperation:
                switch (continuation.reason)
                {
                case PrtContinuationReason.Goto:
                {
                    stateExitReason = PrtStateExitReason.OnGotoStatement;
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    PrtPushExitFunction();
                    goto DoExecuteFunction;
                }

                case PrtContinuationReason.Raise:
                {
                    nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                    hasMoreWork     = true;
                    goto Finish;
                }

                case PrtContinuationReason.Return:
                {
                    switch (stateExitReason)
                    {
                    case PrtStateExitReason.NotExit:
                    {
                        nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                        hasMoreWork     = false;
                        goto Finish;
                    }

                    case PrtStateExitReason.OnGotoStatement:
                    {
                        PrtChangeState(destOfGoto);
                        currentTemperature = destOfGoto.temperature;
                        nextSMOperation    = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                        stateExitReason    = PrtStateExitReason.NotExit;
                        hasMoreWork        = true;
                        goto Finish;
                    }

                    case PrtStateExitReason.OnUnhandledEvent:
                    {
                        hasMoreWork     = !PrtPopState(false);
                        nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                        stateExitReason = PrtStateExitReason.NotExit;
                        goto Finish;
                    }

                    case PrtStateExitReason.OnTransition:
                    {
                        stateExitReason = PrtStateExitReason.OnTransitionAfterExit;
                        nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                        PrtPushTransitionFun(eventValue);
                        goto DoExecuteFunction;
                    }

                    case PrtStateExitReason.OnTransitionAfterExit:
                    {
                        // The parameter to an anonymous transition function is always passed as swap.
                        // Update currentPayload to the latest value of the parameter so that the correct
                        // value gets passed to the entry function of the target state.
                        PrtTransition transition    = CurrentState.transitions[eventValue];
                        PrtFun        transitionFun = transition.transitionFun;
                        if (transitionFun.IsAnonFun)
                        {
                            currentPayload = continuation.retLocals[0];
                        }
                        PrtChangeState(transition.gotoState);
                        currentTemperature = transition.gotoState.temperature;
                        hasMoreWork        = true;
                        nextSMOperation    = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                        stateExitReason    = PrtStateExitReason.NotExit;
                        goto Finish;
                    }

                    default:
                    {
                        Debug.Assert(false, "Unexpected value for exit reason");
                        goto Finish;
                    }
                    }
                }

                default:
                {
                    Debug.Assert(false, "Unexpected value for continuation reason");
                    goto Finish;
                }
                }

DoHandleEvent:
                if (!currentTrigger.Equals(PrtValue.@null))
                {
                    currEventValue = currentTrigger;
                    currentTrigger = PrtValue.@null;
                }
                else
                {
                    currEventValue = eventValue;
                }

                if (PrtIsTransitionPresent(currEventValue))
                {
                    stateExitReason = PrtStateExitReason.OnTransition;
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    eventValue      = currEventValue;
                    PrtPushExitFunction();
                    goto DoExecuteFunction;
                }
                else if (PrtIsActionInstalled(currEventValue))
                {
                    eventValue = currEventValue;
                    goto DoAction;
                }
                else
                {
                    stateExitReason = PrtStateExitReason.OnUnhandledEvent;
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    eventValue      = currEventValue;
                    PrtPushExitFunction();
                    goto DoExecuteFunction;
                }

Finish:
                if (hasMoreWork)
                {
                    if (numOfStepsTaken > 100000)
                    {
                        throw new PrtInfiniteRaiseLoop("Infinite loop in spec machine");
                    }
                    else
                    {
                        numOfStepsTaken++;
                        goto Start;
                    }
                }
                else
                {
                    return;
                }
            }
            catch (PrtException ex)
            {
                stateImpl.Exception = ex;
            }
        }
示例#2
0
        public bool PrtStepStateMachine()
        {
            PrtValue currEventValue;
            PrtFun   currAction;
            bool     hasMoreWork = false;

            switch (nextSMOperation)
            {
            case PrtNextStatemachineOperation.ExecuteFunctionOperation:
                goto DoExecuteFunction;

            case PrtNextStatemachineOperation.DequeueOperation:
                goto DoDequeue;

            case PrtNextStatemachineOperation.HandleEventOperation:
                goto DoHandleEvent;

            case PrtNextStatemachineOperation.ReceiveOperation:
                goto DoReceive;
            }

DoExecuteFunction:

            /*
             * Note that we have made an assumption that when a state is pushed on state stack or a transition is taken (update to a state)
             * the action set and deferred set is updated appropriately
             */
            if (invertedFunStack.TopOfStack == null)
            {
                stateImpl.TraceLine("<StateLog> Machine {0}-{1} entering State {2}", this.Name, this.instanceNumber, CurrentState.name);
                if (CurrentState.entryFun.IsAnonFun)
                {
                    PrtPushFunStackFrame(CurrentState.entryFun, CurrentState.entryFun.CreateLocals(currentPayload));
                }
                else
                {
                    PrtPushFunStackFrame(CurrentState.entryFun, CurrentState.entryFun.CreateLocals());
                }
            }
            //invoke the function
            invertedFunStack.TopOfStack.fun.Execute(stateImpl, this);
            goto CheckFunLastOperation;

DoAction:
            currAction = PrtFindActionHandler(eventValue);
            if (currAction == PrtFun.IgnoreFun)
            {
                stateImpl.TraceLine("<ActionLog> Machine {0}-{1} ignoring Event '{2}' in State {3}", this.Name, this.instanceNumber, eventValue, CurrentState.name);
                PrtResetTriggerAndPayload();
                nextSMOperation = PrtNextStatemachineOperation.DequeueOperation;
                hasMoreWork     = true;
                goto Finish;
            }
            else
            {
                if (invertedFunStack.TopOfStack == null)
                {
                    stateImpl.TraceLine("<ActionLog> Machine {0}-{1} executing action for Event '{2}' in State {3}", this.Name, this.instanceNumber, eventValue, CurrentState.name);
                    if (currAction.IsAnonFun)
                    {
                        PrtPushFunStackFrame(currAction, currAction.CreateLocals(currentPayload));
                    }
                    else
                    {
                        PrtPushFunStackFrame(currAction, currAction.CreateLocals());
                    }
                }
                //invoke the action handler
                invertedFunStack.TopOfStack.fun.Execute(stateImpl, this);
            }
            goto CheckFunLastOperation;

CheckFunLastOperation:

            switch (continuation.reason)
            {
            case PrtContinuationReason.Pop:
            {
                //clear the fun stack on pop
                invertedFunStack.Clear();
                stateExitReason = PrtStateExitReason.OnPopStatement;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                PrtPushExitFunction();
                goto DoExecuteFunction;
            }

            case PrtContinuationReason.Goto:
            {
                //clear fun stack on goto
                invertedFunStack.Clear();
                stateExitReason = PrtStateExitReason.OnGotoStatement;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                PrtPushExitFunction();
                goto DoExecuteFunction;
            }

            case PrtContinuationReason.Raise:
            {
                //clear fun stack on raise
                invertedFunStack.Clear();
                nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                hasMoreWork     = true;
                goto Finish;
            }

            case PrtContinuationReason.NewMachine:
            {
                hasMoreWork     = false;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                goto Finish;
            }

            case PrtContinuationReason.Nondet:
            {
                stateImpl.SetPendingChoicesAsBoolean(this);
                continuation.nondet = ((Boolean)stateImpl.GetSelectedChoiceValue(this));
                hasMoreWork         = false;
                goto Finish;
            }

            case PrtContinuationReason.Receive:
            {
                nextSMOperation = PrtNextStatemachineOperation.ReceiveOperation;
                hasMoreWork     = true;
                goto Finish;
            }

            case PrtContinuationReason.Send:
            {
                hasMoreWork     = false;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                goto Finish;
            }

            case PrtContinuationReason.Return:
            {
                switch (stateExitReason)
                {
                case PrtStateExitReason.NotExit:
                {
                    nextSMOperation = PrtNextStatemachineOperation.DequeueOperation;
                    hasMoreWork     = true;
                    goto Finish;
                }

                case PrtStateExitReason.OnPopStatement:
                {
                    var cs = CurrentState;
                    hasMoreWork = !PrtPopState(true);
                    stateImpl.StateTransitionCallback?.Invoke(this, cs, CurrentState, "pop");

                    nextSMOperation = PrtNextStatemachineOperation.DequeueOperation;
                    stateExitReason = PrtStateExitReason.NotExit;
                    goto Finish;
                }

                case PrtStateExitReason.OnGotoStatement:
                {
                    stateImpl.StateTransitionCallback?.Invoke(this, CurrentState, destOfGoto, "goto");
                    PrtChangeState(destOfGoto);
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    stateExitReason = PrtStateExitReason.NotExit;
                    hasMoreWork     = true;
                    goto Finish;
                }

                case PrtStateExitReason.OnUnhandledEvent:
                {
                    hasMoreWork     = !PrtPopState(false);
                    nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                    stateExitReason = PrtStateExitReason.NotExit;
                    goto Finish;
                }

                case PrtStateExitReason.OnTransition:
                {
                    stateImpl.StateTransitionCallback?.Invoke(this, CurrentState, CurrentState.transitions[eventValue].gotoState, eventValue.ToString());
                    stateExitReason = PrtStateExitReason.OnTransitionAfterExit;
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    PrtPushTransitionFun(eventValue);
                    goto DoExecuteFunction;
                }

                case PrtStateExitReason.OnTransitionAfterExit:
                {
                    stateImpl.StateTransitionCallback?.Invoke(this, CurrentState, CurrentState.transitions[eventValue].gotoState, eventValue.ToString());

                    // The parameter to an anonymous transition function is always passed as swap.
                    // Update currentPayload to the latest value of the parameter so that the correct
                    // value gets passed to the entry function of the target state.
                    PrtTransition transition    = CurrentState.transitions[eventValue];
                    PrtFun        transitionFun = transition.transitionFun;
                    if (transitionFun.IsAnonFun)
                    {
                        currentPayload = continuation.retLocals[0];
                    }
                    PrtChangeState(transition.gotoState);
                    stateExitReason = PrtStateExitReason.NotExit;
                    nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                    hasMoreWork     = true;
                    goto Finish;
                }

                default:
                {
                    Debug.Assert(false, "Unexpected value for exit reason");
                    goto Finish;
                }
                }
            }

            default:
            {
                Debug.Assert(false, "Unexpected value for continuation reason");
                goto Finish;
            }
            }

DoDequeue:
            Debug.Assert(receiveSet.Count == 0, "Machine cannot be blocked at receive when here");
            var dequeueStatus = PrtDequeueEvent(CurrentState.hasNullTransition);

            if (dequeueStatus == PrtDequeueReturnStatus.BLOCKED)
            {
                nextSMOperation = PrtNextStatemachineOperation.DequeueOperation;
                hasMoreWork     = false;
                goto Finish;
            }
            else if (dequeueStatus == PrtDequeueReturnStatus.SUCCESS)
            {
                nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                hasMoreWork     = true;
                goto Finish;
            }
            else // NULL transition
            {
                nextSMOperation = PrtNextStatemachineOperation.HandleEventOperation;
                hasMoreWork     = false;
                eventValue      = PrtValue.@null;
                goto Finish;
            }

DoHandleEvent:
            Debug.Assert(receiveSet.Count == 0, "The machine must not be blocked on a receive");
            if (!currentTrigger.Equals(PrtValue.@null))
            {
                currEventValue = currentTrigger;
                currentTrigger = PrtValue.@null;
            }
            else
            {
                currEventValue = eventValue;
            }

            if (PrtIsPushTransitionPresent(currEventValue))
            {
                eventValue = currEventValue;
                stateImpl.StateTransitionCallback?.Invoke(this, CurrentState, CurrentState.transitions[currEventValue].gotoState, currEventValue.ToString());
                PrtPushState(CurrentState.transitions[currEventValue].gotoState);
                goto DoExecuteFunction;
            }
            else if (PrtIsTransitionPresent(currEventValue))
            {
                stateExitReason = PrtStateExitReason.OnTransition;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                eventValue      = currEventValue;
                PrtPushExitFunction();
                goto DoExecuteFunction;
            }
            else if (PrtIsActionInstalled(currEventValue))
            {
                eventValue = currEventValue;
                goto DoAction;
            }
            else
            {
                stateExitReason = PrtStateExitReason.OnUnhandledEvent;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                eventValue      = currEventValue;
                PrtPushExitFunction();
                goto DoExecuteFunction;
            }

DoReceive:
            if (receiveSet.Count == 0)
            {
                stateExitReason = PrtStateExitReason.NotExit;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                goto DoExecuteFunction;
            }
            dequeueStatus = PrtDequeueEvent(false);
            if (dequeueStatus == PrtDequeueReturnStatus.BLOCKED)
            {
                nextSMOperation = PrtNextStatemachineOperation.ReceiveOperation;
                hasMoreWork     = false;
                goto Finish;
            }
            else if (dequeueStatus == PrtDequeueReturnStatus.SUCCESS)
            {
                stateExitReason = PrtStateExitReason.NotExit;
                nextSMOperation = PrtNextStatemachineOperation.ExecuteFunctionOperation;
                goto DoExecuteFunction;
            }
            else // NULL case
            {
                nextSMOperation = PrtNextStatemachineOperation.ReceiveOperation;
                hasMoreWork     = false;
                goto Finish;
            }

Finish:
            Debug.Assert(!hasMoreWork || currentStatus == PrtMachineStatus.Enabled, "hasMoreWork is true but the statemachine is blocked");
            return(hasMoreWork);
        }