//
// 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.
//
// Initializer.cc --
//
// Author           : Richard C. Bilson
// Created On       : Mon May 18 07:44:20 2015
// Last Modified By : Rob Schluntz
// Last Modified On : Fri May 13 13:23:03 2016
// Update Count     : 28
//

#include "Initializer.h"
#include "Expression.h"
#include "Statement.h"
#include "Common/utility.h"

Initializer::Initializer( bool maybeConstructed ) : maybeConstructed( maybeConstructed ) {}
Initializer::Initializer( const Initializer & other ) : maybeConstructed( other.maybeConstructed ) {
}


Initializer::~Initializer() {}

std::string Initializer::designator_name( Expression *des ) {
	if ( NameExpr *n = dynamic_cast<NameExpr *>(des) )
		return n->get_name();
	else
		throw 0;
}

void Initializer::print( std::ostream &os, int indent ) {}

SingleInit::SingleInit( Expression *v, const std::list< Expression *> &_designators, bool maybeConstructed ) : Initializer( maybeConstructed ), value ( v ), designators( _designators ) {
}

SingleInit::SingleInit( const SingleInit &other ) : Initializer(other), value ( maybeClone( other.value ) ) {
	cloneAll(other.designators, designators );
}

SingleInit::~SingleInit() {
	delete value;
	deleteAll(designators);
}

void SingleInit::print( std::ostream &os, int indent ) {
	os << std::endl << std::string(indent, ' ' ) << "Simple Initializer: " << std::endl;
	os << std::string(indent+4, ' ' );
	value->print( os, indent+4 );

	if ( ! designators.empty() ) {
		os << std::endl << std::string(indent + 2, ' ' ) << "designated by: " << std::endl;
		for ( std::list < Expression * >::iterator i = designators.begin(); i != designators.end(); i++ ) {
			os << std::string(indent + 4, ' ' );
			( *i )->print(os, indent + 4 );
		}
	} // if
}

ListInit::ListInit( const std::list<Initializer*> &_initializers, const std::list<Expression *> &_designators, bool maybeConstructed )
	: Initializer( maybeConstructed ), initializers( _initializers ), designators( _designators ) {
}

ListInit::ListInit( const ListInit & other ) : Initializer( other ) {
	cloneAll( other.initializers, initializers );
	cloneAll( other.designators, designators );
}


ListInit::~ListInit() {
	deleteAll( initializers );
	deleteAll( designators );
}

void ListInit::print( std::ostream &os, int indent ) {
	os << std::endl << std::string(indent, ' ') << "Compound initializer:  ";
	if ( ! designators.empty() ) {
		os << std::string(indent + 2, ' ' ) << "designated by: [";
		for ( std::list < Expression * >::iterator i = designators.begin();
			  i != designators.end(); i++ ) {
			( *i )->print(os, indent + 4 );
		} // for

		os << std::string(indent + 2, ' ' ) << "]";
	} // if

	for ( std::list<Initializer *>::iterator i = initializers.begin(); i != initializers.end(); i++ )
		(*i)->print( os, indent + 2 );
}


ConstructorInit::ConstructorInit( Statement * ctor, Statement * dtor, Initializer * init ) : Initializer( true ), ctor( ctor ), dtor( dtor ), init( init ) {}
ConstructorInit::ConstructorInit( const ConstructorInit &other ) : Initializer( other ), ctor( maybeClone( other.ctor ) ), dtor( maybeClone( other.dtor ) ), init( maybeClone( other.init ) ) {
}

ConstructorInit::~ConstructorInit() {
	delete ctor;
	delete dtor;
	delete init;
}

void ConstructorInit::print( std::ostream &os, int indent ) {
	os << std::endl << std::string(indent, ' ') << "Constructor initializer: " << std::endl;
	if ( ctor ) {
		os << std::string(indent+2, ' ');
		os << "initially constructed with ";
		ctor->print( os, indent+4 );
	} // if

	if ( dtor ) {
		os << std::string(indent+2, ' ');
		os << "destructed with ";
		dtor->print( os, indent+4 );
	}

	if ( init ) {
		os << std::string(indent+2, ' ');
		os << "with fallback C-style initializer: ";
		init->print( os, indent+4 );
	}
}

std::ostream & operator<<( std::ostream & out, Initializer * init ) {
	init->print( out );
	return out;
}

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