cauldron 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (398) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.txt +20 -0
  4. data/README +1 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +53 -0
  7. data/VERSION +1 -0
  8. data/bin/cauldron +10 -0
  9. data/cauldron/.autotest +23 -0
  10. data/cauldron/History.txt +6 -0
  11. data/cauldron/Manifest.txt +8 -0
  12. data/cauldron/README.txt +57 -0
  13. data/cauldron/Rakefile +27 -0
  14. data/cauldron/bin/cauldron +3 -0
  15. data/cauldron/lib/cauldron.rb +3 -0
  16. data/cauldron/test/test_cauldron.rb +8 -0
  17. data/features/cauldron_example_cases.feature +13 -0
  18. data/features/cauldron_generates_runtime_method.feature +12 -0
  19. data/features/cauldron_start_terminal.feature +13 -0
  20. data/features/step_definitions/cauldron_steps.rb +16 -0
  21. data/features/step_definitions/terminal_steps.rb +34 -0
  22. data/features/support/env.rb +19 -0
  23. data/lib/Chain.rb +879 -0
  24. data/lib/ChainMapping.rb +172 -0
  25. data/lib/CodeHandler.rb +517 -0
  26. data/lib/Mapping.rb +26 -0
  27. data/lib/MappingValues.rb +24 -0
  28. data/lib/ScopeDependencies.rb +7 -0
  29. data/lib/Theory.rb +274 -0
  30. data/lib/UnifiedChain.rb +110 -0
  31. data/lib/cauldron.rb +6 -0
  32. data/lib/cauldron/conversion.rb +15 -0
  33. data/lib/cauldron/pot.rb +134 -0
  34. data/lib/cauldron/sexp2cauldron.rb +156 -0
  35. data/lib/cauldron/terminal.rb +120 -0
  36. data/lib/cauldron/theory_factory.rb +10 -0
  37. data/lib/core/ActsAsCode.rb +25 -0
  38. data/lib/core/BlockToken.rb +33 -0
  39. data/lib/core/CCall.rb +7 -0
  40. data/lib/core/CTestCase.rb +27 -0
  41. data/lib/core/ClassMethodCallContainer.rb +45 -0
  42. data/lib/core/Container.rb +85 -0
  43. data/lib/core/InstanceCallContainer.rb +272 -0
  44. data/lib/core/MethodUsage.rb +66 -0
  45. data/lib/core/PrintVariables.rb +25 -0
  46. data/lib/core/TheoryGenerator.rb +764 -0
  47. data/lib/core/Token.rb +7 -0
  48. data/lib/core/assignment/Assignment.rb +18 -0
  49. data/lib/core/assignment/Equal.rb +39 -0
  50. data/lib/core/assignment/Equivalent.rb +20 -0
  51. data/lib/core/assignment/NotEqual.rb +14 -0
  52. data/lib/core/call_container/CallContainer.rb +66 -0
  53. data/lib/core/class_method_call/New.rb +15 -0
  54. data/lib/core/class_method_call/RuntimeClassMethodCall.rb +31 -0
  55. data/lib/core/declaration/Declaration.rb +16 -0
  56. data/lib/core/declaration/LiteralDeclaration.rb +47 -0
  57. data/lib/core/declaration/VariableDeclaration.rb +59 -0
  58. data/lib/core/instance_call/ArrayEach.rb +23 -0
  59. data/lib/core/instance_call/ArrayLength.rb +15 -0
  60. data/lib/core/instance_call/Chop.rb +28 -0
  61. data/lib/core/instance_call/Copy.rb +22 -0
  62. data/lib/core/instance_call/DeclaredVariable.rb +18 -0
  63. data/lib/core/instance_call/InstanceCall.rb +77 -0
  64. data/lib/core/instance_call/Params.rb +15 -0
  65. data/lib/core/instance_call/Push.rb +20 -0
  66. data/lib/core/instance_call/StringLength.rb +32 -0
  67. data/lib/core/instance_call/Times.rb +20 -0
  68. data/lib/core/instance_call/instance_calls.rb +168 -0
  69. data/lib/core/instance_call/length_equal.rb +15 -0
  70. data/lib/core/kernal/EvalCall.rb +15 -0
  71. data/lib/core/kernal/LocalVariablesCall.rb +15 -0
  72. data/lib/core/literal/Literal.rb +111 -0
  73. data/lib/core/literal/Raw.rb +23 -0
  74. data/lib/core/literal/RuntimeMethodLiteral.rb +21 -0
  75. data/lib/core/literal/StatementLiteral.rb +28 -0
  76. data/lib/core/method_call/AvailableVariablesCall.rb +25 -0
  77. data/lib/core/method_call/ClassCall.rb +33 -0
  78. data/lib/core/method_call/DefCall.rb +72 -0
  79. data/lib/core/method_call/EvaluateClassCall.rb +29 -0
  80. data/lib/core/method_call/MethodNameCall.rb +27 -0
  81. data/lib/core/method_call/ToDeclarationCall.rb +15 -0
  82. data/lib/core/requirement/Requirement.rb +291 -0
  83. data/lib/core/runtime_class/ArrayClass.rb +19 -0
  84. data/lib/core/runtime_class/ClassCallClass.rb +23 -0
  85. data/lib/core/runtime_class/ClassEvaluationClass.rb +19 -0
  86. data/lib/core/runtime_class/ClassName.rb +18 -0
  87. data/lib/core/runtime_class/DefCallClass.rb +21 -0
  88. data/lib/core/runtime_class/EqualClass.rb +19 -0
  89. data/lib/core/runtime_class/FixnumClass.rb +15 -0
  90. data/lib/core/runtime_class/IfStatementClass.rb +12 -0
  91. data/lib/core/runtime_class/InstanceCallClass.rb +19 -0
  92. data/lib/core/runtime_class/InstanceCallContainerClass.rb +16 -0
  93. data/lib/core/runtime_class/InstanceClassCallClass.rb +19 -0
  94. data/lib/core/runtime_class/LiteralClass.rb +19 -0
  95. data/lib/core/runtime_class/MethodParameterClass.rb +27 -0
  96. data/lib/core/runtime_class/MethodUsageClass.rb +27 -0
  97. data/lib/core/runtime_class/RequirementClass.rb +19 -0
  98. data/lib/core/runtime_class/ReturnClass.rb +21 -0
  99. data/lib/core/runtime_class/RuntimeClass.rb +30 -0
  100. data/lib/core/runtime_class/RuntimeClassClass.rb +19 -0
  101. data/lib/core/runtime_class/RuntimeMethodClass.rb +34 -0
  102. data/lib/core/runtime_class/StatementClass.rb +53 -0
  103. data/lib/core/runtime_class/StringClass.rb +23 -0
  104. data/lib/core/runtime_class/StringLengthClass.rb +19 -0
  105. data/lib/core/runtime_class/StringVariableClass.rb +19 -0
  106. data/lib/core/runtime_class/ThisClass.rb +15 -0
  107. data/lib/core/runtime_class/UnknownClass.rb +23 -0
  108. data/lib/core/runtime_class/class_names.rb +95 -0
  109. data/lib/core/runtime_class/runtime_class.rb +123 -0
  110. data/lib/core/runtime_method/ActsAsRuntimeMethod.rb +300 -0
  111. data/lib/core/runtime_method/ParametersContainer.rb +29 -0
  112. data/lib/core/runtime_method/RealisedRuntimeMethod.rb +94 -0
  113. data/lib/core/runtime_method/RuntimeMethod.rb +817 -0
  114. data/lib/core/runtime_method/WriteParameters.rb +35 -0
  115. data/lib/core/statement/ActsAsStatement.rb +116 -0
  116. data/lib/core/statement/ArrayAccess.rb +96 -0
  117. data/lib/core/statement/BlockStatement.rb +348 -0
  118. data/lib/core/statement/DeclarationStatement.rb +19 -0
  119. data/lib/core/statement/HackStatement.rb +25 -0
  120. data/lib/core/statement/HashAccess.rb +18 -0
  121. data/lib/core/statement/OpenStatement.rb +171 -0
  122. data/lib/core/statement/RealisedStatement.rb +5 -0
  123. data/lib/core/statement/SingleLineBlockStatement.rb +39 -0
  124. data/lib/core/statement/Statement.rb +1223 -0
  125. data/lib/core/statement/StatementDependencies.rb +271 -0
  126. data/lib/core/statement/StatementGroup.rb +157 -0
  127. data/lib/core/statement/StatementStructure2.rb +224 -0
  128. data/lib/core/statement/TheoryStatement.rb +60 -0
  129. data/lib/core/statement/TopologicalStatements.rb +34 -0
  130. data/lib/core/structure/DeclareNewInstanceStructure.rb +49 -0
  131. data/lib/core/structure/DeclareRuntimeMethodStructure.rb +34 -0
  132. data/lib/core/structure/DeclareVariableAsLiteralStructure.rb +31 -0
  133. data/lib/core/structure/DeclareVariableAsVariableStructure.rb +52 -0
  134. data/lib/core/structure/FixnumAdditionStructure.rb +56 -0
  135. data/lib/core/structure/InstanceCallContainerStructure.rb +50 -0
  136. data/lib/core/structure/InstanceCallStructure.rb +53 -0
  137. data/lib/core/structure/InstanceMethodCallStructure.rb +21 -0
  138. data/lib/core/structure/ReturnStructure.rb +20 -0
  139. data/lib/core/structure/StatementStructure.rb +11 -0
  140. data/lib/core/syntax/Addition.rb +25 -0
  141. data/lib/core/syntax/BlockContainer.rb +130 -0
  142. data/lib/core/syntax/Boolean.rb +15 -0
  143. data/lib/core/syntax/Code.rb +11 -0
  144. data/lib/core/syntax/Do.rb +20 -0
  145. data/lib/core/syntax/False.rb +12 -0
  146. data/lib/core/syntax/If.rb +28 -0
  147. data/lib/core/syntax/IfContainer.rb +100 -0
  148. data/lib/core/syntax/Nil.rb +15 -0
  149. data/lib/core/syntax/Return.rb +33 -0
  150. data/lib/core/syntax/Subtract.rb +19 -0
  151. data/lib/core/syntax/This.rb +40 -0
  152. data/lib/core/syntax/True.rb +20 -0
  153. data/lib/core/syntax/syntax.rb +24 -0
  154. data/lib/core/tracking/ActsAsTrackable.rb +65 -0
  155. data/lib/core/tracking/History.rb +167 -0
  156. data/lib/core/tracking/RuntimeTrackingMethod.rb +32 -0
  157. data/lib/core/tracking/Step.rb +52 -0
  158. data/lib/core/variable/ArrayVariable.rb +76 -0
  159. data/lib/core/variable/BaseVariable.rb +154 -0
  160. data/lib/core/variable/BlockVariable.rb +92 -0
  161. data/lib/core/variable/FixnumVariable.rb +36 -0
  162. data/lib/core/variable/HistoryVariable.rb +8 -0
  163. data/lib/core/variable/MethodParameter.rb +206 -0
  164. data/lib/core/variable/MethodUsageVariable.rb +60 -0
  165. data/lib/core/variable/NilVariable.rb +29 -0
  166. data/lib/core/variable/RuntimeMethodParameter.rb +67 -0
  167. data/lib/core/variable/StatementVariable.rb +72 -0
  168. data/lib/core/variable/StepVariable.rb +7 -0
  169. data/lib/core/variable/StringVariable.rb +46 -0
  170. data/lib/core/variable/TypeVariable.rb +72 -0
  171. data/lib/core/variable/Unknown.rb +116 -0
  172. data/lib/core/variable/UnknownVariable.rb +29 -0
  173. data/lib/core/variable/Variable.rb +70 -0
  174. data/lib/core/variable/VariableContainer.rb +28 -0
  175. data/lib/core/variable/VariableIncluded.rb +27 -0
  176. data/lib/core/variable/VariableReference.rb +85 -0
  177. data/lib/error/FailedToFindStatementContainerError.rb +7 -0
  178. data/lib/error/FailedToFindStatementError.rb +7 -0
  179. data/lib/error/FailedToFindVariableError.rb +7 -0
  180. data/lib/error/FailedToLiteraliseError.rb +7 -0
  181. data/lib/error/FailedVariableMatch.rb +7 -0
  182. data/lib/error/ImproperStatementUsageError.rb +7 -0
  183. data/lib/error/IncompatiableRequirementsError.rb +7 -0
  184. data/lib/error/InvalidStatementError.rb +7 -0
  185. data/lib/error/MethodSizeError.rb +7 -0
  186. data/lib/error/RuntimeSyntaxError.rb +7 -0
  187. data/lib/error/UnexpectedStatementTypeError.rb +7 -0
  188. data/lib/error/UnknownStatementType.rb +7 -0
  189. data/lib/error/UnliteralisableError.rb +7 -0
  190. data/lib/implemented_chain.rb +34 -0
  191. data/lib/intrinsic/IntrinsicLastRuntimeMethod.rb +20 -0
  192. data/lib/intrinsic/IntrinsicLiteral.rb +26 -0
  193. data/lib/intrinsic/IntrinsicObject.rb +22 -0
  194. data/lib/intrinsic/IntrinsicRuntimeMethod.rb +27 -0
  195. data/lib/intrinsic/IntrinsicTestCases.rb +17 -0
  196. data/lib/logger/StandardLogger.rb +62 -0
  197. data/lib/required.rb +236 -0
  198. data/lib/ruby_code/Array.rb +95 -0
  199. data/lib/ruby_code/Fixnum.rb +39 -0
  200. data/lib/ruby_code/Hash.rb +25 -0
  201. data/lib/ruby_code/NilClass.rb +19 -0
  202. data/lib/ruby_code/Object.rb +24 -0
  203. data/lib/ruby_code/String.rb +86 -0
  204. data/lib/ruby_code/Symbol.rb +7 -0
  205. data/lib/standard_library/Tasks.rb +12 -0
  206. data/lib/theories.rb +143 -0
  207. data/lib/theory/ActionImplementation.rb +17 -0
  208. data/lib/theory/TheoryAction.rb +70 -0
  209. data/lib/theory/TheoryChainValidator.rb +101 -0
  210. data/lib/theory/TheoryComponent.rb +42 -0
  211. data/lib/theory/TheoryConnector.rb +755 -0
  212. data/lib/theory/TheoryDependent.rb +135 -0
  213. data/lib/theory/TheoryImplementation.rb +74 -0
  214. data/lib/theory/TheoryResult.rb +131 -0
  215. data/lib/theory/TheoryVariable.rb +63 -0
  216. data/lib/theory/theory_collection.rb +62 -0
  217. data/lib/util/ClassEvaluation.rb +68 -0
  218. data/lib/util/CodeEvaluation.rb +35 -0
  219. data/lib/util/DeclarationStatementEvaluation.rb +31 -0
  220. data/lib/util/MethodEvaluation.rb +49 -0
  221. data/lib/util/MethodTester.rb +71 -0
  222. data/lib/util/MethodValidation.rb +145 -0
  223. data/lib/util/MethodWriter.rb +66 -0
  224. data/lib/util/Parser.rb +299 -0
  225. data/lib/util/StatementCheck.rb +42 -0
  226. data/lib/util/StringToTheory.rb +119 -0
  227. data/lib/util/System.rb +8 -0
  228. data/spec/cauldron/pot_spec.rb +6 -0
  229. data/spec/cauldron/runtime_method_spec.rb +36 -0
  230. data/spec/cauldron/sexp_2_cauldron_spec.rb +26 -0
  231. data/spec/cauldron/terminal_spec.rb +38 -0
  232. data/spec/cauldron/theory_action_spec.rb +5 -0
  233. data/spec/spec_helper.rb +4 -0
  234. data/test/fixtures/chains/1/declaration.txt +26 -0
  235. data/test/fixtures/chains/1/dump +0 -0
  236. data/test/fixtures/chains/2/declaration.txt +26 -0
  237. data/test/fixtures/chains/2/dump +0 -0
  238. data/test/fixtures/chains/3/declaration.txt +26 -0
  239. data/test/fixtures/chains/3/dump +0 -0
  240. data/test/fixtures/implementation_results/0/declaration.txt +3 -0
  241. data/test/fixtures/implementation_results/0/dump +0 -0
  242. data/test/fixtures/theories/0/declaration.txt +9 -0
  243. data/test/fixtures/theories/0/desc +10 -0
  244. data/test/fixtures/theories/0/dump +0 -0
  245. data/test/fixtures/theories/1/declaration.txt +15 -0
  246. data/test/fixtures/theories/1/desc +11 -0
  247. data/test/fixtures/theories/1/dump +0 -0
  248. data/test/fixtures/theories/10/declaration.txt +23 -0
  249. data/test/fixtures/theories/10/desc +17 -0
  250. data/test/fixtures/theories/10/dump +0 -0
  251. data/test/fixtures/theories/11/declaration.txt +20 -0
  252. data/test/fixtures/theories/11/desc +14 -0
  253. data/test/fixtures/theories/11/dump +0 -0
  254. data/test/fixtures/theories/12/declaration.txt +18 -0
  255. data/test/fixtures/theories/12/desc +12 -0
  256. data/test/fixtures/theories/12/dump +0 -0
  257. data/test/fixtures/theories/13/declaration.txt +24 -0
  258. data/test/fixtures/theories/13/desc +20 -0
  259. data/test/fixtures/theories/13/dump +0 -0
  260. data/test/fixtures/theories/14/declaration.txt +26 -0
  261. data/test/fixtures/theories/14/desc +20 -0
  262. data/test/fixtures/theories/14/dump +0 -0
  263. data/test/fixtures/theories/15/declaration.txt +20 -0
  264. data/test/fixtures/theories/15/desc +14 -0
  265. data/test/fixtures/theories/15/dump +0 -0
  266. data/test/fixtures/theories/16/declaration.txt +30 -0
  267. data/test/fixtures/theories/16/desc +14 -0
  268. data/test/fixtures/theories/16/dump +0 -0
  269. data/test/fixtures/theories/17/declaration.txt +25 -0
  270. data/test/fixtures/theories/17/desc +11 -0
  271. data/test/fixtures/theories/17/dump +0 -0
  272. data/test/fixtures/theories/18/declaration.txt +23 -0
  273. data/test/fixtures/theories/18/desc +11 -0
  274. data/test/fixtures/theories/18/dump +0 -0
  275. data/test/fixtures/theories/19/declaration.txt +23 -0
  276. data/test/fixtures/theories/19/desc +11 -0
  277. data/test/fixtures/theories/19/dump +0 -0
  278. data/test/fixtures/theories/2/declaration.txt +12 -0
  279. data/test/fixtures/theories/2/desc +10 -0
  280. data/test/fixtures/theories/2/dump +0 -0
  281. data/test/fixtures/theories/20/declaration.txt +23 -0
  282. data/test/fixtures/theories/20/desc +17 -0
  283. data/test/fixtures/theories/20/dump +0 -0
  284. data/test/fixtures/theories/3/declaration.txt +19 -0
  285. data/test/fixtures/theories/3/desc +11 -0
  286. data/test/fixtures/theories/3/dump +0 -0
  287. data/test/fixtures/theories/4/declaration.txt +11 -0
  288. data/test/fixtures/theories/4/desc +11 -0
  289. data/test/fixtures/theories/4/dump +0 -0
  290. data/test/fixtures/theories/5/declaration.txt +6 -0
  291. data/test/fixtures/theories/5/desc +9 -0
  292. data/test/fixtures/theories/5/dump +0 -0
  293. data/test/fixtures/theories/6/declaration.txt +13 -0
  294. data/test/fixtures/theories/6/desc +11 -0
  295. data/test/fixtures/theories/6/dump +0 -0
  296. data/test/fixtures/theories/7/declaration.txt +19 -0
  297. data/test/fixtures/theories/7/desc +11 -0
  298. data/test/fixtures/theories/7/dump +0 -0
  299. data/test/fixtures/theories/8/declaration.txt +21 -0
  300. data/test/fixtures/theories/8/desc +11 -0
  301. data/test/fixtures/theories/8/dump +0 -0
  302. data/test/fixtures/theories/9/declaration.txt +24 -0
  303. data/test/fixtures/theories/9/desc +20 -0
  304. data/test/fixtures/theories/9/dump +0 -0
  305. data/test/fixtures/theory_implementations/0/declaration.txt +11 -0
  306. data/test/fixtures/theory_implementations/0/desc.txt +9 -0
  307. data/test/fixtures/theory_implementations/0/dump +0 -0
  308. data/test/fixtures/theory_implementations/0/theory_id +1 -0
  309. data/test/fixtures/theory_implementations/1/desc.txt +9 -0
  310. data/test/fixtures/theory_implementations/1/dump +0 -0
  311. data/test/fixtures/theory_implementations/1/theory_id +1 -0
  312. data/test/fixtures/theory_implementations/2/desc.txt +9 -0
  313. data/test/fixtures/theory_implementations/2/dump +0 -0
  314. data/test/fixtures/theory_implementations/2/theory_id +1 -0
  315. data/test/output/simple_method.txt +6 -0
  316. data/test/output/test_method/first_possible_method.txt +6 -0
  317. data/test/output/test_simple_cases/simple_case_01.txt +8 -0
  318. data/test/output/test_simple_cases/simple_case_02.txt +7 -0
  319. data/test/output/test_simple_cases/simple_case_03.txt +8 -0
  320. data/test/output/test_simple_cases/simple_case_04.txt +8 -0
  321. data/test/output/test_simple_cases/simple_case_05.txt +8 -0
  322. data/test/output/test_simple_cases/simple_case_06.txt +9 -0
  323. data/test/output/test_simple_cases/simple_case_07.txt +9 -0
  324. data/test/output/test_simple_cases/simple_case_08.txt +9 -0
  325. data/test/tc_contextual_variables.rb +87 -0
  326. data/test/tc_describe.rb +47 -0
  327. data/test/tc_method.rb +133 -0
  328. data/test/tc_requirement.rb +30 -0
  329. data/test/tc_suite_complete.rb +26 -0
  330. data/test/tc_variable.rb +52 -0
  331. data/test/ts_complete.rb +84 -0
  332. data/test/ts_stable.rb +81 -0
  333. data/test/unit/core/declaration/tc_literal_declaration.rb +34 -0
  334. data/test/unit/core/method_call/tc_class_call.rb +20 -0
  335. data/test/unit/core/runtime_method/tc_realised_runtime_method.rb +129 -0
  336. data/test/unit/core/runtime_method/tc_runtime_method.rb +616 -0
  337. data/test/unit/core/statement/tc_array_access.rb +63 -0
  338. data/test/unit/core/statement/tc_block_statement.rb +51 -0
  339. data/test/unit/core/statement/tc_hack_statement.rb +26 -0
  340. data/test/unit/core/statement/tc_open_statement.rb +70 -0
  341. data/test/unit/core/statement/tc_statement.rb +681 -0
  342. data/test/unit/core/statement/tc_statement_dependencies.rb +146 -0
  343. data/test/unit/core/statement/tc_statement_group.rb +35 -0
  344. data/test/unit/core/statement/tc_statement_replace_variable.rb +61 -0
  345. data/test/unit/core/statement/tc_theory_statement.rb +51 -0
  346. data/test/unit/core/structure/tc_declare_new_instance_structure.rb +41 -0
  347. data/test/unit/core/structure/tc_declare_variable_as_literal_structure.rb +41 -0
  348. data/test/unit/core/structure/tc_declare_variable_as_variable_structure.rb +66 -0
  349. data/test/unit/core/structure/tc_instance_call_container_structure.rb +41 -0
  350. data/test/unit/core/structure/tc_return_structure.rb +32 -0
  351. data/test/unit/core/syntax/tc_block_container.rb +32 -0
  352. data/test/unit/core/syntax/tc_if_container.rb +39 -0
  353. data/test/unit/core/tc_class_method_call.rb +34 -0
  354. data/test/unit/core/tc_container.rb +41 -0
  355. data/test/unit/core/tc_ctest_case.rb +25 -0
  356. data/test/unit/core/tc_instance_call_container.rb +93 -0
  357. data/test/unit/core/tc_literal.rb +30 -0
  358. data/test/unit/core/tc_theory_generator.rb +336 -0
  359. data/test/unit/core/tc_theory_generator_heavy.rb +42 -0
  360. data/test/unit/core/tracking/tc_history.rb +102 -0
  361. data/test/unit/core/tracking/tc_step.rb +65 -0
  362. data/test/unit/core/variable/tc_array_variable.rb +61 -0
  363. data/test/unit/core/variable/tc_block_variable.rb +17 -0
  364. data/test/unit/core/variable/tc_fixnum_variable.rb +54 -0
  365. data/test/unit/core/variable/tc_method_parameter_variable.rb +22 -0
  366. data/test/unit/core/variable/tc_runtime_method_variable.rb +32 -0
  367. data/test/unit/core/variable/tc_string_variable.rb +37 -0
  368. data/test/unit/core/variable/tc_unknown.rb +24 -0
  369. data/test/unit/core/variable/tc_variable_reference.rb +28 -0
  370. data/test/unit/ruby_code/tc_array.rb +64 -0
  371. data/test/unit/ruby_code/tc_fixnum.rb +18 -0
  372. data/test/unit/ruby_code/tc_hash.rb +41 -0
  373. data/test/unit/ruby_code/tc_string.rb +38 -0
  374. data/test/unit/tc_chain.rb +434 -0
  375. data/test/unit/tc_chain_mapping.rb +62 -0
  376. data/test/unit/tc_chain_with_case_1.rb +169 -0
  377. data/test/unit/tc_instance_call.rb +40 -0
  378. data/test/unit/tc_instance_call_structure.rb +35 -0
  379. data/test/unit/tc_method_usage.rb +35 -0
  380. data/test/unit/tc_pot.rb +124 -0
  381. data/test/unit/tc_runtime_tracking_method.rb +40 -0
  382. data/test/unit/tc_statement_structure_2.rb +43 -0
  383. data/test/unit/tc_theory.rb +533 -0
  384. data/test/unit/tc_variable_declaration.rb +32 -0
  385. data/test/unit/theory/tc_theory_action.rb +80 -0
  386. data/test/unit/theory/tc_theory_action_implementation.rb +23 -0
  387. data/test/unit/theory/tc_theory_chain_validator.rb +340 -0
  388. data/test/unit/theory/tc_theory_connector.rb +396 -0
  389. data/test/unit/theory/tc_theory_dependent.rb +151 -0
  390. data/test/unit/theory/tc_theory_implementation.rb +133 -0
  391. data/test/unit/theory/tc_theory_result.rb +111 -0
  392. data/test/unit/theory/tc_theory_variable.rb +45 -0
  393. data/test/unit/util/tc_method_validation.rb +98 -0
  394. data/test/unit/util/tc_parser.rb +108 -0
  395. data/test/unit/util/tc_string_to_theory.rb +299 -0
  396. data/test/unit/variable/tc_method_usage_variable.rb +25 -0
  397. data/tmp/runtime_method_evaluation.rb +10 -0
  398. metadata +522 -0
@@ -0,0 +1,101 @@
1
+ # Instances of this class receive a chain of order theories and proceed
2
+ # to apply each of them and confirm their expected output. The valid chain
3
+ # can then be used to generate an appropriate runtime method.
4
+ #
5
+ class TheoryChainValidator
6
+
7
+ # TODO Is 'potential_values' used?
8
+ # Returns the first runtime method that could be created with the implemented chains
9
+ # supplied. This actually generates the runtime method to check the links of the chain
10
+ # are accurate - unlike the complete? check in chain instances.
11
+ #
12
+ def build(runtime_method,test_cases,theory_implementation_chains,potential_values=[])
13
+ validated_chains = []
14
+ theory_implementation_chains.each do |chain|
15
+ validate_next_chain_link(validated_chains,chain,runtime_method.copy,test_cases,0)
16
+ end
17
+ raise StandardError.new('Failed to generate a valid runtime method') if validated_chains.length == 0
18
+
19
+ # Select the first chain and return the runtime method it generates
20
+ return build_method_from_chain(validated_chains.first,runtime_method.copy,test_cases)
21
+
22
+ end
23
+
24
+ # Validates that the next link in the chain is consistent with the
25
+ # theories expected result. If it is then the next link is checked
26
+ # and so on. if all the links are consistent then the chain is add
27
+ # to the validated chain array.
28
+ #
29
+ def validate_next_chain_link(validated_chains,chain,runtime_method,test_cases,position)
30
+ # Check that current link in the chain meets in dependencies
31
+ # if its dependents are met it isn't suppose to work
32
+ unless chain[position].meets_dependencies?(runtime_method.copy,test_cases.copy)
33
+ return nil
34
+ end
35
+
36
+ # Add the theories action to the chains runtime method and realise the runtime method
37
+ # TODO This creates a new runtime method each time (so ignores what the previous theory did - BAD)
38
+ result = runtime_method.copy
39
+ unless chain[position].action.nil?
40
+ begin
41
+ result = add_statement_to_method(test_cases,runtime_method.copy,chain[position].action)
42
+ rescue SyntaxError => e
43
+ StandardLogger.instance.warn e
44
+ return nil
45
+ rescue TypeError => e
46
+ StandardLogger.instance.warn e
47
+ return nil
48
+ end
49
+
50
+ end
51
+
52
+ # Now check that the runtime method with the theories action also responds
53
+ # as the theory said it would in the result.
54
+ if chain[position].results.all? {|x| x.validates?(result,test_cases)}
55
+
56
+ # Has the chain been completed?
57
+ if (position+1) == chain.length
58
+ validated_chains << chain
59
+ return
60
+ else
61
+ # Continue along the chain
62
+ validate_next_chain_link(validated_chains,chain,result,test_cases,(position+1))
63
+ end
64
+ else
65
+ # Theory was wrong
66
+ chain[position].results.each do |x|
67
+ unless x.validates?(result,test_cases)
68
+ StandardLogger.instance.info('The following result failed to be met')
69
+ StandardLogger.instance.info(x.write)
70
+ end
71
+ end
72
+ return nil
73
+ end
74
+
75
+ end
76
+
77
+ # Builds the method using the chain without checking that the depenedents
78
+ # and results are accurate.
79
+ #
80
+ def build_method_from_chain(chain,runtime_method,test_cases)
81
+ runtime_method = runtime_method.copy
82
+ chain.each do |link|
83
+ next if link.action.nil?
84
+ runtime_method = add_statement_to_method(test_cases,runtime_method,link.action)
85
+ end
86
+ return runtime_method
87
+ end
88
+
89
+ def add_statement_to_method(test_cases,runtime_method,action)
90
+ evaluation_code = ''
91
+ # TODO I don't think this line below is needed
92
+ evaluation_code += "test_cases = #{test_cases.write}"+"\n"
93
+ evaluation_code += "last_runtime_method = runtime_method.copy"+"\n"
94
+ evaluation_code += action.write+"\n"
95
+ evaluation_code += 'return runtime_method'+"\n"
96
+ eval evaluation_code
97
+ rescue NoMethodError => e
98
+ return nil
99
+ end
100
+
101
+ end
@@ -0,0 +1,42 @@
1
+ module TheoryComponent
2
+ include ActsAsCode
3
+
4
+ attr_reader :theory_component_id
5
+
6
+ # TODO Complete hack for issue where component ids aren't unique - using marshal load
7
+ @@theory_component_id = 0
8
+
9
+ def generate_theory_component_id
10
+ if @theory_component_id.nil?
11
+ @theory_component_id = @@theory_component_id
12
+ @@theory_component_id += 1
13
+ end
14
+ end
15
+
16
+ # Returns all the theory vairables in this theory
17
+ # dependent.
18
+ #
19
+ def theory_variables
20
+ return @statement.select_all {|x| x.kind_of?(TheoryVariable)}
21
+ end
22
+
23
+ def tokens
24
+ return @statement.tokens
25
+ end
26
+
27
+ # Returns an array of any of the accessors in the statement. An accessor
28
+ # is the chain to access a property e.g. in the following statement =>
29
+ #
30
+ # var1[:params][var3].something(var6)
31
+ #
32
+ # it would return ["var1[:params][var3]","var6"]
33
+ #
34
+ # The needed when trying to determine intrinsic values. So in this case
35
+ # var1 couln't be a runtime_method instance becuase it doesn't use
36
+ # the has key
37
+ #
38
+ def accessors
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,755 @@
1
+
2
+ # Instances are expected to connect any number of theories so
3
+ # that the chain finishes with a particular outcome.
4
+ #
5
+ # e.g. '<runtime_method>.all_pass?(<test_cases>) = true'
6
+ #
7
+ class TheoryConnector
8
+
9
+ def initialize(potential_values)
10
+ @potential_values = potential_values
11
+ end
12
+
13
+ # Attempts to chain the theories togeather so that the final theory
14
+ # results in the specified "finish".
15
+ #
16
+ # @param runtime_method This is an instance of the core runtime method
17
+ # instance that is populated with any number of statements.
18
+ # @param test_cases An array of test cases that contain the values for
19
+ # runtime method's paramters and the expected return value
20
+ # given those parameters.
21
+ # @param finish A description of the desired final outcome - this will
22
+ # probably be
23
+ # '<runtime_method>.all_pass?(<test_cases>) = true'
24
+ # @param theories A array of theories to be chained togeather to result
25
+ # in the finish outcome.
26
+ #
27
+ # TODO Last runtime method dependencies can't be shared down the the theory chain
28
+ #
29
+ def chain(runtime_method,test_cases,finish,theories)
30
+
31
+ return create_possible_chains(runtime_method,test_cases,finish,theories)
32
+
33
+ end
34
+
35
+ # NOTE: Will probably replace the create_possible_chains and chain call
36
+ # Returns an array of complete chains that conclude with a valid
37
+ # runtime method.
38
+ #
39
+ def generate_chains(runtime_method,test_cases,theories)
40
+
41
+ # Create the inital chain (with the head and tail)
42
+ intial_chain = Chain.new
43
+
44
+ # Find a theory that can act as the head
45
+ possible_head_theories = theories.select {|x| x.dependents.length == 0}
46
+
47
+ # Create the initial chains
48
+ possible_chains = []
49
+ possible_head_theories.each do |x|
50
+ possible_chains += intial_chain.copy.add_link(x)
51
+ end
52
+
53
+ # Check the initial chains incase they're complete
54
+ complete_chains = []
55
+ if possible_chains.any? {|x| x.complete? }
56
+ complete_chains += possible_chains.select {|x| x.complete?}
57
+ possible_chains.delete_if {|x| x.complete?}
58
+ end
59
+
60
+ # Continue to add theories to the chains until they are complete or the theories are exhausted
61
+ possible_chains.each do |x|
62
+ complete_chains += extend_chain(x,theories)
63
+ end
64
+ return complete_chains
65
+
66
+ end
67
+
68
+ # TODO Need to watch out here for infinite chain connections
69
+ def extend_chain(chain,theories)
70
+ complete_chains = []
71
+ theories.each do |x|
72
+ extended_chains = chain.copy.add_link(x)
73
+ next if extended_chains.empty?
74
+ complete_chains += extended_chains.select {|y| y.complete?}
75
+ extended_chains.delete_if {|y| y.complete?}
76
+ extended_chains.each do |y|
77
+ complete_chains += extend_chain(y,theories)
78
+ end
79
+ end
80
+ return complete_chains
81
+ end
82
+
83
+ def create_possible_chains(runtime_method,test_cases,finish,theories)
84
+
85
+ # Generate the head theory - this is the starting point and doesn't have any dependents
86
+ accessors, mapping = TheoryGenerator.new.generate_accessors_and_mapping(test_cases,runtime_method,7,0)
87
+
88
+ # * Generate all the possible results of this runtime method
89
+ theory_results = TheoryGenerator.new.get_theory_results(accessors)
90
+
91
+ # * Create the actual head theory
92
+ head_theory = Theory.new([],nil,theory_results,runtime_method.copy)
93
+
94
+ # Create the initial chain that needs to be connected
95
+ intial_chain = Chain.new
96
+ intial_chain.form_chain(head_theory,finish,mapping)
97
+
98
+ return create_possible_chain_extensions(runtime_method,test_cases,finish,theories,intial_chain)
99
+ end
100
+
101
+ # This method has been created so the initial chain can be passed in to start the method
102
+ # creation. Generating the initial chain can take a couple of minutes.
103
+ #
104
+ def create_possible_chain_extensions(runtime_method,test_cases,finish,theories,intial_chain)
105
+
106
+ # Save any of the complete chains
107
+ possible_chains = []
108
+
109
+ # Search through the available theories and find one that results in the finish
110
+ potential_final_theories = theories.select {|x| x.has_result_structure?(finish)}
111
+
112
+ # Attempt to add the potential link to the end of the chain
113
+ partial_chains = []
114
+ potential_final_theories.each do |theory|
115
+ potential_chain = intial_chain.copy
116
+ # TODO Maybe should be call add_link_to_tail - then check if it completes
117
+ if(potential_chain.add_link(theory))
118
+ # A new link has been added - does this complete the chain (tail -> head)
119
+ res = potential_chain.complete?
120
+ #if potential_chain.complete?
121
+ if res
122
+ possible_chains << potential_chain
123
+ else
124
+ partial_chains << potential_chain
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+
131
+ # If there are any partial chains try to extend them with additional theories
132
+ # - partial chains were connect to the finish but not the head.
133
+ partial_chains.each do |partial_chain|
134
+
135
+ # Select from the chain the dependents that haven't be met.
136
+
137
+ # TODO This looks very messy -
138
+
139
+ # Take the first dependent attempt to add a theory to resolve it
140
+ # - NOTE: This theory may resolve other of the dependents
141
+ #until partial_chain.unmet_dependents.empty?
142
+ limit = 1
143
+ until partial_chain.unmet_dependents.empty? or limit == 0
144
+
145
+ # Select the firs of the unment dependents
146
+ dependent = partial_chain.unmet_dependents.first
147
+
148
+ # Search through the available theories for ones that match the dependent structure
149
+ # TODO This should be empty for "ruby test/unit/theory/tc_theory_connector.rb --name test_chain_with_2_theories"
150
+ potential_theories = theories.select {|x| x.has_result_structure?(dependent) }
151
+ if potential_theories.length > 10
152
+ raise StandardError.new("Have not tested for #{potential_theories.length.to_s} potential theories" )
153
+ end
154
+
155
+ # Attempt to add the theory to the partial chain (prefers the theories that complete)
156
+ potential_theories.each do |t|
157
+ updated_chain = partial_chain.copy
158
+ # TODO Should create a quick way to switch input on and off while the script is running
159
+ if(updated_chain.add_link(t))
160
+ partial_chain = updated_chain
161
+ if updated_chain.complete?
162
+ possible_chains << updated_chain
163
+ break
164
+ else
165
+ end
166
+ else
167
+ end
168
+ end
169
+
170
+ limit -= 1
171
+ end
172
+
173
+ end
174
+
175
+ # Return the complete chains
176
+ return possible_chains
177
+
178
+ end
179
+
180
+ # Returns a new chain so that they all use consistent theory variables ids
181
+ #
182
+ # @param chain An array of theories e.g.
183
+ # [<#Theory>,<#Theory>,<#Theory>,<#Theory>]
184
+ #
185
+ # The last chain contains the finished theory.
186
+ #
187
+ # It is difficult to generate all the arrangements for the chain as soon as
188
+ # there start to be a large number of dependents and results. There is just too
189
+ # many permutations. Once any connection is decided upon e.g. this dependent to
190
+ # that result then the number of permutations is reduced. As such they need to
191
+ # be updated in parallet.
192
+ #
193
+ #
194
+ #
195
+ def unify_chain2(chain)
196
+
197
+ unified_chains = []
198
+
199
+ # Reverse the chain so that the finish is the first theory
200
+ reversed_chain = chain.reverse
201
+
202
+ # This method needs to map the theory variables used in one theory to the
203
+ # rest. This basically means there is a global theory that has a respective
204
+ # id in each of the other theories in the chain. e.g.
205
+ #
206
+ # +----------+--------+--------+--------+--------+
207
+ # |Global #ID| link#1 | link#2 | link#3 | link#4 |
208
+ # +----------+--------+--------+--------+--------+
209
+ # | 0 | 1 | 1 | 2 | 89 |
210
+ # +----------+--------+--------+--------+--------+
211
+ # | 1 | 2 | 4 | 6 | 1 |
212
+ # +----------+--------+--------+--------+--------+
213
+ #
214
+
215
+ # {global#ID=> #{link#1=>1,#link#2=>5}
216
+
217
+ # Take the first theory and set the global theory variables to the first link
218
+ global_theory_variables = {}
219
+
220
+ # * Pop the first link in the chain and set ids of the theory variables
221
+ link = chain.pop
222
+ link.all_theory_variables.each do |theory_variable|
223
+
224
+ # For the first link I'm just going to use the same id as the first link
225
+ global_theory_variables[theory_variable.theory_variable_id] = {link.theory_id=>theory_variable.theory_variable_id}
226
+
227
+ end
228
+
229
+ # 1. Find all the dependent-> result permutations for the last chain
230
+ # 2. Exclude any that are mutually exclusive
231
+
232
+ #possible_global_theory_variables = extend_global_mapping(global_theory_variables,link,chain)
233
+
234
+ # NOTE: Previously I had normalised the theories by working out all the possible permutations
235
+ # of dependent to result. Then work out the variable substitution. This did work but
236
+ # the number of permutations for larger theories meant it was completely impractical. Instead
237
+ # now it needs to form one connection "dependent to result" and then update the consequence of
238
+ # that. Some of the decisions will be mutually exclusive.
239
+
240
+ return unified_chains
241
+
242
+ end
243
+
244
+ def extend_global_mapping(global_theory_variables,link,chain,results=[])
245
+
246
+ next_link = chain.pop
247
+
248
+ # Find all the variables in the next link thats global ids have not been determined
249
+ unidentified_theory_variables = next_link.all_theory_variables.inject([]) do |total,x|
250
+ total << x if global_theory_variables.any? {|key,value| !value[next_link.theory_id].nil? }
251
+ end
252
+
253
+ # Link the previous dependents to the this link
254
+ link.dependents.each do |dependent|
255
+
256
+ # Find the similar
257
+
258
+ end
259
+
260
+ end
261
+
262
+ # Returns a new chain so that they all use consistent theory variables ids
263
+ #
264
+ def unify_chain(chain)
265
+
266
+ #return unify_chain2(chain.reverse)
267
+
268
+ # TODO Break up this method and write tests for the individual parts
269
+
270
+ # Find all the ways the theory and results can connected
271
+ # - the same_structure? approach is quite loose
272
+ arrangements = chain_arrangements(chain.copy.reverse)
273
+ # For each theory in the chain give each each variable a unique id
274
+ starting_id = 1
275
+ uniq_chain = chain.inject([]) do |total,x|
276
+ r = x.uniq_theory_variables(starting_id)
277
+ starting_id = r.highest_theory_variable_id+1
278
+ total << r
279
+ total
280
+ end
281
+
282
+ # Identify the matching variables
283
+ mappings = matching_variables(arrangements,uniq_chain)
284
+ # TODO Why are so many of these identical
285
+ mappings.uniq!
286
+
287
+ # Identify opposed mapping (variables that don't match in the context of the theory aren't equal)
288
+ false_mappings = {}
289
+ uniq_chain.each do |x|
290
+ r = x.all_theory_variables.collect {|x| x.theory_variable_id}
291
+ r.each do |y|
292
+ false_mappings[y] = r.copy.delete_if {|z| z == y}
293
+ end
294
+ end
295
+
296
+ final_mapping = []
297
+ #mappings = [mappings.last]
298
+
299
+ count = 0
300
+ mappings.each do |m|
301
+ count += 1
302
+ # Create an array of all variables that are equalivalent
303
+ master = combine_matches(m.to_a)
304
+
305
+ # Check that the equivalent variables don't occur in the same theory
306
+ # TODO If this never occurs I need to re-think things
307
+ catch :bad_map do
308
+ false_mappings.each do |key,value|
309
+
310
+ master.each do |x|
311
+ if x.include?(key)
312
+ if (x | value).length != x.length+value.length
313
+ throw :bad_map
314
+ end
315
+ end
316
+ end
317
+ end
318
+
319
+ final_mapping << master.collect {|x| x.uniq}
320
+ end
321
+ end
322
+
323
+ # Generate new chains using the final mappings
324
+ return [] if final_mapping.empty?
325
+
326
+ #m = final_mapping.last
327
+ new_chains = []
328
+ final_mapping.each do |x|
329
+
330
+ # Get the id of all the theory variables
331
+ all_theory_variable_ids = uniq_chain.collect {|y| y.all_theory_variables.collect {|z| z.theory_variable_id} }.flatten
332
+
333
+ # Unique theory variables
334
+ uniq_variables = all_theory_variable_ids-x.flatten
335
+ unique_count = (all_theory_variable_ids-x.flatten).length + x.length
336
+
337
+ # Prepare the mapping to match each id to a new variable
338
+ # (at this stage each of the mappings should be unique)
339
+ map = Mapping.new
340
+ unique_count.times do |k|
341
+ unless uniq_variables.empty?
342
+ #map << {uniq_variables.shift=>TheoryVariable.new(k)}
343
+ map[uniq_variables.shift] = TheoryVariable.new(k)
344
+ next
345
+ end
346
+ #t = m.shift
347
+ var = TheoryVariable.new(k)
348
+ #map += x.shift.collect {|u| {u=>var} }
349
+ x.shift.each do |j|
350
+ map[j] = var
351
+ end
352
+ end
353
+
354
+ # Copy the the chain and update the mapping
355
+ new_chains << Chain.new(uniq_chain.collect {|y| y.copy.map_to(map)})
356
+
357
+ end
358
+ return new_chains
359
+
360
+ end
361
+
362
+ # Returns an array of arrays containing matching ids
363
+ #
364
+ # matches e.g. [[5,10],[11,17],[12,18],[1,6],[7,12],[13,5]]
365
+ #
366
+ def combine_matches(matches)
367
+
368
+ results = []
369
+ until matches.empty?
370
+ start = matches.shift
371
+
372
+ catch :no_change do
373
+ loop do
374
+ initial_length = start.length
375
+ #removed = temp2.delete_if {|x| (x | start).length != start.length+x.length }
376
+
377
+ # TODO A delete command to that returns what you were deleting would be nice
378
+ index = matches.index {|x| (x | start).length != start.length+x.length }
379
+ if index.nil?
380
+ results << start
381
+ throw :no_change
382
+ end
383
+ b = matches.slice!(index)
384
+ start += b
385
+ start.uniq!
386
+ end
387
+
388
+ end
389
+ end
390
+ return results
391
+ end
392
+
393
+ # Returns an array that matches one variable to another indicating that
394
+ # they should be considered equal.
395
+ #
396
+ def matching_variables(arrangements,uniq_chain)
397
+ #chains = []
398
+ mappings = []
399
+ arrangements.each do |arrangement|
400
+ map = {}
401
+ arrangement.each do |theory|
402
+
403
+ dependents = uniq_chain.inject([]) {|total,x| total += x.dependents}
404
+ results = uniq_chain.inject([]) {|total,x| total += x.results}
405
+
406
+ theory.each do |dependent_id,result_id|
407
+
408
+ # Find the dependent with the matching id
409
+ dependent = dependents.detect() {|x| x.theory_component_id == dependent_id}
410
+ result = results.detect() {|x| x.theory_component_id == result_id}
411
+
412
+ # Temporary check that everything is tickety boo
413
+ if result.theory_variables.length != dependent.theory_variables.length
414
+ raise StandardError.new('They should always have the same number of theory variables')
415
+ end
416
+
417
+ # Go through each of the variables and match up the values
418
+ result.theory_variables.zip(dependent.theory_variables) do |x,y|
419
+
420
+ if map.has_key?(x.theory_variable_id)
421
+ end
422
+ map[y.theory_variable_id] = x.theory_variable_id
423
+
424
+ end
425
+
426
+ end
427
+
428
+ end
429
+ mappings << map
430
+ end
431
+ return mappings
432
+ end
433
+
434
+ # Returns an array of all the ways the theory chain can be arranged
435
+ # So dependent A -> result B
436
+ #
437
+ # @param chain An array containing all the theories in order
438
+ #
439
+ def chain_arrangements(chain)
440
+ arrangements = []
441
+ next_link_arrangement(arrangements,[],chain)
442
+ return arrangements
443
+ end
444
+
445
+ def next_link_arrangement(arrangements,arrangement,chain)
446
+ # Take out link and find the results that match its dependents
447
+ link = chain.pop
448
+
449
+ # Stop if the all the links in the chain have been met (the last one has nothing left to be dependent on)
450
+ if chain.empty?
451
+ arrangements << arrangement
452
+ return
453
+ end
454
+
455
+ # TODO Down the line I should see if Cauldron can tidy this up
456
+
457
+ # Saves what dependent connects to what result
458
+ # e.g. connection = {16=>[26, 28], 17=>[26, 28]}
459
+ connection = {}
460
+ link.dependents.each do |dependent|
461
+
462
+ # Get all the results from the rest of the chain
463
+ results = chain.inject([]) {|total,x| total + x.results }
464
+
465
+ # Go through the rest of the chain and find the results with the same structure
466
+ connection[dependent.theory_component_id] = results.select do |x|
467
+ x.same_structure?(dependent)
468
+ end.collect {|x| x.theory_component_id}
469
+
470
+ end
471
+
472
+ # TODO I need to re-do allot of the connecton stuff - I was using theories with arround 650 dependents and
473
+ # it was generating an insane size of arrangements. I think it is plausable to handle that size a theory
474
+ # but I should re-do this bit.
475
+ #
476
+ # I may need to reduce the theories to only include the dependent/result arrangements that change after
477
+ # the action is added.
478
+
479
+ # Calculate the total number of arrangements
480
+ total_arrangements = connection.values.collect {|x| x.length}.inject(1) {|total,y| total *= y}
481
+
482
+ # TODO Need to include an escape here if there are too many total_arrangements
483
+
484
+ # TODO The theory_generator is generating too many results and dependents.
485
+
486
+ # Find the various arrangements for the results
487
+ # e.g. [[26,26],[26,28],[28,26],..]
488
+ # NOTE I get a RangeError: too big to product with larger theories
489
+ connection_arrangements = connection.values.first.product(*connection.values[1..connection.values.length])
490
+
491
+ # Alternative
492
+ # NOTE: I've rewritten this because the code above generates an error for larger theories
493
+ # new_connection_arrangements = []
494
+ # extend_arrangement(new_connection_arrangements,connection.values)
495
+
496
+ # Jump back to the clearer dependent -> result arrangement
497
+ # e.g. [{16=>26, 17=>26}, {16=>26, 17=>28}, {16=>28, 17=>26}, {16=>28, 17=>28}]
498
+ nice_connection_arrangements = connection_arrangements.collect do |x|
499
+ a = []
500
+ connection.keys.zip(x) do |dependent_id,result_id|
501
+ a << dependent_id
502
+ a << result_id
503
+ end
504
+ Hash[*a]
505
+ end
506
+
507
+ # For each arrangement continue to the next link
508
+ nice_connection_arrangements.each do |x|
509
+ # TODO Maybe use a hash with the theory id in instead
510
+ a = arrangement.copy + [x]
511
+ next_link_arrangement(arrangements,a,chain.copy)
512
+ end
513
+
514
+ end
515
+
516
+ def extend_arrangement(total,groups,group=[])
517
+ if groups.empty?
518
+ total << group
519
+ return
520
+ end
521
+ groups.shift.each do |x|
522
+ extend_arrangement(total,groups.copy,group.copy.push(x))
523
+ end
524
+ end
525
+
526
+ # Returns all the implementation permutations for the theory.
527
+ def implement_chain(chain,mapping=Mapping.new)
528
+
529
+
530
+ # Implement the theory in all the permutations
531
+ # NOTE: Need to get the mapping during the implementation
532
+ link = chain.shift
533
+
534
+ # TODO Rewriting permutations takes quite long, I think it could be greatly reduced by
535
+ # stricting the posibilities by reviewing the dependents. For example:
536
+ #
537
+ # if(var6.kind_of?(Fixnum))
538
+ # return true
539
+ # end
540
+ #
541
+ # TODO I shouldn't treat the realisable fixnum variables as fair game. They should only
542
+ # TestCaseIndexFixnum and only available to things of that type.
543
+ #
544
+ link_permutations = link.rewrite_permutations(@potential_values,mapping)
545
+ implemented_chains = []
546
+ link_permutations.each do |x|
547
+ implement_next_link(implemented_chains,chain.copy,[link],[x])
548
+ end
549
+
550
+ return implemented_chains
551
+
552
+ end
553
+
554
+ def implement_next_link(implemented_chains,chain,previous_chain,partial_implemented_chain)
555
+ if chain.empty?
556
+ implemented_chains << partial_implemented_chain
557
+ return
558
+ end
559
+ next_link = chain.shift
560
+
561
+ # Create an hash to show how the results-dependents are linked.
562
+ # TODO Because I am loading the theories from Marshal dumps I need to make sure they all have unique ids
563
+ results_to_dependents = {}
564
+
565
+ dependent_mapping = conversion_mapping(partial_implemented_chain,previous_chain,next_link)
566
+
567
+ # # Now implement the next theory using the mapping dependency already established.
568
+ dependent_mapping.each do |mapping|
569
+
570
+ # NOTE: The mapping is only restricted between the dependent and result connection
571
+ implemented_links = next_link.rewrite_permutations(@potential_values,mapping)
572
+
573
+ implemented_links.each do |x|
574
+ extended_implemented_chain = partial_implemented_chain.copy << x
575
+ previous_chain = previous_chain.copy << next_link
576
+ implement_next_link(implemented_chains,chain,previous_chain,extended_implemented_chain)
577
+ end
578
+ end
579
+
580
+ end
581
+
582
+ # Returns a mapping hash that will describe how to implement the next theory
583
+ # so that it is compatiable with current chain.
584
+ #
585
+ def conversion_mapping(implemented_chain,current_chain,next_theory)
586
+
587
+ # Find all the permutations of theory dependents meet by the current chain.
588
+
589
+ # For each dependent find all the current implementations that meet it
590
+ # e.g. {16=>[26, 28, 12], 17=>[26, 28, 12]}
591
+ # TODO Should only include the most recent chain if the result contains a
592
+ # last_runtime_method variable.
593
+ results = current_chain.inject([]) {|total,x| total + x.results }
594
+ arrangements = next_theory.dependents.inject({}) do |total,dependent|
595
+ total[dependent.theory_component_id] = results.select do |x|
596
+ x.same_structure?(dependent)
597
+ end.collect {|x| x.theory_component_id}
598
+ total
599
+ end
600
+
601
+ # # ------------- Development Code -------------
602
+ # arrangements.each do |key,value|
603
+ # value.each do |x|
604
+ # end
605
+ # end
606
+
607
+ # Get the various permutations of the dependent to result
608
+ result_values = arrangements.values
609
+ # http://www.ruby-doc.org/core/classes/Array.html#M000287
610
+ # TODO Need to check when there is only one dependent
611
+ # [1,2].product() #=> [[1],[2]]
612
+ # [1,2].product([]) #=> []
613
+
614
+ variations = result_values.first.product(*result_values[1..result_values.length])
615
+ # e.g. [[26, 26], [26, 28], [26, 12], [28, 26], [28, 28], [28, 12], [12, 26], [12, 28], [12, 12]]
616
+ # TODO Maybe an array with the dependent id in would be more useful
617
+ # e.g. [[16=>26,17=>26],[16=>26,17=>28],...
618
+
619
+ # Need to find all the mappings that will still be consistent
620
+ potential_mappings = []
621
+ variations.each do |x|
622
+
623
+ # Go through each dependent to result pair
624
+ catch :incompatiable do
625
+ index = 0
626
+ mapping = Mapping.new
627
+
628
+ arrangements.each_key do |dependent_id|
629
+
630
+ # ----------- Development ----------------
631
+
632
+ # Find the implementation with this result
633
+ theory_result = results.detect {|y| y.theory_component_id == x[index]}
634
+
635
+ # Find the dependent that will be mapped
636
+ theory_dependent = next_theory.dependents.detect {|y| y.theory_component_id == dependent_id}
637
+
638
+ # Find the implementation that contains the selected result
639
+ # TODO This approach implies that the same theory can be used twice in the chain.
640
+ # TODO I could probably avoid allot of this by having implementation ids and including the
641
+ # mapping with the implementation's results
642
+ theory_implementation = implemented_chain.detect do |y|
643
+ y.results.any? {|z| z.theory_component_id == x[index]}
644
+ end
645
+
646
+ # Map the id of dependent to the real value used by the result
647
+ theory_result.theory_variables.zip(theory_dependent.theory_variables) do |z,y|
648
+
649
+ if mapping.has_key?(y.theory_variable_id)
650
+ throw :incompatiable if mapping[y.theory_variable_id] != theory_implementation.mapping[z.theory_variable_id]
651
+ end
652
+
653
+ mapping[y.theory_variable_id] = theory_implementation.mapping[z.theory_variable_id]
654
+ end
655
+ index += 1
656
+ end
657
+ potential_mappings << mapping
658
+ end
659
+ end
660
+
661
+ return potential_mappings
662
+
663
+ end
664
+
665
+ def find_theories_with_these_results(theories,results)
666
+ return theories.select do |theory|
667
+ results.all? {|x| theory.has_result_structure?(x)}
668
+ end
669
+ end
670
+
671
+ # Find the theories that match any of the results.
672
+ #
673
+ def find_the_theories_with_these_results(theories,results)
674
+ end
675
+
676
+ #
677
+ def add_link(complete_chains,chain,theories)
678
+
679
+ last_theory = chain.last
680
+
681
+
682
+ # Find the theories that can meet last theories dependency
683
+ # TODO Should this be looking for just one theory? If more than one theory is
684
+ # added they might not be compatible.
685
+ results = find_theories_with_these_results(theories,last_theory.dependents)
686
+ if results.empty?
687
+ complete_chains << chain
688
+ return
689
+ end
690
+
691
+ # Try to find any additional links to the new chain
692
+ results.each do |x|
693
+ extended_chain = chain.copy.push(x)
694
+ add_link(complete_chains,extended_chain,theories)
695
+ end
696
+
697
+ end
698
+
699
+ # Returns a number of updated mappings based on what if possible
700
+ # for the first theory and the current mapping for the end.
701
+ #
702
+ def refine_initial_mapping(theory,mapping,runtime_method,test_cases)
703
+
704
+ # TEMP
705
+ # 1. What theory variables don't have real values?
706
+ # 2. What real values are available?
707
+ # 3. For each real variable identify the theory variables it could be.
708
+ # 4. Given the possibilities work out the permutations
709
+
710
+ # Find the theory variable ids that don't have real values
711
+ var_ids = theory.dependents.inject([]){|total,x| total << x.theory_variables.collect {|z| z.theory_variable_id}}.flatten.uniq
712
+ unasigned_var_ids = var_ids-mapping.keys
713
+
714
+ # Development
715
+
716
+ # Find the available real values
717
+ available_real_values = @potential_values-mapping.values
718
+
719
+ # Determine the mermutations of unassigned var ids to available real values.
720
+ # NOTE: I'm sure how efficient it is working out every permutation especially
721
+ # when a dependent link "varA.kind_of?(Fixnum)" could narrow the
722
+ # combinations considerably.
723
+ value_permutations = available_real_values.permutation(unasigned_var_ids.length).to_a
724
+ var_value_permutations = value_permutations.inject([]) do |total,x|
725
+ r = []
726
+ x.zip(unasigned_var_ids) do |y,z|
727
+ r << z
728
+ r << y
729
+ end
730
+ total << Mapping.new(Hash[*r])
731
+ end
732
+
733
+ # = Remove any mapping permutaions that don't work =
734
+ passible_mappings = []
735
+ var_value_permutations.each_with_index do |possible_mapping,i|
736
+
737
+ # Combine the possible mapping with current actual mapping
738
+ m = mapping.merge(possible_mapping)
739
+
740
+ # Using this mapping go through each dependent and check it works
741
+ # (if it doesn't work then it's a none starter)
742
+ # TODO I don't really need to implement the full theory - just the dependents
743
+ implementation = theory.map_to(m)
744
+
745
+ # Use each implementation and find the ones that work
746
+ next unless implementation.meets_dependencies?(runtime_method,test_cases)
747
+ passible_mappings << m
748
+
749
+
750
+ end
751
+ return passible_mappings
752
+
753
+ end
754
+
755
+ end