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

Module: Traces of GOTO Programs

Author: Daniel Kroening

  Date: July 2005

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

#include <assert.h>

#include "build_goto_trace.h"

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

Function: build_goto_trace

  Inputs:

 Outputs:

 Purpose:

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

void build_goto_trace(
  const symex_target_equationt &target,
  const prop_convt &prop_conv,
  goto_tracet &goto_trace)
{
  unsigned step_nr=0;
  
  for(symex_target_equationt::statest::const_iterator
      it=target.states.begin();
      it!=target.states.end();
      it++)
  {
    const symex_target_equationt::statet &state=*it;
    
    if(prop_conv.prop.l_get(state.guard_literal)!=tvt(true))
      continue;

    if(it->is_assignment())
    {    
      if(state.assignment_type==symex_target_equationt::HIDDEN)
        continue;

      if(it->assignment_type==symex_targett::INIT &&
         step_nr==0)
      {
      }
      else
        step_nr++;
    }
    else
      step_nr++;
    
    goto_trace.steps.push_back(goto_trace_stept());    
    goto_trace_stept &goto_trace_step=goto_trace.steps.back();
    
    goto_trace_step.thread_nr=state.thread_nr;
    goto_trace_step.lhs=state.lhs;
    goto_trace_step.pc=state.pc;
    goto_trace_step.comment=state.comment;
    goto_trace_step.original_lhs=state.original_lhs;
    goto_trace_step.type=state.type;
    goto_trace_step.step_nr=step_nr;
    
    if(state.lhs.is_not_nil())
      prop_conv.get(state.lhs, goto_trace_step.value);
    
    for(std::list<exprt>::const_iterator
        j=state.output_args.begin();
        j!=state.output_args.end();
        j++)
    {
      if(j->is_constant() ||
         j->id()=="string-constant")
        goto_trace_step.output_args.push_back(*j);
      else
      {
        exprt tmp;
        prop_conv.get(*j, tmp);
        goto_trace_step.output_args.push_back(tmp);
      }
    }

    if(state.is_assert() ||
       state.is_assume())
    {
      goto_trace_step.guard=
        prop_conv.prop.l_get(state.cond_literal).is_true();
      
      if(!goto_trace_step.guard)
      {
        assert(state.is_assert());
        break;
      }
    }
  }
}
