cauldron 0.1.0 → 0.1.1

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 (131) hide show
  1. data/Gemfile +2 -0
  2. data/Rakefile +7 -0
  3. data/VERSION +1 -1
  4. data/features/cauldron_generates_runtime_method.feature +3 -2
  5. data/features/step_definitions/cauldron_steps.rb +0 -1
  6. data/features/support/method_1.example +3 -0
  7. data/features/support/method_2.example +6 -0
  8. data/lib/Chain.rb +140 -264
  9. data/lib/CodeHandler.rb +0 -4
  10. data/lib/ScopeDependencies.rb +1 -0
  11. data/lib/Theory.rb +12 -15
  12. data/lib/UnifiedChain.rb +265 -8
  13. data/lib/cauldron.rb +1 -1
  14. data/lib/cauldron/demos.rb +280 -0
  15. data/lib/cauldron/pot.rb +56 -30
  16. data/lib/cauldron/sexp2cauldron.rb +109 -126
  17. data/lib/cauldron/terminal.rb +5 -74
  18. data/lib/core/ClassMethodCallContainer.rb +14 -0
  19. data/lib/core/Container.rb +12 -2
  20. data/lib/core/InstanceCallContainer.rb +30 -4
  21. data/lib/core/TheoryGenerator.rb +2 -9
  22. data/lib/core/assignment/Equal.rb +1 -1
  23. data/lib/core/assignment/Equivalent.rb +1 -1
  24. data/lib/core/assignment/NotEqual.rb +1 -1
  25. data/lib/core/call_container/CallContainer.rb +7 -1
  26. data/lib/core/instance_call/Chop.rb +0 -9
  27. data/lib/core/instance_call/instance_calls.rb +8 -0
  28. data/lib/core/instance_call/length_equal.rb +1 -1
  29. data/lib/core/requirement/Requirement.rb +1 -0
  30. data/lib/core/runtime_class/class_names.rb +12 -12
  31. data/lib/core/runtime_method/ActsAsRuntimeMethod.rb +0 -7
  32. data/lib/core/runtime_method/RuntimeMethod.rb +59 -45
  33. data/lib/core/statement/ActsAsStatement.rb +1 -1
  34. data/lib/core/statement/ArrayAccess.rb +28 -2
  35. data/lib/core/statement/OpenStatement.rb +7 -0
  36. data/lib/core/statement/Statement.rb +22 -18
  37. data/lib/core/statement/TheoryStatement.rb +8 -1
  38. data/lib/core/syntax/Addition.rb +3 -2
  39. data/lib/core/syntax/If.rb +8 -0
  40. data/lib/core/syntax/Return.rb +1 -1
  41. data/lib/core/variable/BaseVariable.rb +0 -2
  42. data/lib/core/variable/MethodParameter.rb +4 -31
  43. data/lib/core/variable/Unknown.rb +1 -5
  44. data/lib/implemented_chain.rb +3 -2
  45. data/lib/required.rb +0 -1
  46. data/lib/ruby_code/String.rb +0 -17
  47. data/lib/theories.rb +25 -1
  48. data/lib/theory/TheoryAction.rb +35 -5
  49. data/lib/theory/TheoryChainValidator.rb +10 -8
  50. data/lib/theory/TheoryComponent.rb +17 -0
  51. data/lib/theory/TheoryConnector.rb +76 -9
  52. data/lib/theory/TheoryDependent.rb +2 -2
  53. data/lib/theory/TheoryImplementation.rb +7 -7
  54. data/lib/util/ClassEvaluation.rb +2 -7
  55. data/lib/util/MethodValidation.rb +10 -6
  56. data/lib/util/Parser.rb +26 -20
  57. data/lib/util/StringToTheory.rb +27 -3
  58. data/spec/cauldron/chain_spec.rb +24 -0
  59. data/spec/cauldron/demos_spec.rb +30 -0
  60. data/spec/cauldron/pot_spec.rb +66 -0
  61. data/spec/cauldron/runtime_method_spec.rb +47 -5
  62. data/spec/cauldron/sexp_2_cauldron_spec.rb +92 -0
  63. data/spec/cauldron/terminal_spec.rb +1 -1
  64. data/spec/cauldron/theory_action_spec.rb +20 -0
  65. data/spec/cauldron/theory_connector_spec.rb +52 -0
  66. data/spec/cauldron/theory_spec.rb +59 -0
  67. data/spec/cauldron/unified_chain_spec.rb +102 -0
  68. data/spec/spec_helper.rb +10 -1
  69. data/tasks/theory_tasks.rake +274 -0
  70. data/test/fixtures/implementation_results/0/dump +0 -0
  71. data/test/fixtures/theories/0/dump +0 -0
  72. data/test/fixtures/theories/1/dump +0 -0
  73. data/test/fixtures/theories/10/dump +0 -0
  74. data/test/fixtures/theories/11/dump +0 -0
  75. data/test/fixtures/theories/12/dump +0 -0
  76. data/test/fixtures/theories/13/declaration.txt +1 -1
  77. data/test/fixtures/theories/13/desc +1 -1
  78. data/test/fixtures/theories/13/dump +0 -0
  79. data/test/fixtures/theories/14/dump +0 -0
  80. data/test/fixtures/theories/15/dump +0 -0
  81. data/test/fixtures/theories/16/dump +0 -0
  82. data/test/fixtures/theories/17/dump +0 -0
  83. data/test/fixtures/theories/18/dump +0 -0
  84. data/test/fixtures/theories/19/dump +0 -0
  85. data/test/fixtures/theories/2/dump +0 -0
  86. data/test/fixtures/theories/20/declaration.txt +1 -1
  87. data/test/fixtures/theories/20/desc +1 -1
  88. data/test/fixtures/theories/20/dump +0 -0
  89. data/test/fixtures/theories/3/dump +0 -0
  90. data/test/fixtures/theories/4/dump +0 -0
  91. data/test/fixtures/theories/5/dump +0 -0
  92. data/test/fixtures/theories/6/dump +0 -0
  93. data/test/fixtures/theories/7/dump +0 -0
  94. data/test/fixtures/theories/8/dump +0 -0
  95. data/test/fixtures/theories/9/dump +0 -0
  96. data/test/fixtures/theory_implementations/0/declaration.txt +1 -1
  97. data/test/fixtures/theory_implementations/0/dump +0 -0
  98. data/test/fixtures/theory_implementations/1/declaration.txt +11 -0
  99. data/test/fixtures/theory_implementations/1/dump +0 -0
  100. data/test/fixtures/theory_implementations/2/declaration.txt +11 -0
  101. data/test/fixtures/theory_implementations/2/dump +0 -0
  102. data/test/output/simple_method.txt +0 -1
  103. data/test/tc_contextual_variables.rb +2 -41
  104. data/test/tc_describe.rb +1 -2
  105. data/test/tc_method.rb +2 -5
  106. data/test/unit/core/runtime_method/tc_realised_runtime_method.rb +5 -3
  107. data/test/unit/core/runtime_method/tc_runtime_method.rb +34 -56
  108. data/test/unit/core/statement/tc_block_statement.rb +2 -0
  109. data/test/unit/core/statement/tc_open_statement.rb +15 -6
  110. data/test/unit/core/statement/tc_statement.rb +4 -5
  111. data/test/unit/core/statement/tc_statement_dependencies.rb +1 -0
  112. data/test/unit/core/statement/tc_theory_statement.rb +2 -0
  113. data/test/unit/core/syntax/tc_if_container.rb +5 -5
  114. data/test/unit/core/tc_theory_generator_heavy.rb +1 -1
  115. data/test/unit/core/tracking/tc_history.rb +3 -1
  116. data/test/unit/core/variable/tc_method_parameter_variable.rb +2 -2
  117. data/test/unit/tc_chain_with_case_1.rb +1 -1
  118. data/test/unit/tc_method_usage.rb +1 -1
  119. data/test/unit/tc_theory.rb +8 -2
  120. data/test/unit/theory/tc_theory_action.rb +37 -5
  121. data/test/unit/theory/tc_theory_chain_validator.rb +3 -3
  122. data/test/unit/theory/tc_theory_connector.rb +2 -37
  123. data/test/unit/theory/tc_theory_dependent.rb +2 -0
  124. data/test/unit/theory/tc_theory_implementation.rb +5 -1
  125. data/test/unit/theory/tc_theory_result.rb +3 -2
  126. data/test/unit/util/tc_method_validation.rb +4 -1
  127. data/test/unit/util/tc_parser.rb +2 -0
  128. data/test/unit/util/tc_string_to_theory.rb +3 -2
  129. data/tmp/runtime_method_evaluation.rb +7 -4
  130. metadata +59 -13
  131. data/lib/core/syntax/IfContainer.rb +0 -100
@@ -36,7 +36,7 @@ protected
36
36
  when 0
37
37
  return StatementStructure::BLANK_STATEMENT
38
38
  when 1
39
- return StatementStructure::IF_STATEMENT if first.kind_of?(IfContainer)
39
+ return StatementStructure::IF_STATEMENT if first.kind_of?(If)
40
40
  #return StatementStructure::USAGE_STATEMENT if self.classes_match?(InstanceCallContainer)
41
41
  if self.classes_match?(InstanceCallContainer)
42
42
  if first.method_call.destructive?
@@ -1,3 +1,5 @@
1
+ # TODO I'm sure Container could replace ArrayAccess InstanceCallCOntainer etc.
2
+
1
3
  # TODO I am duplicating variables here with array, index, subject and method_call
2
4
  class ArrayAccess < InstanceCallContainer
3
5
  include VariableIncluded
@@ -67,9 +69,7 @@ class ArrayAccess < InstanceCallContainer
67
69
  def equivalent?(to)
68
70
  return false if to.class != self.class
69
71
  return false unless to.array.equivalent?(@array)
70
- #return false unless to.array == @array
71
72
  return false unless to.index.equivalent?(@index)
72
- #return false unless to.index == @index
73
73
  return true
74
74
  end
75
75
 
@@ -91,6 +91,32 @@ class ArrayAccess < InstanceCallContainer
91
91
  @index.replace_theory_variables!(mapping)
92
92
  end
93
93
 
94
+ end
95
+
96
+ def replace_variables_alt!(map)
97
+ if @array.kind_of?(TheoryVariable)
98
+ map.each do |key,value|
99
+ if @array.theory_variable_id == key.theory_variable_id
100
+ @array = value
101
+ break
102
+ end
103
+ end
104
+ else
105
+ @array.replace_variables_alt!(map)
106
+ end
107
+
108
+ #
109
+ if @index.kind_of?(TheoryVariable)
110
+ map.each do |key,value|
111
+ if @index.theory_variable_id == key.theory_variable_id
112
+ @index = value
113
+ break
114
+ end
115
+ end
116
+ elsif(@index.kind_of?(Literal))
117
+ else
118
+ @index.replace_variables_alt!(map)
119
+ end
94
120
  end
95
121
 
96
122
  end
@@ -131,6 +131,13 @@ class OpenStatement < StatementGroup
131
131
  end
132
132
  end
133
133
 
134
+ def subst_variable!(id,var)
135
+ @statement.subst_variable!(id,var)
136
+ self.each do |statement|
137
+ statement.subst_variable!(id,var)
138
+ end
139
+ end
140
+
134
141
  # Returns the statement_id of the embeded statement.
135
142
  #
136
143
  # TODO The nested statement should maybe have an idea
@@ -156,7 +156,6 @@ class Statement < Array
156
156
  self.each do |code|
157
157
  line += code.write
158
158
  break if code.object_id == self.last.object_id
159
- line += ' '
160
159
  end
161
160
  return line
162
161
  end
@@ -170,7 +169,6 @@ class Statement < Array
170
169
  self.each do |code|
171
170
  line += code.describe
172
171
  break if code.object_id == self.last.object_id
173
- line += ' '
174
172
  end
175
173
  return line
176
174
  end
@@ -206,9 +204,9 @@ class Statement < Array
206
204
  if code.kind_of?(Variable)
207
205
 
208
206
  line += code.write+'('+code.value.write+')'
209
- unless code == self.last
210
- line += ' '
211
- end
207
+ # unless code == self.last
208
+ # line += ' '
209
+ # end
212
210
  next
213
211
  end
214
212
 
@@ -507,12 +505,8 @@ class Statement < Array
507
505
  raise FailedToFindVariableError.new('Couldn\'t find a variable with the id '+uniq_id.to_s+' in "'+self.write+'"')
508
506
  end
509
507
 
510
- # TODO This doesn't check anything
511
- #
512
508
  def replace_variable!(id,var)
513
-
514
- unless var.kind_of?(Variable) then raise StandardError.new('Only expecting a variable') end
515
-
509
+
516
510
  # Find the variable to be replaced
517
511
  target = self.find_actual_variable(id)
518
512
 
@@ -536,6 +530,24 @@ class Statement < Array
536
530
 
537
531
  end
538
532
 
533
+ # TODO Not sure whether both replace_variable! and subst_variable! are both needed - either ways
534
+ # their names aren't descriptive enough to distinguish that one uses the uniq_id and one uses
535
+ # the variable.
536
+ #
537
+ def subst_variable!(id,var)
538
+ # => TODO Use replace_variable_if?
539
+ self.each_with_index do |token,i|
540
+ if token.kind_of?(Variable) && id == token.variable_id
541
+ self[i] = var
542
+ next
543
+ end
544
+ if token.kind_of?(Container)
545
+ self[i] = token.subst_variable!(id,var)
546
+ end
547
+ end
548
+ self
549
+ end
550
+
539
551
  # Returns a declaration for this statement. So it will look something
540
552
  # like -
541
553
  # Statement.new(StringVariable.new('test'),Equal.new,'test')
@@ -1139,14 +1151,6 @@ protected
1139
1151
 
1140
1152
  end
1141
1153
 
1142
- # This runs some simple checks of the structure of the statement
1143
- # for example if the statement had two = signs then that would
1144
- # invalidate it.
1145
- #
1146
- def validate_statment_structure
1147
-
1148
- end
1149
-
1150
1154
  # Returns the two arrays split between the kind of class
1151
1155
  # provided.
1152
1156
  #
@@ -45,6 +45,14 @@ class TheoryStatement < Statement
45
45
  #return TheoryDependent.new(rewritten_statement,@theory_component_id)
46
46
  end
47
47
 
48
+ # =>
49
+ # => map [<TheoryVariable>=><TheoryVariable>]
50
+ def replace_variables_alt!(map)
51
+ self.each do |x|
52
+ x.replace_variables_alt!(map)
53
+ end
54
+ end
55
+
48
56
  # TODO Maybe use a opject to handle the output of the statement.
49
57
  def describe(tab=0)
50
58
  line = ''
@@ -52,7 +60,6 @@ class TheoryStatement < Statement
52
60
  self.each do |code|
53
61
  line += code.describe
54
62
  break if code.object_id == self.last.object_id
55
- line += ' '
56
63
  end
57
64
  return line
58
65
  end
@@ -11,7 +11,7 @@ class Addition < InstanceCall
11
11
  end
12
12
 
13
13
  def write
14
- return ' +'
14
+ return ' + '
15
15
  end
16
16
 
17
17
  def to_literal_string
@@ -19,7 +19,8 @@ class Addition < InstanceCall
19
19
  end
20
20
 
21
21
  def closure
22
- return [' ','']
22
+ #return [' ','']
23
+ return ['','']
23
24
  end
24
25
 
25
26
  end
@@ -9,6 +9,10 @@ class If
9
9
  return ("\t"*tab)+'if'
10
10
  end
11
11
 
12
+ def describe(tab=0)
13
+ return write(tab)
14
+ end
15
+
12
16
  def copy
13
17
  return If.new
14
18
  end
@@ -17,6 +21,10 @@ class If
17
21
  return 'If.new'
18
22
  end
19
23
 
24
+ def to_literal_string
25
+ return write
26
+ end
27
+
20
28
  end
21
29
 
22
30
  # TODO I need to go over my "if statement" construction
@@ -7,7 +7,7 @@ class Return
7
7
  end
8
8
 
9
9
  def write(method_context=nil)
10
- return 'return'
10
+ return 'return '
11
11
  end
12
12
 
13
13
  def describe
@@ -9,8 +9,6 @@ class BaseVariable < Array
9
9
 
10
10
  include Variable
11
11
  include Token
12
- # TODO VariableIncluded is in Variable so i can probably get rid of the VariableIncluded
13
- #include VariableIncluded
14
12
 
15
13
  # TODO I think I'll get rid of the id parameter and just use blocks
16
14
  #
@@ -1,13 +1,9 @@
1
1
  class MethodParameter < BaseVariable
2
2
  attr_reader :usage_variable
3
+ attr_writer :variable_id
3
4
 
4
- # TODO I'm trying to move away from requirements
5
- #
6
- # @param *requirements Any number of requirements that describe the
7
- # the properties of the method variable.
8
- # For example self == 6
9
- def initialize(*requirements)
10
- super(nil)
5
+ def initialize(id=nil)
6
+ super(id)
11
7
  end
12
8
 
13
9
  # Returns true if this variables meets the requirements of the
@@ -66,11 +62,7 @@ class MethodParameter < BaseVariable
66
62
 
67
63
  # Print out each of the requirements
68
64
  copied_var.each do |x|
69
-
70
- #tmp = gets
71
65
  desc = x.describe(context)
72
-
73
- #tmp = gets
74
66
  desc.each_line do |l|
75
67
  line += "\t"+l
76
68
  end
@@ -83,9 +75,7 @@ class MethodParameter < BaseVariable
83
75
  end
84
76
 
85
77
  def copy
86
- result = self.class.new(*self) {{:variable_id => self.variable_id,:uniq_id=>@uniq_id, :uniq_id_history=>@uniq_id_history.copy}}
87
- result.instance_variable = @instance_variable
88
- return result
78
+ return Marshal.load(Marshal.dump(self))
89
79
  end
90
80
 
91
81
  # Returns a reference to the usage variable that is represented
@@ -186,21 +176,4 @@ private
186
176
 
187
177
  end
188
178
 
189
- # TODO Write tests for this
190
- def meets_requirements_of_instance_call(instance_call)
191
- #unless instance_call.literalisable?
192
- # raise StandardError.new('Unable to litralise instance call '+instance_call.write)
193
- #end
194
-
195
- # Attempt to litralise the variable
196
- # TODO The variable class returns a Literal the InstanceCallContainer returns a
197
- # value. They don't need to do different things.
198
- if(self.literalisable?)
199
- return self.literalise.value == instance_call.literalise
200
- else
201
- raise FailedVariableMatch.new('Unable to litralise variable to see if it meets requirements')
202
- end
203
-
204
- end
205
-
206
179
  end
@@ -62,12 +62,8 @@ class Unknown < BaseVariable
62
62
  line += write
63
63
 
64
64
  # Print out each of the requirements
65
- copied_var.each do |x|
66
-
67
- #tmp = gets
65
+ copied_var.each do |x|
68
66
  desc = x.describe(context)
69
-
70
- #tmp = gets
71
67
  desc.each_line do |l|
72
68
  line += "\t"+l
73
69
  end
@@ -3,11 +3,12 @@
3
3
  #
4
4
  class ImplementedChain
5
5
 
6
+ attr_reader :mapping
6
7
  #
7
8
  #
8
9
  #
9
- def initialize(nodes)
10
- @nodes = nodes
10
+ def initialize(nodes,mapping)
11
+ @nodes, @mapping = nodes, mapping
11
12
  end
12
13
 
13
14
  def each(&block)
@@ -187,7 +187,6 @@ require $LOC+File.join(['core','syntax','Addition'])
187
187
  require $LOC+File.join(['core','syntax','Do'])
188
188
  require $LOC+File.join(['core','syntax','If'])
189
189
  require $LOC+File.join(['core','syntax','BlockContainer'])
190
- require $LOC+File.join(['core','syntax','IfContainer'])
191
190
  require $LOC+File.join(['core','syntax','This'])
192
191
 
193
192
  require $LOC+File.join(['theory','TheoryVariable'])
@@ -45,15 +45,6 @@ class String
45
45
  return Literal.new(self.clone)
46
46
  end
47
47
 
48
- # TODO Write tests
49
- # Returns a requirement instance declaring this as a literal.
50
- #
51
- # Example 'test'.to_requirement -> Requirement.new(This.new,Equivalent.new,'test'.to_literal)
52
- #
53
- def to_requirement
54
- return Requirement.new(This.new,Equivalent.new,self.to_literal)
55
- end
56
-
57
48
  # Returns a statement declaring a variable with the value of
58
49
  # this string e.g.
59
50
  #
@@ -67,19 +58,11 @@ class String
67
58
  # TODO There is a BASH command `quote` and `quote_readline` that
68
59
  # might be more useful here.
69
60
  def escape_single_quotes
70
- # TODO I don't properly follow this
71
61
  return self.gsub(/[']/, '\\\\\'')
72
62
  end
73
63
 
74
64
  def cauldron_method_calls
75
65
  return ['.length']
76
- end
77
-
78
- protected
79
-
80
- def identify(x)
81
- # Check if it is a assignment
82
-
83
66
  end
84
67
 
85
68
  end
@@ -9,7 +9,31 @@ module ContainsTheories
9
9
  def setup
10
10
  @theory_1 = Theory.load_theory(1)
11
11
  @theory_2 = Theory.load_theory(2)
12
- @theory_3 = Theory.load_theory(3)
12
+ #@theory_3 = Theory.load_theory(3)
13
+ @theory_3 = theory_3
14
+ end
15
+
16
+ def theory_3
17
+
18
+ dependent_one = TheoryDependent.new(
19
+ StringToTheory.run(
20
+ "if(var1.realise2(var2[var3][:params]).params[0].value.length == var2[var3][:output])\nreturn true\nend"
21
+ )
22
+ )
23
+ action_one = TheoryAction.new(
24
+ TheoryStatement.new(
25
+ StringToTheory.run(
26
+ 'Statement.new(Return.new,InstanceCallContainer.new(var1.params[0],StringLength.new))'
27
+ )
28
+ ),
29
+ StringToTheory.run("var1.statement_id")
30
+ )
31
+ result_one = TheoryResult.new(
32
+ StringToTheory.run("if(var1.all_pass?(var2))\nreturn true\nend"),true
33
+ )
34
+ Theory.new([dependent_one],action_one,[result_one])
35
+
36
+
13
37
  end
14
38
 
15
39
  def load_theory_implementation(implementation_id)
@@ -44,7 +44,7 @@ class TheoryAction
44
44
  # the values in the mapping hash.
45
45
  #
46
46
  def map_to(mapping)
47
-
47
+
48
48
  # Duplicate the current statement before it is rewritten
49
49
  rewritten_statement = @action.copy
50
50
  target_id = @target_id.copy
@@ -53,10 +53,22 @@ class TheoryAction
53
53
  containers = [rewritten_statement,target_id].select_all {|x| x.respond_to?(:has?)}
54
54
  theory_variable_containers = containers.select {|x| x.has? {|y| y.kind_of?(TheoryVariable)}}
55
55
 
56
- # Rewrite the statement replacing the values
57
- theory_variable_containers.each do |z|
58
- z.replace_theory_variables!(mapping)
59
- end
56
+ # Do any of the containers contain each other?
57
+ # => TODO Need to prevent this
58
+ all_theory_variables = Set.new
59
+ theory_variable_containers.each do |x|
60
+ results = x.select_all([]) {|y| y.kind_of?(TheoryVariable)}
61
+ all_theory_variables += results
62
+ end
63
+
64
+ map = {}
65
+ all_theory_variables.each do |x|
66
+ next if mapping[x.theory_variable_id].nil?
67
+ map[x] = mapping[x.theory_variable_id]
68
+ end
69
+
70
+ rewritten_statement.replace_variables_alt!(map)
71
+ target_id.replace_variables_alt!(map)
60
72
 
61
73
  return ActionImplementation.new(rewritten_statement,target_id,@theory_component_id)
62
74
 
@@ -66,5 +78,23 @@ class TheoryAction
66
78
  return TheoryAction.new(@action.copy,@target_id,@theory_component_id)
67
79
  end
68
80
 
81
+ def statements_with_variable(variable_id)
82
+
83
+ # Duplicate the current statement before it is rewritten
84
+ rewritten_statement = @action.copy
85
+ target_id = @target_id.copy
86
+
87
+ # Find all containers of VariableDeclarations that declare a TheoryVariable
88
+ containers = [rewritten_statement,target_id].select_all {|x| x.respond_to?(:has?)}
89
+ theory_variable_containers = containers.select {|x| x.has? {|y| y.kind_of?(TheoryVariable)}}
90
+
91
+ results = theory_variable_containers.select do |x|
92
+ reg = eval '/var'+variable_id.to_s+'/'
93
+ x.write.match(reg)
94
+ end
95
+ return results
96
+
97
+ end
98
+
69
99
 
70
100
  end