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