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
|