// 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 __CodeGenerator_h__
#define __CodeGenerator_h__

#include <string>
#include <iostream>
#include <vector>

#include "BackEndProblems.h"
#include "AspectIncludes.h"

class AspectInfo;
class AdviceInfo;
class ACProject;
class ACFileID;
class ThisJoinPoint;
class ACM_Aspect;
class ACM_Code;
class ACM_Function;
class ACM_CodePlan;

class CodeGenerator {

  ACProject &project_;
  const BackEndProblems &beps_;

  // helper function that find the file (id) in which an aspect 'ai' is defined
  ACFileID aspect_unit (ACM_Aspect *a) const;

  static ACM_Function *that_func (ACM_Code *loc);
  
public:
  CodeGenerator(ACProject &project, const BackEndProblems &beps) :
    project_(project), beps_(beps) {}

  // generate the invocation function forward declarations for an aspect
  std::string aspect_ifct_decls (const AspectInfo &) const;

  // generate the invocation function definitions for an aspect
  std::string aspect_ifct_defs (const AspectInfo &) const;

  // generate the references / forward decls for an aspect and its advice
  std::string aspect_refs (const AspectRefSet &) const;

  // generate the JoinPoint data structure for a give code joinpoint
  void tjp_struct (std::ostream &code, const ThisJoinPoint &tjp, ACM_Code *loc,
    int depth) const;

  // generate the initialization of the JoinPoint data structure for a joinpoint
  void tjp_init (std::ostream &code, const ThisJoinPoint &tjp, ACM_Code *loc,
    int depth, bool is_dep = false, std::vector<std::string> *arg_names = 0,
    int wrapper_number = -1 ) const;

  // generate the call of an advice invocation function
  void advice_invocation_func_call (std::ostream &stmt,
    const AdviceInfo &advice_info, const std::string &tjp_tp,
    const std::string &tjp_obj);

  // generate the binding templates for according to the plan of a code joinpoint
  void binding_templates (std::ostream &out, ACM_CodePlan *plan,
    const std::string &jpname) const;

private:

  // generate declaration or definition of an advice invocation function
  void advice_invocation_func (std::ostream &out, const AdviceInfo &advice_info,
    bool def) const;

  // generate a binding template for advice
  void advice_binding_template (std::ostream &out,
    const AdviceInfo &advice_info, const std::string &jpname) const;

};

#endif // __CodeGenerator_h__
