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.
Files changed (89) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -1
  3. data/.rspec +1 -0
  4. data/Gemfile +16 -9
  5. data/Gemfile.lock +134 -64
  6. data/README.md +26 -0
  7. data/Rakefile +24 -99
  8. data/build_sandbox.rb +41 -0
  9. data/cucumber.yml +8 -0
  10. data/features/chop.feature +23 -0
  11. data/features/create_dynamic_statements.feature +14 -0
  12. data/features/generate_known_solution.feature +42 -0
  13. data/features/generate_new_statement.feature +20 -0
  14. data/features/step_definitions/cauldron_steps.rb +47 -0
  15. data/features/support/env.rb +1 -1
  16. data/features/use_existing_statements.feature +23 -0
  17. data/lib/cauldron.rb +41 -5
  18. data/lib/cauldron/actualized_composite.rb +35 -0
  19. data/lib/cauldron/array_collect_template/default.rb +95 -0
  20. data/lib/cauldron/array_collect_template/template.rb +57 -0
  21. data/lib/cauldron/builder.rb +60 -0
  22. data/lib/cauldron/caret.rb +50 -0
  23. data/lib/cauldron/dynamic_operator.rb +90 -0
  24. data/lib/cauldron/dynamic_operator_module.rb +140 -0
  25. data/lib/cauldron/example.rb +18 -0
  26. data/lib/cauldron/example_set.rb +36 -0
  27. data/lib/cauldron/histories.rb +53 -0
  28. data/lib/cauldron/history.rb +34 -0
  29. data/lib/cauldron/if_relationship.rb +4 -6
  30. data/lib/cauldron/number_addition_template/add_five.rb +71 -0
  31. data/lib/cauldron/number_addition_template/template.rb +56 -0
  32. data/lib/cauldron/operator.rb +62 -0
  33. data/lib/cauldron/operator/array_reverse_operator.rb +160 -0
  34. data/lib/cauldron/operator/concat_operator.rb +72 -0
  35. data/lib/cauldron/operator/hash_key_value_operator.rb +74 -0
  36. data/lib/cauldron/operator/numeric_operator.rb +115 -0
  37. data/lib/cauldron/operator/string_asterisk_operator.rb +131 -0
  38. data/lib/cauldron/operator/to_s_operator.rb +18 -0
  39. data/lib/cauldron/operator/var_collect_operator.rb +29 -0
  40. data/lib/cauldron/pot.rb +136 -26
  41. data/lib/cauldron/scope.rb +24 -0
  42. data/lib/cauldron/solution/composite.rb +236 -0
  43. data/lib/cauldron/solution/one.rb +49 -0
  44. data/lib/cauldron/statement_generator.rb +298 -0
  45. data/lib/cauldron/template_base.rb +14 -0
  46. data/lib/cauldron/tracer.rb +55 -0
  47. data/lib/cauldron/version.rb +1 -1
  48. data/lib/pry_tester.rb +76 -0
  49. data/ruby_to_sexp.rb +74 -0
  50. data/sandbox.rb +7 -0
  51. data/sexp_to_ruby.rb +150 -0
  52. data/spec/cauldron/actualized_composite_spec.rb +140 -0
  53. data/spec/cauldron/array_collect_template/default_spec.rb +41 -0
  54. data/spec/cauldron/builder_spec.rb +186 -0
  55. data/spec/cauldron/dynamic/add_number_template_spec.rb +30 -0
  56. data/spec/cauldron/dynamic_operator_spec.rb +416 -0
  57. data/spec/cauldron/example_set_spec.rb +49 -0
  58. data/spec/cauldron/example_spec.rb +33 -0
  59. data/spec/cauldron/histories_spec.rb +135 -0
  60. data/spec/cauldron/history_spec.rb +118 -0
  61. data/spec/cauldron/if_relationship_spec.rb +1 -1
  62. data/spec/cauldron/operator/array_reverse_operator_spec.rb +73 -0
  63. data/spec/cauldron/{concat_operator_spec.rb → operator/concat_operator_spec.rb} +30 -12
  64. data/spec/cauldron/operator/hash_key_value_operator_spec.rb +98 -0
  65. data/spec/cauldron/operator/numeric_operator_spec.rb +110 -0
  66. data/spec/cauldron/operator/string_asterisk_operator_spec.rb +196 -0
  67. data/spec/cauldron/operator/var_collect_operator_spec.rb +38 -0
  68. data/spec/cauldron/pot_spec.rb +176 -14
  69. data/spec/cauldron/solution/composite_spec.rb +421 -0
  70. data/spec/cauldron/solution/one_spec.rb +24 -0
  71. data/spec/cauldron/statement_generator_spec.rb +211 -0
  72. data/spec/cauldron/terminal_spec.rb +2 -2
  73. data/spec/spec_helper.rb +5 -1
  74. data/spec/support/code_matcher.rb +55 -0
  75. data/spec/support/include_instance_of_matcher.rb +9 -0
  76. data/spec/support/shared_examples_for_leaf_operators.rb +22 -0
  77. data/spec/support/shared_examples_for_operators.rb +23 -0
  78. data/syntax_spec.txt +2 -0
  79. metadata +104 -41
  80. data/README +0 -1
  81. data/README.rdoc +0 -19
  82. data/VERSION +0 -1
  83. data/features/cauldron_new_approach.feature +0 -46
  84. data/lib/cauldron/array_reverse_operator.rb +0 -39
  85. data/lib/cauldron/concat_operator.rb +0 -34
  86. data/lib/cauldron/numeric_operator.rb +0 -45
  87. data/lib/cauldron/relationship.rb +0 -5
  88. data/spec/cauldron/array_reverse_operator_spec.rb +0 -59
  89. 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 < Relationship
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[:arguments][0])+"\n"
17
- result += ' return '+quote(x[:response])+"\n"
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