Class: YATM::StateMachine

Inherits:
Object
  • Object
show all
Defined in:
lib/yatm/state_machine/state_machine.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeStateMachine

Returns a new instance of StateMachine.



14
15
16
17
# File 'lib/yatm/state_machine/state_machine.rb', line 14

def initialize
  @events = {}
  @final_states = []
end

Instance Attribute Details

#current_stateObject (readonly)

The current state of the state machine



8
9
10
# File 'lib/yatm/state_machine/state_machine.rb', line 8

def current_state
  @current_state
end

#eventsArray<YATM::StateMachine::Event> (readonly)

Returns A list of the events that can processed by the machine.

Returns:

  • (Array<YATM::StateMachine::Event>)

    A list of the events that can processed by the machine



10
11
12
# File 'lib/yatm/state_machine/state_machine.rb', line 10

def events
  @events
end

#final_statesArray (readonly)

Returns A list of the final states.

Returns:

  • (Array)

    A list of the final states



12
13
14
# File 'lib/yatm/state_machine/state_machine.rb', line 12

def final_states
  @final_states
end

Class Method Details

.statify(state) ⇒ Symbol | nil

Returns If the object could be statified, it’s statified form. Nil otherwise.

Parameters:

  • state (#to_s && #to_sym)

    The object to be statified

Returns:

  • (Symbol | nil)

    If the object could be statified, it’s statified form. Nil otherwise



134
135
136
# File 'lib/yatm/state_machine/state_machine.rb', line 134

def statify(state)
  statify!(state) rescue StateMachineError
end

.statify!(state) ⇒ Symbol

Returns The object’s statified form.

Parameters:

  • state (#to_s && #to_sym)

    The object to be statified

Returns:

  • (Symbol)

    The object’s statified form

Raises:

  • (InvalidState)

    The object given could not be statified



122
123
124
125
126
127
128
129
# File 'lib/yatm/state_machine/state_machine.rb', line 122

def statify!(state)
  raise InvalidState, state unless state.respond_to?(:to_s)

  state = state.to_s
  raise InvalidState, state unless state.respond_to?(:to_sym)

  state.to_sym
end

Instance Method Details

#event(name, **transitions) ⇒ YATM::StateMachine::Event

Returns The event object creared.

Parameters:

  • name (Object)

    The name of the event.

    Note that this is also the value which, when read from the tape, will trigger the processing of this event.

  • **transitions (Hash | Hash[, Hash...])

    One or more transitions.

    Transitions can be of the following forms:

    • ‘state1 => [state2, value, movement]`

    • ‘state1 => [state2, value]`

    • ‘state1 => [state2]`

    • ‘state1 => state2`

    On all cases, the machine is going from state1 to state2, writing value on the current position of the tape, and moving the head in the direction specified by movement.

Returns:

  • (YATM::StateMachine::Event)

    The event object creared



85
86
87
# File 'lib/yatm/state_machine/state_machine.rb', line 85

def event(name, **transitions)
  @events[name] = YATM::Event.new(name, **transitions)
end

#final_state(*states) ⇒ Array

Returns The complete list of final states.

Parameters:

  • states (#to_s && #to_sym)

    The state or array of states to be marked as final states

Returns:

  • (Array)

    The complete list of final states



63
64
65
66
67
68
# File 'lib/yatm/state_machine/state_machine.rb', line 63

def final_state(*states)
  states.each do |state|
    (@final_states << self.class.statify(state)).uniq!
  end
  @final_states
end

#initial_state(state) ⇒ Object #initial_stateObject

Overloads:

  • #initial_state(state) ⇒ Object

    Returns The initial state.

    Parameters:

    • state (#to_s && #to_sym)

      The state to be set as the starting state

    Returns:

    • (Object)

      The initial state

  • #initial_stateObject

    Returns The initial state.

    Returns:

    • (Object)

      The initial state

See Also:



53
54
55
56
57
58
# File 'lib/yatm/state_machine/state_machine.rb', line 53

def initial_state(state = nil)
  return @initial_state if state.nil?

  @initial_state = self.class.statify(state)
  @current_state = @initial_state
end

#process(value) ⇒ Hash | nil

Returns A representation of the transition which was triggered, or nil if none was.

Parameters:

  • value (Object)

    Tape value to be processed (trigger corresponding event) by the machine

Returns:

  • (Hash | nil)

    A representation of the transition which was triggered, or nil if none was



93
94
95
96
97
# File 'lib/yatm/state_machine/state_machine.rb', line 93

def process(value)
  process!(value)
rescue StateMachineError
  nil
end

#process!(value) ⇒ Hash

Returns A representation of the transition which was triggered.

Parameters:

  • value (Object)

    Tape value to be processed (trigger corresponding event) by the machine

Returns:

  • (Hash)

    A representation of the transition which was triggered

Raises:

  • (InitialStateNotSet)

    No initial state was set. See #initial_state

  • (InvalidEvent)

    There is no event registered under the given value

  • (InvalidTransition)

    There is an event registered under the given value, but it contains no transitions from the machine’s current state



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/yatm/state_machine/state_machine.rb', line 106

def process!(value)
  return { final: @current_state } if @final_states.include?(@current_state)
  raise InitialStateNotSet unless @current_state
  raise InvalidEvent, value unless (event = @events[value])
  raise InvalidTransition.new(@current_state, event) unless (
    transition = event[@current_state] || event[YATM::ANY]
  )

  @current_state = transition[:to] unless transition[:to] == YATM::SAME
  transition
end

#resetObject



19
20
21
# File 'lib/yatm/state_machine/state_machine.rb', line 19

def reset
  @current_state = @initial_state
end

#statesArray

Returns The list of all states of the state machine.

Returns:

  • (Array)

    The list of all states of the state machine



40
41
42
43
44
# File 'lib/yatm/state_machine/state_machine.rb', line 40

def states
  @events.map do |_name, event|
    event.keys + event.map { |_, val| val[:to] }
  end.flatten.uniq
end

#to_sString

Returns A string representation of the state machine.

Examples:

Example output

puts state_machine.to_s

| states:  [:start, :A, :B, :end]
| current: :start
| events: [nil, 0, 1]

Returns:

  • (String)

    A string representation of the state machine



31
32
33
34
35
36
37
# File 'lib/yatm/state_machine/state_machine.rb', line 31

def to_s
  <<~TO_S.chomp
    | states:  #{states}
    | current: #{@current_state}
    | events: #{@events.map(&:name)}
  TO_S
end