/* $Id$ 
 *
 * AST node representing a function call.
 *
 * Copyright (C) 2007-2009 FAUmachine Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */


#ifndef __FUNCTION_CALL_HPP_INCLUDED
#define __FUNCTION_CALL_HPP_INCLUDED

#include <list>
#include <cassert>
#include "frontend/ast/Name.hpp"
#include "frontend/ast/Expression.hpp"
#include "frontend/ast/FunctionDeclaration.hpp"
#include "frontend/ast/AssociationElement.hpp"

namespace ast {

//! represents a function call
/** This class represents one VHDL Function call.
 */
class FunctionCall : public Expression {
public:
	//! c'tor Functions with various arguments.
	/** @param fName name referring to the function declaration.
	 *  @param args argument list.
	 *  @param loc Location of the function call.
	 */
	FunctionCall(
		Name *fName,
		std::list<AssociationElement*> *args,
		Location loc
		) : 	Expression(loc),
			subprog(fName),
			arguments(args),
			definition(NULL) {}

	//! c'tor for unary Operator.
	/** @param fName name referring to the operator declaration.
	 *  @param operand operand of the unary operator.
	 *  @param loc Location of the operator symbol.
	 */
	FunctionCall(
		Name *fName,
		Expression *operand,
		Location loc
		) : 	Expression(loc),
			subprog(fName),
			arguments(new std::list<AssociationElement*>()),
			definition(NULL) {

			assert(operand);

			AssociationElement *elem = 
				new AssociationElement(NULL, operand, 
							operand->location);
			this->arguments->push_back(elem);
	}

	//! c'tor for binary Operator.
	/** @param fName name referring to the operator declaration.
	 *  @param left left operand of the binary operator.
	 *  @param right right operand of the binary operator.
	 *  @param loc Location of the operator symbol.
	 */
	FunctionCall(
		Name *fName,
		Expression *left,
		Expression *right,
		Location loc
		) : 	Expression(loc),
			subprog(fName),
			arguments(new std::list<AssociationElement*>()),
			definition(NULL) {

			assert(left);
			assert(right);

			AssociationElement *elem = 
				new AssociationElement(NULL, left, 
							left->location);
			this->arguments->push_back(elem);
			elem = new AssociationElement(NULL, right, 
							right->location);

			this->arguments->push_back(elem);
	}


	//! Accept a Visitor.
 	/** All leaf AST nodes need to implement this method.
         *
         *  @param visitor the Visitor that can visit this node.
         */
	virtual void accept(Visitor& visitor) {
		visitor.visit(*this);
	}

	/** Put a textual representation of the AstNode on the stream.
	 *  @param stream stream to put the textual representation to.
	 */
	virtual void put(std::ostream &stream) const {
		stream << this->subprog;
		if (  (this->arguments != NULL) 
		   && (this->arguments->size() > 1)) {
		   	stream << "(";
			util::MiscUtil::listPut(this->arguments, stream, ", ");
			stream << ')';
		}
	}


	/** name of the called function. */
	Name *subprog;
	/** arguments of the function call. */
	std::list<AssociationElement*> *arguments;
	/** definition of the FunctionCall */
	FunctionDeclaration *definition;

protected:
	/** Destructor */
	virtual ~FunctionCall() {
		util::MiscUtil::terminate(subprog);
		util::MiscUtil::lterminate(arguments);
		util::MiscUtil::terminate(definition);
	}
};

}; /* namespace ast */

#endif /* __FUNCTION_CALL_HPP_INCLUDED */
