Class: Idl::ConditionalReturnStatementAst

Inherits:
AstNode
  • Object
show all
Includes:
Returns
Defined in:
lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb,
lib/idlc/passes/reachable_functions.rb,
lib/idlc/passes/reachable_exceptions.rb

Constant Summary

Constants inherited from AstNode

AstNode::Bits1Type, AstNode::Bits32Type, AstNode::Bits64Type, AstNode::BoolType, AstNode::ConstBoolType, AstNode::PossiblyUnknownBits1Type, AstNode::PossiblyUnknownBits32Type, AstNode::PossiblyUnknownBits64Type, AstNode::ReachableFunctionCacheType, AstNode::StringType, AstNode::VoidType

Instance Attribute Summary

Attributes inherited from AstNode

#children, #input, #interval, #parent

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Returns

#expected_return_type

Methods inherited from AstNode

#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_dst_registers, #find_referenced_csrs, #find_src_registers, #freeze_tree, #gen_option_adoc, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #nullify_assignments, #pass_find_return_values, #path, #print_ast, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested

Constructor Details

#initialize(input, interval, return_expression, condition) ⇒ ConditionalReturnStatementAst

Returns a new instance of ConditionalReturnStatementAst.



7024
7025
7026
# File 'lib/idlc/ast.rb', line 7024

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

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
# File 'lib/idlc/ast.rb', line 7081

def self.from_h(yaml, source_mapper)
  raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "conditional_stmt"

  input = input_from_source_yaml(yaml.fetch("source"), source_mapper)
  interval = interval_from_source_yaml(yaml.fetch("source"))
  ConditionalReturnStatementAst.new(
    input, interval,
    AstNode.from_h(yaml.fetch("expr"), source_mapper),
    AstNode.from_h(yaml.fetch("condition"), source_mapper)
  )
end

Instance Method Details

#conditionObject



7022
# File 'lib/idlc/ast.rb', line 7022

def condition = @children[1]

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


7019
# File 'lib/idlc/ast.rb', line 7019

def const_eval?(symtab) = condition.const_eval?(symtab) && return_expression.const_eval?(symtab)

#gen_adoc(indent = 0, indent_spaces: 2) ⇒ Object



30
31
32
# File 'lib/idlc/passes/gen_adoc.rb', line 30

def gen_adoc(indent = 0, indent_spaces: 2)
  "#{' ' * indent}#{return_expression.gen_adoc(indent, indent_spaces:)} if (#{condition.gen_adoc(0, indent_spaces:)});"
end

#prune(symtab, forced_type: nil) ⇒ Object



596
597
598
599
600
601
602
603
604
605
606
607
# File 'lib/idlc/passes/prune.rb', line 596

def prune(symtab, forced_type: nil)
  value_result = value_try do
    if condition.value(symtab)
      return return_expression.prune(symtab)
    else
      return NoopAst.new
    end
  end
  value_else(value_result) do
    ConditionalReturnStatementAst.new(input, interval, return_expression.prune(symtab), condition.prune(symtab))
  end
end

#reachable_exceptions(symtab, cache = {}) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/idlc/passes/reachable_exceptions.rb', line 143

def reachable_exceptions(symtab, cache = {})
  mask = condition.is_a?(FunctionCallExpressionAst) ? condition.reachable_exceptions(symtab, cache) : 0
  value_result = value_try do
    if condition.value(symtab)
      mask |= return_expression.is_a?(FunctionCallExpressionAst) ? return_expression.reachable_exceptions(symtab, cache) : 0
        # ok
    end
  end
  value_else(value_result) do
    mask |= return_expression.is_a?(FunctionCallExpressionAst) ? return_expression.reachable_exceptions(symtab, cache) : 0
  end
  mask
end

#reachable_functions(symtab, cache = T.let({}, ReachableFunctionCacheType)) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/idlc/passes/reachable_functions.rb', line 160

def reachable_functions(symtab, cache = T.let({}, ReachableFunctionCacheType))
  fns = condition.is_a?(FunctionCallExpressionAst) ? condition.reachable_functions(symtab, cache) : []
  value_result = value_try do
    cv = condition.value(symtab)
    if cv
      fns.concat return_expression.reachable_functions(symtab, cache)
    end
  end
  value_else(value_result) do
    fns.concat return_expression.reachable_functions(symtab, cache)
  end

  fns
end

#return_expressionObject



7021
# File 'lib/idlc/ast.rb', line 7021

def return_expression = @children[0]

#return_type(symtab) ⇒ Type

Returns The actual return type.

Returns:

  • (Type)

    The actual return type



7036
7037
7038
# File 'lib/idlc/ast.rb', line 7036

def return_type(symtab)
  return_expression.return_type(symtab)
end

#return_types(symtab) ⇒ Array<Type>

Returns List of actual return types.

Returns:

  • (Array<Type>)

    List of actual return types



7041
7042
7043
# File 'lib/idlc/ast.rb', line 7041

def return_types(symtab)
  return_expression.return_types(symtab)
end

#return_value(symtab) ⇒ Integer, ...

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

Parameters:

  • symtab (SymbolTable)

    The symbol table for the context

Returns:

  • (Integer)

    The return value, if it is integral

  • (Boolean)

    The return value, if it is boolean

  • (nil)

    if the return value is not compile-time-known

Raises:

  • ValueError if, during evaluation, a node without a compile-time value is found



7047
7048
7049
7050
7051
7052
7053
# File 'lib/idlc/ast.rb', line 7047

def return_value(symtab)
  cond = condition.value(symtab)

  if cond
    return_expression.return_value(symtab)
  end
end

#return_values(symtab) ⇒ Array<Integer>, Array<Boolean>

Evaluate all possible compile-time return values of this node, or, if the node does not return (e.g., because it is an IfAst but there is no return on a possible path), execute the node and update the symtab

Parameters:

  • symtab (SymbolTable)

    The symbol table for the context

Returns:

  • (Array<Integer>)

    The possible return values. Will be an empty array if there are no return values

  • (Array<Boolean>)

    The possible return values. Will be an empty array if there are no return values

Raises:

  • ValueError if, during evaluation, a node without a compile-time value is found



7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
# File 'lib/idlc/ast.rb', line 7056

def return_values(symtab)
  value_result = value_try do
    cond = condition.value(symtab)

    return cond ? return_expression.return_values(symtab) : EMPTY_ARRAY

  end
  value_else(value_result) do
    # condition isn't known, so the return value is always possible
    return_expression.return_values(symtab)
  end
end

#to_hObject



7073
7074
7075
7076
7077
7078
# File 'lib/idlc/ast.rb', line 7073

def to_h = {
  "kind" => "conditional_stmt",
  "condition" => condition.to_h,
  "expr" => return_expression.to_h,
  "source" => source_yaml
}

#to_idlObject



7070
# File 'lib/idlc/ast.rb', line 7070

def to_idl = "#{return_expression.to_idl} if (#{condition.to_idl});"

#type_check(symtab, strict:) ⇒ 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:



7029
7030
7031
7032
7033
# File 'lib/idlc/ast.rb', line 7029

def type_check(symtab, strict:)
  condition.type_check(symtab, strict:)
  type_error "Condition must be boolean" unless condition.type(symtab).kind == :boolean
  return_expression.type_check(symtab, strict:)
end