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,24 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class Scope
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_reader :variables
|
7
|
+
|
8
|
+
def initialize(variables)
|
9
|
+
@variables = variables
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_variable!
|
13
|
+
#@variables << "var#{variables.length+1}"
|
14
|
+
@variables << "var#{variables.length}"
|
15
|
+
@variables.last
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](index)
|
19
|
+
variables[index]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
module Cauldron::Solution
|
2
|
+
|
3
|
+
class Composite
|
4
|
+
|
5
|
+
attr_reader :operators
|
6
|
+
|
7
|
+
def initialize(children)
|
8
|
+
raise StandardError.new('inital value should be an array') unless children.kind_of?(Array)
|
9
|
+
@operators = children
|
10
|
+
end
|
11
|
+
|
12
|
+
def record(example)
|
13
|
+
# TODO params passed twice - and example not used at all
|
14
|
+
insert_tracking(example.params).process(example)
|
15
|
+
end
|
16
|
+
|
17
|
+
def end_points
|
18
|
+
results = []
|
19
|
+
operators.each do |x|
|
20
|
+
if x.content.branch?
|
21
|
+
results << [0,x.children.length]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
results << [operators.length]
|
25
|
+
end
|
26
|
+
|
27
|
+
def clone_solution
|
28
|
+
#self.clone
|
29
|
+
tree_operators = operators.collect do |node|
|
30
|
+
Tree::TreeNode.new('x', node.content.clone_statement)
|
31
|
+
end
|
32
|
+
Composite.new(tree_operators)
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_statement_at(statement, point)
|
36
|
+
if point.length == 2
|
37
|
+
container = self.operators[0]
|
38
|
+
#return self if container.length > 1 # TODO: Quick hack to get it working
|
39
|
+
container << Tree::TreeNode.new('SASA', statement)
|
40
|
+
elsif point.length == 1
|
41
|
+
operators << Tree::TreeNode.new('SASA', statement)
|
42
|
+
else
|
43
|
+
raise StandardError.new('Have not written code: '+point.inspect)
|
44
|
+
end
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
def insert_tracking(params)
|
49
|
+
scope = Cauldron::Scope.new(params.clone)
|
50
|
+
|
51
|
+
# TODO Might be useful
|
52
|
+
# trace = TracePoint.new(:call) do |tp|
|
53
|
+
# p [tp.lineno, tp.event, tp.raised_exception]
|
54
|
+
# end
|
55
|
+
|
56
|
+
|
57
|
+
# NEW: Implementation
|
58
|
+
m = %Q{
|
59
|
+
def function(#{params.join(',')})
|
60
|
+
#{to_ruby(Cauldron::Scope.new(params.clone))}
|
61
|
+
end
|
62
|
+
}
|
63
|
+
|
64
|
+
sexp = Ripper::SexpBuilder.new(m).parse
|
65
|
+
rendered_code = Sorcerer.source(sexp, indent: true)
|
66
|
+
caret = Cauldron::Caret.new
|
67
|
+
|
68
|
+
rendered_code = Sorcerer.source(sexp, indent: true).gsub(/end/,"\nend").split("\n").reject(&:empty?).join("\n")
|
69
|
+
|
70
|
+
# Generate tracking code with pending substitutions
|
71
|
+
tracked_code = []
|
72
|
+
rendered_code.each_line do |line|
|
73
|
+
#if line.match /end\s+/
|
74
|
+
if line.match /end/
|
75
|
+
tracked_code << Sorcerer.source(Ripper::SexpBuilder.new(Cauldron::Tracer.substitue_tracking).parse) #Sorcerer.source(Cauldron::Tracer.substitue_tracking)
|
76
|
+
end
|
77
|
+
tracked_code << line
|
78
|
+
end
|
79
|
+
sexp = Ripper::SexpBuilder.new(tracked_code.join("\n")).parse
|
80
|
+
code_tracking = Sorcerer.source(sexp, indent: true)
|
81
|
+
code_tracking.split("\n")
|
82
|
+
|
83
|
+
current_line = -1
|
84
|
+
total_lines = 0
|
85
|
+
new_tracked_code = []
|
86
|
+
last_line = nil
|
87
|
+
relative_line = 0
|
88
|
+
placeholder = nil
|
89
|
+
point = [0,0]
|
90
|
+
current_depth = 0
|
91
|
+
caret = Cauldron::Caret.new
|
92
|
+
|
93
|
+
points = end_points
|
94
|
+
|
95
|
+
code_tracking.split("\n").each do |line|
|
96
|
+
|
97
|
+
if line.match /record/
|
98
|
+
depth = (line.match(/^(\s+)/)[0].length / 2) -1
|
99
|
+
if depth > current_depth
|
100
|
+
relative_line = 0
|
101
|
+
end
|
102
|
+
current_depth = depth
|
103
|
+
|
104
|
+
new_tracked_code << last_line
|
105
|
+
new_tracked_code << Sorcerer.source(
|
106
|
+
Cauldron::Tracer.tracking(relative_line, depth, total_lines, points.shift)
|
107
|
+
)
|
108
|
+
new_tracked_code << placeholder
|
109
|
+
else
|
110
|
+
total_lines += 1
|
111
|
+
|
112
|
+
unless line['=']
|
113
|
+
placeholder = "#{'placeholder_'+rand(10000000000).to_s}"
|
114
|
+
last_line = "#{placeholder} = "+line
|
115
|
+
end
|
116
|
+
|
117
|
+
if last_line
|
118
|
+
if !last_line.match(/\s+end/).nil? || !last_line.match(/function/).nil? # || last_line.match /function/
|
119
|
+
last_line = nil
|
120
|
+
placeholder = nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
if line.match /end$/
|
125
|
+
unless line.strip == 'end'
|
126
|
+
line = line.gsub(/end$/,'')
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
new_tracked_code << line
|
131
|
+
current_line += 1
|
132
|
+
end
|
133
|
+
#total_lines += 1
|
134
|
+
end
|
135
|
+
|
136
|
+
# NOTE: Keep this to debug before conversion of S-EXP
|
137
|
+
sexp = Ripper::SexpBuilder.new(new_tracked_code.join("\n")).parse
|
138
|
+
|
139
|
+
Cauldron::Tracer.new(sexp)
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
def reset_and_track(caret)
|
144
|
+
caret.return_depth(0)
|
145
|
+
Cauldron::Tracer.tracking(caret.line, caret.current_depth, caret.total_lines)
|
146
|
+
end
|
147
|
+
|
148
|
+
def to_sexp(scope=Cauldron::Scope.new)
|
149
|
+
|
150
|
+
res = operators.collect do |operator|
|
151
|
+
#begin
|
152
|
+
operator.content.to_ruby(scope, operator.children)
|
153
|
+
# rescue NoMethodError => e
|
154
|
+
# binding.pry
|
155
|
+
# end
|
156
|
+
|
157
|
+
end.join("\n")
|
158
|
+
|
159
|
+
sexp = Ripper::SexpBuilder.new(res).parse
|
160
|
+
return sexp
|
161
|
+
end
|
162
|
+
|
163
|
+
def to_ruby(scope)
|
164
|
+
return '' if operators.empty?
|
165
|
+
Sorcerer.source(to_sexp(scope))
|
166
|
+
end
|
167
|
+
|
168
|
+
def add_first_statement(statement)
|
169
|
+
[:stmts_add, [:stmts_new], statement]
|
170
|
+
end
|
171
|
+
|
172
|
+
def add_statement(statement, inner)
|
173
|
+
[:stmts_add, inner, statement]
|
174
|
+
end
|
175
|
+
|
176
|
+
def solution?(problems)
|
177
|
+
o = Object.new
|
178
|
+
m = %Q{
|
179
|
+
def function(#{problems.variables.join(',')})
|
180
|
+
#{to_ruby(problems.scope)}
|
181
|
+
end
|
182
|
+
}
|
183
|
+
o.instance_eval(m)
|
184
|
+
|
185
|
+
#o.function *problems.examples.first.arguments
|
186
|
+
problems.all? do |example|
|
187
|
+
o.function(*example.arguments) == example.response
|
188
|
+
end
|
189
|
+
|
190
|
+
# TODO: Remove this resque - it is just a temp
|
191
|
+
rescue NoMethodError => e
|
192
|
+
return false
|
193
|
+
rescue NameError => e
|
194
|
+
return false
|
195
|
+
rescue TypeError => e
|
196
|
+
return false
|
197
|
+
end
|
198
|
+
|
199
|
+
# TODO Drop this method
|
200
|
+
def successful?(problem)
|
201
|
+
|
202
|
+
# # TODO track the parameters of the operator
|
203
|
+
# operators.trace(problem)
|
204
|
+
|
205
|
+
# # TODO For now just evalute the code
|
206
|
+
# return true if problem[:arguments].first == problem[:response]
|
207
|
+
# false
|
208
|
+
|
209
|
+
pt = PryTester.new
|
210
|
+
|
211
|
+
args = problem.arguments
|
212
|
+
variables = problem.params #(0...args.length).collect {|x| 'var'+x.to_s}
|
213
|
+
a = [
|
214
|
+
'def function('+variables.join(',')+');'+self.to_ruby(variables)+"; end",
|
215
|
+
'function('+problem.arguments.collect {|x| to_programme(x) }.join(',')+')'
|
216
|
+
]
|
217
|
+
|
218
|
+
res = pt.eval(
|
219
|
+
['def function('+variables.join(',')+');'+self.to_ruby(variables)+"; end", 'function('+problem.arguments.collect {|x| to_programme(x) }.join(',')+')']
|
220
|
+
)
|
221
|
+
|
222
|
+
problem.response == res
|
223
|
+
end
|
224
|
+
|
225
|
+
def to_programme(value)
|
226
|
+
if value.kind_of?(String)
|
227
|
+
return %Q{'#{value}'}
|
228
|
+
end
|
229
|
+
value.to_s
|
230
|
+
end
|
231
|
+
|
232
|
+
# TODO Add a safety evalutor
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# def function(var0)
|
2
|
+
# var0.collect { |x| x * 2 }
|
3
|
+
# end
|
4
|
+
|
5
|
+
module Cauldron::Solution
|
6
|
+
|
7
|
+
class One
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def successful?(problem)
|
14
|
+
return false unless problem.arguments.first.kind_of?(Array)
|
15
|
+
return false unless problem.arguments.first[0] * 2 == problem.response[0]
|
16
|
+
return false unless problem.arguments.first[1] * 2 == problem.response[1]
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_ruby(variables)
|
21
|
+
sexp =
|
22
|
+
[:method_add_block,
|
23
|
+
[:call,
|
24
|
+
[:vcall,
|
25
|
+
[:@ident, variables[0]]
|
26
|
+
],
|
27
|
+
:".",
|
28
|
+
[:@ident, "collect"]
|
29
|
+
],
|
30
|
+
[:brace_block,
|
31
|
+
[:block_var,
|
32
|
+
[:params,
|
33
|
+
[[:@ident, "x"]]
|
34
|
+
]
|
35
|
+
],
|
36
|
+
[
|
37
|
+
:binary,
|
38
|
+
[:var_ref, [:@ident, "x"]],
|
39
|
+
:*,
|
40
|
+
[:@int, "2"]
|
41
|
+
]
|
42
|
+
]
|
43
|
+
]
|
44
|
+
Sorcerer.source(sexp)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
module Cauldron
|
2
|
+
|
3
|
+
class StatementGenerator
|
4
|
+
|
5
|
+
# Build appropriate classes that can build appropriate instances - instances
|
6
|
+
# must have the constants
|
7
|
+
def build(instance,dynamic_methods,declare_variable=false)
|
8
|
+
dynamic_methods.collect do |x|
|
9
|
+
build_template(instance,x)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO Change to build_blue_print
|
14
|
+
def build_template(instance, dynamic_method)
|
15
|
+
build_class(instance, dynamic_method)
|
16
|
+
end
|
17
|
+
|
18
|
+
def sexp_method_to_ruby(instance, dynamic_method)
|
19
|
+
%Q{
|
20
|
+
def to_ruby(scope, operators)
|
21
|
+
Sorcerer.source self.to_sexp(scope, operators)
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def sexp_method_to_desc
|
27
|
+
%Q{
|
28
|
+
def to_desc
|
29
|
+
to_ruby( Cauldron::Scope.new(['var0']), [] )
|
30
|
+
end
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_to_sexp(instance, dynamic_method)
|
35
|
+
|
36
|
+
# Does it expect arguments?
|
37
|
+
begin
|
38
|
+
instance.send(dynamic_method)
|
39
|
+
rescue ArgumentError => e
|
40
|
+
|
41
|
+
number_of_arguments = e.message.match(/(\d+)\)/)[1].to_i
|
42
|
+
|
43
|
+
#statement = "scope[@indexes[0]] #{dynamic_method}"
|
44
|
+
statement = "scope[@indexes[0]]"
|
45
|
+
|
46
|
+
to_sexp_method = %Q^
|
47
|
+
def to_sexp(scope, operators)
|
48
|
+
Ripper::SexpBuilder.new(#{statement}).parse
|
49
|
+
end
|
50
|
+
^
|
51
|
+
# to_sexp_method = %Q^
|
52
|
+
# def to_sexp(scope, operators)
|
53
|
+
# Ripper::SexpBuilder.new("\#{scope[@indexes[0]]} + \#{constant}").parse
|
54
|
+
# end
|
55
|
+
# ^
|
56
|
+
return to_sexp_method
|
57
|
+
end
|
58
|
+
|
59
|
+
if instance.send(dynamic_method).class == Enumerator
|
60
|
+
%Q^
|
61
|
+
def to_sexp(scope, operators)
|
62
|
+
scope_var = scope.new_variable!
|
63
|
+
scope_var_two = scope.new_variable!
|
64
|
+
dynamic_method = '#{dynamic_method}'
|
65
|
+
|
66
|
+
first_variable = 'var'+@indexes[0].to_s
|
67
|
+
|
68
|
+
a = "\#{scope_var} = \#{first_variable}.\#{dynamic_method} do |\#{scope_var_two}|"+"\n"
|
69
|
+
a += operators.collect {|x| x.content.to_ruby(scope, x.children) }.join("\n")
|
70
|
+
a += "\n"+"end"+"\n"
|
71
|
+
puts a
|
72
|
+
Ripper::SexpBuilder.new(a).parse
|
73
|
+
|
74
|
+
end
|
75
|
+
^
|
76
|
+
else
|
77
|
+
%Q{
|
78
|
+
def to_sexp(scope, operators)
|
79
|
+
first_variable = 'var'+@indexes[0].to_s
|
80
|
+
[:call,
|
81
|
+
[:vcall, [:@ident, first_variable ]],
|
82
|
+
:".",
|
83
|
+
[:@ident, "#{dynamic_method}"]
|
84
|
+
]
|
85
|
+
end
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def requires_arguments?(instance, dynamic_method)
|
91
|
+
instance.send(dynamic_method)
|
92
|
+
false
|
93
|
+
rescue ArgumentError => e
|
94
|
+
true
|
95
|
+
end
|
96
|
+
|
97
|
+
def expects_block?(instance, dynamic_method)
|
98
|
+
instance.send(dynamic_method).class == Enumerator
|
99
|
+
end
|
100
|
+
|
101
|
+
def branch_method(instance, dynamic_method)
|
102
|
+
if requires_arguments?(instance, dynamic_method)
|
103
|
+
return %q{
|
104
|
+
def branch?
|
105
|
+
false
|
106
|
+
end
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
if expects_block?(instance, dynamic_method)
|
111
|
+
return %q{
|
112
|
+
def branch?
|
113
|
+
true
|
114
|
+
end
|
115
|
+
}
|
116
|
+
end
|
117
|
+
%q{
|
118
|
+
def branch?
|
119
|
+
false
|
120
|
+
end
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
def template_sexp(instance, dynamic_method)
|
125
|
+
|
126
|
+
res = %Q{
|
127
|
+
|
128
|
+
#{sexp_method_to_ruby(instance, dynamic_method)}
|
129
|
+
|
130
|
+
#{method_to_sexp(instance, dynamic_method)}
|
131
|
+
|
132
|
+
#{sexp_method_to_desc}
|
133
|
+
|
134
|
+
#{branch_method(instance, dynamic_method)}
|
135
|
+
|
136
|
+
def self.instances(histories, composite, examples, insert_points)
|
137
|
+
|
138
|
+
# TEMP
|
139
|
+
unless examples.class == ExampleSet
|
140
|
+
raise StandardError.new('Examples should be an example')
|
141
|
+
end
|
142
|
+
|
143
|
+
# Print out each insertable statements
|
144
|
+
scope = examples.scope
|
145
|
+
|
146
|
+
# self.init([0]).to_ruby(scope)
|
147
|
+
# - this will print out "var0.chop"
|
148
|
+
|
149
|
+
# Get the variables available at each point
|
150
|
+
results = []
|
151
|
+
|
152
|
+
insert_points.each do |point|
|
153
|
+
|
154
|
+
# Find the variables at a particular point
|
155
|
+
# TODO Change to test
|
156
|
+
contexts = histories.contexts_at(point)
|
157
|
+
composites = context_instances(contexts)
|
158
|
+
|
159
|
+
composites.each do |x|
|
160
|
+
if contexts.all? do |context|
|
161
|
+
x.context_realizable?(context)
|
162
|
+
end
|
163
|
+
results << extend_actualized_composite(x, composite, examples, point)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
results
|
170
|
+
end
|
171
|
+
|
172
|
+
}
|
173
|
+
Ripper::SexpBuilder.new(res).parse
|
174
|
+
end
|
175
|
+
|
176
|
+
def dynamic_template_name(instance, dynamic_method)
|
177
|
+
dynamic_method_name = dynamic_method.to_s.gsub(/\+/,'Add')
|
178
|
+
dynamic_name = ('Dynamic'+'_'+instance.class.to_s+'_'+dynamic_method_name.to_s).camelize
|
179
|
+
dynamic_name+'Template'
|
180
|
+
end
|
181
|
+
|
182
|
+
def default_template(instance, dynamic_method)
|
183
|
+
blue_print = build_class(instance, dynamic_method)
|
184
|
+
blue_print.statement_classes.first
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_class(instance, dynamic_method)
|
188
|
+
sexp = template_sexp(instance, dynamic_method)
|
189
|
+
information = { constants: false }
|
190
|
+
|
191
|
+
template_name = dynamic_template_name(instance, dynamic_method)
|
192
|
+
|
193
|
+
# http://ruby-doc.org/core-2.3.0/Class.html
|
194
|
+
# http://stackoverflow.com/questions/4113479/dynamic-class-definition-with-a-class-name
|
195
|
+
unless Object.const_defined? template_name
|
196
|
+
c = Object.const_set(
|
197
|
+
template_name,
|
198
|
+
Class.new do
|
199
|
+
|
200
|
+
attr_reader :indexes, :dynamic_name, :sexp_methods
|
201
|
+
attr_accessor :failed_uses
|
202
|
+
|
203
|
+
def initialize(information, sexp_methods)
|
204
|
+
@information, @sexp_methods = information, sexp_methods
|
205
|
+
@failed_uses = []
|
206
|
+
end
|
207
|
+
|
208
|
+
# NOTE: These theses classes define the constants
|
209
|
+
def statement_classes(examples = nil)
|
210
|
+
|
211
|
+
#binding.pry
|
212
|
+
|
213
|
+
# Find the constants
|
214
|
+
b = Object.const_set(
|
215
|
+
self.class.to_s+rand(4000000).to_s,
|
216
|
+
Class.new do
|
217
|
+
|
218
|
+
include Cauldron::Operator
|
219
|
+
include Cauldron::DynamicOperatorModule
|
220
|
+
|
221
|
+
attr_reader :indexes
|
222
|
+
attr_accessor :failed_uses
|
223
|
+
|
224
|
+
def initialize(indexes)
|
225
|
+
@indexes = indexes
|
226
|
+
@failed_uses = []
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.context_instances(contexts)
|
230
|
+
temp = []
|
231
|
+
contexts.each do |context|
|
232
|
+
temp << context.keys.collect(&:to_s).select {|x| x.match(/var\d/) }
|
233
|
+
end
|
234
|
+
results = temp.flatten.uniq
|
235
|
+
|
236
|
+
variable_numbers = results.collect { |x| x.match(/var(\d+)/)[1] }
|
237
|
+
# TODO Presumes that only one variable is passed
|
238
|
+
variable_numbers.collect { |x| new([x.to_i])}
|
239
|
+
end
|
240
|
+
|
241
|
+
def self.extend_actualized_composite(x, container, examples, point)
|
242
|
+
cloned_container = container.clone_solution
|
243
|
+
cloned_container.add_statement_at(x, point)
|
244
|
+
cloned_container
|
245
|
+
Cauldron::ActualizedComposite.new(cloned_container, examples)
|
246
|
+
end
|
247
|
+
|
248
|
+
def rip2
|
249
|
+
%Q{
|
250
|
+
def function(var0)
|
251
|
+
#{Sorcerer.source(to_sexp(Cauldron::Scope.new(['var0']),[]), indent: true)}
|
252
|
+
end
|
253
|
+
}
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
)
|
258
|
+
b.class_eval(Sorcerer.source(sexp_methods, indent: true))
|
259
|
+
[b]
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
)
|
264
|
+
|
265
|
+
|
266
|
+
#a = c.new(information, sexp.clone)
|
267
|
+
|
268
|
+
#return a.statement_classes.first
|
269
|
+
return c.new(information, sexp.clone)
|
270
|
+
else
|
271
|
+
#a = eval(template_name).new(information, sexp.clone)
|
272
|
+
return eval(template_name).new(information, sexp.clone) #a.statement_classes.first
|
273
|
+
end
|
274
|
+
|
275
|
+
raise StandardError.new('Should not get here')
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
# TODO stacking mulitple rescues does not work
|
283
|
+
# realizable?
|
284
|
+
|
285
|
+
# def realizable?(composite, examples)
|
286
|
+
# o = Object.new
|
287
|
+
# composite.to_ruby(examples.scope)
|
288
|
+
# sexp = rip(composite,examples)
|
289
|
+
# o.instance_eval(Sorcerer.source(sexp, indent: true))
|
290
|
+
# begin
|
291
|
+
# o.function(examples.examples.first.arguments.first)
|
292
|
+
# rescue NoMethodError
|
293
|
+
# # TODO Need to record failing tests here
|
294
|
+
# failed_uses << { composite:composite, examples: examples}
|
295
|
+
# return false
|
296
|
+
# end
|
297
|
+
# true
|
298
|
+
# end
|