Class: BlockStatement
- Inherits:
-
OpenStatement
- Object
- Array
- StatementGroup
- OpenStatement
- BlockStatement
- Includes:
- ActsAsStatement, ActsAsTrackable
- Defined in:
- lib/core/statement/BlockStatement.rb
Overview
A nested statement is a special kind of statement group that contains a opening statement. For example the .each method of an array would be a nested statement.
Below is the parser intrepretaiton for var1.any? { |x| x.include? var2.id }
var1.any? do |x|
var2 = var1.chop
end
s(:iter,
s(:call,
s(:call, nil, :var1, s(:arglist)),
:any?,
s(:arglist)
),
s(:lasgn, :x),
s(:lasgn,
:var2,
s(:call,
s(:call, nil, :var1, s(:arglist)),
:chop,
s(:arglist)
)
)
)
=========================
var1.any? { |x| x.include? var2.id }
s(:iter,
s(:call,
s(:call, nil, :var1, s(:arglist)),
:any?,
s(:arglist)
),
s(:lasgn, :x),
s(:call,
s(:lvar, :x),
:include?,
s(:arglist,
s(:call,
s(:call, nil, :var2, s(:arglist)),
:id,
s(:arglist)
)
)
)
)
TODO I might just combine BlockStatement and StatementGroup since you
all groups of statements have a containing statement even if
that statement is a method.
e.g. [‘garrus’,‘wrex’].each do |x|
# internal_statements
end
This is equivalent to :iter of the parser
Direct Known Subclasses
Instance Attribute Summary
Attributes inherited from StatementGroup
#scope, #scope_id, #statement_level
Instance Method Summary collapse
- #copy ⇒ Object
-
#copy_base ⇒ Object
Creates a copy of the current nested statement but without any statements.
-
#declared_variable_id ⇒ Object
Returns the id of the block variable - although the terminolgy of declared might imply a = sign essential it is declared here.
-
#each_unrealised_variable ⇒ Object
Returns each unrealised variable.
- #find_statement_that_declares_variable(id) ⇒ Object
-
#find_variable(id) ⇒ Object
Returns the first copy of a variable it can find.
-
#initialize(statement, block_container = BlockContainer.new(BlockVariable.new), *internal_statements) ⇒ BlockStatement
constructor
TODO I’m not sure whether I need to use a statement since a instance call will generally do.
-
#is_simple? ⇒ Boolean
This is a quick check that really only applies to standard statements.
-
#not_declared_variables ⇒ Object
Returns all the variables used in the statement since the statement should never declare new variables.
-
#partial(limit) ⇒ Object
Returns a duplicate of this nested statement up until the the specified limt.
-
#realise2(method_map) ⇒ Object
Returns an unpdated nested statement that has been fully realised.
-
#realised? ⇒ Boolean
Returns true if the opening statement and all internal statements have been realised.
-
#statement_count ⇒ Object
Returns the number of statements represented by this nested statement.
-
#to_literal_string ⇒ Object
TODO This seems wrong there is no block or opening statement.
-
#trackify(tracking_method, line) ⇒ Object
TODO This duplicates allot of the calls in the super.trackify method Returns a new block statement that has been trackified.
-
#unrealised_variables ⇒ Object
Returns an array of all the unrealised variables in the nested statement.
-
#variables ⇒ Object
Returns an array of all the variables contained within the nested statement.
- #write(tab = 0) ⇒ Object
- #write_with_uniq_id(tab = 0) ⇒ Object
-
#write_with_value(tab = 0) ⇒ Object
Writes out the nested statement with the appropriate tabbing but also includes the value of variables within the output.
Methods included from ActsAsStatement
#classes_match?, #statement_type
Methods included from ActsAsTrackable
#abstract_variables_for_tracking, #tracking_statement
Methods inherited from OpenStatement
#describe, #has?, #replace_theory_variables!, #select_all, #statement_id, #subst_variable!, #tokens
Methods included from ActsAsCode
Methods inherited from StatementGroup
#array_push, #cauldron_method_calls, #describe, #find_all_required_runtime_methods, #find_container_at_level, #find_overriding_statements, #find_statement, #identify_overriding_statements, #push, #remove_simple, #statement_id
Methods inherited from Array
#cauldron_method_calls, #contains?, #select_all, #to_declaration, #to_intrinsic, #to_literal, #to_var
Constructor Details
#initialize(statement, block_container = BlockContainer.new(BlockVariable.new), *internal_statements) ⇒ BlockStatement
TODO I’m not sure whether I need to use a statement since a instance call will generally do. Although
I'll need to fix the tabbing in "write" if I stop it from using statements.
69 70 71 72 73 74 75 76 |
# File 'lib/core/statement/BlockStatement.rb', line 69 def initialize(statement,block_container=BlockContainer.new(BlockVariable.new),*internal_statements) super(statement,*internal_statements) #@statement = statement raise StandardError.new('Expecting block_container ') unless block_container.kind_of?(BlockContainer) @block_container = block_container end |
Instance Method Details
#copy ⇒ Object
120 121 122 123 124 125 126 127 128 |
# File 'lib/core/statement/BlockStatement.rb', line 120 def copy result = BlockStatement.new(@statement.copy,@block_container.copy,*self.collect {|x| x.copy}) # TODO This means the scope id is being incremented for statements only exist for the declaration result.scope_id = scope_id result.scope = scope.copy result.statement_level = statement_level return result end |
#copy_base ⇒ Object
Creates a copy of the current nested statement but without any statements
132 133 134 135 136 137 |
# File 'lib/core/statement/BlockStatement.rb', line 132 def copy_base result = BlockStatement.new(@statement.copy,@block_container.copy) # TODO This means the scope id is being incremented for statements only exist for the declaration result.scope_id = scope_id return result end |
#declared_variable_id ⇒ Object
Returns the id of the block variable - although the terminolgy of declared might imply a = sign essential it is declared here. TODO My approach implies only one block variable but there could
be more than that. I should allow multiple block variables.
158 159 160 161 |
# File 'lib/core/statement/BlockStatement.rb', line 158 def declared_variable_id raise StandardError.new('Not allowing multiple block variables just yet') if @block_container.length > 1 return @block_container.first.variable_id end |
#each_unrealised_variable ⇒ Object
Returns each unrealised variable
224 225 226 227 228 |
# File 'lib/core/statement/BlockStatement.rb', line 224 def each_unrealised_variable unrealised_variables.each do |x| yield x end end |
#find_statement_that_declares_variable(id) ⇒ Object
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/core/statement/BlockStatement.rb', line 263 def find_statement_that_declares_variable(id) @block_container.each do |x| if x.variable_id == id return self.copy end end self.each do |y| if y.kind_of?(Statement) if y.declared_variable_id == id then return y.copy end next end if y.kind_of?(BlockStatement) y.find_statement_that_declares_variable(variable_id) end end # TODO I would rather a custom error raise StandardError.new('Failed to find statement that declared variable id '+id.to_s) end |
#find_variable(id) ⇒ Object
Returns the first copy of a variable it can find.
TODO Really it should find the latest version of the variable
working backwards like the RuntimeMethod call. Although
this might be a redundant concept since I don't think there
can ever be more than one variable with the exact id.
247 248 249 250 |
# File 'lib/core/statement/BlockStatement.rb', line 247 def find_variable(id) failed_to_find = lambda{raise StandardError.new("Unable to find variable with id "+id.to_s) } return variables.detect(failed_to_find) {|x| x.variable_id == id} end |
#is_simple? ⇒ Boolean
This is a quick check that really only applies to standard statements. It checks that the statement doesn’t just re-declare an existing variable e.g. var_a = var_b would be classed as simple.
143 144 145 |
# File 'lib/core/statement/BlockStatement.rb', line 143 def is_simple? return false end |
#not_declared_variables ⇒ Object
Returns all the variables used in the statement since the statement should never declare new variables.
150 151 152 |
# File 'lib/core/statement/BlockStatement.rb', line 150 def not_declared_variables return @statement.variables end |
#partial(limit) ⇒ Object
Returns a duplicate of this nested statement up until the the specified limt.
TODO I need to use an array rather than a fixnum for the limit
since scope is lost otherwise. This seems a bit of hack
and I should revise.
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'lib/core/statement/BlockStatement.rb', line 321 def partial(limit) # Check that limit is greater 0 raise StandardError.new('At least one line is required to create nested statement') if limit == 0 # Add the nested statement and reduce the limit result = copy_base limit.pop # Goes through each statement contained in the nested statement and adds it # to the returned nested method until the limit has been reached or this # nested statement has exhausted its statements. index = 0 while(limit.length >0 && index < self.length) x = self[index] if x.kind_of?(Statement) result.push(x.copy) index += 1 limit.pop elsif x.kind_of(BlockStatement) result.push(x.partial(limit)) index += 1 end end return result end |
#realise2(method_map) ⇒ Object
Returns an unpdated nested statement that has been fully realised.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/core/statement/BlockStatement.rb', line 168 def realise2(method_map) # Start by realising the containing method opening_statement = @statement.realise2(method_map) # Now realise the block container block_container = @block_container.realise2(method_map) # Finally realise the internal statements copied_internal_statements = [] self.each do |x| copied_internal_statements.push(x.realise2(method_map)) end # Now create a duplicate nested statement result = BlockStatement.new(opening_statement,block_container,*copied_internal_statements) result.scope_id = scope_id result.scope = scope.copy result.statement_level = statement_level return result end |
#realised? ⇒ Boolean
Returns true if the opening statement and all internal statements have been realised.
203 204 205 206 207 208 |
# File 'lib/core/statement/BlockStatement.rb', line 203 def realised? return false unless @statement.realised? return false unless @block_container.realised? return false unless self.all? {|x| x.realised? } return true end |
#statement_count ⇒ Object
Returns the number of statements represented by this nested statement.
NOTE I have been counting the opening statement and closing statement
as separate statements. I'm not sure if this is the write
approach though. I might have line_count and statement_count
236 237 238 |
# File 'lib/core/statement/BlockStatement.rb', line 236 def statement_count return self.inject(2) {|count,x| count += x.statement_count} end |
#to_literal_string ⇒ Object
TODO This seems wrong there is no block or opening statement
192 193 194 195 196 197 198 |
# File 'lib/core/statement/BlockStatement.rb', line 192 def to_literal_string a = '' self.each do |x| a += x.to_literal_string end return a end |
#trackify(tracking_method, line) ⇒ Object
TODO This duplicates allot of the calls in the super.trackify method Returns a new block statement that has been trackified. A trackified block statement has a statement call after each line.
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/core/statement/BlockStatement.rb', line 290 def trackify(tracking_method,line) # First copy the base nested statement and repopulate it result = copy_base # Start by trackifying the opening statement opening_variables = abstract_variables_for_tracking(@statement,@block_container) result.push(tracking_statement(tracking_method,line,@statement,opening_variables)) # For each line in the nested statement include a tracking call # TODO I don't think this would trackify further open statements self.each do |x| result.push(x.copy) # Now include a tracking call for after the statement line_variables = abstract_variables_for_tracking(x) # TODO Check that the line is going up result.push tracking_statement(tracking_method,line,x,line_variables) end return result end |
#unrealised_variables ⇒ Object
Returns an array of all the unrealised variables in the nested statement
212 213 214 215 216 217 218 219 220 |
# File 'lib/core/statement/BlockStatement.rb', line 212 def unrealised_variables results = [] results += @statement.unrealised_variables results += @block_container.unrealised_variables self.each do |x| results += x.unrealised_variables end return results end |
#variables ⇒ Object
Returns an array of all the variables contained within the nested statement.
255 256 257 258 259 260 261 |
# File 'lib/core/statement/BlockStatement.rb', line 255 def variables results = [] results += @statement.variables.collect {|x| x.copy} results += @block_container.variables.collect {|x| x.copy} self.each {|x| results += x.variables} return results end |
#write(tab = 0) ⇒ Object
78 79 80 81 82 83 84 85 86 |
# File 'lib/core/statement/BlockStatement.rb', line 78 def write(tab=0) l = @statement.write(tab)+' '+Do.new.write+" "+@block_container.write+"\n" self.each do |x| l += x.write(tab+1)+"\n" end tab.times {l += "\t" } l += 'end'+"\n" return l end |
#write_with_uniq_id(tab = 0) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/core/statement/BlockStatement.rb', line 88 def write_with_uniq_id(tab=0) # Check the file type of tab raise StandardError.new('Unexpexted class "'+tab.class.to_s+'" for Fixnum (number of tabs)') unless tab.kind_of? Fixnum line = @statement.write_with_uniq_id(tab)+Do.new.write+" "+@block_container.write_with_uniq_id+"\n" self.each do |x| if x.respond_to?('write_with_uniq_id') line += x.write_with_uniq_id(tab+1)+"\n" else line += x.write(tab+1)+"\n" end end tab.times {line += "\t" } line += 'end'+"\n" return line end |
#write_with_value(tab = 0) ⇒ Object
Writes out the nested statement with the appropriate tabbing but also includes the value of variables within the output. This method presumes that the nested statement has been realised.
110 111 112 113 114 115 116 117 118 |
# File 'lib/core/statement/BlockStatement.rb', line 110 def write_with_value(tab=0) l = @statement.write_with_value(tab)+" "+Do.new.write+" "+@block_container.write_with_value+"\n" self.each do |x| l += x.write_with_value(tab+1)+"\n" end tab.times {l += "\t" } l += 'end'+"\n" return l end |