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

Module:

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

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

#include <error_handler.h>

#include "c_final.h"

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

Function: c_final

  Inputs:

 Outputs:

 Purpose:

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

void c_finalize_expression(
  const contextt &context,
  exprt &expr,
  message_handlert &message_handler)
{
  if(expr.id()=="symbol")
  {
    if(expr.type().id()=="incomplete_array")
    {
      symbolst::const_iterator it=
        context.symbols.find(expr.get("identifier"));

      if(it==context.symbols.end())
      {
        error_handlert error_handler(message_handler);
        error_handler.err
          << "failed to find symbol "
          << expr.get("identifier");
        error_handler.error();
        throw 0;
      }
      
      const symbolt &symbol=it->second;

      if(symbol.type.id()=="array")
        expr.type()=symbol.type;
      else if(symbol.type.id()=="incomplete_array")
      {
        error_handlert error_handler(message_handler);
        error_handler.err_location(symbol.location);
        error_handler.err
          << "symbol `" << symbol.display_name()
          << "' has incomplete type";
        error_handler.error();
        throw 0;            
      }
      else
      {
        error_handlert error_handler(message_handler);
        error_handler.err_location(symbol.location);
        error_handler.err
          << "symbol `" << symbol.display_name()
          << "' has unexpected type";
        error_handler.error();
        throw 0;      
      }
    }
  }

  if(expr.has_operands())
    Forall_operands(it, expr)
      c_finalize_expression(context, *it, message_handler);
}

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

Function: c_final

  Inputs:

 Outputs:

 Purpose:

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

bool c_final(contextt &context, message_handlert &message_handler)
{
  try
  {
    Forall_symbols(it, context.symbols)
    {
      symbolt &symbol=it->second;

      if(symbol.mode=="C")
      {
        c_finalize_expression(context, symbol.value, message_handler);
      }
    }
  }

  catch(int e)
  {
    return true;
  }

  return false;
}
