Class: Idl::TernaryOperatorExpressionAst

Inherits:
AstNode
  • Object
show all
Includes:
Rvalue
Defined in:
lib/idl/ast.rb

Overview

Represents a ternary operator

for example:

condition ? a : b
(a < b) ? c : d

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, condition, true_expression, false_expression) ⇒ TernaryOperatorExpressionAst

Returns a new instance of TernaryOperatorExpressionAst.



3612
3613
3614
# File 'lib/idl/ast.rb', line 3612

def initialize(input, interval, condition, true_expression, false_expression)
  super(input, interval, [condition, true_expression, false_expression])
end

Instance Method Details

#conditionObject



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

def condition = @children[0]

#false_expressionObject



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

def false_expression = @children[2]

#to_idlString

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

Returns:

  • (String)

    IDL code for the node



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

def to_idl = "#{condition.to_idl} ? #{true_expression.to_idl} : #{false_expression.to_idl}"

#true_expressionObject



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

def true_expression = @children[1]

#type(symtab) ⇒ Type

Given a specific symbol table, return the type of this node.

Should not be called until #type_check is called with the same arguments

Parameters:

Returns:

  • (Type)

    The type of the node

Raises:



3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
# File 'lib/idl/ast.rb', line 3644

def type(symtab)
  condition.type_check(symtab)
  value_result = value_try do
    cond = condition.value(symtab)
    # if the condition is compile-time-known, only check the used field
    if cond
      return true_expression.type(symtab)
    else
      return false_expression.type(symtab)
    end
  end
  value_else(value_result) do
    t =
      if true_expression.type(symtab).kind == :bits && false_expression.type(symtab).kind == :bits
        true_width = true_expression.type(symtab).width
        false_width = false_expression.type(symtab).width
        if true_width == :unknown || false_width == :unknown
          Type.new(:bits, width: :unknown)
        else
          Type.new(:bits, width: [true_width, false_width].max)
        end
      else
        true_expression.type(symtab).clone
      end
    if condition.type(symtab).const? && true_expression.type(symtab).const? && false_expression.type(symtab).const?
      t.make_const
    end
    return t
  end
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:



3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
# File 'lib/idl/ast.rb', line 3617

def type_check(symtab)
  condition.type_check(symtab)
  if condition.type(symtab).kind == :bits
    type_error "ternary selector must be bool (maybe you meant '#{condition.text_value} != 0'?)"
  else
    type_error "ternary selector must be bool" unless condition.type(symtab).kind == :boolean
  end

  value_result = value_try do
    cond = condition.value(symtab)
    # if the condition is compile-time-known, only check the used field
    cond ? true_expression.type_check(symtab) : false_expression.type_check(symtab)
  end
  value_else(value_result) do
    true_expression.type_check(symtab)
    false_expression.type_check(symtab)

    unless true_expression.type(symtab).equal_to?(false_expression.type(symtab))
      # we'll allow dissimilar if they are both bits type
      unless true_expression.type(symtab).kind == :bits && false_expression.type(symtab).kind == :bits
        type_error "True and false options must be same type (have #{true_expression.type(symtab)} and #{false_expression.type(symtab)})"
      end
    end
  end
end

#value(symtab) ⇒ Object

Return the compile-time-known value of the node



3676
3677
3678
# File 'lib/idl/ast.rb', line 3676

def value(symtab)
  condition.value(symtab) ? true_expression.value(symtab) : false_expression.value(symtab)
end

#values(symtab) ⇒ Array<Integer>, ...

Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined

For most AstNodes, this will just be a single-entry array

Parameters:

  • symtab (SymbolTable)

    The context for the evaulation

Returns:

  • (Array<Integer>)

    The complete list of compile-time-known values, when they are integral

  • (Array<Boolean>)

    The complete list of compile-time-known values, when they are booleans

  • (AstNode::ValueError)

    if the list of values is not knowable at compile time



3681
3682
3683
3684
3685
3686
3687
3688
# File 'lib/idl/ast.rb', line 3681

def values(symtab)
  value_result = value_try do
    return condition.value(symtab) ? true_expression.values(symtab) : false_expression.values(symtab)
  end
  value_else(value_result) do
    (true_expression.values(symtab) + false_expression.values(symtab)).uniq
  end
end