cauldron 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
@@ -9,5 +9,5 @@ Feature: Cauldron generates a runtime method
|
|
9
9
|
|
10
10
|
Scenarios: example with only one parameter
|
11
11
|
| cases | runtime_method | demo_num |
|
12
|
-
| "'sparky','sparky'*'kel','kel'" | "def
|
13
|
-
| "'fish','animal'*'carrot','
|
12
|
+
| "'sparky','sparky'*'kel','kel'" | "def method_0(var_0)\n\treturn var_0\nend\n" | 1 |
|
13
|
+
| "'fish','animal'*'carrot','vegetable'" | "def method_0(var_0)\n\tif(var_0 == 'fish')\n\t\treturn 'animal'\n\tend\n\treturn 'vegetable'\nend\n" | 2 |
|
data/lib/Chain.rb
CHANGED
@@ -3,6 +3,7 @@ class Chain
|
|
3
3
|
# TODO This access is proably temporary
|
4
4
|
attr_reader :chain_mapping
|
5
5
|
|
6
|
+
@@default_tail_theory = nil
|
6
7
|
#
|
7
8
|
# @param nodes An array of theories in order
|
8
9
|
#
|
@@ -13,13 +14,10 @@ class Chain
|
|
13
14
|
@uniq_theory_instance_ids = ('A'...'Z').to_a
|
14
15
|
|
15
16
|
# Create a result version of 'finish'
|
16
|
-
|
17
|
-
tail_theory = finish.write
|
18
|
-
tail_theory.gsub!('runtime_method','var1')
|
19
|
-
tail_theory.gsub!('test_cases','var2')
|
20
|
-
tail_dependent = TheoryDependent.new(StringToTheory.run(tail_theory))
|
17
|
+
|
21
18
|
# TODO Drop @tail_theory as a instance variable
|
22
|
-
|
19
|
+
#@tail_theory = Theory.new([tail_dependent],nil,[])
|
20
|
+
@tail_theory = Chain.default_tail_theory
|
23
21
|
|
24
22
|
# NOTE: Now the head and tail are using the same ids for their variables
|
25
23
|
@chain_mapping = ChainMapping.new()
|
@@ -34,6 +32,20 @@ class Chain
|
|
34
32
|
|
35
33
|
end
|
36
34
|
|
35
|
+
def self.default_tail_theory
|
36
|
+
if @@default_tail_theory.nil?
|
37
|
+
finish = Parser.run("if(runtime_method.all_pass?(test_cases))\nreturn true\nend")
|
38
|
+
tail_theory = finish.write
|
39
|
+
tail_theory.gsub!('runtime_method','var1')
|
40
|
+
tail_theory.gsub!('test_cases','var2')
|
41
|
+
tail_dependent = TheoryDependent.new(StringToTheory.run(tail_theory))
|
42
|
+
@@default_tail_theory = Theory.new([tail_dependent],nil,[])
|
43
|
+
@@default_tail_theory.copy
|
44
|
+
else
|
45
|
+
@@default_tail_theory.copy
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
37
49
|
# TODO I want to drop allot of these quick methods
|
38
50
|
def <<(node)
|
39
51
|
@nodes << node
|
@@ -111,6 +123,10 @@ class Chain
|
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
126
|
+
def theories_sequence
|
127
|
+
@nodes.collect {|x| x.theory_id}
|
128
|
+
end
|
129
|
+
|
114
130
|
# Returns a new chain where they are all using the same respective theory
|
115
131
|
# variables.
|
116
132
|
#
|
data/lib/UnifiedChain.rb
CHANGED
@@ -58,7 +58,7 @@ class UnifiedChain < Chain
|
|
58
58
|
valid_mappings = [Mapping.new]
|
59
59
|
|
60
60
|
#itteration_limit = 6
|
61
|
-
itteration_limit =
|
61
|
+
itteration_limit = 9
|
62
62
|
|
63
63
|
@nodes.each_with_index do |node,index|
|
64
64
|
|
@@ -87,7 +87,8 @@ class UnifiedChain < Chain
|
|
87
87
|
limit += 1
|
88
88
|
end
|
89
89
|
if limit > itteration_limit
|
90
|
-
|
90
|
+
pp missing_variables(node.action,valid_mappings)
|
91
|
+
raise StandardError.new('Unable to resolve action: '+"\n"+node.action.write)
|
91
92
|
end
|
92
93
|
end
|
93
94
|
|
@@ -116,12 +117,26 @@ class UnifiedChain < Chain
|
|
116
117
|
return true
|
117
118
|
end
|
118
119
|
|
120
|
+
def missing_variables(component,mappings)
|
121
|
+
results = []
|
122
|
+
component.theory_variables.each do |var|
|
123
|
+
mappings.each do |mapping|
|
124
|
+
#return false unless mapping.has_key? var.theory_variable_id
|
125
|
+
results << var unless mapping.has_key? var.theory_variable_id
|
126
|
+
end
|
127
|
+
end
|
128
|
+
return results
|
129
|
+
end
|
130
|
+
|
119
131
|
def extend_mapping(valid_mappings,component,runtime_method,test_cases,chain,available_values)
|
120
132
|
|
121
133
|
new_mappings = []
|
122
134
|
component.theory_variables.each do |var|
|
123
135
|
next if valid_mappings.first.has_key?(var.theory_variable_id)
|
136
|
+
#next if valid_mappings.any? {|x| x.has_key?(var.theory_variable_id)}
|
124
137
|
valid_mappings.each do |mapping|
|
138
|
+
|
139
|
+
#next if mapping.has_key?(var.theory_variable_id)
|
125
140
|
|
126
141
|
#next if mapping.has_key?(var.theory_variable_id)
|
127
142
|
implemented_chain = chain.implement(Mapping.new(mapping))
|
data/lib/cauldron.rb
CHANGED
data/lib/cauldron/pot.rb
CHANGED
@@ -3,70 +3,76 @@ module Cauldron
|
|
3
3
|
class Pot
|
4
4
|
include ContainsTheories
|
5
5
|
|
6
|
-
VERSION = '0-
|
6
|
+
VERSION = '0-1-1'
|
7
7
|
|
8
8
|
def initialize()
|
9
|
-
|
9
|
+
StandardLogger.instance.level = Logger::FATAL
|
10
10
|
end
|
11
11
|
|
12
12
|
def brew(test_cases)
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
exclude = []
|
15
|
+
chain = next_chain(test_cases,exclude)
|
16
|
+
if chain.nil?
|
16
17
|
raise StandardError.new('Failed to generate a chain for this problem')
|
17
18
|
end
|
18
19
|
|
19
|
-
# => TODO This probably shouldn't be needed
|
20
|
-
written_chains = chains.collect {|x| x.write}
|
21
|
-
unique_written_chains = written_chains.uniq
|
22
|
-
unique_chains = []
|
23
|
-
chains.each do |x|
|
24
|
-
unless unique_chains.any? {|y| y.write == x.write}
|
25
|
-
unique_chains << x
|
26
|
-
end
|
27
|
-
end
|
28
|
-
chains = unique_chains
|
29
|
-
|
30
20
|
runtime_method = RuntimeMethod.new(MethodUsage.new(MethodParameter.new))
|
31
|
-
|
32
|
-
|
21
|
+
if chain_valid?(chain,test_cases.copy)
|
22
|
+
validator = TheoryChainValidator.new
|
33
23
|
unified_chain = chain.unify_chain
|
34
24
|
implementation_permutations = unified_chain.implementation_permuatations(runtime_method.copy,test_cases.copy,Mapping.new)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
25
|
+
return validator.build(runtime_method.copy,test_cases.copy,implementation_permutations)
|
26
|
+
else
|
27
|
+
exclude << chain.theories_sequence
|
28
|
+
chain = next_chain(test_cases,exclude)
|
29
|
+
if chain_valid?(chain,test_cases.copy)
|
30
|
+
validator = TheoryChainValidator.new
|
31
|
+
unified_chain = chain.unify_chain
|
32
|
+
implementation_permutations = unified_chain.implementation_permuatations(runtime_method.copy,test_cases.copy,Mapping.new)
|
33
|
+
return validator.build(runtime_method.copy,test_cases.copy,implementation_permutations)
|
34
|
+
end
|
45
35
|
end
|
46
36
|
return nil
|
47
37
|
|
48
38
|
end
|
49
39
|
|
40
|
+
def chain_valid?(chain,test_cases)
|
41
|
+
runtime_method = RuntimeMethod.new(MethodUsage.new(MethodParameter.new))
|
42
|
+
unified_chain = chain.unify_chain
|
43
|
+
implementation_permutations = unified_chain.implementation_permuatations(runtime_method.copy,test_cases.copy,Mapping.new)
|
44
|
+
|
45
|
+
# Go through each of the permutations and create the runtime method for the chain
|
46
|
+
validator = TheoryChainValidator.new
|
47
|
+
begin
|
48
|
+
result = validator.build(runtime_method.copy,test_cases.copy,implementation_permutations)
|
49
|
+
rescue StandardError => e
|
50
|
+
StandardLogger.instance.warning e
|
51
|
+
return false
|
52
|
+
end
|
53
|
+
return true
|
54
|
+
end
|
55
|
+
|
50
56
|
def complete_chains(test_cases)
|
57
|
+
return [next_chain(test_cases)]
|
58
|
+
end
|
59
|
+
|
60
|
+
def next_chain(test_cases,exclude=[])
|
51
61
|
|
52
62
|
theories = saved_theories
|
53
63
|
|
64
|
+
res = theories.collect {|x| x.theory_id }
|
65
|
+
|
54
66
|
runtime_method = RuntimeMethod.new(MethodUsage.new(MethodParameter.new))
|
55
|
-
|
56
|
-
|
57
|
-
tc_index_1 = IntrinsicLiteral.new(1)
|
58
|
-
param_0 = IntrinsicLiteral.new(0)
|
59
|
-
real_method = Parser.run('runtime_method')
|
60
|
-
|
61
|
-
# Create the thoery connector and the values available
|
62
|
-
# TODO These values should actually be retreived progressively
|
63
|
-
potential_values = MappingValues.new([tc,tc_index_0,tc_index_1,param_0,real_method])
|
67
|
+
|
68
|
+
potential_values = MappingValues.new([])
|
64
69
|
connector = TheoryConnector.new(potential_values)
|
65
70
|
|
66
71
|
# Attempt to generate a complete chain for the solution
|
67
|
-
chains = connector.generate_chains(runtime_method,test_cases,theories)
|
68
|
-
return chains
|
69
|
-
|
72
|
+
chains = connector.generate_chains(runtime_method,test_cases,theories,exclude)
|
73
|
+
return chains.first
|
74
|
+
|
75
|
+
end
|
70
76
|
|
71
77
|
def saved_theories
|
72
78
|
saved_theory_file_paths = Dir.glob(File.join(theory_repository_path,'*','dump'))
|
@@ -133,7 +139,11 @@ module Cauldron
|
|
133
139
|
|
134
140
|
# Define the theory's directory
|
135
141
|
theory_path = File.join(repository,theory.theory_id.to_s)
|
136
|
-
|
142
|
+
if File.exists?(theory_path)
|
143
|
+
puts theory_path+' already exists'
|
144
|
+
#raise StandardError.new('Directory already exists - how as this happened?') if File.exists?(theory_path)
|
145
|
+
return
|
146
|
+
end
|
137
147
|
|
138
148
|
# Save a file containing the theory
|
139
149
|
FileUtils.mkdir_p(theory_path)
|
data/lib/cauldron/terminal.rb
CHANGED
@@ -16,7 +16,7 @@ module Cauldron
|
|
16
16
|
@pot = Cauldron::Pot.new
|
17
17
|
@pot.clear
|
18
18
|
@output.puts '* Adding example case'
|
19
|
-
|
19
|
+
@pot.simmer(demo_one)
|
20
20
|
@pot.simmer(demo_two)
|
21
21
|
|
22
22
|
@output.puts "Thanks for trying Cauldron - it's at really early stage right now"
|
@@ -40,7 +40,7 @@ module Cauldron
|
|
40
40
|
|
41
41
|
def submit(input)
|
42
42
|
if input =~ /^RUN$/
|
43
|
-
@output.puts @pot.brew(@cases).basic_write
|
43
|
+
@output.puts @pot.brew(@cases).reset_ids!.basic_write
|
44
44
|
else
|
45
45
|
@cases << convert_to_example(separate_values(input))
|
46
46
|
end
|
data/lib/core/MethodUsage.rb
CHANGED
data/lib/core/TheoryGenerator.rb
CHANGED
@@ -232,10 +232,6 @@ class TheoryGenerator
|
|
232
232
|
)
|
233
233
|
end
|
234
234
|
end
|
235
|
-
# Add the 'if(var1 == var2)' statement
|
236
|
-
# TODO Might only allow values in the action at this point
|
237
|
-
# 'IfStatement.new(var2[var3][:params][var6],Equivalent.new,var2[var3][:output])'
|
238
|
-
# TODO Should the values be equal at this point??
|
239
235
|
|
240
236
|
# Exclude the runtime method from being included as a value (.write method becomes messy)
|
241
237
|
# also excludes the orginal test_cases.
|
@@ -206,7 +206,7 @@ class RuntimeMethod < StatementGroup
|
|
206
206
|
|
207
207
|
# Confirms that supplied statement is a statement
|
208
208
|
unless statement.kind_of? Statement or statement.kind_of?(StatementGroup)
|
209
|
-
raise StandardError.new('Only statements can be included in a runtime method')
|
209
|
+
raise StandardError.new('Only statements can be included in a runtime method not '+statement.class.to_s)
|
210
210
|
end
|
211
211
|
|
212
212
|
# Check if the statement creates a new variable - and add it the available variables
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class Statement
|
1
|
+
class Statement
|
2
2
|
include PrintVariables
|
3
3
|
include ActsAsStatement
|
4
4
|
include ActsAsCode
|
@@ -7,7 +7,9 @@ class Statement < Array
|
|
7
7
|
# TODO scope and statement level are confusing - not sure of the difference (I think it's legacy)
|
8
8
|
attr_writer :scope, :statement_level, :overrides, :statement_id
|
9
9
|
|
10
|
-
alias :array_push :push
|
10
|
+
#alias :array_push :push
|
11
|
+
|
12
|
+
|
11
13
|
|
12
14
|
@@statement_id = 0
|
13
15
|
|
@@ -27,9 +29,12 @@ class Statement < Array
|
|
27
29
|
# Sets the flag that indicates the structure of the statement
|
28
30
|
@structure = nil
|
29
31
|
|
32
|
+
@nodes = []
|
33
|
+
|
30
34
|
# Add the parameters to the array
|
31
35
|
parameters.each do |code|
|
32
|
-
|
36
|
+
# self.push(code.copy)
|
37
|
+
@nodes.push(code.copy)
|
33
38
|
end
|
34
39
|
|
35
40
|
# TODO I might change the statement_id to be determined by the structure
|
@@ -63,7 +68,7 @@ class Statement < Array
|
|
63
68
|
# as not.
|
64
69
|
#
|
65
70
|
def identify_overriding_statements(already_declared=[])
|
66
|
-
[BaseVariable,Equal].zip(
|
71
|
+
[BaseVariable,Equal].zip(@nodes) do |x,y|
|
67
72
|
return unless y.kind_of?(x)
|
68
73
|
end
|
69
74
|
already_declared.each do |x|
|
@@ -268,7 +273,8 @@ class Statement < Array
|
|
268
273
|
def push(code)
|
269
274
|
|
270
275
|
# Add the new piece of code to the statement
|
271
|
-
array_push(code)
|
276
|
+
#array_push(code)
|
277
|
+
@nodes << code
|
272
278
|
|
273
279
|
# Update the requirements to reflect the change
|
274
280
|
update
|
@@ -279,6 +285,48 @@ class Statement < Array
|
|
279
285
|
push(element)
|
280
286
|
end
|
281
287
|
|
288
|
+
def select_all(results=[],&block)
|
289
|
+
return @nodes.select_all(results,&block)
|
290
|
+
end
|
291
|
+
|
292
|
+
def each
|
293
|
+
@nodes.each {|x| yield x}
|
294
|
+
end
|
295
|
+
|
296
|
+
def last
|
297
|
+
return @nodes.last
|
298
|
+
end
|
299
|
+
|
300
|
+
def each_with_index
|
301
|
+
@nodes.each_with_index do |x,i|
|
302
|
+
yield x, i
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
def []=(index,value)
|
307
|
+
@nodes[index] = value
|
308
|
+
end
|
309
|
+
|
310
|
+
def [](index)
|
311
|
+
return @nodes[index]
|
312
|
+
end
|
313
|
+
|
314
|
+
def length
|
315
|
+
return @nodes.length
|
316
|
+
end
|
317
|
+
|
318
|
+
def select_all(results=[],&block)
|
319
|
+
return @nodes.select_all(results,&block)
|
320
|
+
end
|
321
|
+
|
322
|
+
def first
|
323
|
+
@nodes.first
|
324
|
+
end
|
325
|
+
|
326
|
+
def clear
|
327
|
+
@nodes.clear
|
328
|
+
end
|
329
|
+
|
282
330
|
# Indicates whether the statement is one that assigns
|
283
331
|
# a value to another. Essential "Does the statement
|
284
332
|
# contain an equals sign?"
|
@@ -432,8 +480,8 @@ class Statement < Array
|
|
432
480
|
# @param var The variable to replace any elements that match the block.
|
433
481
|
#
|
434
482
|
def replace_variable_if(var,&block)
|
435
|
-
container =
|
436
|
-
|
483
|
+
container = []
|
484
|
+
@nodes.each do |x|
|
437
485
|
if x.kind_of?(Variable)
|
438
486
|
if block.call(x)
|
439
487
|
container.push(var)
|
@@ -446,7 +494,10 @@ class Statement < Array
|
|
446
494
|
end
|
447
495
|
container.push(x.copy)
|
448
496
|
end
|
449
|
-
return container
|
497
|
+
#return self.copy(*container)
|
498
|
+
copied = self.copy().clear
|
499
|
+
container.each {|x| copied.push(x) }
|
500
|
+
return copied
|
450
501
|
|
451
502
|
end
|
452
503
|
|
@@ -470,29 +521,12 @@ class Statement < Array
|
|
470
521
|
# TODO Write test to retrieve declarared variable in a statement with two variables
|
471
522
|
# e.g. varA = varB-varC
|
472
523
|
#
|
473
|
-
# TODO Write tests for this
|
474
|
-
#
|
475
524
|
def find_variable(id)
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
next unless code.kind_of? Variable or code.kind_of? InstanceCallContainer
|
480
|
-
|
481
|
-
# Determine if the variable matches the id
|
482
|
-
if code.variable_id == id
|
483
|
-
|
484
|
-
# Does the statement declare a new variable?
|
485
|
-
if decalares_variable?
|
486
|
-
return find_variable_in_declaration_statement(code)
|
487
|
-
else
|
488
|
-
return code.copy
|
489
|
-
end
|
490
|
-
|
491
|
-
end
|
492
|
-
|
525
|
+
results = variables.select() {|x| x.variable_id == id}
|
526
|
+
if results.empty?
|
527
|
+
raise FailedToFindVariableError.new('Couldn\'t find variable with id = '+id.to_s+' in "'+self.write+'"')
|
493
528
|
end
|
494
|
-
|
495
|
-
raise FailedToFindVariableError.new('Couldn\'t find variable with id = '+id.to_s+' in "'+self.write+'"')
|
529
|
+
return results.first
|
496
530
|
end
|
497
531
|
|
498
532
|
# Returns the variable in this statement with uniq_id specified. In
|
@@ -616,7 +650,7 @@ class Statement < Array
|
|
616
650
|
# and come up with a solution then.
|
617
651
|
#
|
618
652
|
def to_literal_string
|
619
|
-
return
|
653
|
+
return @nodes.inject('') do |complete,part|
|
620
654
|
complete += part.to_literal_string
|
621
655
|
end
|
622
656
|
end
|
@@ -736,7 +770,7 @@ class Statement < Array
|
|
736
770
|
# statement. In all likelyhood there will no more than one.
|
737
771
|
#
|
738
772
|
def find_all_required_runtime_methods
|
739
|
-
defcalls =
|
773
|
+
defcalls = @nodes.find_all {|x| x.kind_of?(DefCall)}
|
740
774
|
return defcalls.collect {|x| x.runtime_method}
|
741
775
|
end
|
742
776
|
|
@@ -900,121 +934,6 @@ class Statement < Array
|
|
900
934
|
end
|
901
935
|
|
902
936
|
protected
|
903
|
-
|
904
|
-
# Presumes this is a declaration statement and attempts to return
|
905
|
-
# specified variable in the context of the method.
|
906
|
-
#
|
907
|
-
def find_variable_in_declaration_statement(var)
|
908
|
-
|
909
|
-
# Duplicate the variable
|
910
|
-
# TODo I think I want to get rid of this "copy_contextual_variable"and just use copy
|
911
|
-
copied_variable = var.copy_contextual_variable
|
912
|
-
|
913
|
-
# Is the variable declared in this statement?
|
914
|
-
if(self[0].variable_id == copied_variable.variable_id)
|
915
|
-
|
916
|
-
# Create a requirement reflecting the declaration statement
|
917
|
-
# e.g varA = 'test'.chop becomes self = 'test'.chop
|
918
|
-
# statement_requirement = declared_variable_requirement
|
919
|
-
|
920
|
-
# Add this requirement to the variable and return it
|
921
|
-
# copied_variable.push(statement_requirement)
|
922
|
-
|
923
|
-
# TODO I think determining the value of variables at this point should
|
924
|
-
# be removed or re-thought. I think the typify method is more useful.
|
925
|
-
# The problem is that each statement is dependent on other statements
|
926
|
-
# or method calls.
|
927
|
-
|
928
|
-
# # NOTE I have included the untyped_variables call becuase it was continually throwing
|
929
|
-
# # since so many statements include method calls.
|
930
|
-
# if self.untyped_variables.length == 0 && !contains_method_call?
|
931
|
-
# # Convert the variable to be typed (if possible)
|
932
|
-
# if copied_variable.kind_of?(Unknown)
|
933
|
-
# begin
|
934
|
-
# return copied_variable.classify(CodeEvaluation.new.evaluate_code(literalise))
|
935
|
-
# # TODO I shouldn't use NameError - since I want to catch badly formed syntax - I
|
936
|
-
# # should have a custom error for bad syntax that will occu
|
937
|
-
# rescue NameError => e
|
938
|
-
# StandardLogger.log(' -- Statement: find_variable_in_declaration_statement'+e)
|
939
|
-
# end
|
940
|
-
# end
|
941
|
-
# end
|
942
|
-
|
943
|
-
return copied_variable
|
944
|
-
|
945
|
-
else
|
946
|
-
|
947
|
-
# The variable isn't declared in this statement
|
948
|
-
# So if varB is the declared variriable we might have
|
949
|
-
# varB = varA.chop
|
950
|
-
#
|
951
|
-
# This would create the requirement self.chop = varB
|
952
|
-
#
|
953
|
-
# Declare the statement requirement to be created
|
954
|
-
statement_requirement = nil
|
955
|
-
|
956
|
-
# Does the statement only have three elements
|
957
|
-
if(self.length == 3)
|
958
|
-
|
959
|
-
# Create a requirement for the variable in the statement
|
960
|
-
if(self[2].kind_of?(InstanceCallContainer))
|
961
|
-
|
962
|
-
# Create the matching requirement
|
963
|
-
statement_requirement = Requirement.new(InstanceCallContainer.new(This.new,self[2].method_call.class.new),Equal.new,self[0].copy)
|
964
|
-
|
965
|
-
elsif(self[2].kind_of?(Variable))
|
966
|
-
|
967
|
-
# Create the requirement reflecting the statement
|
968
|
-
statement_requirement = Requirement.new(This.new,Equal.new,self[0].copy)
|
969
|
-
|
970
|
-
else
|
971
|
-
raise StandardError.new('Unexpected class type '+self[2].class.to_s)
|
972
|
-
end
|
973
|
-
|
974
|
-
else
|
975
|
-
|
976
|
-
raise StandardError.new('Unexpected statement length'+self.length.to_s+' for requirement re-write') unless self.length == 5
|
977
|
-
|
978
|
-
# Handle the case were we have varA = varB-varC and we want varB's requirement
|
979
|
-
# e.g. we need varB = varA+varC
|
980
|
-
|
981
|
-
# TODO This can probably be re-written to be more abstract
|
982
|
-
# Case varA = varB-varC
|
983
|
-
if( self[2].kind_of?(Variable) and self[3].kind_of?(Subtract) and self[4].kind_of?(Variable) )
|
984
|
-
|
985
|
-
# where varB is the subject -> this = varA + varC
|
986
|
-
if(self[2].variable_id == var.variable_id)
|
987
|
-
statement_requirement = Requirement.new(This.new,Equal.new,self[0].copy,Addition.new,self[4].copy)
|
988
|
-
end
|
989
|
-
|
990
|
-
# where varC is the subject -> this = varB-varA
|
991
|
-
if(self[4].variable_id == var.variable_id)
|
992
|
-
statement_requirement = Requirement.new(This.new,Equal.new,self[2].copy,Subtract.new,self[0].copy)
|
993
|
-
end
|
994
|
-
|
995
|
-
elsif(self[2].kind_of?(Variable) and self[3].kind_of?(Addition) and self[4].kind_of?(Variable) )
|
996
|
-
|
997
|
-
if(self[2].variable_id == var.variable_id)
|
998
|
-
statement_requirement = Requirement.new(This.new,Equal.new,self[0].copy,Subtract.new,self[4].copy)
|
999
|
-
end
|
1000
|
-
|
1001
|
-
if(self[4].variable_id == var.variable_id)
|
1002
|
-
statement_requirement = Requirement.new(This.new,Equal.new,self[2].copy,Addition.new,self[0].copy)
|
1003
|
-
end
|
1004
|
-
|
1005
|
-
else
|
1006
|
-
raise StandardError.new('Unknown statement structure "'+self.write+'"')
|
1007
|
-
end
|
1008
|
-
|
1009
|
-
end
|
1010
|
-
|
1011
|
-
# Adding the new requirement to the variable
|
1012
|
-
copied_variable.push(statement_requirement)
|
1013
|
-
return copied_variable
|
1014
|
-
|
1015
|
-
end
|
1016
|
-
|
1017
|
-
end
|
1018
937
|
|
1019
938
|
# @param var The subsitute variable
|
1020
939
|
# @param id The id of the substitee
|