cauldron 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/Gemfile +2 -1
  2. data/VERSION +1 -1
  3. data/features/cauldron_generates_runtime_method.feature +2 -2
  4. data/lib/Chain.rb +22 -6
  5. data/lib/UnifiedChain.rb +17 -2
  6. data/lib/cauldron.rb +3 -0
  7. data/lib/cauldron/pot.rb +50 -40
  8. data/lib/cauldron/terminal.rb +2 -2
  9. data/lib/core/ClassMethodCallContainer.rb +0 -1
  10. data/lib/core/MethodUsage.rb +0 -1
  11. data/lib/core/TheoryGenerator.rb +0 -4
  12. data/lib/core/runtime_method/RuntimeMethod.rb +1 -1
  13. data/lib/core/statement/ActsAsStatement.rb +1 -1
  14. data/lib/core/statement/Statement.rb +65 -146
  15. data/lib/core/statement/TheoryStatement.rb +1 -0
  16. data/lib/core/variable/FixnumVariable.rb +4 -5
  17. data/lib/core/variable/Unknown.rb +1 -11
  18. data/lib/core/variable/Variable.rb +1 -1
  19. data/lib/required.rb +0 -1
  20. data/lib/ruby_code/String.rb +0 -6
  21. data/lib/theory/TheoryConnector.rb +54 -117
  22. data/lib/util/ClassEvaluation.rb +9 -28
  23. data/lib/util/CodeEvaluation.rb +22 -18
  24. data/lib/util/DeclarationStatementEvaluation.rb +4 -3
  25. data/lib/util/MethodEvaluation.rb +6 -6
  26. data/lib/util/StatementCheck.rb +5 -3
  27. data/lib/util/StringToTheory.rb +0 -1
  28. data/spec/cauldron/pot_spec.rb +40 -0
  29. data/test/fixtures/theories/0/dump +0 -0
  30. data/test/fixtures/theories/1/dump +0 -0
  31. data/test/fixtures/theories/10/dump +0 -0
  32. data/test/fixtures/theories/11/dump +0 -0
  33. data/test/fixtures/theories/12/dump +0 -0
  34. data/test/fixtures/theories/13/dump +0 -0
  35. data/test/fixtures/theories/14/dump +0 -0
  36. data/test/fixtures/theories/15/dump +0 -0
  37. data/test/fixtures/theories/16/dump +0 -0
  38. data/test/fixtures/theories/17/dump +0 -0
  39. data/test/fixtures/theories/18/dump +0 -0
  40. data/test/fixtures/theories/19/dump +0 -0
  41. data/test/fixtures/theories/2/dump +0 -0
  42. data/test/fixtures/theories/20/dump +0 -0
  43. data/test/fixtures/theories/3/dump +0 -0
  44. data/test/fixtures/theories/4/dump +0 -0
  45. data/test/fixtures/theories/5/dump +0 -0
  46. data/test/fixtures/theories/6/dump +0 -0
  47. data/test/fixtures/theories/7/dump +0 -0
  48. data/test/fixtures/theories/8/dump +0 -0
  49. data/test/fixtures/theories/9/declaration.txt +1 -1
  50. data/test/fixtures/theories/9/desc +1 -1
  51. data/test/fixtures/theories/9/dump +0 -0
  52. data/test/ts_complete.rb +0 -1
  53. data/test/unit/core/runtime_method/tc_runtime_method.rb +0 -25
  54. data/test/unit/core/statement/tc_statement.rb +0 -52
  55. data/test/unit/core/tc_theory_generator.rb +2 -2
  56. data/test/unit/tc_theory.rb +2 -10
  57. data/test/unit/theory/tc_theory_action.rb +2 -6
  58. data/test/unit/util/tc_string_to_theory.rb +2 -2
  59. data/tmp/runtime_method_evaluation.rb +10 -7
  60. metadata +28 -30
  61. data/lib/core/runtime_class/IfStatementClass.rb +0 -12
  62. data/test/tc_contextual_variables.rb +0 -48
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ group :development do
10
10
  gem "bundler", "~> 1.0.15"
11
11
  gem "jeweler", "~> 1.6.2"
12
12
  gem "rcov", ">= 0"
13
- gem "ruby2ruby", "~>1.2.5"
14
13
  gem "ruby_parser", "~>2.0.6"
15
14
  end
15
+
16
+ gem "ruby2ruby", "~>1.2.5"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.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 method_3(var_6)\n\treturn var_6\nend\n" | 1 |
13
- | "'fish','animal'*'carrot','vegatable'" | "def method_3(var_0)\n\tif(var_0 == 'fish')\n\t\treturn 'animal'\n\tend\n\treturn 'vegetable'\nend\n" | 2 |
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 |
@@ -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
- finish = Parser.run("if(runtime_method.all_pass?(test_cases))\nreturn true\nend")
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
- @tail_theory = Theory.new([tail_dependent],nil,[])
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
  #
@@ -58,7 +58,7 @@ class UnifiedChain < Chain
58
58
  valid_mappings = [Mapping.new]
59
59
 
60
60
  #itteration_limit = 6
61
- itteration_limit = 8
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
- raise StandardError.new('Unable to resolve action: '+node.action.write)
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))
@@ -1,3 +1,6 @@
1
+ require 'rubygems'
2
+ require 'tempfile'
3
+
1
4
  require 'required'
2
5
 
3
6
  require 'cauldron/sexp2cauldron'
@@ -3,70 +3,76 @@ module Cauldron
3
3
  class Pot
4
4
  include ContainsTheories
5
5
 
6
- VERSION = '0-01'
6
+ VERSION = '0-1-1'
7
7
 
8
8
  def initialize()
9
- #StandardLogger.instance.level = Logger::FATAL
9
+ StandardLogger.instance.level = Logger::FATAL
10
10
  end
11
11
 
12
12
  def brew(test_cases)
13
13
 
14
- chains = complete_chains(test_cases)
15
- if chains.empty?
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
- chains.each do |chain|
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
- # Go through each of the permutations and create the runtime method for the chain
37
- validator = TheoryChainValidator.new
38
- begin
39
- result = validator.build(runtime_method.copy,test_cases.copy,implementation_permutations)
40
- rescue StandardError => e
41
- StandardLogger.instance.warning e
42
- next
43
- end
44
- return result
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
- tc = Parser.run('test_cases')
56
- tc_index_0 = IntrinsicLiteral.new(0)
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
- end
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
- raise StandardError.new('Directory already exists - how as this happened?') if File.exists?(theory_path)
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)
@@ -16,7 +16,7 @@ module Cauldron
16
16
  @pot = Cauldron::Pot.new
17
17
  @pot.clear
18
18
  @output.puts '* Adding example case'
19
- #@pot.simmer(demo('1'))
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
@@ -28,7 +28,6 @@ class ClassMethodCallContainer < CallContainer
28
28
  return @class_name.write+'.'+@method_call.to_literal_string
29
29
  end
30
30
 
31
- # TODO Write tests
32
31
  # Returns true if the supplied argument is the same class, has the equivalent subjects
33
32
  # and parameters.
34
33
  #
@@ -46,7 +46,6 @@ class MethodUsage < Array
46
46
  return MethodUsageVariable.new(*self.collect {|x| x.copy}) {{:variable_id => id,:uniq_id=>uniq_id}}
47
47
  end
48
48
 
49
- # TODO Test this
50
49
  def copy
51
50
  return MethodUsage.new(*self.collect {|x| x.copy})
52
51
  end
@@ -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
@@ -21,7 +21,7 @@ module ActsAsStatement
21
21
  #
22
22
  def classes_match?(*classes)
23
23
  return false unless classes.length == self.length
24
- self.zip(classes) do |x,y|
24
+ @nodes.zip(classes) do |x,y|
25
25
  return false unless x.instance_of?(y)
26
26
  end
27
27
  return true
@@ -1,4 +1,4 @@
1
- class Statement < Array
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
- self.push(code.copy)
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(self) do |x,y|
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 = self.copy.clear
436
- self.each do |x|
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
- # Go through each element of code in the statement and find instance calls and variables
478
- self.each do |code|
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 self.inject('') do |complete,part|
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 = self.find_all {|x| x.kind_of?(DefCall)}
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