(*
  File: Graph.sml

  Compile the derivation graph for a PEPA model
*)
(* structure Graph :> Graph = *)
structure Graph =
struct

  val exceptionsRaised = ref 0

  local 
    fun lookup I [] = Error.internal_error ("undeclared identifier: " ^ HashTable.unhash I)
      | lookup I ((Id, P) :: t) = if I = Id then P else (lookup I t)

(*     fun lookup I [] =  *)
(*         Error.internal_error ("undeclared identifier: " ^ HashTable.unhash I) *)
(*       | lookup I ((Id, P) :: t) = if I = Id then P else *)
(* 	(TextIO.output(TextIO.stdOut, "rejected: "^(HashTable.show Id)^" \n"); *)
(* 	 TextIO.flushOut(TextIO.stdOut); *)
(* 	 (lookup I t) *)
(* 	 ) *)

    fun graph E (A as (Pepa.PREFIX ((alpha, rate), P)))
	    = usual E A
      | graph E (A as (Pepa.CHOICE (P, Q)))
	    = usual E A
(*       | graph E (A as (Pepa.COOP (P, Q, L))) *)
(* 	    = usual E A *)
(* gcla - remove later *)
      | graph E (A as (Pepa.COOP (_, L))) 
	    = usual E A
      | graph E (A as (Pepa.HIDING (P, L)))
	    = usual E A
      | graph E (A as (Pepa.VAR I))
	    = let val A' = lookup I E 
	       in (graph E A';  ())
              end
      | graph E (A as (Pepa.CONSTS (I, P, L)))
	    = graph ((I, P) :: E) L

    and list E A [] = ()
      | list E A ((a, _, A')::t) = 
		    ((graph E A'); 
		     (list E A' t);
		     ())

    and usual E A =
       case Table.addState A of
         Table.AlreadySeen _ => ()
       | Table.NotYetSeen stateCode => 
	   let  val dA = Derivatives.derivative E A
	    in   
	      map (fn ((a,r), n, A') => 
		(
		 Statespace.addTransition (A, SOME ((a,r), n), A'))) dA;
                 Table.markSeen stateCode;
		 list E A dA;
		 () 
	   end 


  in
    fun compile C = 
        (Table.initialize();
         Statespace.initialize (); 
	 graph [] C;
	 Statespace.finalize();
	 map (RewLang.processAttachment C) (!Identifiers.attachmentids);
	 ()
	 )
  end  

end;
