Class: Idl::IfAst
- Includes:
- Executable, Returns
- Defined in:
- lib/idl/ast.rb
Instance Method Summary collapse
- #elseifs ⇒ Object
-
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call.
- #final_else_body ⇒ Object
- #if_body ⇒ Object
- #if_cond ⇒ Object
-
#initialize(input, interval, if_cond, if_body, elseifs, final_else_body) ⇒ IfAst
constructor
A new instance of IfAst.
- #return_value(symtab) ⇒ Object (also: #execute)
-
#return_values(symtab) ⇒ Array<Integer,Bool>
Returns a list of all possible return values, if known.
-
#taken_body(symtab) ⇒ Boolean
True if the taken path is knowable at compile-time.
-
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree).
-
#type_check(symtab) ⇒ void
type check this node and all children.
Constructor Details
#initialize(input, interval, if_cond, if_body, elseifs, final_else_body) ⇒ IfAst
Returns a new instance of IfAst.
5459 5460 5461 5462 5463 5464 5465 |
# File 'lib/idl/ast.rb', line 5459 def initialize(input, interval, if_cond, if_body, elseifs, final_else_body) children_nodes = [if_cond, if_body] children_nodes += elseifs children_nodes << final_else_body super(input, interval, children_nodes) end |
Instance Method Details
#elseifs ⇒ Object
[View source]
5456 |
# File 'lib/idl/ast.rb', line 5456 def elseifs = @children[2..-2] |
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call
5664 5665 5666 5667 |
# File 'lib/idl/ast.rb', line 5664 def execute_unknown(symtab) if_body.execute_unknown(symtab) execute_unknown_after_if(symtab) end |
#final_else_body ⇒ Object
[View source]
5457 |
# File 'lib/idl/ast.rb', line 5457 def final_else_body = @children.last |
#return_value(symtab) ⇒ Object Also known as: execute
[View source]
5519 5520 5521 5522 5523 5524 5525 |
# File 'lib/idl/ast.rb', line 5519 def return_value(symtab) body = taken_body(symtab) return nil if body.nil? body.return_value(symtab) end |
#return_values(symtab) ⇒ Array<Integer,Bool>
Returns a list of all possible return values, if known. Otherwise, raises a ValueError
5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 |
# File 'lib/idl/ast.rb', line 5561 def return_values(symtab) value_result = value_try do if_cond_value = if_cond.value(symtab) if if_cond_value # if is taken, so the only possible return values are those in the if body return if_body.return_values(symtab) else # if cond not taken; check else ifs and possibly final else return return_values_after_if(symtab) end end value_else(value_result) do # if condition not known; both paths are possible (if_body.return_values(symtab) + return_values_after_if(symtab)).uniq end end |
#taken_body(symtab) ⇒ Boolean
Returns true if the taken path is knowable at compile-time.
5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 |
# File 'lib/idl/ast.rb', line 5506 def taken_body(symtab) return if_body if if_cond.value(symtab) unless elseifs.empty? elseifs.each do |eif| return eif.body if eif.cond.value(symtab) end end final_else_body.stmts.empty? ? nil : final_else_body end |
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree)
5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 |
# File 'lib/idl/ast.rb', line 5670 def to_idl result = "if (#{if_cond.to_idl}) { " result << if_body.to_idl result << "} " elseifs.each do |eif| result << eif.to_idl end unless final_else_body.stmts.empty? result << " else { " result << final_else_body.to_idl result << "} " end result end |
#type_check(symtab) ⇒ void
This method returns an undefined value.
type check this node and all children
Calls to #type and/or #value may depend on type_check being called first with the same symtab. If not, those functions may raise an AstNode::InternalError
5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 |
# File 'lib/idl/ast.rb', line 5468 def type_check(symtab) level = symtab.levels if_cond.type_check(symtab) unless if_cond.type(symtab).convertable_to?(:boolean) if if_cond.type(symtab).kind == :bits type_error "'#{if_cond.text_value}' is not boolean. Maybe you meant 'if ((#{if_cond.text_value}) != 0)'?" else type_error "'#{if_cond.text_value}' is not boolean" end end if_cond_value = nil value_try do if_cond_value = if_cond.value(symtab) end # short-circuit the if body if we can if_body.type_check(symtab) unless if_cond_value == false internal_error "not at same level #{level} #{symtab.levels}" unless level == symtab.levels unless (if_cond_value == true) || elseifs.empty? elseifs.each do |eif| eif.type_check(symtab) end end internal_error "not at same level #{level} #{symtab.levels}" unless level == symtab.levels final_else_body.type_check(symtab) unless if_cond_value == true internal_error "not at same level #{level} #{symtab.levels}" unless level == symtab.levels end |