roby 0.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (644) hide show
  1. checksums.yaml +7 -0
  2. data/.deep-cover.rb +3 -0
  3. data/.gitattributes +1 -0
  4. data/.gitignore +24 -0
  5. data/.simplecov +10 -0
  6. data/.travis.yml +17 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +15 -0
  9. data/README.md +11 -0
  10. data/Rakefile +47 -177
  11. data/benchmark/{alloc_misc.rb → attic/alloc_misc.rb} +2 -2
  12. data/benchmark/{discovery_latency.rb → attic/discovery_latency.rb} +19 -19
  13. data/benchmark/{garbage_collection.rb → attic/garbage_collection.rb} +9 -9
  14. data/benchmark/{genom.rb → attic/genom.rb} +0 -0
  15. data/benchmark/attic/transactions.rb +62 -0
  16. data/benchmark/plan_basic_operations.rb +28 -0
  17. data/benchmark/relations/graph.rb +63 -0
  18. data/benchmark/ruby/identity.rb +18 -0
  19. data/benchmark/ruby/set_intersect_vs_hash_merge.rb +39 -0
  20. data/benchmark/ruby/yield_vs_block.rb +35 -0
  21. data/benchmark/run +5 -0
  22. data/benchmark/synthetic_plan_modifications_with_transactions.rb +79 -0
  23. data/benchmark/transactions.rb +99 -51
  24. data/bin/roby +38 -197
  25. data/bin/roby-display +14 -0
  26. data/bin/roby-log +3 -176
  27. data/doc/guide/{src → attic}/abstraction/achieve_with.page +1 -1
  28. data/doc/guide/{src → attic}/abstraction/forwarding.page +1 -1
  29. data/doc/guide/{src → attic}/abstraction/hierarchy.page +1 -1
  30. data/doc/guide/{src → attic}/abstraction/index.page +1 -1
  31. data/doc/guide/{src → attic}/abstraction/task_models.page +1 -1
  32. data/doc/guide/{overview.rdoc → attic/cycle/api_overview.rdoc} +6 -1
  33. data/doc/guide/{src → attic}/cycle/cycle-overview.png +0 -0
  34. data/doc/guide/{src → attic}/cycle/cycle-overview.svg +0 -0
  35. data/doc/guide/attic/cycle/error_handling.page +98 -0
  36. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.png +0 -0
  37. data/doc/guide/{src → attic}/cycle/error_instantaneous_repair.svg +0 -0
  38. data/doc/guide/{src/cycle/error_handling.page → attic/cycle/error_sources.page} +46 -89
  39. data/doc/guide/{src → attic}/cycle/garbage_collection.page +1 -1
  40. data/doc/guide/{src → attic}/cycle/index.page +1 -1
  41. data/doc/guide/{src → attic}/cycle/propagation.page +11 -1
  42. data/doc/guide/{src → attic}/cycle/propagation_diamond.png +0 -0
  43. data/doc/guide/{src → attic}/cycle/propagation_diamond.svg +0 -0
  44. data/doc/guide/attic/plans/building_plans.page +89 -0
  45. data/doc/guide/attic/plans/code.page +192 -0
  46. data/doc/guide/{src/basics → attic/plans}/events.page +3 -4
  47. data/doc/guide/attic/plans/index.page +7 -0
  48. data/doc/guide/{plan_modifications.rdoc → attic/plans/plan_modifications.rdoc} +5 -3
  49. data/doc/guide/{src/basics → attic/plans}/plan_objects.page +2 -1
  50. data/doc/guide/attic/plans/querying_plans.page +5 -0
  51. data/doc/guide/{src/basics → attic/plans}/tasks.page +20 -20
  52. data/doc/guide/config.yaml +7 -4
  53. data/doc/guide/ext/extended_menu.rb +29 -0
  54. data/doc/guide/ext/init.rb +6 -0
  55. data/doc/guide/ext/rdoc_links.rb +7 -6
  56. data/doc/guide/src/advanced_concepts/history.page +5 -0
  57. data/doc/guide/src/advanced_concepts/index.page +11 -0
  58. data/doc/guide/src/advanced_concepts/recognizing_patterns.page +83 -0
  59. data/doc/guide/src/advanced_concepts/scheduling.page +87 -0
  60. data/doc/guide/src/advanced_concepts/transactions.page +5 -0
  61. data/doc/guide/src/advanced_concepts/unreachability.page +42 -0
  62. data/doc/guide/src/base.template +96 -0
  63. data/doc/guide/src/basics_shell_header.txt +5 -7
  64. data/doc/guide/src/building/action_coordination.page +96 -0
  65. data/doc/guide/src/building/actions.page +124 -0
  66. data/doc/guide/src/building/file_layout.page +71 -0
  67. data/doc/guide/src/building/index.page +50 -0
  68. data/doc/guide/src/building/patterns.page +86 -0
  69. data/doc/guide/src/building/patterns_forwarding.png +0 -0
  70. data/doc/guide/src/building/patterns_forwarding.svg +277 -0
  71. data/doc/guide/src/building/runtime.page +95 -0
  72. data/doc/guide/src/building/task_models.page +94 -0
  73. data/doc/guide/src/building/tasks.page +284 -0
  74. data/doc/guide/src/concepts/error_handling.page +100 -0
  75. data/doc/guide/src/concepts/exception_propagation.png +0 -0
  76. data/doc/guide/src/concepts/exception_propagation.svg +445 -0
  77. data/doc/guide/src/concepts/execution.page +85 -0
  78. data/doc/guide/src/concepts/execution.png +0 -0
  79. data/doc/guide/src/concepts/execution.svg +573 -0
  80. data/doc/guide/src/concepts/execution_cycle.png +0 -0
  81. data/doc/guide/src/concepts/garbage_collection.page +57 -0
  82. data/doc/guide/src/concepts/index.page +27 -0
  83. data/doc/guide/src/concepts/plans.page +101 -0
  84. data/doc/guide/src/concepts/policy.page +31 -0
  85. data/doc/guide/src/concepts/reactor.page +61 -0
  86. data/doc/guide/src/concepts/simple_plan_example.png +0 -0
  87. data/doc/guide/src/concepts/simple_plan_example.svg +376 -0
  88. data/doc/guide/src/default.template +9 -74
  89. data/doc/guide/src/event_relations/forward.page +71 -0
  90. data/doc/guide/src/event_relations/index.page +12 -0
  91. data/doc/guide/src/event_relations/scheduling_constraints.page +43 -0
  92. data/doc/guide/src/event_relations/signal.page +55 -0
  93. data/doc/guide/src/event_relations/temporal_constraints.page +77 -0
  94. data/doc/guide/src/htmldoc.metainfo +21 -8
  95. data/doc/guide/src/index.page +8 -3
  96. data/doc/guide/src/{introduction/install.page → installation/index.page} +37 -25
  97. data/doc/guide/src/installation/publications.page +14 -0
  98. data/doc/guide/src/{introduction → installation}/videos.page +14 -7
  99. data/doc/guide/src/interacting/index.page +16 -0
  100. data/doc/guide/src/interacting/run.page +33 -0
  101. data/doc/guide/src/interacting/shell.page +95 -0
  102. data/doc/guide/src/plugins/creating_plugins.page +72 -0
  103. data/doc/guide/src/plugins/index.page +27 -5
  104. data/doc/guide/src/plugins/{fault_tolerance.page → standard_plugins/fault_tolerance.page} +2 -2
  105. data/doc/guide/src/plugins/standard_plugins/index.page +11 -0
  106. data/doc/guide/src/plugins/{subsystems.page → standard_plugins/subsystems.page} +2 -2
  107. data/doc/guide/src/style_screen.css +687 -0
  108. data/doc/guide/src/task_relations/dependency.page +107 -0
  109. data/doc/guide/src/task_relations/executed_by.page +77 -0
  110. data/doc/guide/src/task_relations/index.page +12 -0
  111. data/doc/guide/src/task_relations/new_relations.page +119 -0
  112. data/doc/guide/src/task_relations/planned_by.page +46 -0
  113. data/doc/guide/src/tutorial/app.page +117 -0
  114. data/doc/guide/src/{basics → tutorial}/code_examples.page +6 -5
  115. data/doc/guide/src/{basics → tutorial}/dry.page +15 -15
  116. data/doc/guide/src/{basics → tutorial}/errors.page +43 -68
  117. data/doc/guide/src/tutorial/events.page +195 -0
  118. data/doc/guide/src/{basics → tutorial}/hierarchy.page +53 -52
  119. data/doc/guide/src/tutorial/index.page +13 -0
  120. data/doc/guide/src/tutorial/log_replay/goForward_1.png +0 -0
  121. data/doc/guide/src/tutorial/log_replay/goForward_2.png +0 -0
  122. data/doc/guide/src/tutorial/log_replay/goForward_3.png +0 -0
  123. data/doc/guide/src/{basics → tutorial}/log_replay/goForward_4.png +0 -0
  124. data/doc/guide/src/tutorial/log_replay/goForward_5.png +0 -0
  125. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_1.png +0 -0
  126. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_2.png +0 -0
  127. data/doc/guide/src/{basics → tutorial}/log_replay/hierarchy_error_3.png +0 -0
  128. data/doc/guide/src/tutorial/log_replay/moveto_code_error.png +0 -0
  129. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_1.png +0 -0
  130. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_2.png +0 -0
  131. data/doc/guide/src/{basics → tutorial}/log_replay/plan_repair_3.png +0 -0
  132. data/doc/guide/src/tutorial/log_replay/plan_repair_4.png +0 -0
  133. data/doc/guide/src/tutorial/log_replay/roby_log_main_window.png +0 -0
  134. data/doc/guide/src/{basics → tutorial}/log_replay/roby_log_relation_window.png +0 -0
  135. data/doc/guide/src/{basics → tutorial}/log_replay/roby_replay_event_representation.png +0 -0
  136. data/doc/guide/src/tutorial/relations_display.page +153 -0
  137. data/doc/guide/src/{basics → tutorial}/roby_cycle_overview.png +0 -0
  138. data/doc/guide/src/tutorial/shell.page +121 -0
  139. data/doc/guide/src/{basics → tutorial}/summary.page +1 -1
  140. data/doc/guide/src/tutorial/tasks.page +374 -0
  141. data/lib/roby.rb +102 -47
  142. data/lib/roby/actions.rb +17 -0
  143. data/lib/roby/actions/action.rb +80 -0
  144. data/lib/roby/actions/interface.rb +45 -0
  145. data/lib/roby/actions/library.rb +23 -0
  146. data/lib/roby/actions/models/action.rb +224 -0
  147. data/lib/roby/actions/models/coordination_action.rb +58 -0
  148. data/lib/roby/actions/models/interface.rb +22 -0
  149. data/lib/roby/actions/models/interface_base.rb +294 -0
  150. data/lib/roby/actions/models/library.rb +12 -0
  151. data/lib/roby/actions/models/method_action.rb +90 -0
  152. data/lib/roby/actions/task.rb +114 -0
  153. data/lib/roby/and_generator.rb +125 -0
  154. data/lib/roby/app.rb +2795 -829
  155. data/lib/roby/app/autotest_console_reporter.rb +138 -0
  156. data/lib/roby/app/base.rb +21 -0
  157. data/lib/roby/app/cucumber.rb +2 -0
  158. data/lib/roby/app/cucumber/controller.rb +439 -0
  159. data/lib/roby/app/cucumber/helpers.rb +280 -0
  160. data/lib/roby/app/cucumber/world.rb +32 -0
  161. data/lib/roby/app/debug.rb +136 -0
  162. data/lib/roby/app/gen.rb +2 -0
  163. data/lib/roby/app/rake.rb +178 -38
  164. data/lib/roby/app/robot_config.rb +9 -0
  165. data/lib/roby/app/robot_names.rb +115 -0
  166. data/lib/roby/app/run.rb +3 -2
  167. data/lib/roby/app/scripts.rb +72 -0
  168. data/lib/roby/app/scripts/autotest.rb +173 -0
  169. data/lib/roby/app/scripts/display.rb +2 -0
  170. data/lib/roby/app/scripts/restart.rb +52 -0
  171. data/lib/roby/app/scripts/results.rb +17 -8
  172. data/lib/roby/app/scripts/run.rb +155 -24
  173. data/lib/roby/app/scripts/shell.rb +147 -62
  174. data/lib/roby/app/scripts/test.rb +107 -22
  175. data/lib/roby/app/test_reporter.rb +74 -0
  176. data/lib/roby/app/test_server.rb +159 -0
  177. data/lib/roby/app/vagrant.rb +47 -0
  178. data/lib/roby/backports.rb +16 -0
  179. data/lib/roby/cli/display.rb +190 -0
  180. data/lib/roby/cli/exceptions.rb +17 -0
  181. data/lib/roby/cli/gen/actions/class.rb +5 -0
  182. data/lib/roby/cli/gen/actions/test.rb +6 -0
  183. data/lib/roby/cli/gen/app/.yardopts +6 -0
  184. data/lib/roby/cli/gen/app/README.md +28 -0
  185. data/lib/roby/cli/gen/app/Rakefile +15 -0
  186. data/{app → lib/roby/cli/gen/app}/config/app.yml +29 -39
  187. data/lib/roby/cli/gen/app/models/.gitattributes +1 -0
  188. data/{app → lib/roby/cli/gen/app/scripts}/controllers/.gitattributes +0 -0
  189. data/{app/data/.gitattributes → lib/roby/cli/gen/app/test/.gitignore} +0 -0
  190. data/lib/roby/cli/gen/class/class.rb +6 -0
  191. data/lib/roby/cli/gen/class/test.rb +7 -0
  192. data/lib/roby/cli/gen/helpers.rb +203 -0
  193. data/lib/roby/cli/gen/module/module.rb +5 -0
  194. data/lib/roby/cli/gen/module/test.rb +6 -0
  195. data/lib/roby/cli/gen/roby_app/config/init.rb +17 -0
  196. data/lib/roby/cli/gen/roby_app/config/robots/robot.rb +40 -0
  197. data/lib/roby/cli/gen/task/class.rb +44 -0
  198. data/lib/roby/cli/gen/task/test.rb +6 -0
  199. data/lib/roby/cli/gen_main.rb +120 -0
  200. data/lib/roby/cli/log.rb +276 -0
  201. data/lib/roby/cli/log/flamegraph.html +499 -0
  202. data/lib/roby/cli/log/flamegraph_renderer.rb +88 -0
  203. data/lib/roby/cli/main.rb +153 -0
  204. data/lib/roby/coordination.rb +60 -0
  205. data/lib/roby/coordination/action_script.rb +25 -0
  206. data/lib/roby/coordination/action_state_machine.rb +125 -0
  207. data/lib/roby/coordination/actions.rb +106 -0
  208. data/lib/roby/coordination/base.rb +145 -0
  209. data/lib/roby/coordination/calculus.rb +40 -0
  210. data/lib/roby/coordination/child.rb +28 -0
  211. data/lib/roby/coordination/event.rb +29 -0
  212. data/lib/roby/coordination/fault_handler.rb +25 -0
  213. data/lib/roby/coordination/fault_handling_task.rb +13 -0
  214. data/lib/roby/coordination/fault_response_table.rb +110 -0
  215. data/lib/roby/coordination/models/action_script.rb +64 -0
  216. data/lib/roby/coordination/models/action_state_machine.rb +224 -0
  217. data/lib/roby/coordination/models/actions.rb +191 -0
  218. data/lib/roby/coordination/models/arguments.rb +55 -0
  219. data/lib/roby/coordination/models/base.rb +176 -0
  220. data/lib/roby/coordination/models/capture.rb +86 -0
  221. data/lib/roby/coordination/models/child.rb +35 -0
  222. data/lib/roby/coordination/models/event.rb +41 -0
  223. data/lib/roby/coordination/models/exceptions.rb +42 -0
  224. data/lib/roby/coordination/models/fault_handler.rb +219 -0
  225. data/lib/roby/coordination/models/fault_response_table.rb +77 -0
  226. data/lib/roby/coordination/models/root.rb +22 -0
  227. data/lib/roby/coordination/models/script.rb +283 -0
  228. data/lib/roby/coordination/models/task.rb +184 -0
  229. data/lib/roby/coordination/models/task_from_action.rb +50 -0
  230. data/lib/roby/coordination/models/task_from_as_plan.rb +33 -0
  231. data/lib/roby/coordination/models/task_from_instanciation_object.rb +31 -0
  232. data/lib/roby/coordination/models/task_from_variable.rb +27 -0
  233. data/lib/roby/coordination/models/task_with_dependencies.rb +48 -0
  234. data/lib/roby/coordination/models/variable.rb +32 -0
  235. data/lib/roby/coordination/script.rb +200 -0
  236. data/lib/roby/coordination/script_instruction.rb +12 -0
  237. data/lib/roby/coordination/task.rb +45 -0
  238. data/lib/roby/coordination/task_base.rb +69 -0
  239. data/lib/roby/coordination/task_script.rb +293 -0
  240. data/lib/roby/coordination/task_state_machine.rb +308 -0
  241. data/lib/roby/decision_control.rb +33 -21
  242. data/lib/roby/distributed_object.rb +76 -0
  243. data/lib/roby/droby.rb +17 -0
  244. data/lib/roby/droby/droby_id.rb +6 -0
  245. data/lib/roby/droby/enable.rb +153 -0
  246. data/lib/roby/droby/event_logger.rb +189 -0
  247. data/lib/roby/droby/event_logging.rb +57 -0
  248. data/lib/roby/droby/exceptions.rb +14 -0
  249. data/lib/roby/droby/identifiable.rb +22 -0
  250. data/lib/roby/droby/logfile.rb +141 -0
  251. data/lib/roby/droby/logfile/client.rb +176 -0
  252. data/lib/roby/droby/logfile/file_format.md +97 -0
  253. data/lib/roby/droby/logfile/index.rb +117 -0
  254. data/lib/roby/droby/logfile/reader.rb +139 -0
  255. data/lib/roby/droby/logfile/server.rb +199 -0
  256. data/lib/roby/droby/logfile/writer.rb +114 -0
  257. data/lib/roby/droby/marshal.rb +264 -0
  258. data/lib/roby/droby/marshallable.rb +12 -0
  259. data/lib/roby/droby/null_event_logger.rb +25 -0
  260. data/lib/roby/droby/object_manager.rb +205 -0
  261. data/lib/roby/droby/peer_id.rb +6 -0
  262. data/lib/roby/droby/plan_rebuilder.rb +373 -0
  263. data/lib/roby/droby/rebuilt_plan.rb +160 -0
  264. data/lib/roby/droby/remote_droby_id.rb +6 -0
  265. data/lib/roby/droby/timepoints.rb +205 -0
  266. data/lib/roby/droby/timepoints_ctf.metadata.erb +101 -0
  267. data/lib/roby/droby/timepoints_ctf.rb +125 -0
  268. data/lib/roby/droby/v5.rb +14 -0
  269. data/lib/roby/droby/v5/builtin.rb +120 -0
  270. data/lib/roby/droby/v5/droby_class.rb +45 -0
  271. data/lib/roby/droby/v5/droby_constant.rb +81 -0
  272. data/lib/roby/droby/v5/droby_dump.rb +1026 -0
  273. data/lib/roby/droby/v5/droby_id.rb +44 -0
  274. data/lib/roby/droby/v5/droby_model.rb +82 -0
  275. data/lib/roby/droby/v5/peer_id.rb +10 -0
  276. data/lib/roby/droby/v5/remote_droby_id.rb +42 -0
  277. data/lib/roby/event.rb +79 -957
  278. data/lib/roby/event_constraints.rb +835 -0
  279. data/lib/roby/event_generator.rb +1047 -0
  280. data/lib/roby/event_structure/causal_link.rb +6 -0
  281. data/lib/roby/event_structure/forwarding.rb +6 -0
  282. data/lib/roby/event_structure/precedence.rb +7 -0
  283. data/lib/roby/event_structure/signal.rb +8 -0
  284. data/lib/roby/event_structure/temporal_constraints.rb +640 -0
  285. data/lib/roby/exceptions.rb +446 -152
  286. data/lib/roby/executable_plan.rb +549 -0
  287. data/lib/roby/execution_engine.rb +1997 -950
  288. data/lib/roby/filter_generator.rb +26 -0
  289. data/lib/roby/gui/chronicle_view.rb +225 -0
  290. data/lib/roby/gui/chronicle_widget.rb +925 -0
  291. data/lib/roby/gui/dot_id.rb +11 -0
  292. data/lib/roby/gui/exception_view.rb +44 -0
  293. data/lib/roby/gui/log_display.rb +273 -0
  294. data/lib/roby/gui/model_views.rb +2 -0
  295. data/lib/roby/gui/model_views/action_interface.rb +53 -0
  296. data/lib/roby/gui/model_views/task.rb +47 -0
  297. data/lib/roby/gui/model_views/task.rhtml +41 -0
  298. data/lib/roby/gui/object_info_view.rb +89 -0
  299. data/lib/roby/gui/plan_dot_layout.rb +427 -0
  300. data/lib/roby/gui/plan_rebuilder_widget.rb +357 -0
  301. data/lib/roby/gui/qt4_toMSecsSinceEpoch.rb +8 -0
  302. data/lib/roby/gui/relations_view.rb +278 -0
  303. data/lib/roby/gui/relations_view/relations.ui +139 -0
  304. data/lib/roby/gui/relations_view/relations_canvas.rb +1088 -0
  305. data/lib/roby/gui/relations_view/relations_config.rb +292 -0
  306. data/lib/roby/gui/relations_view/relations_view.ui +53 -0
  307. data/lib/roby/gui/scheduler_view.css +24 -0
  308. data/lib/roby/gui/scheduler_view.rb +46 -0
  309. data/lib/roby/gui/scheduler_view.rhtml +53 -0
  310. data/lib/roby/gui/stepping.rb +93 -0
  311. data/lib/roby/gui/stepping.ui +181 -0
  312. data/lib/roby/gui/styles.rb +81 -0
  313. data/lib/roby/gui/task_display_configuration.rb +42 -0
  314. data/lib/roby/gui/task_state_at.rb +38 -0
  315. data/lib/roby/hooks.rb +26 -0
  316. data/lib/roby/interface.rb +136 -469
  317. data/lib/roby/interface/async.rb +20 -0
  318. data/lib/roby/interface/async/action_monitor.rb +188 -0
  319. data/lib/roby/interface/async/interface.rb +498 -0
  320. data/lib/roby/interface/async/job_monitor.rb +213 -0
  321. data/lib/roby/interface/async/log.rb +238 -0
  322. data/lib/roby/interface/async/new_job_listener.rb +79 -0
  323. data/lib/roby/interface/async/ui_connector.rb +183 -0
  324. data/lib/roby/interface/client.rb +553 -0
  325. data/lib/roby/interface/command.rb +24 -0
  326. data/lib/roby/interface/command_argument.rb +16 -0
  327. data/lib/roby/interface/command_library.rb +92 -0
  328. data/lib/roby/interface/droby_channel.rb +174 -0
  329. data/lib/roby/interface/exceptions.rb +22 -0
  330. data/lib/roby/interface/interface.rb +655 -0
  331. data/lib/roby/interface/job.rb +47 -0
  332. data/lib/roby/interface/rest.rb +10 -0
  333. data/lib/roby/interface/rest/api.rb +29 -0
  334. data/lib/roby/interface/rest/helpers.rb +24 -0
  335. data/lib/roby/interface/rest/server.rb +212 -0
  336. data/lib/roby/interface/server.rb +154 -0
  337. data/lib/roby/interface/shell_client.rb +468 -0
  338. data/lib/roby/interface/shell_subcommand.rb +24 -0
  339. data/lib/roby/interface/subcommand_client.rb +35 -0
  340. data/lib/roby/interface/tcp.rb +168 -0
  341. data/lib/roby/models/arguments.rb +112 -0
  342. data/lib/roby/models/plan_object.rb +83 -0
  343. data/lib/roby/models/task.rb +835 -0
  344. data/lib/roby/models/task_event.rb +62 -0
  345. data/lib/roby/models/task_service.rb +78 -0
  346. data/lib/roby/or_generator.rb +88 -0
  347. data/lib/roby/plan.rb +1751 -864
  348. data/lib/roby/plan_object.rb +611 -0
  349. data/lib/roby/plan_service.rb +200 -0
  350. data/lib/roby/promise.rb +332 -0
  351. data/lib/roby/queries.rb +23 -0
  352. data/lib/roby/queries/and_matcher.rb +32 -0
  353. data/lib/roby/queries/any.rb +27 -0
  354. data/lib/roby/queries/code_error_matcher.rb +58 -0
  355. data/lib/roby/queries/event_generator_matcher.rb +9 -0
  356. data/lib/roby/queries/execution_exception_matcher.rb +165 -0
  357. data/lib/roby/queries/index.rb +165 -0
  358. data/lib/roby/queries/localized_error_matcher.rb +149 -0
  359. data/lib/roby/queries/matcher_base.rb +107 -0
  360. data/lib/roby/queries/none.rb +27 -0
  361. data/lib/roby/queries/not_matcher.rb +30 -0
  362. data/lib/roby/queries/op_matcher.rb +8 -0
  363. data/lib/roby/queries/or_matcher.rb +30 -0
  364. data/lib/roby/queries/plan_object_matcher.rb +363 -0
  365. data/lib/roby/queries/query.rb +188 -0
  366. data/lib/roby/queries/task_event_generator_matcher.rb +86 -0
  367. data/lib/roby/queries/task_matcher.rb +344 -0
  368. data/lib/roby/relations.rb +42 -678
  369. data/lib/roby/relations/bidirectional_directed_adjacency_graph.rb +492 -0
  370. data/lib/roby/relations/directed_relation_support.rb +268 -0
  371. data/lib/roby/relations/event_relation_graph.rb +19 -0
  372. data/lib/roby/relations/fork_merge_visitor.rb +154 -0
  373. data/lib/roby/relations/graph.rb +533 -0
  374. data/lib/roby/relations/models/directed_relation_support.rb +11 -0
  375. data/lib/roby/relations/models/graph.rb +75 -0
  376. data/lib/roby/relations/models/task_relation_graph.rb +18 -0
  377. data/lib/roby/relations/space.rb +380 -0
  378. data/lib/roby/relations/task_relation_graph.rb +20 -0
  379. data/lib/roby/robot.rb +85 -38
  380. data/lib/roby/schedulers/basic.rb +155 -25
  381. data/lib/roby/schedulers/null.rb +20 -0
  382. data/lib/roby/schedulers/reporting.rb +31 -0
  383. data/lib/roby/schedulers/state.rb +129 -0
  384. data/lib/roby/schedulers/temporal.rb +91 -0
  385. data/lib/roby/singletons.rb +87 -0
  386. data/lib/roby/standalone.rb +4 -2
  387. data/lib/roby/standard_errors.rb +405 -82
  388. data/lib/roby/state.rb +6 -3
  389. data/lib/roby/state/conf_model.rb +5 -0
  390. data/lib/roby/state/events.rb +181 -95
  391. data/lib/roby/state/goal_model.rb +77 -0
  392. data/lib/roby/state/open_struct.rb +591 -0
  393. data/lib/roby/state/open_struct_model.rb +68 -0
  394. data/lib/roby/state/pos.rb +45 -45
  395. data/lib/roby/state/shapes.rb +11 -11
  396. data/lib/roby/state/state_model.rb +303 -0
  397. data/lib/roby/state/task.rb +43 -0
  398. data/lib/roby/support.rb +88 -148
  399. data/lib/roby/task.rb +1361 -1750
  400. data/lib/roby/task_arguments.rb +428 -0
  401. data/lib/roby/task_event.rb +127 -0
  402. data/lib/roby/task_event_generator.rb +337 -0
  403. data/lib/roby/task_service.rb +6 -0
  404. data/lib/roby/task_structure/conflicts.rb +104 -0
  405. data/lib/roby/task_structure/dependency.rb +932 -0
  406. data/lib/roby/task_structure/error_handling.rb +118 -0
  407. data/lib/roby/task_structure/executed_by.rb +234 -0
  408. data/lib/roby/task_structure/planned_by.rb +90 -0
  409. data/lib/roby/tasks/aggregator.rb +37 -0
  410. data/lib/roby/tasks/external_process.rb +275 -0
  411. data/lib/roby/tasks/group.rb +27 -0
  412. data/lib/roby/tasks/null.rb +19 -0
  413. data/lib/roby/tasks/parallel.rb +43 -0
  414. data/lib/roby/tasks/sequence.rb +88 -0
  415. data/lib/roby/tasks/simple.rb +21 -0
  416. data/lib/roby/{thread_task.rb → tasks/thread.rb} +50 -24
  417. data/lib/roby/tasks/timeout.rb +17 -0
  418. data/lib/roby/tasks/virtual.rb +55 -0
  419. data/lib/roby/template_plan.rb +7 -0
  420. data/lib/roby/test/aruba_minitest.rb +74 -0
  421. data/lib/roby/test/assertion.rb +16 -0
  422. data/lib/roby/test/assertions.rb +490 -0
  423. data/lib/roby/test/common.rb +368 -591
  424. data/lib/roby/test/dsl.rb +149 -0
  425. data/lib/roby/test/error.rb +18 -0
  426. data/lib/roby/test/event_reporter.rb +83 -0
  427. data/lib/roby/test/execution_expectations.rb +1134 -0
  428. data/lib/roby/test/expect_execution.rb +151 -0
  429. data/lib/roby/test/minitest_helpers.rb +166 -0
  430. data/lib/roby/test/roby_app_helpers.rb +200 -0
  431. data/lib/roby/test/run_planners.rb +155 -0
  432. data/lib/roby/test/self.rb +112 -0
  433. data/lib/roby/test/spec.rb +198 -0
  434. data/lib/roby/test/tasks/empty_task.rb +4 -4
  435. data/lib/roby/test/tasks/goto.rb +28 -27
  436. data/lib/roby/test/teardown_plans.rb +100 -0
  437. data/lib/roby/test/testcase.rb +239 -307
  438. data/lib/roby/test/tools.rb +159 -155
  439. data/lib/roby/test/validate_state_machine.rb +75 -0
  440. data/lib/roby/transaction.rb +1125 -0
  441. data/lib/roby/transaction/event_generator_proxy.rb +63 -0
  442. data/lib/roby/transaction/plan_object_proxy.rb +99 -0
  443. data/lib/roby/transaction/plan_service_proxy.rb +43 -0
  444. data/lib/roby/transaction/proxying.rb +120 -0
  445. data/lib/roby/transaction/task_event_generator_proxy.rb +19 -0
  446. data/lib/roby/transaction/task_proxy.rb +135 -0
  447. data/lib/roby/until_generator.rb +30 -0
  448. data/lib/roby/version.rb +5 -0
  449. data/lib/roby/yard.rb +169 -0
  450. data/lib/yard-roby.rb +1 -0
  451. data/manifest.xml +32 -6
  452. data/roby.gemspec +59 -0
  453. metadata +788 -587
  454. data/Manifest.txt +0 -321
  455. data/NOTES +0 -4
  456. data/README.txt +0 -166
  457. data/TODO.txt +0 -146
  458. data/app/README.txt +0 -24
  459. data/app/Rakefile +0 -8
  460. data/app/config/ROBOT.rb +0 -5
  461. data/app/config/init.rb +0 -33
  462. data/app/config/roby.yml +0 -3
  463. data/app/controllers/ROBOT.rb +0 -2
  464. data/app/planners/ROBOT/main.rb +0 -6
  465. data/app/planners/main.rb +0 -5
  466. data/app/scripts/distributed +0 -3
  467. data/app/scripts/generate/bookmarks +0 -3
  468. data/app/scripts/replay +0 -3
  469. data/app/scripts/results +0 -3
  470. data/app/scripts/run +0 -3
  471. data/app/scripts/server +0 -3
  472. data/app/scripts/shell +0 -3
  473. data/app/scripts/test +0 -3
  474. data/app/tasks/.gitattributes +0 -0
  475. data/app/tasks/ROBOT/.gitattributes +0 -0
  476. data/bin/roby-shell +0 -25
  477. data/doc/guide/src/basics/app.page +0 -139
  478. data/doc/guide/src/basics/index.page +0 -11
  479. data/doc/guide/src/basics/log_replay/goForward_1.png +0 -0
  480. data/doc/guide/src/basics/log_replay/goForward_2.png +0 -0
  481. data/doc/guide/src/basics/log_replay/goForward_3.png +0 -0
  482. data/doc/guide/src/basics/log_replay/goForward_5.png +0 -0
  483. data/doc/guide/src/basics/log_replay/plan_repair_4.png +0 -0
  484. data/doc/guide/src/basics/log_replay/roby_log_main_window.png +0 -0
  485. data/doc/guide/src/basics/relations_display.page +0 -203
  486. data/doc/guide/src/basics/shell.page +0 -102
  487. data/doc/guide/src/default.css +0 -319
  488. data/doc/guide/src/introduction/index.page +0 -29
  489. data/doc/guide/src/introduction/publications.page +0 -14
  490. data/doc/guide/src/relations/dependency.page +0 -89
  491. data/doc/guide/src/relations/index.page +0 -12
  492. data/ext/droby/dump.cc +0 -175
  493. data/ext/droby/extconf.rb +0 -3
  494. data/ext/graph/algorithm.cc +0 -746
  495. data/ext/graph/extconf.rb +0 -7
  496. data/ext/graph/graph.cc +0 -575
  497. data/ext/graph/graph.hh +0 -183
  498. data/ext/graph/iterator_sequence.hh +0 -102
  499. data/ext/graph/undirected_dfs.hh +0 -226
  500. data/ext/graph/undirected_graph.hh +0 -421
  501. data/lib/roby/app/scripts/generate/bookmarks.rb +0 -162
  502. data/lib/roby/app/scripts/replay.rb +0 -31
  503. data/lib/roby/app/scripts/server.rb +0 -18
  504. data/lib/roby/basic_object.rb +0 -151
  505. data/lib/roby/config.rb +0 -14
  506. data/lib/roby/distributed.rb +0 -36
  507. data/lib/roby/distributed/base.rb +0 -448
  508. data/lib/roby/distributed/communication.rb +0 -875
  509. data/lib/roby/distributed/connection_space.rb +0 -616
  510. data/lib/roby/distributed/distributed_object.rb +0 -206
  511. data/lib/roby/distributed/drb.rb +0 -62
  512. data/lib/roby/distributed/notifications.rb +0 -531
  513. data/lib/roby/distributed/peer.rb +0 -555
  514. data/lib/roby/distributed/protocol.rb +0 -529
  515. data/lib/roby/distributed/proxy.rb +0 -343
  516. data/lib/roby/distributed/subscription.rb +0 -311
  517. data/lib/roby/distributed/transaction.rb +0 -498
  518. data/lib/roby/external_process_task.rb +0 -225
  519. data/lib/roby/graph.rb +0 -160
  520. data/lib/roby/log.rb +0 -3
  521. data/lib/roby/log/chronicle.rb +0 -303
  522. data/lib/roby/log/console.rb +0 -74
  523. data/lib/roby/log/data_stream.rb +0 -275
  524. data/lib/roby/log/dot.rb +0 -279
  525. data/lib/roby/log/event_stream.rb +0 -161
  526. data/lib/roby/log/file.rb +0 -396
  527. data/lib/roby/log/gui/basic_display.ui +0 -83
  528. data/lib/roby/log/gui/basic_display_ui.rb +0 -89
  529. data/lib/roby/log/gui/chronicle.rb +0 -26
  530. data/lib/roby/log/gui/chronicle_view.rb +0 -40
  531. data/lib/roby/log/gui/chronicle_view.ui +0 -70
  532. data/lib/roby/log/gui/chronicle_view_ui.rb +0 -90
  533. data/lib/roby/log/gui/data_displays.rb +0 -171
  534. data/lib/roby/log/gui/data_displays.ui +0 -155
  535. data/lib/roby/log/gui/data_displays_ui.rb +0 -146
  536. data/lib/roby/log/gui/notifications.rb +0 -26
  537. data/lib/roby/log/gui/relations.rb +0 -269
  538. data/lib/roby/log/gui/relations.ui +0 -123
  539. data/lib/roby/log/gui/relations_ui.rb +0 -120
  540. data/lib/roby/log/gui/relations_view.rb +0 -185
  541. data/lib/roby/log/gui/relations_view.ui +0 -149
  542. data/lib/roby/log/gui/relations_view_ui.rb +0 -144
  543. data/lib/roby/log/gui/replay.rb +0 -366
  544. data/lib/roby/log/gui/replay_controls.rb +0 -206
  545. data/lib/roby/log/gui/replay_controls.ui +0 -282
  546. data/lib/roby/log/gui/replay_controls_ui.rb +0 -249
  547. data/lib/roby/log/gui/runtime.rb +0 -130
  548. data/lib/roby/log/hooks.rb +0 -186
  549. data/lib/roby/log/logger.rb +0 -203
  550. data/lib/roby/log/notifications.rb +0 -244
  551. data/lib/roby/log/plan_rebuilder.rb +0 -468
  552. data/lib/roby/log/relations.rb +0 -1084
  553. data/lib/roby/log/server.rb +0 -547
  554. data/lib/roby/log/sqlite.rb +0 -47
  555. data/lib/roby/log/timings.rb +0 -233
  556. data/lib/roby/plan-object.rb +0 -371
  557. data/lib/roby/planning.rb +0 -13
  558. data/lib/roby/planning/loops.rb +0 -309
  559. data/lib/roby/planning/model.rb +0 -1012
  560. data/lib/roby/planning/task.rb +0 -180
  561. data/lib/roby/query.rb +0 -655
  562. data/lib/roby/relations/conflicts.rb +0 -67
  563. data/lib/roby/relations/dependency.rb +0 -358
  564. data/lib/roby/relations/ensured.rb +0 -19
  565. data/lib/roby/relations/error_handling.rb +0 -22
  566. data/lib/roby/relations/events.rb +0 -7
  567. data/lib/roby/relations/executed_by.rb +0 -208
  568. data/lib/roby/relations/influence.rb +0 -10
  569. data/lib/roby/relations/planned_by.rb +0 -63
  570. data/lib/roby/state/information.rb +0 -55
  571. data/lib/roby/state/state.rb +0 -367
  572. data/lib/roby/task-operations.rb +0 -186
  573. data/lib/roby/task_index.rb +0 -80
  574. data/lib/roby/test/distributed.rb +0 -230
  575. data/lib/roby/test/tasks/simple_task.rb +0 -23
  576. data/lib/roby/transactions.rb +0 -507
  577. data/lib/roby/transactions/proxy.rb +0 -325
  578. data/plugins/fault_injection/History.txt +0 -4
  579. data/plugins/fault_injection/README.txt +0 -34
  580. data/plugins/fault_injection/Rakefile +0 -12
  581. data/plugins/fault_injection/TODO.txt +0 -0
  582. data/plugins/fault_injection/app.rb +0 -52
  583. data/plugins/fault_injection/fault_injection.rb +0 -89
  584. data/plugins/fault_injection/test/test_fault_injection.rb +0 -78
  585. data/plugins/subsystems/README.txt +0 -37
  586. data/plugins/subsystems/Rakefile +0 -13
  587. data/plugins/subsystems/app.rb +0 -182
  588. data/plugins/subsystems/test/app/README +0 -24
  589. data/plugins/subsystems/test/app/Rakefile +0 -8
  590. data/plugins/subsystems/test/app/config/app.yml +0 -71
  591. data/plugins/subsystems/test/app/config/init.rb +0 -12
  592. data/plugins/subsystems/test/app/config/roby.yml +0 -3
  593. data/plugins/subsystems/test/app/planners/main.rb +0 -20
  594. data/plugins/subsystems/test/app/scripts/distributed +0 -3
  595. data/plugins/subsystems/test/app/scripts/replay +0 -3
  596. data/plugins/subsystems/test/app/scripts/results +0 -3
  597. data/plugins/subsystems/test/app/scripts/run +0 -3
  598. data/plugins/subsystems/test/app/scripts/server +0 -3
  599. data/plugins/subsystems/test/app/scripts/shell +0 -3
  600. data/plugins/subsystems/test/app/scripts/test +0 -3
  601. data/plugins/subsystems/test/app/tasks/services.rb +0 -15
  602. data/plugins/subsystems/test/test_subsystems.rb +0 -78
  603. data/test/distributed/test_communication.rb +0 -195
  604. data/test/distributed/test_connection.rb +0 -284
  605. data/test/distributed/test_execution.rb +0 -378
  606. data/test/distributed/test_mixed_plan.rb +0 -341
  607. data/test/distributed/test_plan_notifications.rb +0 -238
  608. data/test/distributed/test_protocol.rb +0 -525
  609. data/test/distributed/test_query.rb +0 -106
  610. data/test/distributed/test_remote_plan.rb +0 -491
  611. data/test/distributed/test_transaction.rb +0 -466
  612. data/test/mockups/external_process +0 -28
  613. data/test/mockups/tasks.rb +0 -27
  614. data/test/planning/test_loops.rb +0 -432
  615. data/test/planning/test_model.rb +0 -427
  616. data/test/planning/test_task.rb +0 -126
  617. data/test/relations/test_conflicts.rb +0 -42
  618. data/test/relations/test_dependency.rb +0 -324
  619. data/test/relations/test_ensured.rb +0 -38
  620. data/test/relations/test_executed_by.rb +0 -224
  621. data/test/relations/test_planned_by.rb +0 -56
  622. data/test/suite_core.rb +0 -29
  623. data/test/suite_distributed.rb +0 -10
  624. data/test/suite_planning.rb +0 -4
  625. data/test/suite_relations.rb +0 -8
  626. data/test/tasks/test_external_process.rb +0 -126
  627. data/test/tasks/test_thread_task.rb +0 -70
  628. data/test/test_bgl.rb +0 -528
  629. data/test/test_event.rb +0 -969
  630. data/test/test_exceptions.rb +0 -591
  631. data/test/test_execution_engine.rb +0 -987
  632. data/test/test_gui.rb +0 -20
  633. data/test/test_interface.rb +0 -43
  634. data/test/test_log.rb +0 -125
  635. data/test/test_log_server.rb +0 -133
  636. data/test/test_plan.rb +0 -418
  637. data/test/test_query.rb +0 -424
  638. data/test/test_relations.rb +0 -260
  639. data/test/test_state.rb +0 -432
  640. data/test/test_support.rb +0 -16
  641. data/test/test_task.rb +0 -1181
  642. data/test/test_testcase.rb +0 -138
  643. data/test/test_transactions.rb +0 -610
  644. data/test/test_transactions_proxy.rb +0 -216
@@ -0,0 +1,835 @@
1
+ module Roby
2
+ # This namespace contains predicates that allow to specify logic ordering
3
+ # constraints between events. The predicate objects can then be evaluated
4
+ # (return true/false), and can tell whether their value may change in the
5
+ # future.
6
+ #
7
+ # Moreover, for all three states (true, false, and static), the predicates
8
+ # can explain which events and/or generators explain this state of the
9
+ # predicate.
10
+ #
11
+ # For instance,
12
+ #
13
+ # pred = :intermediate.to_unbound_task_predicate
14
+ #
15
+ # is a predicate that will return true if the intermediate event of the task
16
+ # it represents has already been emitted, and false otherwise.
17
+ #
18
+ # pred.evaluate(task) => true or false
19
+ #
20
+ # If task.intermediate? is true (the event has been emitted), then
21
+ #
22
+ # pred.explain_true(task)
23
+ #
24
+ # will return an Explanation instance where +elements+ ==
25
+ # [pred.intermediate_event.last] (the Event instance that has been emitted).
26
+ #
27
+ # However, if the event is not yet emitted then,
28
+ #
29
+ # pred.explain_false(task) => #<Explanation @elements=[pred.intermediate_event]>
30
+ #
31
+ # i.e. the reason is that intermediate_event has not been emitted.
32
+ #
33
+ # Finally, if intermediate has never been emitted and the task is finished
34
+ # (let's say because success has been emitted), the intermediate event
35
+ # cannot be emitted anymore. In this case,
36
+ #
37
+ # pred.static?(task) => true
38
+ # pred.evaluate(task) => false
39
+ # pred.explain_static(task) => #<Explanation @elements=[task.event(:success)]>
40
+ #
41
+ module EventConstraints
42
+ # Module that defines the unbound task predicate methods that are
43
+ # added to the Symbol class
44
+ module UnboundPredicateSupport
45
+ # Returns an UnboundTaskPredicate that will be true if the generator
46
+ # represented by this symbol has emitted at least once.
47
+ #
48
+ # In its simplest form,
49
+ #
50
+ # :blocked.emitted?
51
+ #
52
+ # will be true when evaluated on a task whose +blocked+ event has
53
+ # emitted at least once
54
+ def emitted?
55
+ to_unbound_task_predicate
56
+ end
57
+
58
+ # @deprecated use {#emitted?} instead
59
+ def happened?
60
+ Roby.warn_deprecated "#happened? is deprecated, use #emitted? instead"
61
+ emitted?
62
+ end
63
+
64
+ # Protocol method. The unbound task predicate call always calls
65
+ # #to_unbound_task_predicate on the arguments given to it.
66
+ def to_unbound_task_predicate
67
+ UnboundTaskPredicate::SingleEvent.new(self)
68
+ end
69
+
70
+ # Returns an UnboundTaskPredicate that will be true if the generator
71
+ # represented by this symbol will never be emitted.
72
+ #
73
+ # In its simplest form,
74
+ #
75
+ # :blocked.never
76
+ #
77
+ # will be true when evaluated on a task whose +blocked+ event has
78
+ # not yet been emitted, and has been declared as unreachable
79
+ def never
80
+ to_unbound_task_predicate.never
81
+ end
82
+
83
+ # Returns an UnboundTaskPredicate that will be true if the generator
84
+ # represented by this symbol has emitted at least once, and the
85
+ # predicate represented by +other+ is true at the same time.
86
+ #
87
+ # In its simplest form,
88
+ #
89
+ # :blocked.and(:updated)
90
+ #
91
+ # it will be true if the task on which it is applied has both
92
+ # emitted :blocked and :updated at least once.
93
+ def and(other)
94
+ to_unbound_task_predicate.
95
+ and(other.to_unbound_task_predicate)
96
+ end
97
+
98
+ # Returns an UnboundTaskPredicate that will be true if the generator
99
+ # represented by this symbol has emitted at least once, or the
100
+ # predicate represented by +other+ is true.
101
+ #
102
+ # In its simplest form,
103
+ #
104
+ # :blocked.or(:updated)
105
+ #
106
+ # it will be true if the task on which it is applied has either
107
+ # emitted :blocked, or emitted :updated, or both.
108
+ def or(other)
109
+ to_unbound_task_predicate.
110
+ or(other.to_unbound_task_predicate)
111
+ end
112
+
113
+ # Returns an UnboundTaskPredicate that will be true if the generator
114
+ # represented by this symbol and the generator represented by
115
+ # +other+ (as a symbol) have emitted in sequence, i.e. if both
116
+ # +self+ and +other+ have emitted at least once, and if the last
117
+ # event e0 emitted by +self+ and the last event e1 emitted by
118
+ # +other+ match
119
+ #
120
+ # e0.time < e1.time
121
+ #
122
+ # Unlike +and+, +or+ and +negate+, this only works on single events
123
+ # (i.e. it cannot be applied on other predicates)
124
+ def followed_by(other)
125
+ to_unbound_task_predicate.
126
+ followed_by(other.to_unbound_task_predicate)
127
+ end
128
+
129
+ # Returns an UnboundTaskPredicate that will be true if the generator
130
+ # represented by this symbol and the generator represented by
131
+ # +other+ (as a symbol) have not emitted in sequence, i.e. if +self+
132
+ # has emitted at least once, and either +other+ has not emitted or
133
+ # +other+ has emitted and the last event e0 emitted by +self+ and
134
+ # the last event e1 emitted by +other+ do not match
135
+ #
136
+ # e0.time < e1.time
137
+ #
138
+ # Unlike +and+, +or+ and +negate+, this only works on single events
139
+ # (i.e. it cannot be applied on other predicates)
140
+ def not_followed_by(other)
141
+ to_unbound_task_predicate.
142
+ not_followed_by(other.to_unbound_task_predicate)
143
+ end
144
+
145
+ # Returns an UnboundTaskPredicate that will be true if the generator
146
+ # represented by +self+ has never emitted
147
+ def negate
148
+ to_unbound_task_predicate.negate
149
+ end
150
+ end
151
+ ::Symbol.include UnboundPredicateSupport
152
+
153
+ class ::FalseClass
154
+ # Returns an UnboundTaskPredicate object that will always evaluate
155
+ # to false
156
+ def to_unbound_task_predicate
157
+ Roby::EventConstraints::UnboundTaskPredicate::False.new
158
+ end
159
+ end
160
+
161
+ # Represents a temporal logic predicate that applies on the internal
162
+ # events of a single task. As the events are represented by their name,
163
+ # the predicate can be reused to be applied on different tasks.
164
+ class UnboundTaskPredicate
165
+ def to_unbound_task_predicate
166
+ self
167
+ end
168
+
169
+ # Returns a predicate that is true if both +self+ and
170
+ # +other_predicate+ are true.
171
+ #
172
+ # Because of the "and" semantic, the predicate is static if one of
173
+ # the two predicates is false and static, or if both predicates
174
+ # are static.
175
+ def and(other_predicate)
176
+ if self == other_predicate then self
177
+ elsif other_predicate.kind_of?(UnboundTaskPredicate::False)
178
+ other_predicate
179
+ else
180
+ And.new(self, other_predicate)
181
+ end
182
+ end
183
+
184
+ # Returns a predicate that is true if either or both of +self+ and
185
+ # +other_predicate+ are true.
186
+ #
187
+ # Because of the "or" semantic, the predicate is static if one of
188
+ # the two predicates are true and static, or if both predicates
189
+ # are static.
190
+ def or(other_predicate)
191
+ if self == other_predicate then self
192
+ elsif other_predicate.kind_of?(UnboundTaskPredicate::False)
193
+ self
194
+ else
195
+ Or.new(self, other_predicate)
196
+ end
197
+ end
198
+
199
+ # Returns a predicate that is the negation of +self+
200
+ #
201
+ # Because of the "not" semantic, the predicate is static if +self+
202
+ # is static.
203
+ def negate
204
+ Negate.new(self)
205
+ end
206
+
207
+ # Returns an Explanation object that explains why +self+ is true.
208
+ # Note that it is valid only if evaluate(task) actually returned
209
+ # true (it will silently return an invalid explanation if
210
+ # evaluate(task) returns false).
211
+ def explain_true(task); nil end
212
+
213
+ # Returns an Explanation object that explains why +self+ is false.
214
+ # Note that it is valid only if evaluate(task) actually returned
215
+ # false (it will silently return an invalid explanation if
216
+ # evaluate(task) returns true).
217
+ def explain_false(task); nil end
218
+
219
+ # Returns an Explanation object that explains why +self+ will not
220
+ # change its value anymore.
221
+ #
222
+ # Note that it is valid only if static?(task) actually returned
223
+ # true (it will silently return an invalid explanation otherwise)
224
+ def explain_static(task)
225
+ end
226
+
227
+ def pretty_print(pp)
228
+ pp.text to_s
229
+ end
230
+
231
+ # See #compile.
232
+ #
233
+ # Objects of this class hold the compiled predicate used for
234
+ # evaluation
235
+ class CompiledPredicate
236
+ def marshal_dump; nil end
237
+ def marshal_load(obj); nil end
238
+ end
239
+
240
+ # Predicates are first represented as an AST using the subclasses of
241
+ # UnboundTaskPredicate, but are then compiled into code before being
242
+ # evaluated (for performance reasons).
243
+ #
244
+ # This is the main call that performs this compilation
245
+ def compile
246
+ prelude = required_events.map do |event_name|
247
+ " task_event_#{event_name} = task.event(:#{event_name})\n" +
248
+ " task_#{event_name} = task_event_#{event_name}.last"
249
+ end.join("\n")
250
+
251
+ compiled_predicate = CompiledPredicate.new
252
+ eval <<-END, binding, __FILE__, __LINE__+1
253
+ def compiled_predicate.evaluate(task)
254
+ #{prelude}
255
+ #{code}
256
+ end
257
+ END
258
+ @compiled_predicate = compiled_predicate
259
+ end
260
+
261
+ # Evaluates this predicate on +task+. It returns either true or
262
+ # false.
263
+ def evaluate(task)
264
+ compile if !@compiled_predicate || !@compiled_predicate.respond_to?(:evaluate)
265
+ @compiled_predicate.evaluate(task)
266
+ end
267
+ end
268
+
269
+ # An explanation for a given predicate value. +predicate+ is the
270
+ # predicate, +elements+ the explanations for +predicate+ having reached
271
+ # the value.
272
+ #
273
+ # +elements+ is an array of Event and EventGenerator instances.
274
+ #
275
+ # If an Event is stored there, the explanation is that this event has
276
+ # been emitted.
277
+ #
278
+ # If an EventGenerator is stored there, the reason depends on +value+.
279
+ # If +value+ is nil (static), the reason is that the generator is
280
+ # unreachable. If +value+ is false (not emitted), it is that the
281
+ # generator did not emit.
282
+ class Explanation
283
+ # Representation of what is being explained. It is true if it is
284
+ # explaining why a predicate is true, false if it is explaining why
285
+ # it is false and nil for static.
286
+ attr_accessor :value
287
+ # The predicate that we are providing an explanation for
288
+ attr_reader :predicate
289
+ # The elements of explanation
290
+ attr_reader :elements
291
+
292
+ def simple?
293
+ elements.size == 1 && !elements.first.kind_of?(Explanation)
294
+ end
295
+
296
+ def initialize(value, predicate, elements)
297
+ @value, @predicate, @elements = value, predicate, elements
298
+ end
299
+
300
+ def report_exceptions_on(e)
301
+ elements.each do |el|
302
+ case el
303
+ when Explanation
304
+ el.report_exceptions_on(e)
305
+ when Exception
306
+ e.report_exceptions_from(el)
307
+ when Event
308
+ el.all_sources.each do |ev|
309
+ e.report_exceptions_from(ev)
310
+ end
311
+ when EventGenerator
312
+ if value == nil
313
+ e.report_exceptions_from(el.unreachability_reason)
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ def pretty_print(pp)
320
+ if value == false
321
+ predicate.pretty_print(pp)
322
+ pp.text " is false"
323
+ elsif value == true
324
+ predicate.pretty_print(pp)
325
+ pp.text " is true"
326
+ elsif value == nil
327
+ pp.text "the value of "
328
+ predicate.pretty_print(pp)
329
+ pp.text " will not change anymore"
330
+ end
331
+
332
+ pp.nest(2) do
333
+ elements.each do |explanation|
334
+ pp.breakable
335
+ case explanation
336
+ when Event
337
+ pp.text "the following event has been emitted "
338
+ when EventGenerator
339
+ if value == nil
340
+ pp.text "the following event is unreachable "
341
+ elsif value == true
342
+ pp.text "the following event is reachable, but has not been emitted "
343
+ else
344
+ pp.text "the following event has been emitted "
345
+ end
346
+ end
347
+
348
+ explanation.pretty_print(pp)
349
+ case explanation
350
+ when Event
351
+ sources = explanation.all_sources
352
+ if !sources.empty?
353
+ pp.breakable
354
+ pp.text "The emission was caused by the following events"
355
+ sources.each do |ev|
356
+ pp.breakable
357
+ pp.text "< "
358
+ ev.pretty_print(pp, false)
359
+ end
360
+ end
361
+
362
+ when EventGenerator
363
+ if value == nil && explanation.unreachability_reason
364
+ pp.breakable
365
+ pp.text "The unreachability was caused by "
366
+ pp.nest(2) do
367
+ pp.breakable
368
+ explanation.unreachability_reason.pretty_print(pp)
369
+ end
370
+ end
371
+ else
372
+ explanation.pretty_print(pp)
373
+ end
374
+ pp.breakable
375
+ end
376
+ end
377
+ end
378
+ end
379
+
380
+ # Representation of a predicate that is always false
381
+ class UnboundTaskPredicate::False < UnboundTaskPredicate
382
+ def required_events; Set.new end
383
+ def explain_true(task); Hash.new end
384
+ def explain_false(task); Hash.new end
385
+ def explain_static(task); Hash.new end
386
+ def evaluate(task); false end
387
+ def static?(task); true end
388
+ def to_s; "false" end
389
+
390
+ def ==(pred); pred.kind_of?(False) end
391
+
392
+ def code
393
+ "false"
394
+ end
395
+
396
+ def or(pred); pred end
397
+ def and(pred); self end
398
+ end
399
+
400
+ # Representation of predicates UnboundPredicateSupport#negate and
401
+ # UnboundTaskPredicate#negate
402
+ #
403
+ # See documentation from UnboundTaskPredicate
404
+ class UnboundTaskPredicate::Negate < UnboundTaskPredicate
405
+ attr_reader :predicate
406
+ def initialize(pred)
407
+ @predicate = pred
408
+ end
409
+
410
+ def ==(pred); pred.kind_of?(Negate) && pred.predicate == predicate end
411
+
412
+ def explain_true(task); predicate.explain_false(task) end
413
+ def explain_false(task); predicate.explain_true(task) end
414
+ def explain_static(task); predicate.explain_static(task) end
415
+
416
+ def required_events; predicate.required_events end
417
+ def code
418
+ "!(#{predicate.code})"
419
+ end
420
+ def static?(task); predicate.static?(task) end
421
+ def to_s; "!#{predicate}" end
422
+ end
423
+
424
+ # Representation of UnboundPredicateSupport#never
425
+ #
426
+ # See documentation from UnboundPredicateSupport
427
+ class UnboundTaskPredicate::Never < UnboundTaskPredicate
428
+ attr_reader :predicate
429
+ def initialize(pred)
430
+ if !pred.kind_of?(UnboundTaskPredicate::SingleEvent)
431
+ raise ArgumentError, "can only create a Never predicate on top of a SingleEvent"
432
+ end
433
+
434
+ @predicate = pred
435
+ end
436
+
437
+ def ==(pred); pred.kind_of?(Never) && pred.predicate == predicate end
438
+
439
+ def explain_true(task)
440
+ return if !evaluate(task)
441
+ predicate.explain_static(task)
442
+ end
443
+ def explain_false(task)
444
+ return if evaluate(task)
445
+ if predicate.evaluate(task)
446
+ predicate.explain_true(task)
447
+ elsif !predicate.static?(task)
448
+ explanation = predicate.explain_false(task)
449
+ explanation.value = true
450
+ explanation
451
+ end
452
+ end
453
+ def explain_static(task)
454
+ if predicate.evaluate(task)
455
+ predicate.explain_true(task)
456
+ else
457
+ predicate.explain_static(task)
458
+ end
459
+ end
460
+
461
+ def required_events; predicate.required_events end
462
+ def code
463
+ "(!task_#{predicate.event_name} && task_event_#{predicate.event_name}.unreachable?)"
464
+ end
465
+ def static?(task)
466
+ evaluate(task) || predicate.static?(task)
467
+ end
468
+ def to_s; "never(#{predicate})" end
469
+ end
470
+
471
+ # Representation of a binary combination of predicates that is
472
+ # commutative. It is used to simplify expressions, especially for
473
+ # explanations.
474
+ class UnboundTaskPredicate::BinaryCommutativePredicate < UnboundTaskPredicate
475
+ attr_reader :predicates
476
+ def initialize(left, right)
477
+ @predicates = [left, right]
478
+ end
479
+
480
+ def required_events; predicates[0].required_events | predicates[1].required_events end
481
+
482
+ def ==(pred)
483
+ pred.kind_of?(self.class) &&
484
+ ((predicates[0] == pred.predicates[0] && predicates[1] == pred.predicates[1]) ||
485
+ (predicates[0] == pred.predicates[1] && predicates[1] == pred.predicates[0]))
486
+ end
487
+
488
+ def explain_true(task)
489
+ return if !evaluate(task)
490
+
491
+ reason0 = predicates[0].explain_true(task)
492
+ reason1 = predicates[1].explain_true(task)
493
+ if reason0 && reason1
494
+ Explanation.new(true, self, [reason0, reason1])
495
+ else
496
+ reason0 || reason1
497
+ end
498
+ end
499
+ def explain_false(task)
500
+ return if evaluate(task)
501
+
502
+ reason0 = predicates[0].explain_false(task)
503
+ reason1 = predicates[1].explain_false(task)
504
+ if reason0 && reason1
505
+ Explanation.new(false, self, [reason0, reason1])
506
+ else
507
+ reason0 || reason1
508
+ end
509
+ end
510
+ def explain_static(task)
511
+ return if !static?(task)
512
+
513
+ reason0 = predicates[0].explain_static(task)
514
+ reason1 = predicates[1].explain_static(task)
515
+ if reason0 && reason1
516
+ Explanation.new(nil, self, [reason0, reason1])
517
+ else
518
+ reason0 || reason1
519
+ end
520
+ end
521
+
522
+ def has_atomic_predicate?(pred)
523
+ pred = pred.to_unbound_task_predicate
524
+ each_atomic_predicate do |p|
525
+ return(true) if p == pred
526
+ end
527
+ false
528
+ end
529
+
530
+ def each_atomic_predicate(&block)
531
+ 2.times do |i|
532
+ if predicates[i].kind_of?(self.class)
533
+ predicates[i].each_atomic_predicate(&block)
534
+ else
535
+ yield(predicates[i])
536
+ end
537
+ end
538
+ end
539
+ end
540
+
541
+ # Representation of UnboundPredicateSupport#and and
542
+ # UnboundTaskPredicate#and
543
+ #
544
+ # See documentation from UnboundTaskPredicate
545
+ class UnboundTaskPredicate::And < UnboundTaskPredicate::BinaryCommutativePredicate
546
+ def code
547
+ "(#{predicates[0].code}) && (#{predicates[1].code})"
548
+ end
549
+
550
+ def and(pred)
551
+ pred = pred.to_unbound_task_predicate
552
+ if pred.kind_of?(And)
553
+ # Only add predicates in +pred+ that are not already in
554
+ # +self+
555
+ result = self
556
+ pred.each_atomic_predicate do |predicate|
557
+ result = result.and(predicate)
558
+ end
559
+ elsif has_atomic_predicate?(pred)
560
+ self
561
+ else
562
+ super
563
+ end
564
+ end
565
+
566
+ def static?(task)
567
+ static0 = predicates[0].static?(task)
568
+ static1 = predicates[1].static?(task)
569
+ static0 && static1 ||
570
+ (static0 && !predicates[0].evaluate(task) ||
571
+ static1 && !predicates[1].evaluate(task))
572
+ end
573
+
574
+ def explain_static(task)
575
+ static0 = predicates[0].static?(task)
576
+ static1 = predicates[1].static?(task)
577
+ if static0 && static1
578
+ super(task)
579
+ elsif static0 && !predicates[0].evaluate(task)
580
+ predicates[0].explain_static(task)
581
+ elsif static1 && !predicates[1].evaluate(task)
582
+ predicates[1].explain_static(task)
583
+ end
584
+ end
585
+
586
+ def to_s; "(#{predicates[0]}) && (#{predicates[1]})" end
587
+ end
588
+
589
+ # Representation of UnboundPredicateSupport#or and
590
+ # UnboundTaskPredicate#or
591
+ #
592
+ # See documentation from UnboundTaskPredicate
593
+ class UnboundTaskPredicate::Or < UnboundTaskPredicate::BinaryCommutativePredicate
594
+ def code
595
+ "(#{predicates[0].code}) || (#{predicates[1].code})"
596
+ end
597
+
598
+ def or(pred)
599
+ pred = pred.to_unbound_task_predicate
600
+ if pred.kind_of?(Or)
601
+ # Only add predicates in +pred+ that are not already in
602
+ # +self+
603
+ result = self
604
+ pred.each_atomic_predicate do |predicate|
605
+ result = result.or(predicate)
606
+ end
607
+ result
608
+ elsif has_atomic_predicate?(pred)
609
+ # Do not add +pred+ if it is already included in +self+
610
+ self
611
+ else
612
+ super
613
+ end
614
+ end
615
+
616
+ def static?(task)
617
+ static0 = predicates[0].static?(task)
618
+ static1 = predicates[1].static?(task)
619
+ static0 && static1 ||
620
+ (static0 && predicates[0].evaluate(task) ||
621
+ static1 && predicates[1].evaluate(task))
622
+ end
623
+
624
+ def explain_static(task)
625
+ static0 = predicates[0].static?(task)
626
+ static1 = predicates[1].static?(task)
627
+ if static0 && static1
628
+ super(task)
629
+ elsif static0 && predicates[0].evaluate(task)
630
+ predicates[0].explain_static(task)
631
+ elsif static1 && predicates[1].evaluate(task)
632
+ predicates[1].explain_static(task)
633
+ end
634
+ end
635
+ def to_s; "(#{predicates[0]}) || (#{predicates[1]})" end
636
+ end
637
+
638
+ # Representation of UnboundPredicateSupport#followed_by
639
+ #
640
+ # See documentation from UnboundTaskPredicate
641
+ class UnboundTaskPredicate::FollowedBy < UnboundTaskPredicate::BinaryCommutativePredicate
642
+ def explain_true(task)
643
+ return if !evaluate(task)
644
+
645
+ this_event = task.event(predicates[0].event_name).last
646
+ other_event = task.event(predicates[1].event_name).last
647
+ Explanation.new(true, self, [this_event, other_event])
648
+ end
649
+ def explain_false(task)
650
+ return if evaluate(task)
651
+
652
+ this_generator = task.event(predicates[0].event_name)
653
+ other_generator = task.event(predicates[1].event_name)
654
+ if !this_generator.last
655
+ Explanation.new(false, self, [this_generator])
656
+ else
657
+ Explanation.new(false, self, [other_generator])
658
+ end
659
+ end
660
+ def explain_static(task)
661
+ return if !static?(task)
662
+
663
+ if predicates[0].static?(task)
664
+ this_generator = task.event(predicates[0].event_name)
665
+ if !predicates[0].evaluate(task) || evaluate(task)
666
+ Explanation.new(nil, self, [this_generator])
667
+ else # first event emitted, second event cannot be emitted (static)
668
+ other_generator = task.event(predicates[1].event_name)
669
+ Explanation.new(nil, self, [other_generator])
670
+ end
671
+ else
672
+ other_generator = task.event(predicates[1].event_name)
673
+ Explanation.new(nil, self, [other_generator])
674
+ end
675
+ end
676
+ def static?(task)
677
+ event0 = task.event(predicates[0].event_name)
678
+ event1 = task.event(predicates[1].event_name)
679
+
680
+ if event0.unreachable?
681
+ (!predicates[0].evaluate(task) || # will stay false as pred[0] can't emit
682
+ evaluate(task) || # will stay true as pred[0] can't emit
683
+ predicates[1].static?(task))
684
+ elsif event1.unreachable?
685
+ !evaluate(task)
686
+ end
687
+ end
688
+
689
+ def code
690
+ this_event = predicates[0].event_name
691
+ other_event = predicates[1].event_name
692
+ "(task_#{this_event} && task_#{other_event} && task_#{other_event}.time > task_#{this_event}.time)"
693
+ end
694
+ def to_s; "#{predicates[0].event_name}.followed_by(#{predicates[1].event_name})" end
695
+ end
696
+
697
+ # Representation of UnboundPredicateSupport#not_followed_by
698
+ #
699
+ # See documentation from UnboundTaskPredicate
700
+ class UnboundTaskPredicate::NotFollowedBy < UnboundTaskPredicate::BinaryCommutativePredicate
701
+ def explain_true(task)
702
+ return if !evaluate(task)
703
+
704
+ this_event = task.event(predicates[0].event_name).last
705
+ other_generator = task.event(predicates[1].event_name)
706
+ other_generator = other_generator.last || other_generator
707
+ Explanation.new(true, self, [this_event, other_generator])
708
+ end
709
+ def explain_false(task)
710
+ return if evaluate(task)
711
+
712
+ this_generator = task.event(predicates[0].event_name)
713
+ if !this_generator.last
714
+ Explanation.new(false, self, [this_generator])
715
+ else
716
+ other_generator = task.event(predicates[1].event_name)
717
+ Explanation.new(false, self, [other_generator.last])
718
+ end
719
+ end
720
+ def explain_static(task)
721
+ return if !static?(task)
722
+
723
+ if predicates[0].static?(task)
724
+ this_generator = task.event(predicates[0].event_name)
725
+ if !predicates[0].evaluate(task) || !evaluate(task)
726
+ Explanation.new(nil, self, [this_generator])
727
+ else
728
+ other_generator = task.event(predicates[1].event_name)
729
+ Explanation.new(nil, self, [this_generator, other_generator])
730
+ end
731
+ else
732
+ other_generator = task.event(predicates[1].event_name)
733
+ Explanation.new(nil, self, [other_generator])
734
+ end
735
+ end
736
+ def static?(task)
737
+ event0 = task.event(predicates[0].event_name)
738
+ event1 = task.event(predicates[1].event_name)
739
+
740
+ if event0.unreachable?
741
+ (!predicates[0].evaluate(task) || # stay false as first event can't emit
742
+ !evaluate(task) || # stay false as first event can't emit
743
+ predicates[1].static?(task))
744
+ elsif event1.unreachable?
745
+ evaluate(task) # stays true as the second event cannot
746
+ # appear after the first anymore
747
+ end
748
+ end
749
+
750
+ def code
751
+ this_event = predicates[0].event_name
752
+ other_event = predicates[1].event_name
753
+ "(task_#{this_event} && (!task_#{other_event} || task_#{other_event}.time < task_#{this_event}.time))"
754
+ end
755
+ def to_s; "#{predicates[0].event_name}.not_followed_by(#{predicates[1].event_name})" end
756
+ end
757
+
758
+ # Subclass of UnboundTaskPredicate to handle single event generators
759
+ #
760
+ # This is the class that is e.g. returned by
761
+ # UnboundPredicateSupport#to_unbound_task_predicate
762
+ class UnboundTaskPredicate::SingleEvent < UnboundTaskPredicate
763
+ # The generator name as a symbol
764
+ attr_reader :event_name
765
+ # The set of events required to compute this predicate. This is used
766
+ # by UnboundTaskPredicate#compile
767
+ attr_reader :required_events
768
+
769
+ def initialize(event_name)
770
+ @event_name = event_name
771
+ @required_events = [event_name].to_set
772
+ super()
773
+ end
774
+
775
+ def ==(pred); pred.kind_of?(SingleEvent) && pred.event_name == event_name end
776
+
777
+ # Code generation to create the overall evaluated predicate
778
+ def code
779
+ if @deadline
780
+ return "task_#{event_name} && (task_#{event_name}.time.to_f > #{@deadline.to_f})"
781
+ else
782
+ "!!task_#{event_name}"
783
+ end
784
+ end
785
+
786
+ # Returns an Explanation object that explains why +self+ is true.
787
+ # Note that it is valid only if evaluate(task) actually returned
788
+ # true (it will silently return an invalid explanation if
789
+ # evaluate(task) returns false).
790
+ def explain_true(task)
791
+ if event = task.event(event_name).last
792
+ Explanation.new(true, self, [event])
793
+ end
794
+ end
795
+ def explain_false(task)
796
+ generator = task.event(event_name)
797
+ if !generator.emitted?
798
+ Explanation.new(false, self, [generator])
799
+ end
800
+ end
801
+ def explain_static(task)
802
+ event = task.event(event_name)
803
+ if event.last
804
+ Explanation.new(true, self, [event.last])
805
+ elsif event.unreachable?
806
+ Explanation.new(nil, self, [event])
807
+ end
808
+ end
809
+ def static?(task)
810
+ event = task.event(event_name)
811
+ evaluate(task) || event.unreachable?
812
+ end
813
+
814
+ def never
815
+ Never.new(self)
816
+ end
817
+
818
+ def from_now
819
+ @deadline = Time.now
820
+ self
821
+ end
822
+
823
+ def not_followed_by(event)
824
+ NotFollowedBy.new(self, event.to_unbound_task_predicate)
825
+ end
826
+
827
+ def followed_by(event)
828
+ FollowedBy.new(self, event.to_unbound_task_predicate)
829
+ end
830
+
831
+ def to_s; "#{event_name}?" end
832
+ end
833
+ end
834
+ end
835
+