cauldron 0.1.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 (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,66 @@
1
+ # Instances of this class describe the parameters that a method uses
2
+ # and is required to have
3
+ #
4
+ class MethodUsage < Array
5
+
6
+ def initialize(*parameters)
7
+ super()
8
+
9
+ # Check the data type of the provided variables
10
+ parameters.each do |x|
11
+ unless x.kind_of? MethodParameter then raise StandardError.new('Unexpected data type: '+x.class.to_s+' expecting MethodParameter') end
12
+ end
13
+
14
+ # Add the method variables to your self
15
+ parameters.collect {|param| self.push param}
16
+
17
+ end
18
+
19
+ # Check whether the rule matches the usage of the method. Essentially
20
+ # checking that the number of parameters is correct and the data types
21
+ # are acceptable.
22
+ #
23
+ def valid_rule? rule
24
+
25
+ # Check that correct number of parameters are provided
26
+ unless rule.paramater_count == self.length then raise ParameterCountError.new('Expected '+self.length.to_s+' parameters') end
27
+
28
+ end
29
+
30
+ def write
31
+ line = 'MethodUsage.new('
32
+ self.each do |x|
33
+ line += x.to_declaration.write
34
+ unless x.object_id == self.last.object_id then line += ', ' end
35
+ end
36
+ line += ')'
37
+ return line
38
+ end
39
+
40
+ # Returns this method usage case as MethodUsageVariable instance.
41
+ #
42
+ # TODO I'm not sure I should be allow this to set it's id
43
+ #
44
+ def to_var(id=nil,uniq_id=nil)
45
+ if id.nil? then return MethodUsageVariable.new(*self.collect {|x| x.copy}) end
46
+ return MethodUsageVariable.new(*self.collect {|x| x.copy}) {{:variable_id => id,:uniq_id=>uniq_id}}
47
+ end
48
+
49
+ # TODO Test this
50
+ def copy
51
+ return MethodUsage.new(*self.collect {|x| x.copy})
52
+ end
53
+
54
+ def to_declaration
55
+ return VariableDeclaration.new('MethodUsage',*self.collect {|x| x.to_declaration})
56
+ end
57
+
58
+ end
59
+
60
+ class ParameterCountError < StandardError
61
+
62
+ def initialize(msg)
63
+ super(msg)
64
+ end
65
+
66
+ end
@@ -0,0 +1,25 @@
1
+ module PrintVariables
2
+
3
+ #
4
+ def display_name_for(var)
5
+
6
+ # Has a name been given to this variable
7
+ unless @variable_names[var.variable_id].nil? then return @variable_names[var.variable_id] end
8
+
9
+ # Save the name of the new variable
10
+ var_name = 'var_'+@variable_counter.to_s
11
+ if var.kind_of? MethodParameter
12
+ var_name = 'param_var_'+@variable_counter.to_s
13
+ end
14
+ if var.kind_of? ResponseVariable
15
+ var_name = 'return_var_'+@variable_counter.to_s
16
+ end
17
+ @variable_counter += 1
18
+
19
+ # Save the existing name
20
+ @variable_names[var.variable_id] = var_name
21
+ return @variable_names[var.variable_id]
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,764 @@
1
+ class TheoryGenerator
2
+
3
+ def initialize(filters=[])
4
+ @filters = filters
5
+ end
6
+
7
+ # Returns an array of master theories(huge theories) generated using the runtime
8
+ # method at each stage of the chain.
9
+ #
10
+ def master_theories(chain,initial_runtime_method,test_cases)
11
+ raise StandardError.new('Currently only able to generate master theories for complete chains') unless chain.complete?
12
+
13
+ # Retrieve the full variable history for the chain - need to avoid duplicate variable creation especially if a variable
14
+ # only exists in the action.
15
+ creation_history = chain.variables_creation(initial_runtime_method,test_cases)
16
+
17
+ # * Create the values array [{:value=>x,:statement=>:step=>}]
18
+ master_theories = []
19
+ chain.each_theory_progression(initial_runtime_method,test_cases) do |implemented_theory,theory|
20
+
21
+ # TODO Include this as a test to confirm an exception is raised
22
+ # QUICK: Adding a new value in the test cases :after so it changes the output
23
+ # and the variable mapping - the error should be picked up.
24
+ # if implemented_theory.accessor_values[:after][1]
25
+ # implemented_theory.accessor_values[:after][1].push({:params=>["pip"],:output=>"pip"})
26
+ # end
27
+
28
+ dependent_accessors = retrieve_accessors(implemented_theory.accessor_values[:before],creation_history)
29
+ result_accessors = retrieve_accessors(implemented_theory.accessor_values[:after],creation_history)
30
+
31
+ # Generate the dependents and results
32
+ theory_dependents = get_theory_dependents(dependent_accessors.copy)[0..8]
33
+ theory_results = get_theory_dependents(result_accessors.copy)[0..2]
34
+
35
+ # Create the complete theory
36
+ master_theories << Theory.new(
37
+ theory_dependents.copy,
38
+ theory.action.copy,
39
+ theory_results
40
+ )
41
+
42
+ end
43
+ return master_theories
44
+
45
+ end
46
+
47
+ # Returns a master and simplistic theory in conext of the supplied runtime
48
+ # method after each of the actions is added. So for each action there is
49
+ # new theory generated.
50
+ #
51
+ # NOTE: This is the first time I've started to introduce this master/simply
52
+ # theory paradigm. The general rule I'm using is that the simple theory
53
+ # only needs to be complex enough so it can indicate the order the actions
54
+ # should be performed.
55
+ #
56
+ # NOTE: The variables that each of theories use always refer to the same value. So
57
+ # if var1 is the rutime method then var1 is the runtime method for all the theories.
58
+ #
59
+ def generate_theories_for_actions(runtime_method,test_cases,actions)
60
+
61
+ end
62
+
63
+ # Returns true if adding the supplied actions to the runtime method results
64
+ # in all the tests cases being met. This is useful to use before attempting
65
+ # to generate the theories to solve the test cases.
66
+ #
67
+ # TODO I would rather the mapping was ChainMapping or ideally the mapping wasn't passed
68
+ # all, just have it as internal to the chain.
69
+ #
70
+ def actions_validate_runtime_method?(runtime_method,test_cases,actions,mapping)
71
+
72
+ # Declare the default finish for any problem
73
+ head = Theory.new([],nil,[])
74
+ tail = Parser.run("if(runtime_method.all_pass?(test_cases))\nreturn true\nend")
75
+
76
+ # Create the chain
77
+ chain = Chain.new
78
+ chain.form_chain(head,tail,mapping)
79
+
80
+ # Add each of the actions to the chain
81
+ actions.each do |action|
82
+ chain.add_link(Theory.new([],action,[]))
83
+ end
84
+
85
+ # Implement the chain so that all variables are unified
86
+ implementd_chain = chain.implement
87
+
88
+ end
89
+
90
+ # This generates an inital set of theories using the initial values. It
91
+ # then continues to generate additional theories after applying the action
92
+ # of the previously generated theories.
93
+ #
94
+ def multiple_generate(runtime_method,test_cases,limit=1)
95
+ theories = generate(test_cases,runtime_method,0)
96
+
97
+ additional_theories = []
98
+ theories.each_with_index do |x,i|
99
+ additional_theories += recursive_generate(test_cases,x,1,(limit-1))
100
+ end
101
+ return theories+additional_theories
102
+
103
+ end
104
+
105
+ def recursive_generate(test_cases,theory,stage,limit=1,results=[])
106
+
107
+ results << theory
108
+ return results if limit == 0
109
+
110
+ # TODO It seems a bit wasteful to generate a whole new set of accessors for each
111
+ # new theory. It should maybe just up accessors that include the runtime method.
112
+ new_theories = generate(test_cases.copy,theory.example_runtime_method.copy,stage)
113
+
114
+ new_theories.each do |x|
115
+ recursive_generate(test_cases.copy,x,(stage+1),(limit-1),results)
116
+ end
117
+ return results
118
+
119
+ end
120
+
121
+ # Returns an array of theories that add a variety of statements to the runtime
122
+ # method. The theories will be quite bloated since they'll contain all the possible
123
+ # dependents and results.
124
+ #
125
+ # @param values An array of literal values
126
+ #
127
+ def generate(test_cases,runtime_method,stage=0)
128
+
129
+ #
130
+ # TODO Not keen on this parallel assignment (should really just
131
+ # have a single instance containing the accessors and
132
+ # mapping or have the mappig generated)
133
+ accessors, mapping = generate_accessors_and_mapping(test_cases,runtime_method,4,stage)
134
+
135
+ # Now generate some possible theories using these values
136
+ return generate_theories(test_cases,runtime_method,accessors,mapping)
137
+
138
+ end
139
+
140
+ # Returns an array of statements that use the values supplied but will return a
141
+ # value(including boolean).
142
+ #
143
+ def generate_accessors_and_mapping(test_cases,runtime_method,itterations=1,stage=0)
144
+
145
+ # TODO I'd like to drop this and just query the mapping instance
146
+ theory_variable_ids = [0,1,2]
147
+
148
+ # Create a theory variable for each of the values
149
+ # runtime_method => 1
150
+ # test_cases => 2
151
+ mapping = Mapping.new({
152
+ 1 => runtime_method.copy,
153
+ 2 => test_cases.copy
154
+ })
155
+ results = [
156
+ {:value=>runtime_method.copy,:statement=>TheoryStatement.new(TheoryVariable.new(1)),:step=>0},
157
+ {:value=>test_cases.copy,:statement=>TheoryStatement.new(TheoryVariable.new(2)),:step=>0}
158
+ ]
159
+
160
+ # Generate a number of values that can be obtained from the current runtime method and test cases
161
+ itterations.times do |step|
162
+ results = extend_accessors(results,mapping,theory_variable_ids,(step+1))
163
+ end
164
+ return results, mapping
165
+
166
+ end
167
+
168
+ def generate_theories(test_cases,runtime_method,accessors,mapping)
169
+
170
+ # Retreive theory dependets relating to the current method
171
+ theory_dependents = get_theory_dependents(accessors.copy)
172
+
173
+ # Retrieve possible statements to include in the theory
174
+ theory_actions = get_theory_action(test_cases.copy,runtime_method.copy,accessors,mapping)
175
+
176
+ # For each action retrieve the results of adding the statement
177
+ theories = []
178
+ theory_actions.each_with_index do |selected_action,i|
179
+
180
+ # Add the statement to the runtime method and construct result theories based on it
181
+ new_values = accessors.copy
182
+
183
+ # Convert the mapping values into intrinsic values
184
+ intrinsic_mapping = covert_to_intrinsic_mapping(mapping)
185
+
186
+ # Re-create the action with intrinsic variables
187
+ implementated_action = selected_action.map_to(intrinsic_mapping)
188
+
189
+ # Generate the runtime method that would be created by using that action
190
+ modified_runtime_method = TheoryChainValidator.new.add_statement_to_method(
191
+ test_cases.copy,
192
+ runtime_method.copy,
193
+ implementated_action
194
+ )
195
+
196
+ # TODO I should maybe keep both runtime methods so the I can compare the runtime method's
197
+ # before and after.
198
+
199
+ # Create a new mapping using the update runtime method
200
+ new_mapping = mapping.copy
201
+ new_mapping[1] = modified_runtime_method
202
+
203
+ # Re-build the results but using the new value for the runtime method
204
+ # re_evaluate_results
205
+ # TODO Using the same result statements is limiting - there might be more calls available.
206
+ new_results = re_evaluate_results(accessors,new_mapping)
207
+
208
+ # Get the theory results for this modified runtime method
209
+ theory_results = get_theory_results(new_results)
210
+
211
+ # Create the complete theory
212
+ theories << Theory.new(
213
+ theory_dependents.copy,
214
+ selected_action,
215
+ theory_results,
216
+ modified_runtime_method
217
+ )
218
+
219
+ end
220
+
221
+ return theories
222
+
223
+ end
224
+
225
+ def get_theory_action(test_cases,runtime_method,results,mapping)
226
+
227
+ # Get possible statements ids
228
+ statement_ids = results.select {|x| x[:value].kind_of?(Fixnum)}
229
+
230
+ actions = []
231
+
232
+ # Add 'return <val>' statement
233
+ results.each do |x|
234
+ statement_ids.each do |y|
235
+ # TODO Shouldn't allow runtime methods to be included here
236
+ actions << TheoryAction.new(
237
+ TheoryStatement.new(StringToTheory.run("Statement.new(Return.new,#{x[:statement].write})")),
238
+ StringToTheory.run(y[:statement].write)
239
+ )
240
+ end
241
+ end
242
+ # Add the 'if(var1 == var2)' statement
243
+ # TODO Might only allow values in the action at this point
244
+ # 'IfStatement.new(var2[var3][:params][var6],Equivalent.new,var2[var3][:output])'
245
+ # TODO Should the values be equal at this point??
246
+
247
+ # Exclude the runtime method from being included as a value (.write method becomes messy)
248
+ # also excludes the orginal test_cases.
249
+ valid_results = results.select do |x|
250
+
251
+ # TODO For some reason "x[:value].all? {|y| y.kind_of?(CTestCase)}" returns true for method Parameter (which is why this is here)
252
+ next true if x[:value].kind_of?(MethodParameter)
253
+
254
+ next false if x[:value].kind_of?(RuntimeMethod)
255
+
256
+ # NOTE: This is only temporary - I don't really see anything wrong with nil
257
+ next false if x[:value].kind_of?(NilClass)
258
+
259
+ next false if x[:value].kind_of?(Array) && x[:value].all? {|y| y.kind_of?(CTestCase)}
260
+ next true
261
+ end
262
+
263
+ (results-valid_results).each do |x|
264
+ next if x[:value].nil?
265
+ end
266
+
267
+ # Generate "if(varA == varB) statements"
268
+ value_pairs = valid_results.permutation(2)
269
+ value_pairs.each do |x,y|
270
+ statement_ids.each do |z|
271
+
272
+ # if(x == y)
273
+ # COMPROMISE - Only include statements with the same data type
274
+ # TODO They should be same type not identical so as long as the extend Array
275
+ # TODO I need to get the value of the runtime method parameter e.g. 'var2.params[var5]'
276
+ if x[:value].class != MethodParameter and y[:value].class != MethodParameter
277
+ next unless x[:value].class == y[:value].class
278
+ end
279
+ actions << TheoryAction.new(
280
+ TheoryStatement.new(
281
+ StringToTheory.run(
282
+ "OpenStatement.new(IfContainer.new(#{x[:statement].write},Equivalent.new,#{y[:statement].write}))"
283
+ )
284
+ ),
285
+ StringToTheory.run(z[:statement].write)
286
+ )
287
+ end
288
+ end
289
+
290
+ # TODO I haven't allowed last_runtime_method to be used yet
291
+
292
+ # ========================================================
293
+ # Remove the actions that don't work
294
+ # ========================================================
295
+ # TODO This duplicates the the "covert_to_intrinsic_mapping" method
296
+ # Convert the mapping values into intrinsic values
297
+ intrinsic_mapping = Mapping.new
298
+ test_cases_key = nil
299
+ runtime_method_key = nil
300
+ mapping.each do |key,value|
301
+
302
+ # Convert fixnum into intrinisic fixnums
303
+ if value.kind_of?(Fixnum)
304
+ intrinsic_mapping[key] = IntrinsicLiteral.new(value)
305
+ next
306
+ end
307
+
308
+ end
309
+ intrinsic_mapping[1] = Parser.run('runtime_method')
310
+ intrinsic_mapping[2] = Parser.run('test_cases')
311
+
312
+ # Attempt to add the statement to the actual runtime method
313
+ valid_actions = []
314
+ actions.each do |x|
315
+ implementation = x.map_to(intrinsic_mapping)
316
+ if action_works_with_runtime_method?(test_cases.copy,runtime_method.copy,implementation)
317
+ valid_actions << x
318
+ end
319
+ end
320
+
321
+ return valid_actions
322
+
323
+ end
324
+
325
+ def covert_to_intrinsic_mapping(mapping)
326
+
327
+ # Convert the mapping values into intrinsic values
328
+ intrinsic_mapping = Mapping.new
329
+ test_cases_key = nil
330
+ runtime_method_key = nil
331
+ mapping.each do |key,value|
332
+
333
+ # Convert fixnum into intrinisic fixnums
334
+ if value.kind_of?(Fixnum)
335
+ intrinsic_mapping[key] = IntrinsicLiteral.new(value)
336
+ next
337
+ end
338
+
339
+ if value.kind_of?(RuntimeMethod)
340
+ intrinsic_mapping[key] = Parser.run('runtime_method')
341
+ runtime_method_key = key
342
+ next
343
+ end
344
+
345
+ if value.kind_of?(Array) && value.first.has_key?(:params)
346
+ intrinsic_mapping[key] = Parser.run('test_cases')
347
+ test_cases_key = key
348
+ next
349
+ end
350
+ raise StandardError.new('Unknown value '+value.class.to_s)
351
+ end
352
+ return intrinsic_mapping
353
+ end
354
+
355
+ # Attempt to use the generated action with the runtime method to determine if
356
+ # it's valid syntax.
357
+ #
358
+ def action_works_with_runtime_method?(test_cases,runtime_method,action)
359
+ return TheoryChainValidator.new.add_statement_to_method(test_cases,runtime_method,action) ? true : false
360
+ rescue StandardError => e
361
+ return false
362
+ end
363
+
364
+ # Returns an array of theory dependents
365
+ #
366
+ def get_theory_dependents(results)
367
+
368
+ # Create the theory dependents for all the values
369
+ value_pairs = results.permutation(2)
370
+ theory_dependents = []
371
+ value_pairs.each do |x,y|
372
+ if x[:value] == y[:value]
373
+ theory_dependents << TheoryDependent.new(
374
+ StringToTheory.run("if(#{x[:statement].write} == #{y[:statement].write})\nreturn true\nend")
375
+ )
376
+ else
377
+ theory_dependents << TheoryDependent.new(
378
+ StringToTheory.run("if((#{x[:statement].write} == #{y[:statement].write})==false)\nreturn true\nend")
379
+ )
380
+ end
381
+ end
382
+ return theory_dependents
383
+ end
384
+
385
+ def get_theory_results(results)
386
+ theory_results = []
387
+
388
+ # Create the single statement theory results
389
+ results.each do |x|
390
+ if x[:value]
391
+ theory_results << TheoryResult.new(
392
+ StringToTheory.run("if(#{x[:statement].write})\nreturn true\nend")
393
+ )
394
+ elsif x[:value] == false
395
+ theory_results << TheoryResult.new(
396
+ StringToTheory.run("if((#{x[:statement].write})==false)\nreturn true\nend")
397
+ )
398
+ else
399
+ StandardLogger.instance.error(x[:statement].write+' is '+x[:value].to_s)
400
+ end
401
+ # TODO Should probably have else x[:value].nil? and StringToTheory.run("if((#{x[:statement].write}).nil?)\nreturn true\nend")
402
+ end
403
+
404
+ # Create the theory dependents for all the values
405
+ value_pairs = results.permutation(2)
406
+ value_pairs.each do |x,y|
407
+ if x[:value] == y[:value]
408
+ theory_results << TheoryResult.new(
409
+ StringToTheory.run("if(#{x[:statement].write} == #{y[:statement].write})\nreturn true\nend")
410
+ )
411
+ else
412
+ theory_results << TheoryResult.new(
413
+ StringToTheory.run("if((#{x[:statement].write} == #{y[:statement].write})==false)\nreturn true\nend")
414
+ )
415
+ end
416
+ end
417
+ return theory_results
418
+
419
+ end
420
+
421
+ # Re-evaluate the values of each of the results using an updated
422
+ # runtime method instance.
423
+ #
424
+ def re_evaluate_results(results,mapping)
425
+ new_results = []
426
+ results.each do |x|
427
+ v = obtain_value(x[:statement],mapping)
428
+ new_results << {:value=>v,:statement=>x[:statement],:step=>x[:step]}
429
+ end
430
+ return new_results
431
+ end
432
+
433
+ # Extends the provided accessors by another method call. For example
434
+ # if it is passed "test", it would return 'test'.length and
435
+ # 'test'.lowercase etc.
436
+ #
437
+ # @param initial_accessors An array of initial accessors containing the statement used
438
+ # to generate the value and the value itself.
439
+ # {:value=>#<Some Literal Value>,:statement=><#Statement: A statement instance>}
440
+ # @param mapping The current mapping being used. This is extended when a new
441
+ # index is used. So if test_case[0] is used, then 0 needs to have
442
+ # variable created for it and that added to the mapping.
443
+ # @param variable_history This keeps track of each time a new variable is created via additional
444
+ # array access calls. This allows the structure of the theories to remain
445
+ # unified across the dependents and results.
446
+ #
447
+ def extend_accessors(values,mapping,theory_variable_id,step,variable_history=[])
448
+
449
+ # Go through each of the values and get each of the cauldron method calls
450
+ total_results = []
451
+ values.each do |x|
452
+
453
+ # Get the possible cauldron method calls
454
+ results = []
455
+ x[:value].cauldron_method_calls.each do |y|
456
+
457
+ # Only get array access for values obtained in the last itteration
458
+ if (step-1) == x[:step]
459
+ results += params_output(x,y,mapping,theory_variable_id,step,values)
460
+ results += array_access(x,y,mapping,theory_variable_id,step,values,variable_history)
461
+ end
462
+
463
+ # If the variable is new it should have all the paramters
464
+ # If it isn't new it only needs the recent params
465
+
466
+ # Only include parameters for recently created values
467
+ if (step-1) == x[:step]
468
+ results += use_method_call(x,y,mapping,theory_variable_id,step,values)
469
+ else
470
+ last_results = values.select {|z| z[:step] == (step-1)}
471
+ results += use_method_call(x,y,mapping,theory_variable_id,step,last_results,true)
472
+ end
473
+
474
+ end
475
+ total_results += results
476
+ end
477
+ return total_results+values
478
+ end
479
+
480
+ #
481
+ #
482
+ #
483
+ def use_method_call(result,cauldron_method_call,mapping,theory_variable_id,step,available_params,params_only=false)
484
+
485
+ # Does it start with a '.'
486
+ results = []
487
+ if cauldron_method_call =~ /^\./
488
+
489
+ # Does it require any parameters
490
+ if ['.any?','.all_pass?','.pass?','.history2','.realise2','.kind_of?'].include?(cauldron_method_call)
491
+
492
+ case cauldron_method_call
493
+ when '.pass?'
494
+ # Uses one parameter - a test case
495
+ cauldron_test_cases = available_params.select {|x| x[:value].kind_of?(CTestCase)}
496
+ cauldron_test_cases.each do |x|
497
+ s = TheoryStatement.new(
498
+ StringToTheory.run(result[:statement].write+cauldron_method_call+'('+x[:statement].write+')')
499
+ )
500
+ v = obtain_value(s,mapping)
501
+ results << {:value=>v,:statement=>s,:step=>step}
502
+ end
503
+ when '.kind_of?'
504
+
505
+ # TODO Should probably include value class check here
506
+ s = TheoryStatement.new(
507
+ StringToTheory.run(result[:statement].write+cauldron_method_call+'(CTestCase)')
508
+ )
509
+ v = obtain_value(s,mapping)
510
+ results << {:value=>v,:statement=>s,:step=>step}
511
+
512
+ s2 = TheoryStatement.new(
513
+ StringToTheory.run(result[:statement].write+cauldron_method_call+'(Fixnum)')
514
+ )
515
+ v2 = obtain_value(s,mapping)
516
+ results << {:value=>v2,:statement=>s2,:step=>step}
517
+ when '.all_pass?'
518
+
519
+ available_params.each do |x|
520
+ if x[:value].kind_of?(Array) and x[:value].any? {|y| y.kind_of?(CTestCase)}
521
+ s = TheoryStatement.new(
522
+ StringToTheory.run(
523
+ result[:statement].write+cauldron_method_call+'('+x[:statement].write+')'
524
+ )
525
+ )
526
+ v = obtain_value(s,mapping)
527
+ results << {:value=>v,:statement=>s,:step=>step}
528
+ end
529
+ end
530
+
531
+ when '.history2'
532
+ return []
533
+ cauldron_arrays = available_params.select {|x| x[:value].kind_of?(Array)}
534
+ cauldron_test_case_params = cauldron_arrays.select {|x| x[:statement].write.include?(':params')}
535
+ cauldron_test_case_params.each do |x|
536
+ s = TheoryStatement.new(
537
+ StringToTheory.run(result[:statement].write+cauldron_method_call+'('+x[:statement].write+')')
538
+ )
539
+ v = obtain_value(s,mapping)
540
+ results << {:value=>v,:statement=>s,:step=>step}
541
+ end
542
+ when '.realise2'
543
+ cauldron_arrays = available_params.select {|x| x[:value].kind_of?(Array)}
544
+ cauldron_test_case_params = cauldron_arrays.select {|x| x[:statement].write =~ /:params\]$/}
545
+ cauldron_test_case_params.each do |x|
546
+ s = TheoryStatement.new(
547
+ StringToTheory.run(result[:statement].write+cauldron_method_call+'('+x[:statement].write+')')
548
+ )
549
+ v = obtain_value(s,mapping)
550
+ results << {:value=>v,:statement=>s,:step=>step}
551
+ end
552
+ when '.any?'
553
+ return []
554
+ # if(var5.history2(var2[var3][:params]).any?{ |x| x['statement_id'] == var1.last.statement_id} )
555
+ if result[:value].kind_of?(Array)
556
+ available_params.each do |x|
557
+ # TODO Should probably only match values of the same type - I don't want
558
+ # var1.any?{|x| x == var2.pass?(var1[var4])}
559
+
560
+ # Only allow one block statement -
561
+ next if x[:statement].write.include?('{')
562
+
563
+ # TODO I should reduce the number of possible comparisons
564
+ # (there is no point in comparing things will never be the same)
565
+ s = TheoryStatement.new(
566
+ StringToTheory.run(
567
+ result[:statement].write+cauldron_method_call+'{|x| x == '+x[:statement].write+'}'
568
+ )
569
+ )
570
+ v = obtain_value(s,mapping)
571
+ results << {:value=>v,:statement=>s,:step=>step}
572
+ end
573
+
574
+ # TODO This is is a quick hack to get x[:statement] included - down the line it might
575
+ # require a separate extend_accessors call.
576
+ if(result[:value].first.class==Step)
577
+ result[:value].first.cauldron_method_calls.each do |x|
578
+
579
+ available_params.each do |y|
580
+
581
+ # Only allow one block statement -
582
+ next if y[:statement].write.include?('{')
583
+
584
+ s = TheoryStatement.new(
585
+ StringToTheory.run(
586
+ result[:statement].write+cauldron_method_call+'{|x| x'+x+' == '+y[:statement].write+'}'
587
+ )
588
+ )
589
+ v = obtain_value(s,mapping)
590
+
591
+ results << {:value=>v,:statement=>s,:step=>step}
592
+
593
+ end
594
+ end
595
+ end
596
+
597
+ else
598
+ raise StandardError.new("Not setup for call '#{cauldron_method_call}'")
599
+ end
600
+ else
601
+ raise StandardError.new("Not setup for call '#{cauldron_method_call}'")
602
+ end
603
+
604
+ # NOTE: These don't take parameters
605
+ elsif ['.length','.last','.statement_id','.params','.value'].include?(cauldron_method_call)
606
+
607
+ # Don't include this call if only parameter calls are being considered
608
+ return [] if params_only
609
+
610
+ s = TheoryStatement.new(StringToTheory.run(result[:statement].write+cauldron_method_call))
611
+ v = obtain_value(s,mapping)
612
+ results << {
613
+ :value=>v,
614
+ :statement=>s,
615
+ :step=>step,
616
+ :intrinsic_statement=>self.convert_to_intrinsic_statement(s,mapping)
617
+ }
618
+ else
619
+ raise StandardError.new('Unknown method '+cauldron_method_call)
620
+ end
621
+ end
622
+ return results
623
+ end
624
+
625
+ def params_output(result,cauldron_method_call,mapping,theory_variable_id,step,results=[])
626
+ results = []
627
+ if cauldron_method_call.include?('[:params]') or cauldron_method_call.include?('[:output]')
628
+ s = TheoryStatement.new(StringToTheory.run(result[:statement].write+cauldron_method_call))
629
+ v = obtain_value(s,mapping)
630
+ results << {:value=>v,:statement=>s,:step=>step}
631
+ end
632
+ return results
633
+ end
634
+
635
+ # TODO Why is results passed through if it is just overwritten?
636
+ def array_access(result,cauldron_method_call,mapping,theory_variable_ids,step,results=[],variable_history=[])
637
+
638
+ results = []
639
+ if cauldron_method_call == '[]'
640
+ if result[:value].length > 4 then raise StandardError.new('Cauldron has not been tested with arrays larger that 4') end
641
+
642
+ # Generate theory variables for each of the new accessors
643
+ array_indexs = []
644
+ result[:value].length.times do |z|
645
+
646
+ theory_id = theory_variable_ids.length
647
+
648
+ # TODO Taking this complexity out for now.
649
+ # # Find pre-exisitng variables of the same value
650
+ # # TODO I should make sure I don't include unessary values here - I should check
651
+ # # that the same array access has not already been included indirectly in
652
+ # # via the action. var2, var3 both refer to same fixnum for case 1
653
+ # existing_variables = mapping.select{|key,value| value == z}
654
+ # array_indexs += existing_variables.collect {|key,value| TheoryVariable.new(key)}
655
+
656
+ # Before adding a new variable - check that an existing one doesn't already exist
657
+
658
+ # * Generate the intrinsic statement for it
659
+ new_written_intrinsic_statement = result[:intrinsic_statement].write+'['+z.to_s+']'
660
+ # TODO I might be able to use the results instead for the variable history now that I'm
661
+ # saving the intrinsic_statement
662
+ if variable_history.any? { |x| new_written_intrinsic_statement == x[:intrinsic_statement].write }
663
+ StandardLogger.instance.warning('Identical array access already exists '+new_written_intrinsic_statement)
664
+ saved_variable = variable_history.find {|x| x[:intrinsic_statement].write == new_written_intrinsic_statement}
665
+
666
+ #mapping[saved_variable[:global_variable_id]] = saved_variable[:variable_value].value
667
+ mapping[saved_variable[:global_variable_id]] = z
668
+ array_indexs << TheoryVariable.new(saved_variable[:global_variable_id])
669
+ else
670
+
671
+ mapping[theory_id] = z
672
+ array_indexs << TheoryVariable.new(theory_id)
673
+ theory_variable_ids << theory_variable_ids.length
674
+ end
675
+ end
676
+
677
+ # Generate a statement for each of the calls
678
+ array_indexs.each do |z|
679
+ s = TheoryStatement.new(StringToTheory.run(result[:statement].write+'['+z.write+']'))
680
+ v = obtain_value(s,mapping)
681
+ var_ids = s.variables.collect {|a| a.theory_variable_id}
682
+ var_values = var_ids.collect {|a| mapping[a]}
683
+ results << {
684
+ :value=>v,
685
+ :statement=>s,
686
+ :step=>step,
687
+ :variable_values=>var_values,
688
+ :intrinsic_statement=>convert_to_intrinsic_statement(s,mapping)
689
+ }
690
+
691
+ # Save the array history as well
692
+ unless variable_history.any? {|x| x[:global_variable_id] == z.theory_variable_id}
693
+
694
+ variable_history << {
695
+ :intrinsic_statement=>convert_to_intrinsic_statement(s,mapping),
696
+ :written_statement=>s.write,
697
+ :variable_value=>var_values.last.to_intrinsic,
698
+ :global_variable_id=>z.theory_variable_id
699
+ }
700
+ #raise StandardError.new('This array index has not been saved in the history '+z.theory_variable_id.to_s)
701
+
702
+ end
703
+
704
+ end
705
+ end
706
+ return results
707
+
708
+ end
709
+
710
+ def obtain_value(statement,mapping)
711
+
712
+ # Declare each of the theory variables with the correct value
713
+ declaration = ''
714
+ mapping.each do |key,value|
715
+ declaration += 'var'+key.to_s+' = mapping['+key.to_s+']'+"\n"
716
+ end
717
+ eval(declaration)
718
+ return eval(statement.write)
719
+
720
+ end
721
+
722
+ protected
723
+
724
+ def retrieve_accessors(literal_values,variable_creation_history)
725
+ value_accessors = []
726
+ a = literal_values.copy
727
+ literal_values.each do |key,val|
728
+ s = TheoryStatement.new(StringToTheory.run('var'+key.to_s))
729
+ value_accessors << {
730
+ :value=>val.copy,
731
+ :statement=>s,
732
+ :variable_values=>[val.copy],
733
+ :step=>0,
734
+ :intrinsic_statement=>convert_to_intrinsic_statement(s.copy,a.copy)
735
+ }
736
+ end
737
+ step = 0
738
+
739
+ array_of_variable_ids = literal_values.keys.copy
740
+ # TODO Hate the fact that mapping is modified via 'extend_accessors'
741
+ mapping = literal_values.copy
742
+
743
+ 2.times do
744
+ value_accessors = self.extend_accessors( value_accessors,
745
+ mapping,
746
+ array_of_variable_ids,
747
+ (step+1),
748
+ variable_creation_history
749
+ )
750
+ step += 1
751
+ end
752
+
753
+ return value_accessors
754
+ end
755
+
756
+ # Converts the theory statement to an intrinsic statement.
757
+ #
758
+ def convert_to_intrinsic_statement(theory_statement,literal_values)
759
+ intrinsic_values = literal_values.inject({}) {|total,(key,value)| total[key] = value.to_intrinsic; total}
760
+ intrinsic_statement = theory_statement.map_to(intrinsic_values)
761
+ return intrinsic_statement
762
+ end
763
+
764
+ end