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.



7039
7040
7041
# File 'lib/idlc/ast.rb', line 7039

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

Class Method Details

.from_h(yaml, source_mapper) ⇒ Object



7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
# File 'lib/idlc/ast.rb', line 7096

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



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

def condition = @children[1]

#const_eval?(symtab) ⇒ Boolean

Returns:

  • (Boolean)


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

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



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

def return_expression = @children[0]

#return_type(symtab) ⇒ Type

Returns The actual return type.

Returns:

  • (Type)

    The actual return type



7051
7052
7053
# File 'lib/idlc/ast.rb', line 7051

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



7056
7057
7058
# File 'lib/idlc/ast.rb', line 7056

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



7062
7063
7064
7065
7066
7067
7068
# File 'lib/idlc/ast.rb', line 7062

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



7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
# File 'lib/idlc/ast.rb', line 7071

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



7088
7089
7090
7091
7092
7093
# File 'lib/idlc/ast.rb', line 7088

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

#to_idlObject



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

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:



7044
7045
7046
7047
7048
# File 'lib/idlc/ast.rb', line 7044

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