Chapter 5. The run/step/fire operations

Let us see the behavior of these three operations.

The run algorithm

Behavior :

1 – initialize current state

2 – loop until the user's input equal to "quit"

print the current state

read a string

process a step

catch exceptions if there are some and exit the program displaying the error.

Here is the code of the operation :

operation run() : Void raises FSMException is do  
  // reset if there is no current state
  if self.currentState == void then self.currentState := self.initialState end
  self
  from var str : String init "init"
  until str == "quit"
  loop
    stdio.writeln("Current state : " + self.currentState.name)
    str := stdio.read("give me a letter : ")
    if str == "quit" then
      stdio.writeln("")
      stdio.writeln("quitting ...")
    else 
      if str == "print" then
        stdio.writeln("")
      else	
        stdio.writeln(str)
        stdio.writeln("stepping...")
        do
          var textRes : String
          textRes := self.currentState.step(str)
          if( textRes == void or textRes == "" ) then
            textRes := "NC"
          end

          stdio.writeln("string produced : " + textRes)
          rescue (err : ConstraintViolatedPre)
            stdio.writeln(err.toString)
            stdio.writeln(err.message)
            str := "quit"
          rescue (err : ConstraintViolatedPost)
            stdio.writeln(err.toString)
            stdio.writeln(err.message)
            str := "quit"
          rescue(err : NonDeterminism)
            stdio.writeln(err.toString)
            str := "quit"
          rescue(err : NoTransition)
            stdio.writeln(err.toString)
            str := "quit"
          end
        end
      end
    end
end

The step algorithm

In this operation, there are pre and post conditions. These are conditions checked each time the operation is called. If they are evaluated to false an exception is raised. You can choose to check them or not. Please refer to the corresponding tutorial on how to use run configurations.

Behavior :

1 – Select the possible transitions.

2 – If there is none raise a NoTransition exception.

If there is more than one raise a NonDeterminism exception.

3 – If there is only one transition, call its fire operation and return its result.

// Go to the next state
operation step(c : String) : String raises FSMException

  // Declaration of the pre-condition
  pre notVoidInput is
    c != void and c != ""

  // Declaration of the post-condition
  post notVoidOutput is
  result != void and result != ""
  
  is do
    // Get the valid transitions
    var validTransitions : Collection<Transition> 
    validTransitions :=	outgoingTransition.select { t | t.input.equals(c) }
    // Check if there is one and only one valid transition
    if validTransitions.empty then raise NoTransition.new end
    if validTransitions.size > 1 then raise NonDeterminism.new end

    // Fire the transition
    result := validTransitions.one.fire
  end

The fire algorithm

Behavior :

1 – change the current state of the FSM

2 – return the produced string

// Fire the transition
operation fire() : String is do
  // update FSM current state
  source.owningFSM.currentState := target
  result := output
end