/*
 *  Copyright (c) 2008 Cyrille Berger <cberger@cberger.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * either version 2, or (at your option) any later version of the License.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef _AST_STATEMENT_H_
#define _AST_STATEMENT_H_

#include <list>

#include "Node.h"

namespace Cauchy {
  class Variable;
  namespace AST {
    class Expression;
    class FunctionDefinition;
    class GenerationVisitor;
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class Statement : public Node {
      public:
        virtual ~Statement() {}
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const = 0;
        /**
         * Set the comment that will be added at the end of the statement line
         */
        void setComment(const String& str);
        String comment() const;
      private:
        String m_comment;
    };
    /**
     * @internal
     * Statement that represent a comment.
     * @ingroup Cauchy_AST
     */
    class CommentStatement : public Statement {
      public:
        CommentStatement(const String& str);
        virtual ~CommentStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        String m_string;
    };
    /**
     * @internal
     * Statement that does nothing.
     * @ingroup Cauchy_AST
     */
    class DummyStatement : public Statement {
      public:
        virtual ~DummyStatement() {}
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class StatementsList : public Statement {
      public:
        StatementsList( const std::list<Statement*>& list ) : m_list( list) {}
        ~StatementsList();
        void appendStatement( Statement* );
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        std::list<Statement*> m_list;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class IfStatement : public Statement {
      public:
        IfStatement( Expression* _expression, Statement* _ifStatement) :
          m_expression( _expression), m_ifStatement( _ifStatement )
        {
        }
        ~IfStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        Expression* m_expression;
        Statement* m_ifStatement;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class IfElseStatement : public Statement {
      public:
        IfElseStatement( Expression* _expression, Statement* _ifStatement, const std::vector< std::pair<Expression*, Statement*> >& _elseIfStatements, Statement* _elseStatement ) :
          m_expression( _expression ), m_ifStatement(_ifStatement), m_elseStatement(_elseStatement), m_elseIfStatements(_elseIfStatements)
        {
        }
        ~IfElseStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        Expression* m_expression;
        Statement* m_ifStatement;
        Statement* m_elseStatement;
        std::vector< std::pair<Expression*, Statement*> > m_elseIfStatements;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class WhileStatement : public Statement {
      public:
        WhileStatement( Expression* _expression, Statement* _whileStatement)
        : m_expression(_expression), m_whileStatement(_whileStatement)
        {
        }
        ~WhileStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        Expression* m_expression;
        Statement* m_whileStatement;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class ForStatement : public Statement {
      public:
        ForStatement( Variable* var, Expression* _expression, Statement* _forStatement)
        : m_variable( var ), m_expression( _expression ), m_forStatement( _forStatement )
        {}
        ~ForStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        Variable* m_variable;
        Expression* m_expression;
        Statement* m_forStatement;
    };
    class BreakStatement : public Statement {
      public:
        BreakStatement();
        ~BreakStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class ReturnStatement : public Statement {
      public:
        /**
         * @param _returnExpr
         * @param _variablesToClean list of variables used so far, that will need to be
         *        cleaned by the return expression
         */
        ReturnStatement( AST::FunctionDefinition* _functionDeclaration);
        ~ReturnStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        AST::FunctionDefinition* m_functionDeclaration;
    };
    /**
     * @internal
     * @ingroup Cauchy_AST
     */
    class PrintStatement : public Statement {
      public:
        PrintStatement(Cauchy::AST::Expression* _expr );
        ~PrintStatement();
        virtual void generateStatement( GenerationVisitor* _generationVisitor) const;
      private:
        Cauchy::AST::Expression* m_expr;
    };
  }
}

#endif
