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