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) ⇒ Integer, ...
(also: #execute)
Evaluate the compile-time return value of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on the taken path), execute the node and update the symtab.
-
#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.
5494 5495 5496 5497 5498 5499 5500 |
# File 'lib/idl/ast.rb', line 5494 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
5491 |
# File 'lib/idl/ast.rb', line 5491 def elseifs = @children[2..-2] |
#execute_unknown(symtab) ⇒ Object
nothing to do for a function call
5699 5700 5701 5702 |
# File 'lib/idl/ast.rb', line 5699 def execute_unknown(symtab) if_body.execute_unknown(symtab) execute_unknown_after_if(symtab) end |
#final_else_body ⇒ Object
5492 |
# File 'lib/idl/ast.rb', line 5492 def final_else_body = @children.last |
#if_body ⇒ Object
5490 |
# File 'lib/idl/ast.rb', line 5490 def if_body = @children[1] |
#if_cond ⇒ Object
5489 |
# File 'lib/idl/ast.rb', line 5489 def if_cond = @children[0] |
#return_value(symtab) ⇒ Integer, ... Also known as: execute
Evaluate the compile-time return value of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on the taken path), execute the node and update the symtab
5554 5555 5556 5557 5558 5559 5560 |
# File 'lib/idl/ast.rb', line 5554 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
5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 |
# File 'lib/idl/ast.rb', line 5596 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.
5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 |
# File 'lib/idl/ast.rb', line 5541 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)
5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 |
# File 'lib/idl/ast.rb', line 5705 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
5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 |
# File 'lib/idl/ast.rb', line 5503 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 |