// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: abstractor.h 831 2011-10-09 21:39:48Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#ifndef ABSTRACTOR_H
#define ABSTRACTOR_H

#include "system/variable.h"
#include <inttypes.h>
#include <set>

class Component;
class System;
class Process;
class Invariant;
class Edge;

class Abstractor {
protected:
    mutable uint32_t nrEdges;
    mutable uint32_t nrProcs;
    mutable uint32_t nrLocs;
    const System* system;          // the system to abstract
    System* asys;                  // the abstract system
    typedef std::set<const Component*> procset_t;
    procset_t abstract_procs;      // the procs to abstract
    varset_t abstract_vars;        // the variables to abstract
    std::set<std::string> symbols; // the names of the variables to abstract
    bool weak_abstraction;         // true iff only *guards* (and no
				   // invariants) are abstracted for
				   // clocks

    virtual bool find(const System* system, const std::string& name);
    
    virtual bool keepSymbol(const Variable* v) const;
    virtual bool keepSymbol(const std::string& name) const;
    virtual bool keepAllSymbols(const varset_t& vars) const;

    virtual Process* abstract_process(const Process* p);
    virtual Location* abstract_location(const Location* l, Process* aproc) const;
    virtual Edge* createEdge(const Edge* e, const Process* aproc) const;
    virtual Guard* abstract_guard(Guard* g) const;
    virtual ClockReset* abstract_clockreset(const ClockReset* r) const;
    virtual Invariant* abstract_invariant(Invariant* i) const;    

    virtual bool keep_constraint(Constraint* c) const;

    virtual void abstract_effect(const Edge* e, Process* aproc, Edge* aedge) const;
    virtual void abstract_edge(const Edge* e, Process* aproc) const;    
    virtual void abstract_declarations(const Component* comp, Component* acomp) const;
    
public:           
    Abstractor(const System* system, bool weak_abstraction) :
	nrEdges(0),
	nrProcs(0),
	nrLocs(0),
	system(system),
	asys(NULL),
	weak_abstraction(weak_abstraction)
    {}

    virtual ~Abstractor() {}
    
    virtual void abstractSymbol(const std::string& name);
    virtual System* abstract();  
    virtual void genPDBInfo(const std::string& filename) const;
};

class OldAbstractor : public Abstractor {
private:
    virtual void abstract_effect(const Edge* e, Process* aproc, Edge* aedge) const;
    std::vector<std::vector<int32_t> > var_deps;
    
    void compute_var_deps();
public:
    OldAbstractor(const System* system, bool weak_abstraction) : Abstractor(system, weak_abstraction) {}
    virtual System* abstract();  
};

class RedundancyCleaner {
private:
    void delOnlyReadVars(System* system) const;
public:
    RedundancyCleaner() {}

    bool relevant(const Edge* edge) const;
    void clean(System* system) const;
};

#endif /* ABSTRACTOR_H */
