SCCD_execute.alc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. include "primitives.alh"
  2. include "modelling.alh"
  3. include "object_operations.alh"
  4. include "utils.alh"
  5. include "random.alh"
  6. Void function print_states(model : Element, data : Element):
  7. Element classes
  8. Element states
  9. Element class
  10. String state
  11. log("Current states:")
  12. classes = set_copy(data["classes"])
  13. while (read_nr_out(classes) > 0):
  14. class = set_pop(classes)
  15. log(string_join(string_join(string_join(" ", class["ID"]), " : "), read_attribute(model, class["type"], "name")))
  16. states = set_copy(class["states"])
  17. while (read_nr_out(states) > 0):
  18. state = set_pop(states)
  19. log(string_join(" ", read_attribute(model, state, "name")))
  20. return!
  21. Element function filter(model : Element, set : Element, attribute_name : String, attribute_value : Element):
  22. Element keys
  23. String key
  24. Element result
  25. result = create_node()
  26. while (read_nr_out(set) > 0):
  27. key = set_pop(set)
  28. if (value_eq(read_attribute(model, key, attribute_name), attribute_value)):
  29. set_add(result, key)
  30. return result!
  31. Element function expand_state(model : Element, state : String):
  32. String t
  33. t = read_type(model, state)
  34. if (t == "SCCD/CompositeState"):
  35. // Recurse further in the composite
  36. return expand_composite_state(model, state)!
  37. elif (t == "SCCD/ParallelState"):
  38. // Split up all components
  39. return expand_parallel_state(model, state)!
  40. else:
  41. // Probably just an atomic, so return this one only
  42. Element result
  43. result = create_node()
  44. set_add(result, state)
  45. return result!
  46. Element function expand_composite_state(model : Element, composite_state : String):
  47. // Resolve all initial states from a single composite state
  48. String initial
  49. // Fetch the initial state
  50. initial = set_pop(filter(model, allAssociationDestinations(model, composite_state, "SCCD/composite_children"), "isInitial", True))
  51. // Expand the initial state, depending on what it is
  52. return expand_state(model, initial)!
  53. Element function expand_parallel_state(model : Element, parallel_state : String):
  54. // Resolve all initial states from a single parallel state
  55. Element children
  56. Element result
  57. Element expanded_children
  58. children = allAssociationDestinations(model, parallel_state, "SCCD/parallel_children")
  59. result = create_node()
  60. while (read_nr_out(children) > 0):
  61. set_merge(result, expand_state(model, set_pop(children)))
  62. return result!
  63. Void function start_class(model : Element, data : Element, class : String):
  64. // Start up the class and assign its initial state to it
  65. // Create the data structure for a running class
  66. Element class_handle
  67. class_handle = create_node()
  68. dict_add(class_handle, "type", class)
  69. dict_add(class_handle, "ID", cast_id2s(create_node()))
  70. // Add the current state of the class
  71. String initial_state
  72. // Should only be one behaviour linked to it!
  73. initial_state = set_pop(allAssociationDestinations(model, class, "SCCD/behaviour"))
  74. dict_add(class_handle, "states", expand_state(model, initial_state))
  75. // Add all attributes
  76. Element attributes
  77. attributes = create_node()
  78. Element attrs
  79. attrs = allAssociationDestinations(model, class, "SCCD/class_attributes")
  80. while (read_nr_out(attrs) > 0):
  81. dict_add(attributes, read_attribute(model, set_pop(attrs), "name"), create_node())
  82. dict_add(class_handle, "attributes", attributes)
  83. set_add(data["classes"], class_handle)
  84. return!
  85. Element function get_enabled_transitions(model : Element, state : String, interrupt : Element):
  86. // Returns all enabled transitions
  87. // TODO ignore conditions and afters
  88. Element result
  89. Element to_filter
  90. String attr
  91. String transition
  92. Element cond
  93. result = create_node()
  94. to_filter = allOutgoingAssociationInstances(model, state, "SCCD/transition")
  95. while (read_nr_out(to_filter) > 0):
  96. transition = set_pop(to_filter)
  97. attr = read_attribute(model, transition, "event")
  98. if (bool_or(element_eq(attr, read_root()), value_eq(attr, interrupt))):
  99. // Event is OK
  100. cond = read_attribute(model, transition, "cond")
  101. log("Resolved condition")
  102. if (element_neq(cond, read_root())):
  103. log("Result = " + cast_e2s(cond))
  104. cond = get_func_AL_model(cond)
  105. log("Resolved = " + cast_e2s(cond))
  106. // Execute condition
  107. if (bool_not(cond(create_node()))):
  108. log("Evaluated to True")
  109. // Condition false, so skip
  110. continue!
  111. else:
  112. log("Evaluated to False")
  113. else:
  114. log("NO condition")
  115. // Condition is OK
  116. set_add(result, transition)
  117. return result!
  118. Float function step_class(model : Element, data : Element, class : Element, interrupt : Element):
  119. // Find enabled transitions in a class and execute it, updating the state
  120. // Iterate over all current states, searching for enabled transitions
  121. // Search for enabled transitions in higher levels as well!
  122. Element states
  123. Element new_states
  124. String state
  125. Element transitions
  126. String transition
  127. Float t_min
  128. Float t_current
  129. states = set_copy(class["states"])
  130. new_states = create_node()
  131. while (read_nr_out(states) > 0):
  132. state = set_pop(states)
  133. // Fetch transitions in this state specifically (NO parent)
  134. transitions = get_enabled_transitions(model, state, interrupt)
  135. if (read_nr_out(transitions) != 0):
  136. // Found an enabled transition, so store that one
  137. transition = random_choice(transitions)
  138. set_merge(new_states, expand_state(model, readAssociationDestination(model, transition)))
  139. else:
  140. // Try going to the parent
  141. // TODO
  142. // Nothing found, so stay in the current state
  143. set_add(new_states, state)
  144. // Update states
  145. dict_overwrite(class, "states", new_states)
  146. return 1.0!
  147. Float function step(model : Element, data : Element, interrupt : Element):
  148. // Step through all classes
  149. Element classes
  150. Element class
  151. Float t_min
  152. Float t_class
  153. t_min = 99999.0
  154. classes = set_copy(data["classes"])
  155. while (read_nr_out(classes) > 0):
  156. class = set_pop(classes)
  157. t_class = step_class(model, data, class, interrupt)
  158. if (t_class < t_min):
  159. t_min = t_class
  160. return t_min!
  161. Boolean function main(model : Element):
  162. // Executes the provided SCCD model
  163. Element data
  164. data = create_node()
  165. dict_add(data, "classes", create_node())
  166. // Prepare for input
  167. output("Ready for input!")
  168. // Find initial
  169. String default_class
  170. default_class = set_pop(filter(model, allInstances(model, "SCCD/Class"), "default", True))
  171. // Start up the default class
  172. start_class(model, data, default_class)
  173. Float timeout
  174. Element interrupt
  175. timeout = 0.0
  176. while (True):
  177. print_states(model, data)
  178. interrupt = input_timeout(timeout)
  179. if (value_eq(interrupt, "#EXIT#")):
  180. // Stop execution
  181. return True!
  182. if (element_neq(interrupt, read_root())):
  183. // Got interrupt
  184. log("Got event: " + cast_v2s(interrupt))
  185. output("Processed event, ready for more!")
  186. timeout = step(model, data, interrupt)
  187. // We should never get here!
  188. return False!