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,60 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class Builder
|
4
|
+
|
5
|
+
attr_reader :composite
|
6
|
+
|
7
|
+
def initialize(composite)
|
8
|
+
@composite = composite
|
9
|
+
end
|
10
|
+
|
11
|
+
def tree
|
12
|
+
root_node = Tree::TreeNode.new("ROOT", "Root Content")
|
13
|
+
line_count = 0
|
14
|
+
composite.operators.each do |x|
|
15
|
+
child_node = Tree::TreeNode.new('CHILD-'+line_count.to_s)
|
16
|
+
root_node << child_node
|
17
|
+
line_count += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# NOTE: returns an array of new actualized composites extending the current composite
|
22
|
+
def insertable_operators(examples)
|
23
|
+
actualized_composite = ActualizedComposite.new(composite.clone_solution, examples)
|
24
|
+
h = actualized_composite.histories
|
25
|
+
results = self.class.available_statement_types.inject([]) do |total,x|
|
26
|
+
total += x.instances(h, composite, examples, h.insert_points)
|
27
|
+
total
|
28
|
+
end
|
29
|
+
#binding.pry
|
30
|
+
results
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.available_statement_types
|
34
|
+
|
35
|
+
# CURRENT
|
36
|
+
# StatementGenerator.new.build(
|
37
|
+
# ['A','B', 'AC'],
|
38
|
+
# [:collect]
|
39
|
+
# )+Cauldron::StatementGenerator.new.build('string',[:chop])
|
40
|
+
|
41
|
+
# TRYING
|
42
|
+
# StatementGenerator.new.build(
|
43
|
+
# ['A','B', 'AC'],
|
44
|
+
# [:collect]
|
45
|
+
# )+Cauldron::StatementGenerator.new.build('string',[:chop])+[Cauldron::ArrayCollectTemplate::Template]
|
46
|
+
[StatementGenerator.new.build_template(
|
47
|
+
['A','B', 'AC'],
|
48
|
+
:collect
|
49
|
+
).statement_classes.first]+[Cauldron::StatementGenerator.new.build_template('string',:chop).statement_classes.first]+[Cauldron::ArrayCollectTemplate::Template]+[Cauldron::NumberAdditionTemplate::Template]
|
50
|
+
|
51
|
+
# TODO Not very effient to regenerate the opperators
|
52
|
+
# StatementGenerator.new.build(
|
53
|
+
# ['A','B', 'AC'],
|
54
|
+
# [:collect]
|
55
|
+
# )+Cauldron::StatementGenerator.new.build('string',[:chop])+[ArrayReverseOperator]+[StatementGenerator.new.build(3,[:+])]
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class Caret
|
4
|
+
|
5
|
+
#attr_reader :line, :depth, :total_line
|
6
|
+
attr_reader :total_lines, :current_depth
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@total_lines, @current_depth = 0, 0 #,@line = 0, 0, 0
|
10
|
+
@lines = { 0 => 0}
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO This approach will need re-worked to support nesting - in and out
|
14
|
+
def add_line(depth)
|
15
|
+
unless @lines.has_key?(depth)
|
16
|
+
@lines[depth] = 0
|
17
|
+
end
|
18
|
+
|
19
|
+
@total_lines += 1
|
20
|
+
if @current_depth != depth
|
21
|
+
@current_depth = depth
|
22
|
+
else
|
23
|
+
@lines[depth] += 1
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
def point
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
def line
|
33
|
+
@lines[@current_depth]
|
34
|
+
end
|
35
|
+
|
36
|
+
def step_in
|
37
|
+
@current_depth += 1
|
38
|
+
unless @lines.has_key?(@current_depth)
|
39
|
+
@lines[@current_depth] = 0
|
40
|
+
end
|
41
|
+
#@line = 0
|
42
|
+
end
|
43
|
+
|
44
|
+
def return_depth(depth)
|
45
|
+
@current_depth = depth
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class DynamicOperator
|
4
|
+
|
5
|
+
include Cauldron::Operator
|
6
|
+
|
7
|
+
attr_reader :indexes
|
8
|
+
attr_accessor :failed_uses
|
9
|
+
|
10
|
+
def initialize(information, sexp_methods)
|
11
|
+
@information, @sexp_methods = information, sexp_methods
|
12
|
+
@failed_uses = []
|
13
|
+
@closed = false
|
14
|
+
end
|
15
|
+
|
16
|
+
def uses_constants?
|
17
|
+
@information[:constants]
|
18
|
+
end
|
19
|
+
|
20
|
+
def indexes=(value)
|
21
|
+
raise StandardError.new('') if @closed
|
22
|
+
@indexes = value
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@closed = true
|
27
|
+
end
|
28
|
+
|
29
|
+
def extend_actualized_composite(x, container, examples, point)
|
30
|
+
cloned_container = container.clone_solution
|
31
|
+
cloned_container.add_statement_at(x, point)
|
32
|
+
cloned_container
|
33
|
+
Cauldron::ActualizedComposite.new(cloned_container, examples)
|
34
|
+
end
|
35
|
+
|
36
|
+
def context_realizable?(context)
|
37
|
+
|
38
|
+
vars = context.keys.select {|x| x.match(/var\d/) }
|
39
|
+
var_names = vars.collect(&:to_s)
|
40
|
+
|
41
|
+
a = %Q{
|
42
|
+
def function(var0)
|
43
|
+
#{Sorcerer.source(to_sexp(Cauldron::Scope.new(var_names), []), indent: true)}
|
44
|
+
end
|
45
|
+
}
|
46
|
+
|
47
|
+
o = Object.new
|
48
|
+
o.instance_eval(a)
|
49
|
+
|
50
|
+
begin
|
51
|
+
o.function(vars.collect {|x| context[x] })
|
52
|
+
rescue NoMethodError => e
|
53
|
+
return false
|
54
|
+
rescue StandardError => e
|
55
|
+
puts e
|
56
|
+
end
|
57
|
+
return true
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def write_to_file(filename)
|
62
|
+
FileUtils.mkdir_p File.join('tmp')
|
63
|
+
File.open( File.join('tmp',filename), 'w+') do |file|
|
64
|
+
file << "class DynamicOperator"+"\n"
|
65
|
+
file << Sorcerer.source(@sexp_methods, indent: true)
|
66
|
+
file << "\n"
|
67
|
+
file << "end"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def rip2
|
72
|
+
%Q{
|
73
|
+
def function(var0)
|
74
|
+
#{Sorcerer.source(to_sexp(Cauldron::Scope.new(['var0'])), indent: true)}
|
75
|
+
end
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def rip(composite,examples)
|
80
|
+
Ripper::SexpBuilder.new(
|
81
|
+
%Q{
|
82
|
+
def function(var0)
|
83
|
+
#{composite.to_ruby(examples.scope)}
|
84
|
+
end
|
85
|
+
}).parse
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
module DynamicOperatorModule
|
4
|
+
|
5
|
+
def uses_constants?
|
6
|
+
@information[:constants]
|
7
|
+
end
|
8
|
+
|
9
|
+
def indexes=(value)
|
10
|
+
raise StandardError.new('') if @closed
|
11
|
+
@indexes = value
|
12
|
+
end
|
13
|
+
|
14
|
+
def close
|
15
|
+
@closed = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def clone_statement
|
19
|
+
# TODO Need to clone the sexp methods
|
20
|
+
# o = DynamicOperator.new(@information, @sexp_methods)
|
21
|
+
# o.instance_eval(Sorcerer.source(@sexp_methods, indent: true))
|
22
|
+
# o
|
23
|
+
self.class.new(@indexes.clone)
|
24
|
+
end
|
25
|
+
|
26
|
+
# def context_instances(contexts)
|
27
|
+
# results = []
|
28
|
+
# contexts.each do |context|
|
29
|
+
# results << context.keys.collect(&:to_s).select {|x| x.match(/var\d/) }
|
30
|
+
# end
|
31
|
+
# results = results.flatten.uniq
|
32
|
+
# variable_numbers = results.collect { |x| x.match(/var(\d+)/)[1] }
|
33
|
+
# variable_numbers.collect { |x| init([x.to_i])}
|
34
|
+
# end
|
35
|
+
|
36
|
+
# def extend_actualized_composite(x, container, examples, point)
|
37
|
+
# cloned_container = container.clone_solution
|
38
|
+
# cloned_container.add_statement_at(x, point)
|
39
|
+
# cloned_container
|
40
|
+
# Cauldron::ActualizedComposite.new(cloned_container, examples)
|
41
|
+
# end
|
42
|
+
|
43
|
+
def context_realizable?(context)
|
44
|
+
|
45
|
+
vars = context.keys.select {|x| x.match(/var\d/) }
|
46
|
+
var_names = vars.collect(&:to_s)
|
47
|
+
|
48
|
+
first_variable = 'var'+@indexes[0].to_s
|
49
|
+
|
50
|
+
# a = %Q{
|
51
|
+
# def function(var0)
|
52
|
+
# #{Sorcerer.source(to_sexp(var_names), indent: true)}
|
53
|
+
# end
|
54
|
+
# }
|
55
|
+
# a = %Q{
|
56
|
+
# def function(var0)
|
57
|
+
# #{Sorcerer.source(to_sexp(Cauldron::Scope.new(var_names), []), indent: true)}
|
58
|
+
# end
|
59
|
+
# }
|
60
|
+
a = %Q{
|
61
|
+
def function(#{first_variable})
|
62
|
+
#{Sorcerer.source(to_sexp(Cauldron::Scope.new(var_names), []), indent: true)}
|
63
|
+
end
|
64
|
+
}
|
65
|
+
|
66
|
+
o = Object.new
|
67
|
+
o.instance_eval(a)
|
68
|
+
|
69
|
+
begin
|
70
|
+
#o.function(*vars.collect {|x| context[x] })
|
71
|
+
o.function context[first_variable.to_sym]
|
72
|
+
rescue NoMethodError => e
|
73
|
+
return false
|
74
|
+
rescue StandardError => e
|
75
|
+
puts e
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
return true
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
#o.function(*params.values)
|
83
|
+
|
84
|
+
# a = %Q{
|
85
|
+
# def function(var0)
|
86
|
+
# #{Sorcerer.source(to_sexp(Cauldron::Scope.new(['var0'])), indent: true)}
|
87
|
+
# end
|
88
|
+
# }
|
89
|
+
end
|
90
|
+
|
91
|
+
def write_to_file(filename)
|
92
|
+
File.open( File.join('tmp',filename), 'w+') do |file|
|
93
|
+
file << "class DynamicOperator"+"\n"
|
94
|
+
file << Sorcerer.source(@sexp_methods, indent: true)
|
95
|
+
file << "\n"
|
96
|
+
file << "end"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def rip(composite,examples)
|
101
|
+
Ripper::SexpBuilder.new(
|
102
|
+
%Q{
|
103
|
+
def function(var0)
|
104
|
+
#{composite.to_ruby(examples.scope)}
|
105
|
+
end
|
106
|
+
}).parse
|
107
|
+
end
|
108
|
+
|
109
|
+
# def to_tracking_sexp(operators, scope, caret)
|
110
|
+
# raise StandardError.new('statement has been instance closed') unless @closed
|
111
|
+
# to_sexp(scope)
|
112
|
+
# end
|
113
|
+
|
114
|
+
def realizable?(histories, point)
|
115
|
+
parameters = histories.variable_permutations(@indexes.length)
|
116
|
+
parameters.each do |params|
|
117
|
+
begin
|
118
|
+
realize(params)
|
119
|
+
rescue => e
|
120
|
+
puts e
|
121
|
+
failed_uses.push(histories)
|
122
|
+
return false
|
123
|
+
end
|
124
|
+
end
|
125
|
+
true
|
126
|
+
rescue => e
|
127
|
+
puts e
|
128
|
+
puts e.backtrace
|
129
|
+
# TODO GENERATE RSPEC TEST with arguments
|
130
|
+
end
|
131
|
+
|
132
|
+
def realize(params)
|
133
|
+
o = Object.new
|
134
|
+
o.instance_eval(rip2)
|
135
|
+
o.function(*params.values)
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class Example
|
4
|
+
|
5
|
+
attr_reader :arguments, :response
|
6
|
+
|
7
|
+
def initialize(hash)
|
8
|
+
@arguments, @response = hash[:arguments], hash[:response]
|
9
|
+
@arguments.freeze
|
10
|
+
end
|
11
|
+
|
12
|
+
def params
|
13
|
+
(0...@arguments.length).collect {|x| 'var'+x.to_s}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class ExampleSet
|
4
|
+
|
5
|
+
attr_reader :examples
|
6
|
+
|
7
|
+
def initialize(examples)
|
8
|
+
@examples = examples
|
9
|
+
end
|
10
|
+
|
11
|
+
def variables
|
12
|
+
args = examples.first.arguments
|
13
|
+
(0...args.length).collect {|x| 'var'+x.to_s}
|
14
|
+
end
|
15
|
+
|
16
|
+
def all?(&block)
|
17
|
+
examples.all?(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def collect(&block)
|
21
|
+
examples.collect(&block)
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO Might drop - limit access
|
25
|
+
def each_with_index(&block)
|
26
|
+
examples.each_with_index(&block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def scope
|
30
|
+
sexp = Ripper::SexpBuilder.new(examples.first.params.to_s).parse
|
31
|
+
Cauldron::Scope.new(eval(Sorcerer.source(sexp)))
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class Histories
|
4
|
+
|
5
|
+
def initialize(results)
|
6
|
+
@results = results
|
7
|
+
end
|
8
|
+
|
9
|
+
def variable_permutations(count)
|
10
|
+
variables = @results.first.logs.first.keys.select { |x| x.match /var/ }
|
11
|
+
v = Hash[*variables.collect {|x| [x,nil]}.flatten]
|
12
|
+
|
13
|
+
@results.collect do |history|
|
14
|
+
history.logs.collect do |a|
|
15
|
+
Hash[*v.keys.collect do |x|
|
16
|
+
[x, a[x] ]
|
17
|
+
end.flatten(1)]
|
18
|
+
end
|
19
|
+
end.flatten
|
20
|
+
end
|
21
|
+
|
22
|
+
def each(&block)
|
23
|
+
@results.each(&block)
|
24
|
+
end
|
25
|
+
|
26
|
+
def first
|
27
|
+
@results.first
|
28
|
+
end
|
29
|
+
|
30
|
+
def length
|
31
|
+
@results.length
|
32
|
+
end
|
33
|
+
|
34
|
+
def insert_points
|
35
|
+
@results.inject([]) { |total, x| total += x.insert_points; total }.uniq
|
36
|
+
end
|
37
|
+
|
38
|
+
def contexts_at(point)
|
39
|
+
a = []
|
40
|
+
@results.each do |history|
|
41
|
+
a += history.logs.inject([]) do |total,log|
|
42
|
+
if log[:point] == point
|
43
|
+
total << log
|
44
|
+
end
|
45
|
+
total
|
46
|
+
end
|
47
|
+
end
|
48
|
+
a
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|