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.
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