/*******************************************************************\

Module: Function Inlining

Author: Daniel Kroening, kroening@cs.cmu.edu

\*******************************************************************/

#ifndef CPROVER_GOTO_INLINE_H
#define CPROVER_GOTO_INLINE_H

#include <std_types.h>
#include <hash_cont.h>

#include <error_handler.h>

#include "goto_functions.h"

// do a full inlining
void goto_inline(
  const goto_functionst &goto_functions,
  const namespacet &ns,
  goto_programt &dest,
  message_handlert &message_handler);

// inline those functions marked as "inlined"
void goto_partial_inline(
  goto_functionst &goto_functions,
  const namespacet &ns,
  message_handlert &message_handler);

class goto_inlinet:public error_handlert
{
public:
  goto_inlinet(
    const goto_functionst &_goto_functions,
    const namespacet &_ns,
    message_handlert &_message_handler):
    error_handlert(_message_handler),
    goto_functions(_goto_functions),
    ns(_ns)
  {
  }
  
  void goto_inline(goto_programt &dest);
  void goto_inline_rec(goto_programt &dest, bool full);

protected:
  const goto_functionst &goto_functions;
  const namespacet &ns;
  
  void expand_functioncall(
    goto_programt &dest,
    goto_programt::targett &target,
    const exprt &lhs, exprt &rhs,
    const exprt &constrain,
    bool recursive);
    
  void inline_other(
    goto_programt &dest,
    goto_programt::targett &it,
    bool &changed,
    bool full);
    
  void replace_return(
    goto_programt &body,
    const exprt &lhs,
    const exprt &constrain);
    
  void parameter_assignments(
    const code_typet &code_type,
    const exprt &call,
    goto_programt &dest);

  typedef hash_set_cont<irep_idt, irep_id_hash> recursion_sett;
  recursion_sett recursion_set;
  
  typedef hash_set_cont<irep_idt, irep_id_hash> no_body_sett;
  no_body_sett no_body_set;
};

#endif
