/src/lib/automaton/automaton.e

http://github.com/tybor/Liberty · Specman e · 200 lines · 149 code · 22 blank · 29 comment · 2 complexity · b4327054650380991019c6cbea4fb2e9 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class AUTOMATON[E_]
  5. create {ANY}
  6. manifest_creation
  7. feature {ANY} -- Simple one-shot execution
  8. run (start_state: ABSTRACT_STRING; e: E_)
  9. require
  10. has(start_state)
  11. local
  12. context: AUTOMATON_CONTEXT[E_]
  13. do
  14. from
  15. context := start(start_state, e)
  16. until
  17. not context.is_valid
  18. loop
  19. next(context)
  20. end
  21. end
  22. has (state_name: ABSTRACT_STRING): BOOLEAN
  23. require
  24. state_name /= Void
  25. do
  26. Result := states.fast_has(state_name.intern)
  27. end
  28. feature {ANY} -- Step-by-step execution
  29. start (start_state: ABSTRACT_STRING; e: E_): AUTOMATON_CONTEXT[E_]
  30. require
  31. has(start_state)
  32. local
  33. state: STATE[E_]
  34. do
  35. create Result.make(e)
  36. state := next_transition(Void, start_state, e)
  37. check
  38. state_exists: state /= Void
  39. end
  40. Result.set_current_state(state)
  41. ensure
  42. Result.is_valid
  43. Result.current_state /= Void
  44. end
  45. next (context: AUTOMATON_CONTEXT[E_])
  46. require
  47. context.is_valid
  48. local
  49. next_state: ABSTRACT_STRING
  50. state: STATE[E_]
  51. do
  52. next_state := context.current_state.run(Current, context.data)
  53. if next_state /= Void then
  54. check has(next_state) end
  55. state := next_transition(context.current_state, next_state, context.data)
  56. check
  57. state_exists: state /= Void
  58. end
  59. context.set_current_state(state)
  60. else
  61. last_transition(context.current_state, context.data)
  62. context.invalidate
  63. end
  64. end
  65. feature {}
  66. next_transition (from_state: STATE[E_]; state_name: ABSTRACT_STRING; e: E_): STATE[E_]
  67. do
  68. debug ("automaton/transition")
  69. if from_state = Void then
  70. std_output.put_line("Void => " + state_name.out)
  71. else
  72. std_output.put_line(from_state.name.out + " => " + state_name.out)
  73. end
  74. end
  75. Result := states.fast_reference_at(state_name.intern)
  76. transition.call([e, from_state, Result])
  77. end
  78. last_transition (from_state: STATE[E_]; e: E_)
  79. require
  80. from_state /= Void
  81. local
  82. no_state: STATE[E_]
  83. do
  84. debug ("automaton/transition")
  85. std_output.put_line(from_state.name.out + " => Void")
  86. end
  87. transition.call([e, from_state, no_state])
  88. end
  89. feature {STATE} --|* TODO: should be STATE[E_] (when Liberty can bootstrap)
  90. call_before_guards (e: E_; state: STATE[E_])
  91. do
  92. before_guards.call([e, state])
  93. end
  94. call_after_guards (e: E_; state: STATE[E_])
  95. do
  96. after_guards.call([e, state])
  97. end
  98. feature {ANY}
  99. set_before_guards (p: like before_guards)
  100. do
  101. before_guards := p
  102. ensure
  103. before_guards = p
  104. end
  105. set_after_guards (p: like after_guards)
  106. do
  107. after_guards := p
  108. ensure
  109. after_guards = p
  110. end
  111. set_transition (p: like transition)
  112. do
  113. transition := p
  114. ensure
  115. transition = p
  116. end
  117. feature {}
  118. states: DICTIONARY[STATE[E_], FIXED_STRING]
  119. -- A dictionary of all the states
  120. before_guards: PROCEDURE[TUPLE[E_, STATE[E_]]]
  121. -- That agent is called before checking guards. The given state is the current one.
  122. after_guards: PROCEDURE[TUPLE[E_, STATE[E_]]]
  123. -- That agent is called after checking guards, whether a guard was raised or not. The given state
  124. -- the current one.
  125. transition: PROCEDURE[TUPLE[E_, STATE[E_], STATE[E_]]]
  126. -- That agent is called when the next state was found. The given states are resp. the current one
  127. -- (Void if first transition) and the successor (Void is last transition).
  128. default_before_guards, default_after_guards, default_transition
  129. do
  130. end
  131. feature {}
  132. manifest_make (needed_capacity: INTEGER)
  133. do
  134. create {HASHED_DICTIONARY[STATE[E_], FIXED_STRING]} states.with_capacity(needed_capacity)
  135. before_guards := agent default_before_guards
  136. after_guards := agent default_after_guards
  137. transition := agent default_transition
  138. end
  139. manifest_put (index: INTEGER; state_name: ABSTRACT_STRING; state: STATE[E_])
  140. require
  141. index >= 0
  142. not states.fast_has(state_name.intern)
  143. local
  144. name: FIXED_STRING
  145. do
  146. name := state_name.intern
  147. state.set_name(name)
  148. states.add(state, name)
  149. ensure
  150. states.fast_has(state_name.intern)
  151. end
  152. manifest_semicolon_check: INTEGER 2
  153. invariant
  154. states /= Void
  155. before_guards /= Void
  156. after_guards /= Void
  157. transition /= Void
  158. end -- class AUTOMATON
  159. --
  160. -- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
  161. --
  162. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  163. -- of this software and associated documentation files (the "Software"), to deal
  164. -- in the Software without restriction, including without limitation the rights
  165. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  166. -- copies of the Software, and to permit persons to whom the Software is
  167. -- furnished to do so, subject to the following conditions:
  168. --
  169. -- The above copyright notice and this permission notice shall be included in
  170. -- all copies or substantial portions of the Software.
  171. --
  172. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  173. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  174. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  175. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  176. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  177. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  178. -- THE SOFTWARE.