cauldron 0.1.5 → 0.1.6
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.
- checksums.yaml +7 -0
- data/.gitignore +4 -1
- data/.rspec +1 -0
- data/Gemfile +16 -9
- data/Gemfile.lock +134 -64
- data/README.md +26 -0
- data/Rakefile +24 -99
- data/build_sandbox.rb +41 -0
- data/cucumber.yml +8 -0
- data/features/chop.feature +23 -0
- data/features/create_dynamic_statements.feature +14 -0
- data/features/generate_known_solution.feature +42 -0
- data/features/generate_new_statement.feature +20 -0
- data/features/step_definitions/cauldron_steps.rb +47 -0
- data/features/support/env.rb +1 -1
- data/features/use_existing_statements.feature +23 -0
- data/lib/cauldron.rb +41 -5
- data/lib/cauldron/actualized_composite.rb +35 -0
- data/lib/cauldron/array_collect_template/default.rb +95 -0
- data/lib/cauldron/array_collect_template/template.rb +57 -0
- data/lib/cauldron/builder.rb +60 -0
- data/lib/cauldron/caret.rb +50 -0
- data/lib/cauldron/dynamic_operator.rb +90 -0
- data/lib/cauldron/dynamic_operator_module.rb +140 -0
- data/lib/cauldron/example.rb +18 -0
- data/lib/cauldron/example_set.rb +36 -0
- data/lib/cauldron/histories.rb +53 -0
- data/lib/cauldron/history.rb +34 -0
- data/lib/cauldron/if_relationship.rb +4 -6
- data/lib/cauldron/number_addition_template/add_five.rb +71 -0
- data/lib/cauldron/number_addition_template/template.rb +56 -0
- data/lib/cauldron/operator.rb +62 -0
- data/lib/cauldron/operator/array_reverse_operator.rb +160 -0
- data/lib/cauldron/operator/concat_operator.rb +72 -0
- data/lib/cauldron/operator/hash_key_value_operator.rb +74 -0
- data/lib/cauldron/operator/numeric_operator.rb +115 -0
- data/lib/cauldron/operator/string_asterisk_operator.rb +131 -0
- data/lib/cauldron/operator/to_s_operator.rb +18 -0
- data/lib/cauldron/operator/var_collect_operator.rb +29 -0
- data/lib/cauldron/pot.rb +136 -26
- data/lib/cauldron/scope.rb +24 -0
- data/lib/cauldron/solution/composite.rb +236 -0
- data/lib/cauldron/solution/one.rb +49 -0
- data/lib/cauldron/statement_generator.rb +298 -0
- data/lib/cauldron/template_base.rb +14 -0
- data/lib/cauldron/tracer.rb +55 -0
- data/lib/cauldron/version.rb +1 -1
- data/lib/pry_tester.rb +76 -0
- data/ruby_to_sexp.rb +74 -0
- data/sandbox.rb +7 -0
- data/sexp_to_ruby.rb +150 -0
- data/spec/cauldron/actualized_composite_spec.rb +140 -0
- data/spec/cauldron/array_collect_template/default_spec.rb +41 -0
- data/spec/cauldron/builder_spec.rb +186 -0
- data/spec/cauldron/dynamic/add_number_template_spec.rb +30 -0
- data/spec/cauldron/dynamic_operator_spec.rb +416 -0
- data/spec/cauldron/example_set_spec.rb +49 -0
- data/spec/cauldron/example_spec.rb +33 -0
- data/spec/cauldron/histories_spec.rb +135 -0
- data/spec/cauldron/history_spec.rb +118 -0
- data/spec/cauldron/if_relationship_spec.rb +1 -1
- data/spec/cauldron/operator/array_reverse_operator_spec.rb +73 -0
- data/spec/cauldron/{concat_operator_spec.rb → operator/concat_operator_spec.rb} +30 -12
- data/spec/cauldron/operator/hash_key_value_operator_spec.rb +98 -0
- data/spec/cauldron/operator/numeric_operator_spec.rb +110 -0
- data/spec/cauldron/operator/string_asterisk_operator_spec.rb +196 -0
- data/spec/cauldron/operator/var_collect_operator_spec.rb +38 -0
- data/spec/cauldron/pot_spec.rb +176 -14
- data/spec/cauldron/solution/composite_spec.rb +421 -0
- data/spec/cauldron/solution/one_spec.rb +24 -0
- data/spec/cauldron/statement_generator_spec.rb +211 -0
- data/spec/cauldron/terminal_spec.rb +2 -2
- data/spec/spec_helper.rb +5 -1
- data/spec/support/code_matcher.rb +55 -0
- data/spec/support/include_instance_of_matcher.rb +9 -0
- data/spec/support/shared_examples_for_leaf_operators.rb +22 -0
- data/spec/support/shared_examples_for_operators.rb +23 -0
- data/syntax_spec.txt +2 -0
- metadata +104 -41
- data/README +0 -1
- data/README.rdoc +0 -19
- data/VERSION +0 -1
- data/features/cauldron_new_approach.feature +0 -46
- data/lib/cauldron/array_reverse_operator.rb +0 -39
- data/lib/cauldron/concat_operator.rb +0 -34
- data/lib/cauldron/numeric_operator.rb +0 -45
- data/lib/cauldron/relationship.rb +0 -5
- data/spec/cauldron/array_reverse_operator_spec.rb +0 -59
- data/spec/cauldron/numeric_operator_spec.rb +0 -70
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module Cauldron
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              class History
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                attr_reader :logs
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                def initialize(logs)
         | 
| 8 | 
            +
                  @logs = logs
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def variables
         | 
| 12 | 
            +
                  results = []
         | 
| 13 | 
            +
                  @logs.select do |line|
         | 
| 14 | 
            +
                    results += line.keys.select {|x| x.match(/var*/) }
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                  results
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def values(variable_name)
         | 
| 20 | 
            +
                  @logs.inject([]) do |total,line|
         | 
| 21 | 
            +
                    if line.has_key?(variable_name)
         | 
| 22 | 
            +
                      total << line[variable_name]
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                    total
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def insert_points
         | 
| 29 | 
            +
                  logs.collect {|x| x[:point] }.uniq
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            end
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            class IfRelationship  | 
| 1 | 
            +
            class IfRelationship #< Relationship
         | 
| 2 2 |  | 
| 3 3 | 
             
              # TODO Need to change to IfSolution probably
         | 
| 4 4 |  | 
| @@ -6,15 +6,13 @@ class IfRelationship < Relationship | |
| 6 6 | 
             
                @problems = problems
         | 
| 7 7 | 
             
              end
         | 
| 8 8 |  | 
| 9 | 
            -
              def to_ruby
         | 
| 9 | 
            +
              def to_ruby(variables)
         | 
| 10 10 |  | 
| 11 11 | 
             
                # Add the arguments
         | 
| 12 | 
            -
                args = @problems.first[:arguments]
         | 
| 13 | 
            -
                variables = (0...args.length).collect {|x| 'var'+x.to_s}
         | 
| 14 12 | 
             
                result = ''
         | 
| 15 13 | 
             
                @problems.each_with_index do |x,i|
         | 
| 16 | 
            -
                  result += '  if '+variables[0].to_s+' == '+quote(x | 
| 17 | 
            -
                  result += '    return '+quote(x | 
| 14 | 
            +
                  result += '  if '+variables[0].to_s+' == '+quote(x.arguments[0])+"\n"
         | 
| 15 | 
            +
                  result += '    return '+quote(x.response)+"\n"
         | 
| 18 16 | 
             
                  result += '  end'+"\n"
         | 
| 19 17 | 
             
                end    
         | 
| 20 18 | 
             
                result
         | 
| @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            module Cauldron
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module NumberAdditionTemplate
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                class AddFive
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  attr_reader :indexes
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  def initialize(indexes)
         | 
| 10 | 
            +
                    @indexes = indexes
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  def context_realizable?(context)
         | 
| 14 | 
            +
                    
         | 
| 15 | 
            +
                    vars = context.keys.select {|x| x.match(/var\d/) }
         | 
| 16 | 
            +
                    var_names = vars.collect(&:to_s)
         | 
| 17 | 
            +
                    
         | 
| 18 | 
            +
                    first_variable = 'var'+@indexes[0].to_s
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    a = %Q{
         | 
| 21 | 
            +
                    def function(#{first_variable})
         | 
| 22 | 
            +
                      #{Sorcerer.source(to_sexp(Cauldron::Scope.new(var_names), []), indent: true)}
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                    }     
         | 
| 25 | 
            +
                    
         | 
| 26 | 
            +
                    o = Object.new
         | 
| 27 | 
            +
                    o.instance_eval(a)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                    begin
         | 
| 30 | 
            +
                      #o.function(*vars.collect {|x| context[x] })  
         | 
| 31 | 
            +
                      o.function context[first_variable.to_sym]
         | 
| 32 | 
            +
                    rescue NoMethodError => e
         | 
| 33 | 
            +
                      return false
         | 
| 34 | 
            +
                    rescue StandardError => e
         | 
| 35 | 
            +
                      puts e
         | 
| 36 | 
            +
                      return false
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                    return true
         | 
| 39 | 
            +
               
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  def to_sexp(scope, children)
         | 
| 43 | 
            +
                    first_variable = 'var'+@indexes[0].to_s
         | 
| 44 | 
            +
                    #binding.pry
         | 
| 45 | 
            +
                    #'var0 + 5'
         | 
| 46 | 
            +
                    #''
         | 
| 47 | 
            +
                    puts %Q{#{first_variable} + 5}
         | 
| 48 | 
            +
                    Ripper::SexpBuilder.new(%Q{#{first_variable} + 5}).parse
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def clone_statement
         | 
| 52 | 
            +
                    # TODO Need to clone the sexp methods
         | 
| 53 | 
            +
                    # o = DynamicOperator.new(@information, @sexp_methods)
         | 
| 54 | 
            +
                    # o.instance_eval(Sorcerer.source(@sexp_methods, indent: true))
         | 
| 55 | 
            +
                    # o
         | 
| 56 | 
            +
                    self.class.new(@indexes.clone)
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  def to_ruby(scope, operators)
         | 
| 60 | 
            +
                    Sorcerer.source to_sexp(scope, operators)
         | 
| 61 | 
            +
                  end  
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  def branch?
         | 
| 64 | 
            +
                    false
         | 
| 65 | 
            +
                  end              
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            module Cauldron
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module NumberAdditionTemplate
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                class Template < Cauldron::TemplateBase
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def self.instances(histories, composite, examples, insert_points)
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    # TEMP
         | 
| 10 | 
            +
                    unless examples.class == ExampleSet
         | 
| 11 | 
            +
                      raise StandardError.new('Examples should be an example')
         | 
| 12 | 
            +
                    end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    # Print out each insertable statements
         | 
| 15 | 
            +
                    scope = examples.scope
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    # self.init([0]).to_ruby(scope)
         | 
| 18 | 
            +
                    # - this will print out "var0.chop"
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    # Get the variables available at each point
         | 
| 21 | 
            +
                    results = []
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    insert_points.each do |point|
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      # Find the variables at a particular point
         | 
| 26 | 
            +
                      # TODO Change to test
         | 
| 27 | 
            +
                      contexts = histories.contexts_at(point)
         | 
| 28 | 
            +
                      composites = context_instances(contexts)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                      composites.each do |x|
         | 
| 31 | 
            +
                        if contexts.all? { |context| x.context_realizable?(context) }
         | 
| 32 | 
            +
                          results << extend_actualized_composite(x, composite, examples, point)
         | 
| 33 | 
            +
                        end
         | 
| 34 | 
            +
                        #results << extend_actualized_composite(x, composite, examples, point)
         | 
| 35 | 
            +
                      end
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    results
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def self.context_instances(contexts)
         | 
| 42 | 
            +
                    temp = []
         | 
| 43 | 
            +
                    contexts.each do |context|
         | 
| 44 | 
            +
                      temp << context.keys.collect(&:to_s).select {|x| x.match(/var\d/) }
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                    results = temp.flatten.uniq
         | 
| 47 | 
            +
                    
         | 
| 48 | 
            +
                    variable_numbers = results.collect { |x| x.match(/var(\d+)/)[1] }
         | 
| 49 | 
            +
                    variable_numbers.collect { |x| Cauldron::NumberAdditionTemplate::AddFive.new([x.to_i])}
         | 
| 50 | 
            +
                  end      
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            module Cauldron
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module Operator   
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                def self.included(base)
         | 
| 6 | 
            +
                  base.extend ClassMethods
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                module ClassMethods
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def instances(histories, composite, examples, insert_points)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    # TEMP
         | 
| 14 | 
            +
                    unless examples.class == ExampleSet
         | 
| 15 | 
            +
                      raise StandardError.new('Examples should be an example')
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    # Print out each insertable statements
         | 
| 19 | 
            +
                    scope = examples.scope
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                    # self.init([0]).to_ruby(scope)
         | 
| 22 | 
            +
                    # - this will print out "var0.chop"
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    # Get the variables available at each point
         | 
| 25 | 
            +
                    results = []
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    insert_points.each do |point|
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      # Find the variables at a particular point
         | 
| 30 | 
            +
                      # TODO Change to test
         | 
| 31 | 
            +
                      contexts = histories.contexts_at(point)
         | 
| 32 | 
            +
                      composites = context_instances(contexts)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                      composites.each do |x|
         | 
| 35 | 
            +
                        if contexts.all? do |context|
         | 
| 36 | 
            +
                          x.context_realizable?(context)
         | 
| 37 | 
            +
                        end
         | 
| 38 | 
            +
                        results << extend_actualized_composite(x, composite, examples, point)
         | 
| 39 | 
            +
                      end
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                    end
         | 
| 43 | 
            +
                    
         | 
| 44 | 
            +
                    results
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  def context_instances(contexts)
         | 
| 48 | 
            +
                    temp = []
         | 
| 49 | 
            +
                    contexts.each do |context|
         | 
| 50 | 
            +
                      temp << context.keys.collect(&:to_s).select {|x| x.match(/var\d/) }
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    results = temp.flatten.uniq
         | 
| 53 | 
            +
                    
         | 
| 54 | 
            +
                    variable_numbers = results.collect { |x| x.match(/var(\d+)/)[1] }
         | 
| 55 | 
            +
                    variable_numbers.collect { |x| new([x.to_i])}
         | 
| 56 | 
            +
                  end      
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            end
         | 
| @@ -0,0 +1,160 @@ | |
| 1 | 
            +
            class ArrayReverseOperator
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              def initialize(indexes)
         | 
| 4 | 
            +
                raise StandardError.new('Need at least one item') if indexes.empty?
         | 
| 5 | 
            +
                @indexes = indexes
         | 
| 6 | 
            +
              end  
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              # Matching in 
         | 
| 9 | 
            +
              def successful?(problem)
         | 
| 10 | 
            +
                # NOTE - for the future - like the idea of not actually calling the method
         | 
| 11 | 
            +
                # input.length.each do |i|
         | 
| 12 | 
            +
                # does input[0] == output[input.length-0]
         | 
| 13 | 
            +
                # does input[1] == output[input.length-1]
         | 
| 14 | 
            +
                # does input[3] == output[input.length-3]
         | 
| 15 | 
            +
                # end
         | 
| 16 | 
            +
                
         | 
| 17 | 
            +
                # in this case x.reverse will work
         | 
| 18 | 
            +
                return true if problem[:arguments].first.reverse == problem[:response]
         | 
| 19 | 
            +
                false
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              # 1. Only has one argument value
         | 
| 23 | 
            +
              # 2. Argument is an array value
         | 
| 24 | 
            +
              # 3. Response is an array 
         | 
| 25 | 
            +
              def self.viable?(arguments,output)
         | 
| 26 | 
            +
                return false unless arguments.length == 1
         | 
| 27 | 
            +
                return false unless arguments.all? { |x| x.kind_of?(Array) }
         | 
| 28 | 
            +
                return false unless output.kind_of?(Array)
         | 
| 29 | 
            +
                true
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              def self.uses_constants?
         | 
| 33 | 
            +
                false
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              def self.find_constants(problems)
         | 
| 37 | 
            +
                []
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              def self.uses_block?
         | 
| 41 | 
            +
                false
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              def self.process(arguments)
         | 
| 45 | 
            +
                arguments.collect {|x| x.reverse }
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              def to_ruby(operators, scope)
         | 
| 49 | 
            +
                Sorcerer.source build(operators, scope)
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              def build(operators, scope)
         | 
| 53 | 
            +
                to_sexp(operators, scope)
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              def to_sexp(scope, operators)
         | 
| 57 | 
            +
                [:call, 
         | 
| 58 | 
            +
                  [:vcall, 
         | 
| 59 | 
            +
                    [:@ident, scope[@indexes[0]] ]
         | 
| 60 | 
            +
                  ], 
         | 
| 61 | 
            +
                  :".", 
         | 
| 62 | 
            +
                  [:@ident, "reverse"]
         | 
| 63 | 
            +
                ]    
         | 
| 64 | 
            +
              end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              def branch?
         | 
| 67 | 
            +
                false
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              def self.init(indexes)
         | 
| 71 | 
            +
                self.new(indexes)
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              def self.instances(histories, composite, examples, insert_points)
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                # TEMP
         | 
| 77 | 
            +
                unless examples.class == Cauldron::ExampleSet
         | 
| 78 | 
            +
                  raise StandardError.new('Examples should be an example')
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                # Print out each insertable statements
         | 
| 82 | 
            +
                scope = examples.scope
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                # self.init([0]).to_ruby(scope)
         | 
| 85 | 
            +
                # - this will print out "var0.chop"
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                # Get the variables available at each point
         | 
| 88 | 
            +
                results = []
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                insert_points.each do |point|
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  # Find the variables at a particular point
         | 
| 93 | 
            +
                  # TODO Change to test
         | 
| 94 | 
            +
                  contexts = histories.contexts_at(point)
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  composites = context_instances(contexts)
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  # scopes = scopes_at_point(point)
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  composites.each do |x|
         | 
| 101 | 
            +
                    if contexts.all? do |context|
         | 
| 102 | 
            +
                      x.context_realizable?(context)
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
                      
         | 
| 105 | 
            +
                    results << extend_actualized_composite(x, composite, examples, point)
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                end
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
                
         | 
| 111 | 
            +
                results
         | 
| 112 | 
            +
              end  
         | 
| 113 | 
            +
             | 
| 114 | 
            +
              def self.extend_actualized_composite(x, container, examples, point)
         | 
| 115 | 
            +
                cloned_container = container.clone_solution
         | 
| 116 | 
            +
                cloned_container.add_statement_at(x, point)
         | 
| 117 | 
            +
                cloned_container
         | 
| 118 | 
            +
                Cauldron::ActualizedComposite.new(cloned_container, examples)
         | 
| 119 | 
            +
              end  
         | 
| 120 | 
            +
             | 
| 121 | 
            +
              def clone_statement
         | 
| 122 | 
            +
                self.class.init(@indexes.clone)
         | 
| 123 | 
            +
              end  
         | 
| 124 | 
            +
             | 
| 125 | 
            +
              def context_realizable?(context)
         | 
| 126 | 
            +
                
         | 
| 127 | 
            +
                vars = context.keys.select {|x| x.match(/var\d/) }
         | 
| 128 | 
            +
                var_names = vars.collect(&:to_s)
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                a = %Q{
         | 
| 131 | 
            +
                def function(var0)
         | 
| 132 | 
            +
                  #{Sorcerer.source(to_sexp(Cauldron::Scope.new(var_names), []), indent: true)}
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
                }       
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                o = Object.new
         | 
| 137 | 
            +
                o.instance_eval(a)
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                begin
         | 
| 140 | 
            +
                  o.function(vars.collect {|x| context[x] })  
         | 
| 141 | 
            +
                rescue NoMethodError => e
         | 
| 142 | 
            +
                  return false
         | 
| 143 | 
            +
                rescue StandardError => e
         | 
| 144 | 
            +
                  puts e
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
                return true
         | 
| 147 | 
            +
                
         | 
| 148 | 
            +
              end  
         | 
| 149 | 
            +
             | 
| 150 | 
            +
              def self.context_instances(contexts)
         | 
| 151 | 
            +
                results = []
         | 
| 152 | 
            +
                contexts.each do |context|
         | 
| 153 | 
            +
                  results << context.keys.collect(&:to_s).select {|x| x.match(/var\d/) }
         | 
| 154 | 
            +
                end
         | 
| 155 | 
            +
                results = results.flatten.uniq
         | 
| 156 | 
            +
                variable_numbers = results.collect { |x| x.match(/var(\d+)/)[1] }
         | 
| 157 | 
            +
                variable_numbers.collect { |x| init([x.to_i])}
         | 
| 158 | 
            +
              end  
         | 
| 159 | 
            +
             | 
| 160 | 
            +
            end
         | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            class ConcatOperator
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              include Cauldron::Operator
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              def initialize(indexes)
         | 
| 6 | 
            +
                @indexes = indexes
         | 
| 7 | 
            +
                @constant = 'bar'
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def self.viable?(arguments, response)
         | 
| 11 | 
            +
                return false unless arguments.all? { |x| x.kind_of?(String) }
         | 
| 12 | 
            +
                return false unless response.kind_of?(String)
         | 
| 13 | 
            +
                # TODO - Only accpets one argument
         | 
| 14 | 
            +
                true
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def self.find_constants(problems)
         | 
| 18 | 
            +
                problems.examples.inject([]) do |total, x| 
         | 
| 19 | 
            +
                  result = x.response.gsub( Regexp.new('^'+x.arguments.first),'')
         | 
| 20 | 
            +
                  total << result unless result == x.response
         | 
| 21 | 
            +
                  total
         | 
| 22 | 
            +
                end.uniq
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              def self.uses_constants?
         | 
| 26 | 
            +
                true
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              def self.uses_block?
         | 
| 30 | 
            +
                false
         | 
| 31 | 
            +
              end  
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              def branch?
         | 
| 34 | 
            +
                false
         | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              # Operator for "x.concat("bar")"
         | 
| 38 | 
            +
              def successful?(problem)
         | 
| 39 | 
            +
                if (problem[:arguments].first + @constant) == problem[:response]
         | 
| 40 | 
            +
                  return true
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
                return false
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def to_ruby(scope, operators)
         | 
| 46 | 
            +
                Sorcerer.source self.to_sexp(scope, operators)
         | 
| 47 | 
            +
              end  
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def build(operators, scope)
         | 
| 50 | 
            +
                to_sexp(scope)
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              def to_sexp(scope, operators)
         | 
| 54 | 
            +
                first_variable = 'var'+@indexes[0].to_s
         | 
| 55 | 
            +
                [:program,
         | 
| 56 | 
            +
                 [:stmts_add,
         | 
| 57 | 
            +
                  [:stmts_new],
         | 
| 58 | 
            +
                  [:method_add_arg,
         | 
| 59 | 
            +
                   [:call,
         | 
| 60 | 
            +
                    [:vcall, [:@ident, first_variable ]],
         | 
| 61 | 
            +
                    :".",
         | 
| 62 | 
            +
                    [:@ident, "concat"]],
         | 
| 63 | 
            +
                   [:arg_paren,
         | 
| 64 | 
            +
                    [:args_add_block,
         | 
| 65 | 
            +
                     [:args_add,
         | 
| 66 | 
            +
                      [:args_new],
         | 
| 67 | 
            +
                      [:string_literal,
         | 
| 68 | 
            +
                       [:string_add, [:string_content], [:@tstring_content, @constant]]]],
         | 
| 69 | 
            +
                     false]]]]]
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            end
         |