class AdLint::Cc1::SwitchStatementInterpreter
Public Class Methods
new(owner)
click to toggle source
Calls superclass method
AdLint::Cc1::SubInterpreter::new
# File lib/adlint/cc1/interp.rb, line 1462 def initialize(owner) super(owner, SwitchStatement) end
Public Instance Methods
visit_switch_statement(node)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1466 def visit_switch_statement(node) checkpoint(node.location) node.executed = true notify_switch_stmt_started(node) ctrlexpr = node.expression ctrlexpr_var = object_to_variable(interpret(ctrlexpr), ctrlexpr) notify_switch_ctrlexpr_evaled(node, ctrlexpr_var) notify_variable_value_referred(ctrlexpr, ctrlexpr_var) execute_switch_body(ctrlexpr_var, node.statement) notify_switch_stmt_ended(node) end
Private Instance Methods
complete?(block_items)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1628 def complete?(block_items) block_items.any? do |block_item| case block_item when GenericLabeledStatement, CaseLabeledStatement block_item = block_item.statement redo when DefaultLabeledStatement true else false end end end
enter_next_clause(labeled_stmt, block_items, idx, branch, branch_opts)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1575 def enter_next_clause(labeled_stmt, block_items, idx, branch, branch_opts) prepare_fall_through(branch, branch_opts, labeled_stmt) case labeled_stmt when DefaultLabeledStatement branch_opts.push(COMPLEMENTAL) end branch_opts.push(FINAL) if final_branch?(block_items, idx) branch.add_options(*branch_opts) case stmt = labeled_stmt.statement when CaseLabeledStatement, DefaultLabeledStatement enter_next_clause(stmt, block_items, idx, branch, branch_opts) end end
execute_branch(labeled_stmt, block_items, idx, branch_opts)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1526 def execute_branch(labeled_stmt, block_items, idx, branch_opts) ctrlexpr = labeled_stmt.normalized_expression ctrlexpr_val = value_of(interpret(ctrlexpr, QUIET)) case labeled_stmt when DefaultLabeledStatement branch_opts.push(COMPLEMENTAL) end case when ctrlexpr_val.test_must_be_true.true? branch_opts.push(FINAL, COMPLETE) when ctrlexpr_val.test_must_be_false.true? # NOTE: To end the current branch group of switch-statement if this # case-clause is the final one. branched_eval(ctrlexpr, *branch_opts) {} return seek_next_branch(block_items, idx) end branched_eval(ctrlexpr, *branch_opts) do |branch| case stmt = labeled_stmt.statement when CaseLabeledStatement, DefaultLabeledStatement # NOTE: Consecutive label appears! enter_next_clause(stmt, block_items, idx, branch, branch_opts) end interpret(labeled_stmt) idx += 1 while item = block_items[idx] case item when GenericLabeledStatement item.executed = true notify_label_defined(item) item = item.statement redo when CaseLabeledStatement, DefaultLabeledStatement # NOTE: Fall through! enter_next_clause(item, block_items, idx, branch, branch_opts) end interpret(item) idx += 1 end # NOTE: To simulate implicit breaking of the last case-clause. BreakEvent.of_break.throw end branch_opts.include?(FINAL) ? nil : seek_next_branch(block_items, idx) end
execute_switch_body(var, node)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1482 def execute_switch_body(var, node) checkpoint(node.location) node.executed = true scoped_eval do begin notify_block_started(node) execute_switch_branches(var, node.block_items) ensure notify_block_ended(node) end end end
execute_switch_branches(var, block_items)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1496 def execute_switch_branches(var, block_items) if complete?(block_items) base_opts = [SMOTHER_BREAK, IMPLICIT_COND, NARROWING, COMPLETE] else base_opts = [SMOTHER_BREAK, IMPLICIT_COND, NARROWING] end idx = 0 while block_item = block_items[idx] case block_item when GenericLabeledStatement block_item.executed = true notify_label_defined(block_item) block_item = block_item.statement redo when CaseLabeledStatement, DefaultLabeledStatement if final_branch?(block_items, idx) opts = base_opts + [FINAL] else opts = base_opts.dup end idx = execute_branch(block_item, block_items, idx, opts) break unless idx else interpret(block_item) idx += 1 end end end
final_branch?(block_items, idx)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1612 def final_branch?(block_items, idx) idx += 1 while block_item = block_items[idx] case block_item when GenericLabeledStatement block_item = block_item.statement redo when CaseLabeledStatement, DefaultLabeledStatement return false else idx += 1 end end true end
prepare_fall_through(branch, branch_opts, labeled_stmt)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1592 def prepare_fall_through(branch, branch_opts, labeled_stmt) value_domain_manip = nil branch.restart_versioning do ctrlexpr = labeled_stmt.normalized_expression ctrlexpr_val = value_of(interpret(ctrlexpr, QUIET)) case when ctrlexpr_val.test_must_be_true.true? branch_opts.push(FINAL, COMPLETE) when ctrlexpr_val.test_must_be_false.true? return end value_domain_manip = branch.ctrlexpr.ensure_true_by_widening(ctrlexpr) end value_domain_manip.commit! end
seek_next_branch(block_items, idx)
click to toggle source
# File lib/adlint/cc1/interp.rb, line 1642 def seek_next_branch(block_items, idx) idx += 1 while block_item = block_items[idx] case block_item when GenericLabeledStatement notify_label_defined(block_item) block_item = block_item.statement redo when CaseLabeledStatement, DefaultLabeledStatement return idx else idx += 1 end end nil end