Class: Idl::FunctionBodyAst

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

Instance Method Summary collapse

Constructor Details

#initialize(input, interval, stmts) ⇒ FunctionBodyAst

Returns a new instance of FunctionBodyAst.



4764
4765
4766
# File 'lib/idl/ast.rb', line 4764

def initialize(input, interval, stmts)
  super(input, interval, stmts)
end

Instance Method Details

#execute_unknown(symtab) ⇒ void Originally defined in module Executable

This method returns an undefined value.

“execute” the statement, forcing any variable assignments to an unknown state This is used down unknown conditional paths.

Parameters:

  • symtab (SymbolTable)

    The symbol table for the context

Raises:

  • ValueError if some part of the statement cannot be executed at compile time

#return_value(symtab) ⇒ Integer, ... Also known as: execute

Note:

arguments and template arguments must be put on the symtab before calling

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



4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
# File 'lib/idl/ast.rb', line 4799

def return_value(symtab)
  internal_error "Function bodies should be at global + 1 scope" unless symtab.levels == 2

  # go through the statements, and return the first one that has a return value
  stmts.each do |s|
    if s.is_a?(Returns)
      v = s.return_value(symtab)
      return v unless v.nil?
    else
      s.execute(symtab)
    end
  end

  value_error "No function body statement returned a value"
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



4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
# File 'lib/idl/ast.rb', line 4817

def return_values(symtab)
  internal_error "Function bodies should be at global + 1 scope" unless symtab.levels == 2

  values = []
  value_result = value_try do
    # if there is a definite return value, then just return that
    return [return_value(symtab)]
  end
  value_else(value_result) do
    # go through the statements, and collect return values
    # we can stop if we encounter a statement with a known return value
    stmts.each do |s|
      if s.is_a?(Returns)
        value_result = value_try do
          v = s.return_value(symtab)
          return values.push(v).uniq unless v.nil?
        end
        value_else(value_result) do
          values += s.return_values(symtab)
        end
      else
        s.execute(symtab)
      end
    end
  end

  values.uniq
end

#statementsObject



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

def statements = @children

#stmtsObject



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

def stmts = @children

#to_idlObject



4846
4847
4848
4849
4850
4851
4852
4853
# File 'lib/idl/ast.rb', line 4846

def to_idl
  result = ""
  # go through the statements, and return the first one that has a return value
  stmts.each do |s|
    result << s.to_idl
  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:



4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
# File 'lib/idl/ast.rb', line 4773

def type_check(symtab)
  internal_error "Function bodies should be at global + 1 scope (at #{symtab.levels})" unless symtab.levels == 2

  return_value_might_be_known = true

  stmts.each do |s|
    s.type_check(symtab)
    # next unless return_value_might_be_known

    # begin
    #   if s.is_a?(Returns)
    #     s.return_value(symtab)
    #     # if we reach here, the return value is known, so we don't have to go further
    #     break
    #   else
    #     s.execute(symtab)
    #   end
    # rescue ValueError
    #   return_value_might_be_known = false
    # end
  end
end