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.



4729
4730
4731
# File 'lib/idl/ast.rb', line 4729

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) ⇒ Object Also known as: execute

Note:

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



4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
# File 'lib/idl/ast.rb', line 4764

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) ⇒ Object



4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
# File 'lib/idl/ast.rb', line 4782

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 definate 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



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

def statements = @children

#stmtsObject



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

def stmts = @children

#to_idlObject



4811
4812
4813
4814
4815
4816
4817
4818
# File 'lib/idl/ast.rb', line 4811

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:



4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
# File 'lib/idl/ast.rb', line 4738

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 futher
    #     break
    #   else
    #     s.execute(symtab)
    #   end
    # rescue ValueError
    #   return_value_might_be_known = false
    # end
  end
end