// This file is part of the AspectC++ compiler 'ac++'.
// Copyright (C) 1999-2003  The 'ac++' developers (see aspectc.org)
//                                                                
// This program is free software;  you can redistribute it and/or 
// modify it under the terms of the GNU General Public License as 
// published by the Free Software Foundation; either version 2 of 
// the License, or (at your option) any later version.            
//                                                                
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  
// GNU General Public License for more details.                   
//                                                                
// You should have received a copy of the GNU General Public      
// License along with this program; if not, write to the Free     
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
// MA  02111-1307  USA                                            

#ifndef __Transformer_h__
#define __Transformer_h__

#include "clang/Basic/SourceManager.h"

#include "CodeWeaver.h"
#include "ACErrorStream.h"
#include "ACToken.h"
#include "AspectIncludeCluster.h"
#include "PosHints.h"
#include "Plan.h"

class PointCut;
class ModelBuilder;
class ACConfig;
class ACProject;
class IncludeGraph;

typedef std::list<std::tuple<std::string, std::string>> DepRules;

// The transformer drives the code transformation for a single translation unit.
class Transformer {
      ACErrorStream &_err;
      ACProject &_project;
      CodeWeaver _code_weaver;
      PosHints _pos_hints;
      clang::SourceManager *_phase1_sm;
      ACConfig &_conf;
      list<AspectIncludeCluster> _aspect_include_clusters;
      string _aspect_includes;
      string _aspect_fwd_decls;
      set<ACFileID> _touched_files;
      set<ACFileID> _virtual_files;
      DepRules _deps;
      
      bool phase1 (const string &tunit_name,
          ModelBuilder &, IncludeGraph&, bool gen_deps);
      bool phase2 (const string &tunit_name,
          ModelBuilder &, IncludeGraph&);
      void include_aspect (const char *name);
      void determine_aspect_includes (const IncludeGraph &ig);
      void determine_aspect_fwd_decls (ModelBuilder &);
      void aspect_include_cluster (const char *ah_file, const IncludeGraph &ig);
      void determine_aspect_cluster (ACFileID ah_unit,
        const IncludeGraph &ig, set<ACFileID> &cluster);
      void prepare_dynamic_weaving (ModelBuilder &jpm);
      void cleanup (ModelBuilder &jpm);
      void insert_bypass_class (ModelBuilder &);
      void join_points (ModelBuilder &, Plan &);

      // add references to the introduced elements to the plan
      void link_members (ACM_Class &jpl);
      // add references to the introduced base classes to the plan
      void link_bases (ACM_Class &jpl);
      void reinitializeSourceManager(clang::CompilerInstance *ci,
          CodeWeaver &cwb, const char *name);

   public:

      Transformer (ACErrorStream &e, ACProject &p,
                   ACConfig &c, LineDirectiveMgr &ldm):
        _err (e), _project (p), _code_weaver (p, ldm, c), _conf (c) {}
      ACFileID work (const string &tunit_name, bool gen_deps = false);
      list<AspectIncludeCluster> aspect_include_clusters () const { return _aspect_include_clusters; }
      const string &aspect_includes () const { return _aspect_includes; }
      const string &aspect_fwd_decls () const { return _aspect_fwd_decls; }
      const set<ACFileID> &touched_files () const { return _touched_files; }
      const DepRules &deps() const { return _deps; }
 };

#endif // __Transformer_h__
