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.
- data/.document +5 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +20 -0
- data/README +1 -0
- data/README.rdoc +19 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/bin/cauldron +10 -0
- data/cauldron/.autotest +23 -0
- data/cauldron/History.txt +6 -0
- data/cauldron/Manifest.txt +8 -0
- data/cauldron/README.txt +57 -0
- data/cauldron/Rakefile +27 -0
- data/cauldron/bin/cauldron +3 -0
- data/cauldron/lib/cauldron.rb +3 -0
- data/cauldron/test/test_cauldron.rb +8 -0
- data/features/cauldron_example_cases.feature +13 -0
- data/features/cauldron_generates_runtime_method.feature +12 -0
- data/features/cauldron_start_terminal.feature +13 -0
- data/features/step_definitions/cauldron_steps.rb +16 -0
- data/features/step_definitions/terminal_steps.rb +34 -0
- data/features/support/env.rb +19 -0
- data/lib/Chain.rb +879 -0
- data/lib/ChainMapping.rb +172 -0
- data/lib/CodeHandler.rb +517 -0
- data/lib/Mapping.rb +26 -0
- data/lib/MappingValues.rb +24 -0
- data/lib/ScopeDependencies.rb +7 -0
- data/lib/Theory.rb +274 -0
- data/lib/UnifiedChain.rb +110 -0
- data/lib/cauldron.rb +6 -0
- data/lib/cauldron/conversion.rb +15 -0
- data/lib/cauldron/pot.rb +134 -0
- data/lib/cauldron/sexp2cauldron.rb +156 -0
- data/lib/cauldron/terminal.rb +120 -0
- data/lib/cauldron/theory_factory.rb +10 -0
- data/lib/core/ActsAsCode.rb +25 -0
- data/lib/core/BlockToken.rb +33 -0
- data/lib/core/CCall.rb +7 -0
- data/lib/core/CTestCase.rb +27 -0
- data/lib/core/ClassMethodCallContainer.rb +45 -0
- data/lib/core/Container.rb +85 -0
- data/lib/core/InstanceCallContainer.rb +272 -0
- data/lib/core/MethodUsage.rb +66 -0
- data/lib/core/PrintVariables.rb +25 -0
- data/lib/core/TheoryGenerator.rb +764 -0
- data/lib/core/Token.rb +7 -0
- data/lib/core/assignment/Assignment.rb +18 -0
- data/lib/core/assignment/Equal.rb +39 -0
- data/lib/core/assignment/Equivalent.rb +20 -0
- data/lib/core/assignment/NotEqual.rb +14 -0
- data/lib/core/call_container/CallContainer.rb +66 -0
- data/lib/core/class_method_call/New.rb +15 -0
- data/lib/core/class_method_call/RuntimeClassMethodCall.rb +31 -0
- data/lib/core/declaration/Declaration.rb +16 -0
- data/lib/core/declaration/LiteralDeclaration.rb +47 -0
- data/lib/core/declaration/VariableDeclaration.rb +59 -0
- data/lib/core/instance_call/ArrayEach.rb +23 -0
- data/lib/core/instance_call/ArrayLength.rb +15 -0
- data/lib/core/instance_call/Chop.rb +28 -0
- data/lib/core/instance_call/Copy.rb +22 -0
- data/lib/core/instance_call/DeclaredVariable.rb +18 -0
- data/lib/core/instance_call/InstanceCall.rb +77 -0
- data/lib/core/instance_call/Params.rb +15 -0
- data/lib/core/instance_call/Push.rb +20 -0
- data/lib/core/instance_call/StringLength.rb +32 -0
- data/lib/core/instance_call/Times.rb +20 -0
- data/lib/core/instance_call/instance_calls.rb +168 -0
- data/lib/core/instance_call/length_equal.rb +15 -0
- data/lib/core/kernal/EvalCall.rb +15 -0
- data/lib/core/kernal/LocalVariablesCall.rb +15 -0
- data/lib/core/literal/Literal.rb +111 -0
- data/lib/core/literal/Raw.rb +23 -0
- data/lib/core/literal/RuntimeMethodLiteral.rb +21 -0
- data/lib/core/literal/StatementLiteral.rb +28 -0
- data/lib/core/method_call/AvailableVariablesCall.rb +25 -0
- data/lib/core/method_call/ClassCall.rb +33 -0
- data/lib/core/method_call/DefCall.rb +72 -0
- data/lib/core/method_call/EvaluateClassCall.rb +29 -0
- data/lib/core/method_call/MethodNameCall.rb +27 -0
- data/lib/core/method_call/ToDeclarationCall.rb +15 -0
- data/lib/core/requirement/Requirement.rb +291 -0
- data/lib/core/runtime_class/ArrayClass.rb +19 -0
- data/lib/core/runtime_class/ClassCallClass.rb +23 -0
- data/lib/core/runtime_class/ClassEvaluationClass.rb +19 -0
- data/lib/core/runtime_class/ClassName.rb +18 -0
- data/lib/core/runtime_class/DefCallClass.rb +21 -0
- data/lib/core/runtime_class/EqualClass.rb +19 -0
- data/lib/core/runtime_class/FixnumClass.rb +15 -0
- data/lib/core/runtime_class/IfStatementClass.rb +12 -0
- data/lib/core/runtime_class/InstanceCallClass.rb +19 -0
- data/lib/core/runtime_class/InstanceCallContainerClass.rb +16 -0
- data/lib/core/runtime_class/InstanceClassCallClass.rb +19 -0
- data/lib/core/runtime_class/LiteralClass.rb +19 -0
- data/lib/core/runtime_class/MethodParameterClass.rb +27 -0
- data/lib/core/runtime_class/MethodUsageClass.rb +27 -0
- data/lib/core/runtime_class/RequirementClass.rb +19 -0
- data/lib/core/runtime_class/ReturnClass.rb +21 -0
- data/lib/core/runtime_class/RuntimeClass.rb +30 -0
- data/lib/core/runtime_class/RuntimeClassClass.rb +19 -0
- data/lib/core/runtime_class/RuntimeMethodClass.rb +34 -0
- data/lib/core/runtime_class/StatementClass.rb +53 -0
- data/lib/core/runtime_class/StringClass.rb +23 -0
- data/lib/core/runtime_class/StringLengthClass.rb +19 -0
- data/lib/core/runtime_class/StringVariableClass.rb +19 -0
- data/lib/core/runtime_class/ThisClass.rb +15 -0
- data/lib/core/runtime_class/UnknownClass.rb +23 -0
- data/lib/core/runtime_class/class_names.rb +95 -0
- data/lib/core/runtime_class/runtime_class.rb +123 -0
- data/lib/core/runtime_method/ActsAsRuntimeMethod.rb +300 -0
- data/lib/core/runtime_method/ParametersContainer.rb +29 -0
- data/lib/core/runtime_method/RealisedRuntimeMethod.rb +94 -0
- data/lib/core/runtime_method/RuntimeMethod.rb +817 -0
- data/lib/core/runtime_method/WriteParameters.rb +35 -0
- data/lib/core/statement/ActsAsStatement.rb +116 -0
- data/lib/core/statement/ArrayAccess.rb +96 -0
- data/lib/core/statement/BlockStatement.rb +348 -0
- data/lib/core/statement/DeclarationStatement.rb +19 -0
- data/lib/core/statement/HackStatement.rb +25 -0
- data/lib/core/statement/HashAccess.rb +18 -0
- data/lib/core/statement/OpenStatement.rb +171 -0
- data/lib/core/statement/RealisedStatement.rb +5 -0
- data/lib/core/statement/SingleLineBlockStatement.rb +39 -0
- data/lib/core/statement/Statement.rb +1223 -0
- data/lib/core/statement/StatementDependencies.rb +271 -0
- data/lib/core/statement/StatementGroup.rb +157 -0
- data/lib/core/statement/StatementStructure2.rb +224 -0
- data/lib/core/statement/TheoryStatement.rb +60 -0
- data/lib/core/statement/TopologicalStatements.rb +34 -0
- data/lib/core/structure/DeclareNewInstanceStructure.rb +49 -0
- data/lib/core/structure/DeclareRuntimeMethodStructure.rb +34 -0
- data/lib/core/structure/DeclareVariableAsLiteralStructure.rb +31 -0
- data/lib/core/structure/DeclareVariableAsVariableStructure.rb +52 -0
- data/lib/core/structure/FixnumAdditionStructure.rb +56 -0
- data/lib/core/structure/InstanceCallContainerStructure.rb +50 -0
- data/lib/core/structure/InstanceCallStructure.rb +53 -0
- data/lib/core/structure/InstanceMethodCallStructure.rb +21 -0
- data/lib/core/structure/ReturnStructure.rb +20 -0
- data/lib/core/structure/StatementStructure.rb +11 -0
- data/lib/core/syntax/Addition.rb +25 -0
- data/lib/core/syntax/BlockContainer.rb +130 -0
- data/lib/core/syntax/Boolean.rb +15 -0
- data/lib/core/syntax/Code.rb +11 -0
- data/lib/core/syntax/Do.rb +20 -0
- data/lib/core/syntax/False.rb +12 -0
- data/lib/core/syntax/If.rb +28 -0
- data/lib/core/syntax/IfContainer.rb +100 -0
- data/lib/core/syntax/Nil.rb +15 -0
- data/lib/core/syntax/Return.rb +33 -0
- data/lib/core/syntax/Subtract.rb +19 -0
- data/lib/core/syntax/This.rb +40 -0
- data/lib/core/syntax/True.rb +20 -0
- data/lib/core/syntax/syntax.rb +24 -0
- data/lib/core/tracking/ActsAsTrackable.rb +65 -0
- data/lib/core/tracking/History.rb +167 -0
- data/lib/core/tracking/RuntimeTrackingMethod.rb +32 -0
- data/lib/core/tracking/Step.rb +52 -0
- data/lib/core/variable/ArrayVariable.rb +76 -0
- data/lib/core/variable/BaseVariable.rb +154 -0
- data/lib/core/variable/BlockVariable.rb +92 -0
- data/lib/core/variable/FixnumVariable.rb +36 -0
- data/lib/core/variable/HistoryVariable.rb +8 -0
- data/lib/core/variable/MethodParameter.rb +206 -0
- data/lib/core/variable/MethodUsageVariable.rb +60 -0
- data/lib/core/variable/NilVariable.rb +29 -0
- data/lib/core/variable/RuntimeMethodParameter.rb +67 -0
- data/lib/core/variable/StatementVariable.rb +72 -0
- data/lib/core/variable/StepVariable.rb +7 -0
- data/lib/core/variable/StringVariable.rb +46 -0
- data/lib/core/variable/TypeVariable.rb +72 -0
- data/lib/core/variable/Unknown.rb +116 -0
- data/lib/core/variable/UnknownVariable.rb +29 -0
- data/lib/core/variable/Variable.rb +70 -0
- data/lib/core/variable/VariableContainer.rb +28 -0
- data/lib/core/variable/VariableIncluded.rb +27 -0
- data/lib/core/variable/VariableReference.rb +85 -0
- data/lib/error/FailedToFindStatementContainerError.rb +7 -0
- data/lib/error/FailedToFindStatementError.rb +7 -0
- data/lib/error/FailedToFindVariableError.rb +7 -0
- data/lib/error/FailedToLiteraliseError.rb +7 -0
- data/lib/error/FailedVariableMatch.rb +7 -0
- data/lib/error/ImproperStatementUsageError.rb +7 -0
- data/lib/error/IncompatiableRequirementsError.rb +7 -0
- data/lib/error/InvalidStatementError.rb +7 -0
- data/lib/error/MethodSizeError.rb +7 -0
- data/lib/error/RuntimeSyntaxError.rb +7 -0
- data/lib/error/UnexpectedStatementTypeError.rb +7 -0
- data/lib/error/UnknownStatementType.rb +7 -0
- data/lib/error/UnliteralisableError.rb +7 -0
- data/lib/implemented_chain.rb +34 -0
- data/lib/intrinsic/IntrinsicLastRuntimeMethod.rb +20 -0
- data/lib/intrinsic/IntrinsicLiteral.rb +26 -0
- data/lib/intrinsic/IntrinsicObject.rb +22 -0
- data/lib/intrinsic/IntrinsicRuntimeMethod.rb +27 -0
- data/lib/intrinsic/IntrinsicTestCases.rb +17 -0
- data/lib/logger/StandardLogger.rb +62 -0
- data/lib/required.rb +236 -0
- data/lib/ruby_code/Array.rb +95 -0
- data/lib/ruby_code/Fixnum.rb +39 -0
- data/lib/ruby_code/Hash.rb +25 -0
- data/lib/ruby_code/NilClass.rb +19 -0
- data/lib/ruby_code/Object.rb +24 -0
- data/lib/ruby_code/String.rb +86 -0
- data/lib/ruby_code/Symbol.rb +7 -0
- data/lib/standard_library/Tasks.rb +12 -0
- data/lib/theories.rb +143 -0
- data/lib/theory/ActionImplementation.rb +17 -0
- data/lib/theory/TheoryAction.rb +70 -0
- data/lib/theory/TheoryChainValidator.rb +101 -0
- data/lib/theory/TheoryComponent.rb +42 -0
- data/lib/theory/TheoryConnector.rb +755 -0
- data/lib/theory/TheoryDependent.rb +135 -0
- data/lib/theory/TheoryImplementation.rb +74 -0
- data/lib/theory/TheoryResult.rb +131 -0
- data/lib/theory/TheoryVariable.rb +63 -0
- data/lib/theory/theory_collection.rb +62 -0
- data/lib/util/ClassEvaluation.rb +68 -0
- data/lib/util/CodeEvaluation.rb +35 -0
- data/lib/util/DeclarationStatementEvaluation.rb +31 -0
- data/lib/util/MethodEvaluation.rb +49 -0
- data/lib/util/MethodTester.rb +71 -0
- data/lib/util/MethodValidation.rb +145 -0
- data/lib/util/MethodWriter.rb +66 -0
- data/lib/util/Parser.rb +299 -0
- data/lib/util/StatementCheck.rb +42 -0
- data/lib/util/StringToTheory.rb +119 -0
- data/lib/util/System.rb +8 -0
- data/spec/cauldron/pot_spec.rb +6 -0
- data/spec/cauldron/runtime_method_spec.rb +36 -0
- data/spec/cauldron/sexp_2_cauldron_spec.rb +26 -0
- data/spec/cauldron/terminal_spec.rb +38 -0
- data/spec/cauldron/theory_action_spec.rb +5 -0
- data/spec/spec_helper.rb +4 -0
- data/test/fixtures/chains/1/declaration.txt +26 -0
- data/test/fixtures/chains/1/dump +0 -0
- data/test/fixtures/chains/2/declaration.txt +26 -0
- data/test/fixtures/chains/2/dump +0 -0
- data/test/fixtures/chains/3/declaration.txt +26 -0
- data/test/fixtures/chains/3/dump +0 -0
- data/test/fixtures/implementation_results/0/declaration.txt +3 -0
- data/test/fixtures/implementation_results/0/dump +0 -0
- data/test/fixtures/theories/0/declaration.txt +9 -0
- data/test/fixtures/theories/0/desc +10 -0
- data/test/fixtures/theories/0/dump +0 -0
- data/test/fixtures/theories/1/declaration.txt +15 -0
- data/test/fixtures/theories/1/desc +11 -0
- data/test/fixtures/theories/1/dump +0 -0
- data/test/fixtures/theories/10/declaration.txt +23 -0
- data/test/fixtures/theories/10/desc +17 -0
- data/test/fixtures/theories/10/dump +0 -0
- data/test/fixtures/theories/11/declaration.txt +20 -0
- data/test/fixtures/theories/11/desc +14 -0
- data/test/fixtures/theories/11/dump +0 -0
- data/test/fixtures/theories/12/declaration.txt +18 -0
- data/test/fixtures/theories/12/desc +12 -0
- data/test/fixtures/theories/12/dump +0 -0
- data/test/fixtures/theories/13/declaration.txt +24 -0
- data/test/fixtures/theories/13/desc +20 -0
- data/test/fixtures/theories/13/dump +0 -0
- data/test/fixtures/theories/14/declaration.txt +26 -0
- data/test/fixtures/theories/14/desc +20 -0
- data/test/fixtures/theories/14/dump +0 -0
- data/test/fixtures/theories/15/declaration.txt +20 -0
- data/test/fixtures/theories/15/desc +14 -0
- data/test/fixtures/theories/15/dump +0 -0
- data/test/fixtures/theories/16/declaration.txt +30 -0
- data/test/fixtures/theories/16/desc +14 -0
- data/test/fixtures/theories/16/dump +0 -0
- data/test/fixtures/theories/17/declaration.txt +25 -0
- data/test/fixtures/theories/17/desc +11 -0
- data/test/fixtures/theories/17/dump +0 -0
- data/test/fixtures/theories/18/declaration.txt +23 -0
- data/test/fixtures/theories/18/desc +11 -0
- data/test/fixtures/theories/18/dump +0 -0
- data/test/fixtures/theories/19/declaration.txt +23 -0
- data/test/fixtures/theories/19/desc +11 -0
- data/test/fixtures/theories/19/dump +0 -0
- data/test/fixtures/theories/2/declaration.txt +12 -0
- data/test/fixtures/theories/2/desc +10 -0
- data/test/fixtures/theories/2/dump +0 -0
- data/test/fixtures/theories/20/declaration.txt +23 -0
- data/test/fixtures/theories/20/desc +17 -0
- data/test/fixtures/theories/20/dump +0 -0
- data/test/fixtures/theories/3/declaration.txt +19 -0
- data/test/fixtures/theories/3/desc +11 -0
- data/test/fixtures/theories/3/dump +0 -0
- data/test/fixtures/theories/4/declaration.txt +11 -0
- data/test/fixtures/theories/4/desc +11 -0
- data/test/fixtures/theories/4/dump +0 -0
- data/test/fixtures/theories/5/declaration.txt +6 -0
- data/test/fixtures/theories/5/desc +9 -0
- data/test/fixtures/theories/5/dump +0 -0
- data/test/fixtures/theories/6/declaration.txt +13 -0
- data/test/fixtures/theories/6/desc +11 -0
- data/test/fixtures/theories/6/dump +0 -0
- data/test/fixtures/theories/7/declaration.txt +19 -0
- data/test/fixtures/theories/7/desc +11 -0
- data/test/fixtures/theories/7/dump +0 -0
- data/test/fixtures/theories/8/declaration.txt +21 -0
- data/test/fixtures/theories/8/desc +11 -0
- data/test/fixtures/theories/8/dump +0 -0
- data/test/fixtures/theories/9/declaration.txt +24 -0
- data/test/fixtures/theories/9/desc +20 -0
- data/test/fixtures/theories/9/dump +0 -0
- data/test/fixtures/theory_implementations/0/declaration.txt +11 -0
- data/test/fixtures/theory_implementations/0/desc.txt +9 -0
- data/test/fixtures/theory_implementations/0/dump +0 -0
- data/test/fixtures/theory_implementations/0/theory_id +1 -0
- data/test/fixtures/theory_implementations/1/desc.txt +9 -0
- data/test/fixtures/theory_implementations/1/dump +0 -0
- data/test/fixtures/theory_implementations/1/theory_id +1 -0
- data/test/fixtures/theory_implementations/2/desc.txt +9 -0
- data/test/fixtures/theory_implementations/2/dump +0 -0
- data/test/fixtures/theory_implementations/2/theory_id +1 -0
- data/test/output/simple_method.txt +6 -0
- data/test/output/test_method/first_possible_method.txt +6 -0
- data/test/output/test_simple_cases/simple_case_01.txt +8 -0
- data/test/output/test_simple_cases/simple_case_02.txt +7 -0
- data/test/output/test_simple_cases/simple_case_03.txt +8 -0
- data/test/output/test_simple_cases/simple_case_04.txt +8 -0
- data/test/output/test_simple_cases/simple_case_05.txt +8 -0
- data/test/output/test_simple_cases/simple_case_06.txt +9 -0
- data/test/output/test_simple_cases/simple_case_07.txt +9 -0
- data/test/output/test_simple_cases/simple_case_08.txt +9 -0
- data/test/tc_contextual_variables.rb +87 -0
- data/test/tc_describe.rb +47 -0
- data/test/tc_method.rb +133 -0
- data/test/tc_requirement.rb +30 -0
- data/test/tc_suite_complete.rb +26 -0
- data/test/tc_variable.rb +52 -0
- data/test/ts_complete.rb +84 -0
- data/test/ts_stable.rb +81 -0
- data/test/unit/core/declaration/tc_literal_declaration.rb +34 -0
- data/test/unit/core/method_call/tc_class_call.rb +20 -0
- data/test/unit/core/runtime_method/tc_realised_runtime_method.rb +129 -0
- data/test/unit/core/runtime_method/tc_runtime_method.rb +616 -0
- data/test/unit/core/statement/tc_array_access.rb +63 -0
- data/test/unit/core/statement/tc_block_statement.rb +51 -0
- data/test/unit/core/statement/tc_hack_statement.rb +26 -0
- data/test/unit/core/statement/tc_open_statement.rb +70 -0
- data/test/unit/core/statement/tc_statement.rb +681 -0
- data/test/unit/core/statement/tc_statement_dependencies.rb +146 -0
- data/test/unit/core/statement/tc_statement_group.rb +35 -0
- data/test/unit/core/statement/tc_statement_replace_variable.rb +61 -0
- data/test/unit/core/statement/tc_theory_statement.rb +51 -0
- data/test/unit/core/structure/tc_declare_new_instance_structure.rb +41 -0
- data/test/unit/core/structure/tc_declare_variable_as_literal_structure.rb +41 -0
- data/test/unit/core/structure/tc_declare_variable_as_variable_structure.rb +66 -0
- data/test/unit/core/structure/tc_instance_call_container_structure.rb +41 -0
- data/test/unit/core/structure/tc_return_structure.rb +32 -0
- data/test/unit/core/syntax/tc_block_container.rb +32 -0
- data/test/unit/core/syntax/tc_if_container.rb +39 -0
- data/test/unit/core/tc_class_method_call.rb +34 -0
- data/test/unit/core/tc_container.rb +41 -0
- data/test/unit/core/tc_ctest_case.rb +25 -0
- data/test/unit/core/tc_instance_call_container.rb +93 -0
- data/test/unit/core/tc_literal.rb +30 -0
- data/test/unit/core/tc_theory_generator.rb +336 -0
- data/test/unit/core/tc_theory_generator_heavy.rb +42 -0
- data/test/unit/core/tracking/tc_history.rb +102 -0
- data/test/unit/core/tracking/tc_step.rb +65 -0
- data/test/unit/core/variable/tc_array_variable.rb +61 -0
- data/test/unit/core/variable/tc_block_variable.rb +17 -0
- data/test/unit/core/variable/tc_fixnum_variable.rb +54 -0
- data/test/unit/core/variable/tc_method_parameter_variable.rb +22 -0
- data/test/unit/core/variable/tc_runtime_method_variable.rb +32 -0
- data/test/unit/core/variable/tc_string_variable.rb +37 -0
- data/test/unit/core/variable/tc_unknown.rb +24 -0
- data/test/unit/core/variable/tc_variable_reference.rb +28 -0
- data/test/unit/ruby_code/tc_array.rb +64 -0
- data/test/unit/ruby_code/tc_fixnum.rb +18 -0
- data/test/unit/ruby_code/tc_hash.rb +41 -0
- data/test/unit/ruby_code/tc_string.rb +38 -0
- data/test/unit/tc_chain.rb +434 -0
- data/test/unit/tc_chain_mapping.rb +62 -0
- data/test/unit/tc_chain_with_case_1.rb +169 -0
- data/test/unit/tc_instance_call.rb +40 -0
- data/test/unit/tc_instance_call_structure.rb +35 -0
- data/test/unit/tc_method_usage.rb +35 -0
- data/test/unit/tc_pot.rb +124 -0
- data/test/unit/tc_runtime_tracking_method.rb +40 -0
- data/test/unit/tc_statement_structure_2.rb +43 -0
- data/test/unit/tc_theory.rb +533 -0
- data/test/unit/tc_variable_declaration.rb +32 -0
- data/test/unit/theory/tc_theory_action.rb +80 -0
- data/test/unit/theory/tc_theory_action_implementation.rb +23 -0
- data/test/unit/theory/tc_theory_chain_validator.rb +340 -0
- data/test/unit/theory/tc_theory_connector.rb +396 -0
- data/test/unit/theory/tc_theory_dependent.rb +151 -0
- data/test/unit/theory/tc_theory_implementation.rb +133 -0
- data/test/unit/theory/tc_theory_result.rb +111 -0
- data/test/unit/theory/tc_theory_variable.rb +45 -0
- data/test/unit/util/tc_method_validation.rb +98 -0
- data/test/unit/util/tc_parser.rb +108 -0
- data/test/unit/util/tc_string_to_theory.rb +299 -0
- data/test/unit/variable/tc_method_usage_variable.rb +25 -0
- data/tmp/runtime_method_evaluation.rb +10 -0
- 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
|