cauldron 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|