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

#include "Condition.h"
#include "Naming.h"
#include "AdviceInfo.h"

class GenConditionCheck : public Condition::Visitor {
  std::ostream &out_;
  AdviceInfo *advice_info_;
  std::string src_this_;
  std::string tjp_prefix_;
public:
  GenConditionCheck(ostream &out, AdviceInfo* ai,
    const std::string &src_this, const std::string& tjp_prefix) :
    out_(out), advice_info_(ai), src_this_(src_this), tjp_prefix_(tjp_prefix) {}

  virtual void visit(const Condition &obj) {
    if (obj)
      obj.accept(*this);
    else
      out_ << "true";
  }

  virtual void visit(const Condition::That &obj) {
    out_ << src_this_ << "->";
    Naming::type_check_func(out_, obj.name());
    out_ << " ()";
  }

  virtual void visit(const Condition::Target &obj) {
    out_ << "dst.";
    Naming::type_check_func(out_, obj.name());
    out_ << " ()";
  }

  virtual void visit(const Condition::CFlow &obj) {
    Naming::cflow (out_, advice_info_->aspect (), obj.index());
    out_ << "::active ()";
  }

  virtual void visit(const Condition::And &obj) {
    out_ << "(";
    obj.left().accept(*this);
    out_ << "&&";
    obj.right().accept(*this);
    out_ << ")";
  }

  virtual void visit(const Condition::Or &obj) {
    out_ << "(";
    obj.left().accept(*this);
    out_ << "||";
    obj.right().accept(*this);
    out_ << ")";
  }

  virtual void visit(const Condition::Not &obj) {
    out_ << "!";
    obj.arg().accept(*this);
  }

  virtual void visit(const Condition::NeededShortCircuitArg &obj) {
    out_ << "(" << tjp_prefix_ << "_args["
      << obj.index_of_needed_sc_arg() << "] != 0)";
  }
};

#endif // __GenConditionCheck_h__
