// graph.h -- definition of dependency graph for lparse
// Copyright (C) 1999-2000 Tommi Syrjänen <Tommi.Syrjanen@hut.fi>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//  
// This program 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 General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//  

#ifndef GRAPH_H
#define GRAPH_H

#include "../config.h"
#ifndef GLOBAL_H
#include "global.h"
#endif
#ifndef ARRAY_H
#include "array.h"
#endif

// GraphNode implements nodes of the graph. Attributes are:
//     	- long size - how many children the node has
//	- long index - which node this is, no need actually, but can
//		       help debugging.
//	- ResizableArray *children  - array where children are kept
class GraphNode {
public:
  GraphNode(); 
  ~GraphNode() { delete children;}
  void AddChild(long chld);
  void ClearEdges();
  long size;
  long index;
  ResizableArray *children;
};


/* Graph implements the actual graph.
   Attributes:
   	GraphNodeArray *nodes	-- array of nodes
	long *visited		-- array used in cycle checking for
				   keeping information about visited
				   nodes. 
	DomainType *domain	-- array used in cycle checking for
	                           keeping information about domain
				   types of predicates.
        long size		-- size of the graph

   Methods:
   	void AddNode(long nd)	-- adds node 'nd' to graph. Does
        			   nothing if node is in graph
				   already. 
	void AddEdge(long a, long b) -- adds an edge (a,b) to the
				   graph. Doesn't remove duplicates. 
	
	void CheckCycles()	-- finds cycles in graph. Doesn't
			 	   return anything because Visit
				   updates all needed structures.
	int Visit(long nd)	-- Checks if there are any cycles in
				   paths starting from node 'nd' and
				   calculates domain of those
				   predicates that don't have
				   cycles. Also updates the predicates
				   array to correct domain status. 
	*/
class Graph {
public:
  Graph();
  ~Graph();

  void AddNode(long);
  void AddEdge(long, long);
  void CheckCycles();
  void PrintDomains();

  // sort the graph topologically, and store the results in "toposort"
  // array. For example, given edges 0->1 and 2->1 the toposort array
  // contains items: { 0, 2, 1 }. Returns '0' if the graph has cycles. 
  int TopologicalSort();
  void ClearEdges(); // empty the graph

  long GetPosition(long);

  void PropagateExternalDefinitions(long nd);
  
private:
  int Visit(long node);

  int TopologicalVisit(long node);

  GraphNodeArray *nodes;
  long *visited;
  long *toposort;
  DomainType *domain;
  long size;
  long counter;
};


#endif
