//
// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
//
// The contents of this file are covered under the licence agreement in the
// file "LICENCE" distributed with Cforall.
//
// CodeGenerator.h --
//
// Author           : Richard C. Bilson
// Created On       : Mon May 18 07:44:20 2015
// Last Modified By : Peter A. Buhr
// Last Modified On : Thu Jun  9 13:15:58 2016
// Update Count     : 29
//

#ifndef CODEGENV_H
#define CODEGENV_H

#include <list>

#include "SynTree/Declaration.h"
#include "SynTree/SynTree.h"
#include "SynTree/Visitor.h"

#include "SymTab/Indexer.h"

namespace CodeGen {
	class CodeGenerator : public Visitor {
	  public:
		static int tabsize;

		CodeGenerator( std::ostream &os );
		CodeGenerator( std::ostream &os, std::string, int indent = 0, bool infun = false );
		CodeGenerator( std::ostream &os, char *, int indent = 0, bool infun = false );

		//*** Declaration
		virtual void visit( StructDecl * );
		virtual void visit( FunctionDecl * );
		virtual void visit( ObjectDecl * );
		virtual void visit( UnionDecl *aggregateDecl );
		virtual void visit( EnumDecl *aggregateDecl );
		virtual void visit( TraitDecl *aggregateDecl );
		virtual void visit( TypedefDecl *typeDecl );
		virtual void visit( TypeDecl *typeDecl );

		//*** Initializer
		virtual void visit( SingleInit * );
		virtual void visit( ListInit * );

		//*** Constant
		virtual void visit( Constant * );

		//*** Expression
		virtual void visit( ApplicationExpr *applicationExpr );
		virtual void visit( UntypedExpr *untypedExpr );
		virtual void visit( NameExpr *nameExpr );
		virtual void visit( AddressExpr *addressExpr );
		virtual void visit( CastExpr *castExpr );
		virtual void visit( UntypedMemberExpr *memberExpr );
		virtual void visit( MemberExpr *memberExpr );
		virtual void visit( VariableExpr *variableExpr );
		virtual void visit( ConstantExpr *constantExpr );
		virtual void visit( SizeofExpr *sizeofExpr );
		virtual void visit( AlignofExpr *alignofExpr );
		virtual void visit( UntypedOffsetofExpr *offsetofExpr );
		virtual void visit( OffsetofExpr *offsetofExpr );
		virtual void visit( OffsetPackExpr *offsetPackExpr );
		virtual void visit( LogicalExpr *logicalExpr );
		virtual void visit( ConditionalExpr *conditionalExpr );
		virtual void visit( CommaExpr *commaExpr );
		virtual void visit( TupleExpr *tupleExpr );
		virtual void visit( TypeExpr *typeExpr );
		virtual void visit( AsmExpr * );

		//*** Statements
		virtual void visit( CompoundStmt * );
		virtual void visit( ExprStmt * );
		virtual void visit( AsmStmt * );
		virtual void visit( IfStmt * );
		virtual void visit( SwitchStmt * );
		virtual void visit( CaseStmt * );
		virtual void visit( BranchStmt * );
		virtual void visit( ReturnStmt * );
		virtual void visit( WhileStmt * );
		virtual void visit( ForStmt * );
		virtual void visit( NullStmt * );
		virtual void visit( DeclStmt * );

		void genAttributes( std::list< Attribute * > & attributes );

		template< class Iterator > void genCommaList( Iterator begin, Iterator end );

		struct Indenter {
			Indenter(CodeGenerator &cg) : cg(cg) {}
			CodeGenerator & cg;
			std::ostream& operator()(std::ostream & os);
		};

		void extension( Expression *expr ) {
			if ( expr->get_extension() ) {
				output << "__extension__ ";
			} // if
		} // extension
	  private:

		Indenter indent;
		int cur_indent;
		bool insideFunction;
		std::ostream &output;

		void printDesignators( std::list< Expression * > & );
		static std::string printLabels ( std::list < Label > & );
		void handleStorageClass( Declaration *decl );
		void handleAggregate( AggregateDecl *aggDecl );
		void handleTypedef( NamedTypeDecl *namedType );

	};

	template< class Iterator >
	void CodeGenerator::genCommaList( Iterator begin, Iterator end ) {
		if ( begin == end ) return;

		for ( ;; ) {
			(*begin++)->accept( *this );
			if ( begin == end ) return;
			output << ", ";
		} // for
	}

	inline bool doSemicolon( Declaration* decl ) {
		if ( FunctionDecl* func = dynamic_cast< FunctionDecl* >( decl ) ) {
			return ! func->get_statements();
		} // if
		return true;
	}
} // namespace CodeGen

#endif // CODEGENV_H

// Local Variables: //
// tab-width: 4 //
// mode: c++ //
// compile-command: "make install" //
// End: //
