Class: Idl::IfAst

Inherits:
AstNode show all
Includes:
Executable, Returns
Defined in:
lib/idl/ast.rb

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, if_cond, if_body, elseifs, final_else_body) ⇒ IfAst

Returns a new instance of IfAst.

[View source]

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

#elseifsObject

[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

[View source]

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_bodyObject

[View source]

5457
# File 'lib/idl/ast.rb', line 5457

def final_else_body = @children.last

#if_bodyObject

[View source]

5455
# File 'lib/idl/ast.rb', line 5455

def if_body = @children[1]

#if_condObject

[View source]

5454
# File 'lib/idl/ast.rb', line 5454

def if_cond = @children[0]

#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

Parameters:

Returns:

  • (Array<Integer,Bool>)

    List of all possible return values

Raises:

  • ValueError if it is not possible to determine all return values at compile time

[View source]

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.

Returns:

  • (Boolean)

    true if the taken path is knowable at compile-time

Raises:

  • ValueError if the take path is not known at compile time

[View source]

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_idlString

Return valid IDL representation of the node (and its subtree)

Returns:

  • (String)

    IDL code for the node

[View source]

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

Parameters:

Raises:

[View source]

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