/* $Id$
 *
 * Lookup Symbols (currently only References) and annotate them with the
 * corresponding Data nodes.
 *
 * Copyright (C) 2010 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 __LOOKUP_SYMBOLS_HPP_INCLUDED
#define __LOOKUP_SYMBOLS_HPP_INCLUDED

#include "intermediate/visitor/StandardTraversal.hpp"
#include <string>
#include <list>

namespace intermediate {

//! Lookup and resolve symbols in intermediate code.
/** This visitor can resolve Symbols in the intermediate code.
 *  Currently it looks up References.
 */
class LookupSymbols : public StandardTraversal {
public:
	// c'tor
	LookupSymbols() : currentContainer(NULL) {}

private:
	//! visit a CodeContainer node
	/** @param node node that gets visited.
	 */
	virtual void visit(CodeContainer &node);

	//! visit a Reference node
	/** @param node node that gets visited.
	 */
	virtual void visit(Reference &node);

	//! visit a SetParam node
	/** @param node node that gets visited.
	 */
	virtual void visit(SetParam &node);

	//! visit a Call node
	/** @param node node that gets visited.
	 */
	virtual void visit(Call &node);

	//! visit a Proc node
	/** @param node node that gets visited.
	 */
	virtual void visit(Proc &node);

	//! find the target container of a Call or Proc opcode.
	/** @param name look for a container with this name
	 *  @return target container or NULL if not found.
	 */
	const CodeContainer *findCallee(const std::string &name) const;

	//! find the Data definition of a Symbol.
	/** @param name search for symbol Name.
	 *  @return corresponding Data definition.
	 *  @todo this implementation is very simple and
	 *        should be optimized for speed.
	 */
	Data *findSymbol(const std::string &name) const;

	//! currently processed CodeContainer
	const CodeContainer *currentContainer;

	/* ----------------- Nested class: CompareData ----------------- */

	//! subclass implementing a comparison of a Data object with a string
	class CompareData {
	public:
		//! c'tor
		/** @param n Name that should match the comparison. */
		CompareData(const std::string &n) : name(n) {}
		//! Predicate that matches if the string is equal to the name
		/** @param d Data object that should get compared.
		 *  @return true if the name of the data object is the same as
		 *          our name, false otherwise.
		 */
		bool operator ()(const Data *d) const;

	private:
		//! name to match
		const std::string &name;
	};
};

}; /* namespace intermediate */

#endif /* __LOOKUP_SYMBOLS_HPP_INCLUDED */
