cauldron 0.1.1 → 0.1.2
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.
- data/Gemfile +2 -1
- data/VERSION +1 -1
- data/features/cauldron_generates_runtime_method.feature +2 -2
- data/lib/Chain.rb +22 -6
- data/lib/UnifiedChain.rb +17 -2
- data/lib/cauldron.rb +3 -0
- data/lib/cauldron/pot.rb +50 -40
- data/lib/cauldron/terminal.rb +2 -2
- data/lib/core/ClassMethodCallContainer.rb +0 -1
- data/lib/core/MethodUsage.rb +0 -1
- data/lib/core/TheoryGenerator.rb +0 -4
- data/lib/core/runtime_method/RuntimeMethod.rb +1 -1
- data/lib/core/statement/ActsAsStatement.rb +1 -1
- data/lib/core/statement/Statement.rb +65 -146
- data/lib/core/statement/TheoryStatement.rb +1 -0
- data/lib/core/variable/FixnumVariable.rb +4 -5
- data/lib/core/variable/Unknown.rb +1 -11
- data/lib/core/variable/Variable.rb +1 -1
- data/lib/required.rb +0 -1
- data/lib/ruby_code/String.rb +0 -6
- data/lib/theory/TheoryConnector.rb +54 -117
- data/lib/util/ClassEvaluation.rb +9 -28
- data/lib/util/CodeEvaluation.rb +22 -18
- data/lib/util/DeclarationStatementEvaluation.rb +4 -3
- data/lib/util/MethodEvaluation.rb +6 -6
- data/lib/util/StatementCheck.rb +5 -3
- data/lib/util/StringToTheory.rb +0 -1
- data/spec/cauldron/pot_spec.rb +40 -0
- data/test/fixtures/theories/0/dump +0 -0
- data/test/fixtures/theories/1/dump +0 -0
- data/test/fixtures/theories/10/dump +0 -0
- data/test/fixtures/theories/11/dump +0 -0
- data/test/fixtures/theories/12/dump +0 -0
- data/test/fixtures/theories/13/dump +0 -0
- data/test/fixtures/theories/14/dump +0 -0
- data/test/fixtures/theories/15/dump +0 -0
- data/test/fixtures/theories/16/dump +0 -0
- data/test/fixtures/theories/17/dump +0 -0
- data/test/fixtures/theories/18/dump +0 -0
- data/test/fixtures/theories/19/dump +0 -0
- data/test/fixtures/theories/2/dump +0 -0
- data/test/fixtures/theories/20/dump +0 -0
- data/test/fixtures/theories/3/dump +0 -0
- data/test/fixtures/theories/4/dump +0 -0
- data/test/fixtures/theories/5/dump +0 -0
- data/test/fixtures/theories/6/dump +0 -0
- data/test/fixtures/theories/7/dump +0 -0
- data/test/fixtures/theories/8/dump +0 -0
- data/test/fixtures/theories/9/declaration.txt +1 -1
- data/test/fixtures/theories/9/desc +1 -1
- data/test/fixtures/theories/9/dump +0 -0
- data/test/ts_complete.rb +0 -1
- data/test/unit/core/runtime_method/tc_runtime_method.rb +0 -25
- data/test/unit/core/statement/tc_statement.rb +0 -52
- data/test/unit/core/tc_theory_generator.rb +2 -2
- data/test/unit/tc_theory.rb +2 -10
- data/test/unit/theory/tc_theory_action.rb +2 -6
- data/test/unit/util/tc_string_to_theory.rb +2 -2
- data/tmp/runtime_method_evaluation.rb +10 -7
- metadata +28 -30
- data/lib/core/runtime_class/IfStatementClass.rb +0 -12
- data/test/tc_contextual_variables.rb +0 -48
@@ -4,15 +4,14 @@ class FixnumVariable < TypeVariable
|
|
4
4
|
super(val,id)
|
5
5
|
end
|
6
6
|
|
7
|
-
# TODO Write test
|
8
7
|
def to_declaration
|
9
8
|
return VariableDeclaration.new('FixnumVariable',@value.to_declaration)
|
10
9
|
end
|
11
10
|
|
12
|
-
# TODO I wan't to get rid of this call entirly
|
13
|
-
def copy_contextual_variable
|
14
|
-
return copy
|
15
|
-
end
|
11
|
+
# # TODO I wan't to get rid of this call entirly
|
12
|
+
# def copy_contextual_variable
|
13
|
+
# return copy
|
14
|
+
# end
|
16
15
|
|
17
16
|
# Returns true if the variable type is Fixnum, this is used
|
18
17
|
# to determine whether a BlockVariable or VariableContainer
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
# TODO This is not strickly a Variable - it is a data type of it's own
|
3
3
|
|
4
4
|
class Unknown < BaseVariable
|
@@ -9,14 +9,6 @@ class Unknown < BaseVariable
|
|
9
9
|
super(*requirements)
|
10
10
|
end
|
11
11
|
|
12
|
-
# Adds a new requirement to the unknown variable. Unlike
|
13
|
-
# variables requirements can be added from outside the
|
14
|
-
# instance.
|
15
|
-
#
|
16
|
-
def push requirement
|
17
|
-
variable_push requirement
|
18
|
-
end
|
19
|
-
|
20
12
|
# Returns a typed version of the variable with the correct
|
21
13
|
# variable id. This occurs when an Unknown variable is
|
22
14
|
# used in a statement and its value can be determined.
|
@@ -36,7 +28,6 @@ class Unknown < BaseVariable
|
|
36
28
|
end
|
37
29
|
end
|
38
30
|
|
39
|
-
# TODO Test this
|
40
31
|
# TODO Should 'Unknown' have a variable id
|
41
32
|
def copy
|
42
33
|
result = self.class.new(*self) {{:variable_id => variable_id,:uniq_id=>@uniq_id,:uniq_id_history=>@uniq_id_history.copy}}
|
@@ -97,7 +88,6 @@ class Unknown < BaseVariable
|
|
97
88
|
|
98
89
|
def to_var(id=nil,uniq_id=nil)
|
99
90
|
StandardLogger.instance.warning('"Unknown" is NOT a variable - it is a data type')
|
100
|
-
#super(id)
|
101
91
|
return UnknownVariable.new(self) {{:variable_id => id,:uniq_id=>uniq_id}}
|
102
92
|
end
|
103
93
|
|
@@ -27,7 +27,7 @@ module Variable
|
|
27
27
|
def self.reset_global_id
|
28
28
|
#http://www.zenspider.com/Languages/Ruby/QuickRef.html
|
29
29
|
unless $".include?('test/unit.rb')
|
30
|
-
|
30
|
+
StandardLogger.instance.log 'WARNING: Resetting variable id, this should only be done for tests'
|
31
31
|
end
|
32
32
|
@@variable_id = 0
|
33
33
|
@@uniq_id = 0
|
data/lib/required.rb
CHANGED
@@ -143,7 +143,6 @@ require $LOC+File.join(['core','runtime_class','RuntimeMethodClass'])
|
|
143
143
|
require $LOC+File.join(['core','runtime_class','MethodUsageClass'])
|
144
144
|
require $LOC+File.join(['core','runtime_class','UnknownClass'])
|
145
145
|
require $LOC+File.join(['core','runtime_class','StatementClass'])
|
146
|
-
require $LOC+File.join(['core','runtime_class','IfStatementClass'])
|
147
146
|
require $LOC+File.join(['core','runtime_class','ReturnClass'])
|
148
147
|
require $LOC+File.join(['core','runtime_class','RuntimeClassClass'])
|
149
148
|
require $LOC+File.join(['core','runtime_class','DefCallClass'])
|
data/lib/ruby_code/String.rb
CHANGED
@@ -13,7 +13,6 @@ class String
|
|
13
13
|
return '\''+x+'\''
|
14
14
|
end
|
15
15
|
|
16
|
-
# TODO Write tests
|
17
16
|
def instance_call_structures
|
18
17
|
return [
|
19
18
|
InstanceCallContainerStructure.new(StringVariable,Chop.new),
|
@@ -28,11 +27,6 @@ class String
|
|
28
27
|
return StringVariable.new(self,var_id){{:variable_id => var_id,:uniq_id=>unique_id}}
|
29
28
|
end
|
30
29
|
|
31
|
-
# TODO This might have been superceeded by "to_declaration"
|
32
|
-
def creation
|
33
|
-
return self.write
|
34
|
-
end
|
35
|
-
|
36
30
|
def to_declaration
|
37
31
|
return LiteralDeclaration.new(self.clone)
|
38
32
|
end
|
@@ -36,7 +36,7 @@ class TheoryConnector
|
|
36
36
|
# Returns an array of complete chains that conclude with a valid
|
37
37
|
# runtime method.
|
38
38
|
#
|
39
|
-
def generate_chains(runtime_method,test_cases,theories)
|
39
|
+
def generate_chains(runtime_method,test_cases,theories,exclude=[])
|
40
40
|
|
41
41
|
theories = remove_irrelevant_theories(theories)
|
42
42
|
|
@@ -58,10 +58,15 @@ class TheoryConnector
|
|
58
58
|
complete_chains += possible_chains.select {|x| x.complete?}
|
59
59
|
possible_chains.delete_if {|x| x.complete?}
|
60
60
|
end
|
61
|
-
|
61
|
+
complete_chains = complete_chains.delete_if do |x|
|
62
|
+
exclude.any? {|y| y == x.theories_sequence}
|
63
|
+
end
|
64
|
+
unless complete_chains.empty?
|
65
|
+
return complete_chains
|
66
|
+
end
|
62
67
|
|
63
68
|
possible_chains.each do |chain|
|
64
|
-
|
69
|
+
|
65
70
|
# Remove the head theory to avoid it being re-used
|
66
71
|
head_free_theories = theories.copy
|
67
72
|
head_free_theories.delete_if {|theory| theory.theory_id == chain.first.theory_id}
|
@@ -73,56 +78,69 @@ class TheoryConnector
|
|
73
78
|
end
|
74
79
|
|
75
80
|
def complete_chain(chain,theories)
|
76
|
-
|
77
|
-
|
81
|
+
res = catch(:complete) do
|
82
|
+
converge_chain(chain,theories)
|
83
|
+
end
|
84
|
+
|
85
|
+
#return chains
|
86
|
+
return [res]
|
78
87
|
|
79
88
|
end
|
80
89
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
84
|
-
extended_chains = []
|
85
|
-
theories.each do |theory|
|
86
|
-
last_position = 1
|
87
|
-
chains = chain.add_link_to(theory,last_position,[])
|
88
|
-
next if chains.empty?
|
89
|
-
extended_chains += chains
|
90
|
+
def remove_existing_theories(chain,theories)
|
91
|
+
theories.delete_if do |theory|
|
92
|
+
chain.theories_sequence.include?(theory.theory_id)
|
90
93
|
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def converge_chain(chain,theories,step=0)
|
97
|
+
theories = remove_existing_theories(chain.copy,theories)
|
91
98
|
|
92
|
-
|
93
|
-
if extended_chains.any? {|x| x.complete? }
|
94
|
-
return extended_chains.select {|x| x.complete?}
|
95
|
-
end
|
99
|
+
extended_chains = add_to_chain(chain.copy,theories,step)
|
96
100
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
closer_chains << x
|
101
|
-
end
|
101
|
+
if extended_chains.any? {|x| x.complete? }
|
102
|
+
res2 = extended_chains.select {|x| x.complete?}
|
103
|
+
throw :complete, res2.first
|
102
104
|
end
|
103
|
-
|
105
|
+
closer_chains = closer_chains(chain.copy,extended_chains)
|
106
|
+
|
107
|
+
complete_chains = []
|
104
108
|
unless closer_chains.empty?
|
105
109
|
closer_chains.each do |x|
|
106
110
|
complete_chains += converge_chain(x,theories,step+1)
|
107
111
|
end
|
108
|
-
else
|
112
|
+
else
|
109
113
|
extended_chains.each do |x|
|
110
|
-
|
111
|
-
copied_chain = x.copy
|
112
|
-
last_position = 1
|
113
|
-
chains = copied_chain.add_link_to(theory,last_position,[])
|
114
|
-
chains.each do |z|
|
115
|
-
if ((chain.unmet_dependents_ids-z.unmet_dependents_ids).length == chain.unmet_dependents_ids.length)
|
116
|
-
complete_chains += converge_chain(z.copy,theories,step+1)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
114
|
+
complete_chains += converge_chain(x,theories,(step+1))
|
120
115
|
end
|
121
116
|
end
|
122
117
|
|
123
118
|
return complete_chains
|
124
119
|
end
|
125
120
|
|
121
|
+
def closer_chains(chain,chains)
|
122
|
+
closer_chains = []
|
123
|
+
chains.each do |x|
|
124
|
+
if ((chain.unmet_dependents_ids-x.unmet_dependents_ids).length == chain.unmet_dependents_ids.length)
|
125
|
+
closer_chains << x
|
126
|
+
end
|
127
|
+
end
|
128
|
+
return closer_chains
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_to_chain(chain,theories,step)
|
132
|
+
extended_chains = []
|
133
|
+
theories.each do |theory|
|
134
|
+
last_position = 1
|
135
|
+
chains = chain.add_link_to(theory,last_position,[])
|
136
|
+
|
137
|
+
#chains = chain.extension_permutaions(theory,[])
|
138
|
+
next if chains.empty?
|
139
|
+
extended_chains += chains
|
140
|
+
end
|
141
|
+
return extended_chains
|
142
|
+
end
|
143
|
+
|
126
144
|
def extend_chain(chain,theories)
|
127
145
|
|
128
146
|
complete_chains = []
|
@@ -244,88 +262,6 @@ class TheoryConnector
|
|
244
262
|
|
245
263
|
end
|
246
264
|
|
247
|
-
# Returns a new chain so that they all use consistent theory variables ids
|
248
|
-
#
|
249
|
-
# @param chain An array of theories e.g.
|
250
|
-
# [<#Theory>,<#Theory>,<#Theory>,<#Theory>]
|
251
|
-
#
|
252
|
-
# The last chain contains the finished theory.
|
253
|
-
#
|
254
|
-
# It is difficult to generate all the arrangements for the chain as soon as
|
255
|
-
# there start to be a large number of dependents and results. There is just too
|
256
|
-
# many permutations. Once any connection is decided upon e.g. this dependent to
|
257
|
-
# that result then the number of permutations is reduced. As such they need to
|
258
|
-
# be updated in parallet.
|
259
|
-
#
|
260
|
-
#
|
261
|
-
#
|
262
|
-
def unify_chain2(chain)
|
263
|
-
|
264
|
-
unified_chains = []
|
265
|
-
|
266
|
-
# Reverse the chain so that the finish is the first theory
|
267
|
-
reversed_chain = chain.reverse
|
268
|
-
|
269
|
-
# This method needs to map the theory variables used in one theory to the
|
270
|
-
# rest. This basically means there is a global theory that has a respective
|
271
|
-
# id in each of the other theories in the chain. e.g.
|
272
|
-
#
|
273
|
-
# +----------+--------+--------+--------+--------+
|
274
|
-
# |Global #ID| link#1 | link#2 | link#3 | link#4 |
|
275
|
-
# +----------+--------+--------+--------+--------+
|
276
|
-
# | 0 | 1 | 1 | 2 | 89 |
|
277
|
-
# +----------+--------+--------+--------+--------+
|
278
|
-
# | 1 | 2 | 4 | 6 | 1 |
|
279
|
-
# +----------+--------+--------+--------+--------+
|
280
|
-
#
|
281
|
-
|
282
|
-
# {global#ID=> #{link#1=>1,#link#2=>5}
|
283
|
-
|
284
|
-
# Take the first theory and set the global theory variables to the first link
|
285
|
-
global_theory_variables = {}
|
286
|
-
|
287
|
-
# * Pop the first link in the chain and set ids of the theory variables
|
288
|
-
link = chain.pop
|
289
|
-
link.all_theory_variables.each do |theory_variable|
|
290
|
-
|
291
|
-
# For the first link I'm just going to use the same id as the first link
|
292
|
-
global_theory_variables[theory_variable.theory_variable_id] = {link.theory_id=>theory_variable.theory_variable_id}
|
293
|
-
|
294
|
-
end
|
295
|
-
|
296
|
-
# 1. Find all the dependent-> result permutations for the last chain
|
297
|
-
# 2. Exclude any that are mutually exclusive
|
298
|
-
|
299
|
-
#possible_global_theory_variables = extend_global_mapping(global_theory_variables,link,chain)
|
300
|
-
|
301
|
-
# NOTE: Previously I had normalised the theories by working out all the possible permutations
|
302
|
-
# of dependent to result. Then work out the variable substitution. This did work but
|
303
|
-
# the number of permutations for larger theories meant it was completely impractical. Instead
|
304
|
-
# now it needs to form one connection "dependent to result" and then update the consequence of
|
305
|
-
# that. Some of the decisions will be mutually exclusive.
|
306
|
-
|
307
|
-
return unified_chains
|
308
|
-
|
309
|
-
end
|
310
|
-
|
311
|
-
def extend_global_mapping(global_theory_variables,link,chain,results=[])
|
312
|
-
|
313
|
-
next_link = chain.pop
|
314
|
-
|
315
|
-
# Find all the variables in the next link thats global ids have not been determined
|
316
|
-
unidentified_theory_variables = next_link.all_theory_variables.inject([]) do |total,x|
|
317
|
-
total << x if global_theory_variables.any? {|key,value| !value[next_link.theory_id].nil? }
|
318
|
-
end
|
319
|
-
|
320
|
-
# Link the previous dependents to the this link
|
321
|
-
link.dependents.each do |dependent|
|
322
|
-
|
323
|
-
# Find the similar
|
324
|
-
|
325
|
-
end
|
326
|
-
|
327
|
-
end
|
328
|
-
|
329
265
|
# Returns a new chain so that they all use consistent theory variables ids
|
330
266
|
#
|
331
267
|
def unify_chain(chain)
|
@@ -337,6 +273,7 @@ class TheoryConnector
|
|
337
273
|
# Find all the ways the theory and results can connected
|
338
274
|
# - the same_structure? approach is quite loose
|
339
275
|
arrangements = chain_arrangements(chain.copy.reverse)
|
276
|
+
|
340
277
|
# For each theory in the chain give each each variable a unique id
|
341
278
|
starting_id = 1
|
342
279
|
uniq_chain = chain.inject([]) do |total,x|
|
data/lib/util/ClassEvaluation.rb
CHANGED
@@ -1,39 +1,17 @@
|
|
1
|
+
|
1
2
|
# Used to make calls to a dynamically written class.
|
2
3
|
#
|
3
4
|
class ClassEvaluation
|
4
|
-
#include WriteParameters
|
5
5
|
@@count = 0
|
6
6
|
|
7
|
-
def evaluate_class(runtime_class,runtime_call)
|
8
|
-
|
9
|
-
# Create file to include the test method
|
10
|
-
#filepath = $LOC+File.join(['tmp','runtime_class_evaluation.rb'])
|
11
|
-
filepath = $LOC+File.join(['tmp',runtime_class.class_name+'.rb'])
|
12
|
-
file = File.open(filepath,'w+')
|
13
|
-
@@count += 1
|
14
|
-
|
15
|
-
# Include the sytax for the statement in the file
|
16
|
-
file << runtime_class.write
|
17
|
-
file.close
|
18
|
-
|
19
|
-
# Load the newly created class and check the statement
|
20
|
-
load filepath
|
21
|
-
begin
|
22
|
-
return eval("#{runtime_class.class_name}.new.#{runtime_call}")
|
23
|
-
rescue NameError => e
|
24
|
-
StandardLogger.instance.info(runtime_class.write)
|
25
|
-
raise e
|
26
|
-
end
|
27
|
-
|
7
|
+
def evaluate_class(runtime_class,runtime_call)
|
8
|
+
return evaluate_class_2(runtime_class,runtime_call)
|
28
9
|
end
|
29
10
|
|
30
|
-
# TODO This duplicates allot of the code above
|
31
11
|
def evaluate_class_2(runtime_class,runtime_call,*params)
|
32
12
|
|
33
13
|
# Create file to include the test method
|
34
|
-
|
35
|
-
filepath = $LOC+File.join(['tmp',runtime_class.class_name+'.rb'])
|
36
|
-
file = File.open(filepath,'w+')
|
14
|
+
file = Tempfile.new(runtime_class.class_name+'.rb')
|
37
15
|
@@count += 1
|
38
16
|
|
39
17
|
# Include the sytax for the statement in the file
|
@@ -41,7 +19,7 @@ class ClassEvaluation
|
|
41
19
|
file.close
|
42
20
|
|
43
21
|
# Load the newly created class and check the statement
|
44
|
-
load
|
22
|
+
load file.path
|
45
23
|
begin
|
46
24
|
# TODO Make this more generic
|
47
25
|
case params.length
|
@@ -55,7 +33,10 @@ class ClassEvaluation
|
|
55
33
|
rescue NameError => e
|
56
34
|
StandardLogger.instance.info(runtime_class.write)
|
57
35
|
raise e
|
58
|
-
|
36
|
+
ensure
|
37
|
+
file.close
|
38
|
+
file.unlink
|
39
|
+
end
|
59
40
|
|
60
41
|
end
|
61
42
|
|
data/lib/util/CodeEvaluation.rb
CHANGED
@@ -11,25 +11,29 @@ class CodeEvaluation
|
|
11
11
|
def evaluate_code(code)
|
12
12
|
@@COUNT += 1
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
begin
|
15
|
+
|
16
|
+
# Create file to include the test method
|
17
|
+
file = Tempfile.new("runtime_code_evaluation_#{@@COUNT}.rb")
|
18
|
+
|
19
|
+
# Include the sytax for the statement in the file
|
20
|
+
file << "class RuntimeCodeEvaluation#{@@COUNT}"+"\n"
|
21
|
+
file << "\t"+'def check'+"\n"
|
22
|
+
code.each_line do |l|
|
23
|
+
file << "\t\t"+l+"\n"
|
24
|
+
end
|
25
|
+
file << "\t"+'end'+"\n"
|
26
|
+
file << 'end'
|
27
|
+
file.close
|
28
|
+
|
29
|
+
# Load the newly created class and check the statement
|
30
|
+
load file.path
|
31
|
+
|
32
|
+
return eval("RuntimeCodeEvaluation#{@@COUNT}.new.check")
|
33
|
+
ensure
|
34
|
+
file.close
|
35
|
+
file.unlink
|
23
36
|
end
|
24
|
-
file << "\t"+'end'+"\n"
|
25
|
-
file << 'end'
|
26
|
-
file.close
|
27
|
-
|
28
|
-
# Load the newly created class and check the statement
|
29
|
-
load filepath
|
30
|
-
|
31
|
-
return eval("RuntimeCodeEvaluation#{@@COUNT}.new.check")
|
32
|
-
|
33
37
|
end
|
34
38
|
|
35
39
|
end
|
@@ -4,8 +4,7 @@ class DeclarationStatementEvaluation
|
|
4
4
|
def evaluate(written_statement,runtime_methods=[])
|
5
5
|
|
6
6
|
# Create file to include the test method
|
7
|
-
|
8
|
-
file = File.open(filepath,'w+')
|
7
|
+
file = Tempfile.new("runtime_declaration_statement_evaluation.rb")
|
9
8
|
|
10
9
|
# Include the sytax for the statement in the file
|
11
10
|
file << 'class RuntimeDeclarationStatementEvaluation'+"\n"
|
@@ -25,7 +24,9 @@ class DeclarationStatementEvaluation
|
|
25
24
|
load filepath
|
26
25
|
return RuntimeDeclarationStatementEvaluation.new.check
|
27
26
|
|
28
|
-
|
27
|
+
ensure
|
28
|
+
file.close
|
29
|
+
file.unlink
|
29
30
|
end
|
30
31
|
|
31
32
|
end
|