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

Module: Goto Programs with Functions

Author: Daniel Kroening

Date: June 2003

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

#ifndef CPROVER_GOTO_CONVERT_FUNCTIONS_H
#define CPROVER_GOTO_CONVERT_FUNCTIONS_H

#include "goto_functions.h"
#include "goto_convert_class.h"

// start from "main"
void goto_convert_called(
  contextt &context,
  const optionst &options,
  goto_functionst &functions,
  message_handlert &message_handler);

// just convert it all
void goto_convert_all(
  contextt &context,
  const optionst &options,
  goto_functionst &functions,
  message_handlert &message_handler);
  
// remove function_pointer_calls
void remove_function_pointers(
  contextt &context,
  const optionst &options,
  goto_functionst &functions,
  message_handlert &message_handler);

class goto_convert_functionst:public goto_convertt
{
public:
  void goto_convert_all();
  void goto_convert_called();
  bool remove_function_pointers();
  void convert_function(const irep_idt &identifier);

  goto_convert_functionst(
    contextt &_context,
    const optionst &_options,
    goto_functionst &_functions,
    message_handlert &_message_handler);
  
  virtual ~goto_convert_functionst();

protected:
  goto_functionst &functions;
  
  static bool hide(const goto_programt &goto_program);

  //
  // function calls  
  //
  virtual void do_functioncall_symbol(
    const symbolt &symbol)
  {
    // add to todo-list
    function_queue.insert(symbol.name);
  }
  
  typedef std::set<irep_idt> function_queuet;
  function_queuet function_queue, function_done;
  
  void do_function_queue();
  
  void add_return(goto_functiont &f);

  void remove_function_pointer(
    const class value_propagationt &value_propagation,
    goto_programt &dest,
    goto_programt::targett target);

  bool remove_function_pointers(
    const class value_propagationt &value_propagation,
    goto_programt &dest);

  bool have_function_pointers();
  bool have_function_pointers(const goto_programt &dest);
};

#endif
