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,29 @@
1
+ # TODO I think this class is pretty pointless - I should try and drop it
2
+ class ParametersContainer < Array
3
+
4
+ # TODO Should this be able to write parameters?
5
+
6
+ def initialize(*params)
7
+ super()
8
+ params.each do |x|
9
+ self.push(x)
10
+ end
11
+ end
12
+
13
+ def variables
14
+ return self
15
+ end
16
+
17
+ def each_variable
18
+ self.each do |x|
19
+ yield x
20
+ end
21
+ end
22
+
23
+ # Creates a duplicate of this parameters container.
24
+ #
25
+ def copy
26
+ return ParametersContainer.new(*self.collect {|x| x.copy})
27
+ end
28
+
29
+ end
@@ -0,0 +1,94 @@
1
+ class RealisedRuntimeMethod < StatementGroup
2
+ include ActsAsRuntimeMethod
3
+
4
+ attr_reader :method_id
5
+ attr_writer :method_id
6
+
7
+ def initialize(x,*statements)
8
+ @open = true
9
+ @parameters = x
10
+ super(*statements)
11
+ end
12
+
13
+ def push(statement)
14
+ raise StandardError.new('This realised method has been closed') unless @open
15
+ super(statement)
16
+ end
17
+
18
+ def close
19
+ @open = false
20
+ end
21
+
22
+ def cauldron_method_calls
23
+ return ['.params']
24
+ end
25
+
26
+ def write
27
+ return MethodWriter.new.write(
28
+ @parameters,
29
+ self.collect {|x| x.copy}
30
+ )
31
+ end
32
+
33
+ # [Overwrites] Returns a duplicate of this realised runtime
34
+ # method.
35
+ #
36
+ def copy
37
+ #result = self.class.new(@usage.copy,*self.collect {|x| x.copy })
38
+ result = self.class.new(@parameters.copy,*self.collect {|x| x.copy })
39
+ #result = self.class.new(nil,*self.collect {|x| x.copy })
40
+ result.scope_id = scope_id
41
+ result.scope = scope
42
+ result.statement_level = statement_level
43
+ result.close
44
+ return result
45
+ end
46
+
47
+ # TODO I should use ParseTree to get a list of all the methods - I can then use
48
+ # that to see what method aren't used and which ones don't have any
49
+ # tests.
50
+
51
+ # Returns an array of the parameters used in this realised runtime
52
+ # method.
53
+ #
54
+ def params
55
+ return @parameters
56
+ end
57
+
58
+ # Returns an array of all the variables available at the end of the
59
+ # method. This is essentially all the variables available on the
60
+ # last line. As such the variables scope must be the same as the
61
+ # method and it should also take into account if any of the variables
62
+ # have been overriden.
63
+ #
64
+ # @param params A param container instance that contains the necessary parameters for the
65
+ # runtime method instance.
66
+ # @param additional_methods An array of runtime method instances that may be
67
+ # called by this runtime method.
68
+ #
69
+ def final_variables(additional_methods=[])
70
+
71
+ # TODO Params should not be needed for realised runtime methods
72
+ # Relise the method - not sure if this strictly nessesary or preferable but I think
73
+ # it might be required to identify variables that are overwritten.
74
+ relised_method = self.copy
75
+
76
+ # Add the passed parameters
77
+ results = params.collect {|x| x.copy}
78
+
79
+ # Go through each statement that is nested/open etc and find all the declared varibles
80
+ # results = parameters.clone
81
+ relised_method.each do |x|
82
+ next if x.kind_of?(StatementGroup)
83
+ begin
84
+ results.push(x.declared_variable.copy)
85
+ rescue ImproperStatementUsageError => e
86
+ # Catch statements don't declare a variable
87
+ next
88
+ end
89
+ end
90
+ return results
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,817 @@
1
+ require "set"
2
+ # This class represents the code of a method generated at runitme
3
+ #
4
+ # This a variation on code set that contains usage and a return
5
+ # variable. It shouldn't contain any other runtime methods
6
+ # since you can't write methods within methods.
7
+ #
8
+ class RuntimeMethod < StatementGroup
9
+ include ActsAsTrackable
10
+ include ActsAsRuntimeMethod
11
+
12
+ attr_reader :method_id, :method_return, :usage
13
+ attr_writer :method_id
14
+
15
+ alias :statement_group_push :array_push
16
+
17
+ @@METHOD_ID = 0
18
+
19
+ # TODO I'm still not sure how to handle the method usage - a runtime method by default
20
+ # doesn't have literal values since it depends what it is like in each case.
21
+ #
22
+ # @param usage How the method should be used - this usage issue needs re-thought
23
+ # for now the only requirement is for usage.length to equal
24
+ # parameters.length
25
+ # @param method_return The response variable to return or nil if nothing is returned
26
+ #
27
+ def initialize(usage,method_return=nil,*statements)
28
+ super(*statements)
29
+
30
+ # Set the method id for the generated method
31
+ @method_id = @@METHOD_ID
32
+
33
+ @@METHOD_ID += 1
34
+
35
+ # Save how the method should be used
36
+ @usage = usage
37
+ @scope_variables = []
38
+
39
+ if method_return.nil? then method_return = NilVariable.new end
40
+ @method_return = method_return
41
+
42
+ # Set the statement level for runtime method (always - because it is the lowest depth)
43
+ @statement_level = 0
44
+
45
+ end
46
+
47
+ #
48
+ def self.reset_global_id
49
+ #http://www.zenspider.com/Languages/Ruby/QuickRef.html
50
+ unless $".include?('test/unit.rb')
51
+ StandardLogger.log 'WARNING: Resetting variable id, this should only be done for tests'
52
+ end
53
+ @@METHOD_ID = 0
54
+ end
55
+
56
+ #
57
+ def method_id=(id)
58
+
59
+ # Only let this method be called from fellow RuntimeMethod classes
60
+ # TODO Test this prevents the method_id from being set non runtime method class
61
+ unless caller.first.split(':')[0]==__FILE__
62
+ raise StandardError.new('Attempting to set method_id')
63
+ end
64
+ @method_id = id
65
+ end
66
+
67
+ # Returns a declaration instance for this particular runtime
68
+ # method. The declaration doesn't contain any of the internally
69
+ # generated statements.
70
+ #
71
+ # TODO Write tests on this with more variables and statements
72
+ #
73
+ def to_declaration
74
+ return VariableDeclaration.new(
75
+ self.class.to_s,
76
+ @usage.to_declaration,
77
+ @method_return.to_declaration,
78
+ *self.collect {|x| x.to_declaration}
79
+ )
80
+ end
81
+
82
+ # Returns an array of variables that are available at a particular line
83
+ # in the method.
84
+ #
85
+ # TODO This needs tests written for it especially for nested statements
86
+ #
87
+ def available_variable_at(params,line=0)
88
+ reduced_copy = copy.clear
89
+ self.each_with_index do |x,i|
90
+ break if i > line
91
+ reduced_copy.push x.copy
92
+ end
93
+ return reduced_copy.available_variables(params)
94
+ end
95
+
96
+ # NOTE: This doesn't handle the case when there are two unknowns -
97
+ # dependent on each other. e.g. 5 = var1+var2
98
+ def find_next_unknown(complete_statements,concept)
99
+
100
+ # If there are no unknown variables then the concept if fine to use
101
+ if concept.unknown_count == 0
102
+ complete_statements.push(concept)
103
+ return
104
+ end
105
+
106
+ concept.each_unknown do |unknown|
107
+
108
+ #temp = gets
109
+ # Go through each of the varialbes and see if they could be the unknown
110
+ available_variables.each do |var|
111
+
112
+ # Attempt to substitute one variable for another
113
+ updated_concept = concept.subst(unknown.variable_id,var)
114
+ next if updated_concept.nil?
115
+
116
+ # Find any further unknown variables in the statement
117
+ find_next_unknown(complete_statements,updated_concept)
118
+
119
+ end
120
+
121
+ # Actually only look for the first unknown
122
+ return
123
+ end
124
+
125
+ end
126
+
127
+ # TODO This is temporary
128
+ def params
129
+ return usage
130
+ end
131
+
132
+ # Inserts a statement at a particular position within the runtime method. This
133
+ # could be at the root of the runtime method or within one of its statement
134
+ # groups.
135
+ #
136
+ def add_statement_at(statement,position)
137
+ if position == self.statement_id
138
+ push(statement)
139
+ return
140
+ end
141
+ statement_groups = self.select_all {|x| x.kind_of?(StatementGroup) && x.statement_id == position}
142
+ unless statement_groups.empty?
143
+ statement_groups.first.push(statement)
144
+ return
145
+ end
146
+ raise StandardError.new('The is no statement group with the id '+position.to_s)
147
+ end
148
+
149
+ # Returns true if all the test cases when run through this runtime
150
+ # method return the correct value.
151
+ #
152
+ def all_pass?(test_cases)
153
+ test_cases.each do |x|
154
+ result = MethodEvaluation.new.evaluate_method(self.copy,x[:params].collect {|y| y.to_literal})
155
+ return false unless result == x[:output]
156
+ end
157
+ return true
158
+ end
159
+
160
+ def pass?(test_case)
161
+ result = MethodEvaluation.new.evaluate_method(self.copy,test_case[:params].collect {|y| y.to_literal})
162
+ return false unless result == test_case[:output]
163
+ return true
164
+ end
165
+
166
+ def push(statement)
167
+
168
+ # Confirms that supplied statement is a statement
169
+ unless statement.kind_of? Statement or statement.kind_of?(StatementGroup)
170
+ raise StandardError.new('Only statements can be included in a runtime method')
171
+ end
172
+
173
+ # Check if the statement creates a new variable - and add it the available variables
174
+ if statement.kind_of? DeclarationStatement
175
+ @scope_variables.push(statement.declared)
176
+
177
+ # The variable in the statement needs to have its requirements updated
178
+
179
+ end
180
+
181
+ #if statement.kind_of?(StatementGroup)
182
+ if statement.class.to_s == 'StatementGroup'
183
+ statement.each do |x|
184
+ statement_group_push(x)
185
+ end
186
+ else
187
+
188
+ # Adding statement to array
189
+ statement_group_push(statement)
190
+ end
191
+
192
+ end
193
+
194
+ #
195
+ #
196
+ # @param found_variables
197
+ # @param statement The statement that contains the solution. It should be
198
+ # in the following format:
199
+ # return_var = var or return_var = var.<method_call>
200
+ # @param rule
201
+ #
202
+ def build_solution(found_variables,statement,rule)
203
+
204
+ # Create the return statement
205
+ return_statement = Statement.new
206
+ return_statement.push Return.new
207
+
208
+ #new_statement = statement.copy
209
+
210
+ # Check the statement follows a "x = y" structure
211
+ unless statement.assignment? then raise StandardError.new('Statement needs to inlcude an "="') end
212
+
213
+ # Check whether any of the variables are unknown
214
+ statement.each_unknown do |unknown|
215
+
216
+ # Check if any of the unknown variables have been found
217
+ #unless found_variables[unknown.variable_id.to_s].nil?
218
+ if found_variables.has_key?(unknown.variable_id.to_s)
219
+
220
+ # Select the first possible variable id
221
+ match_variable_id = found_variables[unknown.variable_id.to_s].first
222
+
223
+ # Get the right hand side of the statement
224
+ rhs = statement.right_hand_side
225
+
226
+ unless rhs.length == 1 then raise StandardError.new('Only expecting one right hand side element') end
227
+
228
+ case rhs.first.class.to_s
229
+ when 'InstanceCallContainer'
230
+
231
+ # Does the subject of the call match?
232
+ if found_variables.has_key? rhs.first.subject.variable_id.to_s
233
+
234
+ # Replace unknown variable with the known one
235
+ variables(rule) do |v|
236
+ if v.variable_id == found_variables[rhs.first.subject.variable_id.to_s].first
237
+ return_statement.push InstanceCallContainer.new(v.copy,rhs.first.method_call)
238
+ return return_statement
239
+ end
240
+ end
241
+ end
242
+
243
+ when 'Unknown'
244
+
245
+ # Look through the variables
246
+ if found_variables.has_key? rhs.first.variable_id.to_s
247
+
248
+ variables(rule) do |v|
249
+
250
+ if v.variable_id == found_variables[rhs.first.variable_id.to_s].first
251
+ return_statement.push v.copy
252
+ return return_statement
253
+ end
254
+
255
+ end
256
+
257
+ end
258
+
259
+ else
260
+ raise StandardError.new('Unexpected class '+rhs.first.class.to_s)
261
+ end
262
+
263
+ end
264
+
265
+ end
266
+
267
+ raise StandardError.new('Unable to find variable with matching id')
268
+
269
+ end
270
+
271
+ # Creates a copy of the method with the same usage and
272
+ # statements but a different id. I'm not sure if
273
+ # should be using the same id or not.
274
+ #
275
+ def copy
276
+ return Marshal.load(Marshal.dump(self))
277
+ # # Create the copied method
278
+ # empty_copy = copy_base
279
+ # empty_copy.method_id = @method_id
280
+ # empty_copy.scope_id = scope_id
281
+ # empty_copy.scope = scope
282
+ # empty_copy.statement_level = statement_level
283
+ # self.each do |statement|
284
+ # empty_copy.push(statement.copy)
285
+ # end
286
+ #
287
+ # return empty_copy
288
+ end
289
+
290
+ # Returns the total number of statements within the method. Note
291
+ # This includes the statements within nested statements.
292
+ #
293
+ def statement_count
294
+ return self.inject(0) {|count, x| count += x.statement_count}
295
+ end
296
+
297
+ # Returns a dupicate method but only with the statements
298
+ # up to the line given.
299
+ #
300
+ def partial_method(line)
301
+
302
+ # Create a copy of the base runtime method
303
+ x = copy_base
304
+
305
+ # Check the length of method
306
+ if(line>statement_count) then raise MethodSizeError.new('Attmpting to create partial method larger than actual method - crazy bastard!') end
307
+
308
+ # Now add statements up until the line limit has been met
309
+ index = 0
310
+ limit = Array.new(line)
311
+
312
+ while(limit.length>0)
313
+ if self[index].kind_of?(Statement)
314
+ x.push(self[index].copy)
315
+ limit.pop
316
+ index += 1
317
+ elsif self[index].kind_of?(BlockStatement)
318
+ x.push(self[index].partial(limit))
319
+ index += 1
320
+ else
321
+ raise StandardError.new('Unexpected class type '+self[index].class.to_s)
322
+ end
323
+
324
+ end
325
+
326
+ return x
327
+ end
328
+
329
+ # Returns a duplicate method but without any statements in it
330
+ #
331
+ def copy_base
332
+ copied_method = RuntimeMethod.new(@usage.copy,@method_return.copy)
333
+ copied_method.method_id = method_id
334
+ return copied_method
335
+ end
336
+
337
+ # Adds a new statement to the method that returns a variable
338
+ # with the specified id.
339
+ #
340
+ # @param id The id of the variable that a return statement is being created
341
+ # for.
342
+ #
343
+ def add_return_variable_statement!(id)
344
+
345
+ # Find the requested variable
346
+ var = contextual_variable(id)
347
+
348
+ # Create the return statement and add it
349
+ self.push(Statement.new(Return.new,var))
350
+
351
+ end
352
+
353
+ # Returns a describtion of the method and the variables
354
+ # within it.
355
+ #
356
+ # TODO Write test for this method
357
+ #
358
+ def describe
359
+ line = write+"\n"
360
+ available_variables.each do |var|
361
+ line += var.describe(self)
362
+ end
363
+ return line
364
+ end
365
+
366
+ # Searches through each statement and identifies whether they
367
+ # override an existing variable or not.
368
+ #
369
+ def identify_overriding_statements(params)
370
+ previously_declared_variables = params.collect {|x| {:variable_id=>x.variable_id} }
371
+ self.each do |x|
372
+ x.identify_overriding_statements(previously_declared_variables)
373
+ end
374
+ end
375
+
376
+ # Returns a statement that declares the runtime method instance.
377
+ # e.g. RuntimeMethod.new(MethodUsage.new,ResponseVariable.new)
378
+ #
379
+ def declaration_statement
380
+ new_runtime_method = ClassMethodCallContainer.new(RuntimeMethodClass.new,New.new,@usage.declaration_statement,@method_return.declaration_statement)
381
+ return Statement.new(new_runtime_method)
382
+ end
383
+
384
+ # Evaluates the method but includes a return statement for the variable
385
+ # thats id is specified.
386
+ #
387
+ def literal_value_of_var(id,params)
388
+
389
+ # Create a copy of the runtime method
390
+ copied = self.copy
391
+
392
+ # Find a reference to the variable in the method's statements and parameters
393
+ var = nil
394
+ # TODO Remove all the @parameters
395
+ params.each do |param|
396
+ var = param if(param.variable_id == id)
397
+ end
398
+ if var.nil?
399
+ copy.each do |statement|
400
+ begin
401
+ var = statement.find_variable(id)
402
+ rescue FailedToFindVariableError
403
+ next
404
+ end
405
+ break
406
+ end
407
+ end
408
+
409
+ if(var.nil?) then raise FailedToFindVariableError.new('Couldn\'t find variable with the id:'+id.to_s) end
410
+
411
+ # Create a return statement for the requested variable
412
+ copied.push(Statement.new(Return.new,var))
413
+
414
+ # Now use the method to determine its value at runtime
415
+ result = MethodEvaluation.new.evaluate_method(copied,params)
416
+ return result
417
+
418
+ end
419
+
420
+ # Searches the paramaters for a variable with the specified id
421
+ def find_variable_in_parameters(id)
422
+ no_var_error = Proc.new { raise FailedToFindVariableError.new('Unable to find variable with the id '+id.to_s) }
423
+ return @usage.find(no_var_error){|i| i.variable_id == id}.copy
424
+ end
425
+
426
+ # Returns an array of statements with a number of method calls
427
+ # added to it that are equivalent to the variable specified.
428
+ #
429
+ # So a number of statements is provided and a say a string variable.
430
+ # A number method call is added to each statement where the method
431
+ # call will also return a string variable.
432
+ #
433
+ def replace_statement_element_with_method_calls(statements,variable,available=[])
434
+
435
+ updated_statements = []
436
+
437
+ if @method_return.meets_requirements?(variable)
438
+
439
+ # Find potential method calls and include them as partial statements
440
+ callable_combinations(available).each do |x|
441
+ statements.each do |y|
442
+ copied_statement = y.copy
443
+ copied_statement.push(x)
444
+ updated_statements.push(copied_statement)
445
+ end
446
+ end
447
+ end
448
+ return updated_statements
449
+ end
450
+
451
+ # Returns an array of def calls given the code elements made
452
+ # available.
453
+ #
454
+ # @param available An array of possible paramaters for the method call
455
+ #
456
+ def callable_combinations(available=[])
457
+
458
+ # Handle the case where the method doesn't require any parameters
459
+ if @usage.empty?
460
+ return [DefCall.new(@method_return.copy,self.copy)]
461
+ end
462
+
463
+ # NOTE This assumes that all the paramaters must be populated
464
+
465
+ # Go thorugh each usage method variable and construct arranges for each paramater
466
+ # So if the method expects two parameters - say a string and a number you might
467
+ # have variables.
468
+ # A, B
469
+ # C, B
470
+ arrangements = [[]]
471
+ @usage.each do |method_variable|
472
+ extended_arrangements = []
473
+ arrangements.each do |existing_arrangement|
474
+ available.each do |x|
475
+ if method_variable.meets_requirements?(x)
476
+ arrangement = existing_arrangement.copy
477
+ arrangement.push(x)
478
+ extended_arrangements.push(arrangement)
479
+ end
480
+ end
481
+ end
482
+ arrangements = extended_arrangements.copy
483
+ end
484
+
485
+ # Convert the arrangements to DefCalls
486
+ def_calls = []
487
+ arrangements.each do |x|
488
+ def_calls.push(DefCall.new(@method_return.copy,self.copy,*x))
489
+ end
490
+ return def_calls
491
+
492
+ end
493
+
494
+ # Returns an array of possible statements that contain
495
+ # a call to this runtime method.
496
+ #
497
+ def usage_statements(available=[])
498
+ results = []
499
+ def_calls = callable_combinations(available)
500
+ def_calls.each do |x|
501
+ # TODO Unknown variables should be replaced
502
+ results.push Statement.new(Var)
503
+ end
504
+ end
505
+
506
+ # Returns the runtime methods as a RuntimeMethodParameter.
507
+ #
508
+ # @param id The id of the variable to give to the returned method
509
+ # variable.
510
+ #
511
+ def to_var(id=nil,uniq_id=nil)
512
+ var = RuntimeMethodParameter.new(self.copy) {{:variable_id => id,:uniq_id=>uniq_id}}
513
+ # TODO This means that global variable_id is increamented when it doesn't need to be
514
+ var.variable_id = id unless id.nil?
515
+ return var
516
+ end
517
+
518
+ # Returns a history object reflecting how the runtime method
519
+ # is processed.
520
+ #
521
+ # @param params An array of realised variables
522
+ # @param additional_methods An array of add
523
+ #
524
+ def history(params,additional_methods=[])
525
+
526
+ # Check the number of parameters to method usage
527
+ raise StandardError.new('Incorrect number of parameters') unless params.length == @usage.length
528
+
529
+ # Create the method that changes are logged to
530
+ instance_tracking_variable = ArrayVariable.new
531
+ instance_tracking_variable.instance_variable = true
532
+ tracking_method = RuntimeTrackingMethod.new(instance_tracking_variable)
533
+
534
+ # Duplicate the current method and add tracking calls
535
+ copied = self.copy.trackify(params,tracking_method)
536
+
537
+ # Create a method to call the method and return the results
538
+ process_method = RuntimeMethod.new(MethodUsage.new,History.new)
539
+ track_statement = Statement.new( DefCall.new(NilVariable.new,copied,*params.collect {|x| x.value} ) )
540
+ process_method << track_statement
541
+ return_statement = Statement.new( Return.new,instance_tracking_variable )
542
+ process_method << return_statement
543
+
544
+ # Evaluate the method
545
+ # TODO This might need to have a number pre-fixed (I'm not certain it's overwritten)
546
+ # runtime_class = RuntimeClass.new('Temporary'+rand(1000).to_s,tracking_method,copied,process_method,*additional_methods)
547
+ runtime_class = RuntimeClass.new('Temporary',tracking_method,copied,process_method,*additional_methods)
548
+ result = ClassEvaluation.new.evaluate_class(runtime_class,process_method.method_name,self)
549
+ return result
550
+ end
551
+
552
+ # Proxy for the history method except it expects to receive an array of literals.
553
+ #
554
+ # TODO Probably best to change the real history method to use literals
555
+ #
556
+ def history2(params,additional_methods=[])
557
+
558
+ if(params.any? {|x| x.kind_of?(Variable)})
559
+ raise StandardError.new('Currently only literal values can be realised')
560
+ end
561
+
562
+ # TODO Is KnownVariable a better name than LiteralVariable
563
+ # Convert the passed paramters into literal variables with the appropriate ids
564
+ unless usage.length == params.length
565
+ raise StandardError.new('This method expects '+usage.length.to_s+' param(s) but '+params.length.to_s+' were passed')
566
+ end
567
+ realised_params = []
568
+ usage.zip(params).each do |x,y|
569
+ realised_params.push y.to_var(x.variable_id,x.uniq_id)
570
+ end
571
+
572
+ return history(realised_params,methods)
573
+ end
574
+
575
+ # Returns an updated method that includes a method call
576
+ # after each statement to monitor the usage of a runtime method.
577
+ #
578
+ # @param tracking_method A runtime tracking method instance that the track calls
579
+ # saved to.
580
+ #
581
+ def trackify(params,tracking_method)
582
+
583
+ # TODO Really need to give the tracking method parameter proper names - and get them in
584
+ # correct order.
585
+
586
+ # Identify what statements are overridden to inform what variables need tracked
587
+ identify_overriding_statements(params)
588
+
589
+ line = []
590
+ copied = copy_base
591
+ modified_params = params
592
+
593
+ # Start by adding the initial tracking call - to catch the parameters
594
+ # CONTINUE: tracking the statement_id
595
+ initial_tracking_statement = tracking_statement(
596
+ tracking_method,
597
+ line,
598
+ self.statement_id.to_literal,
599
+ abstract_variables_for_tracking(modified_params)
600
+ )
601
+ copied.push(initial_tracking_statement)
602
+
603
+ # TODO Currently I am collect all the variables in the variable container -be that
604
+ # a nested statement or a single statment. I don't know what variables I
605
+ # actually need to retain.
606
+
607
+ # Create an array to update the variable ids to suite the method usage
608
+ # TODO I'm not sure this is needed any more
609
+ id_conversion = Hash.new
610
+ @usage.zip(params) do |x,y|
611
+ new_var = y.copy
612
+ new_var.variable_id = x.variable_id
613
+ new_var.uniq_id = x.uniq_id
614
+ id_conversion[x.uniq_id.to_s.to_sym] = new_var
615
+ end
616
+
617
+ # Copy the runtime method and update each statement
618
+ copy.each_with_index do |x,i|
619
+ if x.kind_of?(Statement)
620
+
621
+ # Update the ids of the variables used in the statement to use the ids of the method usage
622
+ duplicated_statement = x.exchange_variables(id_conversion)
623
+ variable_values = abstract_variables_for_tracking(duplicated_statement)
624
+ copied.push(duplicated_statement)
625
+ copied.push(
626
+ tracking_statement(
627
+ tracking_method,
628
+ line,
629
+ duplicated_statement.statement_id,
630
+ variable_values,
631
+ duplicated_statement
632
+ )
633
+ )
634
+ # TODO I think this has to be a OpenStatement
635
+ elsif(x.kind_of?(StatementGroup))
636
+
637
+ # Retrieve tha variables available at the point before the nested statement opens
638
+ results = []
639
+ available_variable_at(params,line.length).each do |y|
640
+ # TODO I should change these to symbols
641
+ results.push(Hash['id'=>y.variable_id,'value'=>InstanceCallContainer.new(y,Copy.new)])
642
+ end
643
+
644
+ # Retrieve the nested statement and trackify it
645
+ trackifyied_nested_statement = x.trackify(
646
+ tracking_method,line
647
+ )
648
+ copied.push(trackifyied_nested_statement)
649
+
650
+ # Add the tracking call for after the statement (this has the id for the whole nested statement)
651
+
652
+ # Retrieve the variables used in the nested statement - excluding those no longer in scope
653
+ # TODO I should maybe only be concerned with the variables that change in the nested
654
+ # statement.
655
+ # containers = [x.opening_statement]+x.each
656
+
657
+ # Search through the nested statement for all the statements that override a variable
658
+ # TODO It really should be all the variables that are overridden and available
659
+ # outside the nested statement.
660
+ variable_values = abstract_variables_for_tracking(*x.find_overriding_statements)
661
+
662
+ # TODO The only variables recorded here are ones that overriden inside the nested statement
663
+ copied.push(
664
+ tracking_statement(
665
+ tracking_method,
666
+ line,
667
+ self.statement_id,
668
+ variable_values,
669
+ x
670
+ )
671
+ )
672
+
673
+ # TODO I think I'm going to give nested statements two ids - one outside
674
+ # one inside. I might use the internal statment id as one and the
675
+ # actual nested statement as the other.
676
+ else
677
+ raise StandardError.new('Unexpected class '+x.class.to_s)
678
+ end
679
+
680
+ end
681
+ return copied
682
+ end
683
+
684
+ # Rebuilds the method with TypeVariables that all have literal
685
+ # values.
686
+ #
687
+ # @param params A param container instance that contains the necessary parameters for the
688
+ # runtime method instance.
689
+ # @param params [UPDATE] This is being changed to except only an array of literal
690
+ # values e.g. 'tests', 9, <#SomeObject>. This will be converted into
691
+ # a literal variable within the method.
692
+ #
693
+ # @param additional_methods An array of any methods that are required by the runtime method instance
694
+ #
695
+ # TODO I expect "params" could probably be changed from a paramaters container to an
696
+ # array of literal values.
697
+ #
698
+ def realise2(params,additional_methods=[])
699
+
700
+ # TEMP
701
+ if(params.any? {|x| x.kind_of?(Variable)})
702
+ raise StandardError.new('Currently only literal values can be realised')
703
+ end
704
+
705
+ # TODO Is KnownVariable a better name than LiteralVariable
706
+ # Convert the passed paramters into literal variables with the appropriate ids
707
+ unless usage.length == params.length
708
+ raise StandardError.new('This method expects '+usage.length.to_s+' param(s) but '+params.length.to_s+' were passed')
709
+ end
710
+ realised_params = []
711
+ usage.zip(params).each do |x,y|
712
+ realised_params.push y.to_var(x.variable_id,x.uniq_id)
713
+ end
714
+
715
+ # Check that any required runtime methods were supplied
716
+ # TODO Given that I can retrieve all the runtime methods from the statements I probably shouldn't
717
+ # bother passing them in as parameters to the method.
718
+ find_all_required_runtime_methods.each do |x|
719
+ missing_method = lambda{raise StandardError.new('Missing method with id '+x.method_id.to_s)}
720
+ additional_methods.detect(missing_method) {|y| y.method_id == x.method_id}
721
+ end
722
+
723
+ # Retrieve a history object reflecting the use of the runtime method
724
+ past = history(realised_params,additional_methods)
725
+
726
+ # Create a realised method instance to return
727
+ realised_runtime_method = RealisedRuntimeMethod.new(realised_params)
728
+ realised_runtime_method.method_id = @method_id
729
+
730
+ # Go through each statement and substitue any of the variables
731
+ # for those in the history object
732
+ self.each do |x|
733
+ if x.realised?
734
+ realised_runtime_method.push(x)
735
+ next
736
+ end
737
+
738
+ # Handle nested and single statements differently
739
+ if(x.kind_of?(Statement))
740
+ realised_statement = x.realise2(past)
741
+ realised_runtime_method.push(realised_statement)
742
+ elsif(x.kind_of?(BlockStatement))
743
+
744
+ # TODO - TEMP DEBUG
745
+ instance_tracking_variable = ArrayVariable.new
746
+ instance_tracking_variable.instance_variable = true
747
+ tracking_method = RuntimeTrackingMethod.new(instance_tracking_variable)
748
+
749
+ #resulting_method.push(x.realise2(past))
750
+ realised_runtime_method.push(x.realise2(past))
751
+
752
+ # TODO I have just added this ---------------------08/02/2011 - I really need to go through the whole
753
+ # tracking thing.
754
+ elsif(x.kind_of?(OpenStatement))
755
+
756
+ # TODO - TEMP DEBUG
757
+ instance_tracking_variable = ArrayVariable.new
758
+ instance_tracking_variable.instance_variable = true
759
+ tracking_method = RuntimeTrackingMethod.new(instance_tracking_variable)
760
+
761
+ #resulting_method.push(x.realise2(past))
762
+ realised_runtime_method.push(x.realise2(past))
763
+
764
+ else
765
+ raise StandardError.new('Unexpected data type '+x.class.to_s)
766
+ end
767
+
768
+ end
769
+
770
+ realised_runtime_method.close
771
+ return realised_runtime_method
772
+
773
+ end
774
+
775
+ def cauldron_method_calls
776
+ return ['.all_pass?','.pass?','.history2','.last','.statement_id','.params','.realise2']
777
+ end
778
+
779
+ def to_intrinsic
780
+ return IntrinsicRuntimeMethod.new()
781
+ end
782
+
783
+ private
784
+
785
+ # # TODO Not sure this is needed
786
+ # This returns an array of variables and def_calls by replacing
787
+ # any supplied runtime_method instances with def_calls.
788
+ #
789
+ def convert_methods_to_def_calls(available)
790
+ updated_available = []
791
+ available.each do |x|
792
+ if(x.kind_of?(RuntimeMethod))
793
+
794
+ # Create a copy of available values (removing the call for this method)
795
+ copied_available = available.collect! {|x| x.copy}
796
+
797
+ # Separate the variables from the runtime method
798
+ copied_avialable_vars = copied_available.find_all {|y| y.kind_of?(Variable)}
799
+
800
+ # Separate the runtime method calls from the variables excluding the current method
801
+ copied_avialable_methods = copied_available.find_all {|y| y.kind_of?(RuntimeMethod)}
802
+ copied_avialable_methods.delete_if {|y| y.method_id == x.method_id }
803
+
804
+ # Combine the two so that the method used is excluded to prevent recursive calls
805
+ safe_copied_available = copied_avialable_methods+copied_avialable_vars
806
+
807
+ # Convert any runtime method instances to def_call instances
808
+ updated_available += x.callable_combinations(safe_copied_available)
809
+
810
+ else
811
+ updated_available.push(x)
812
+ end
813
+ end
814
+ return updated_available
815
+ end
816
+
817
+ end