(* 
 File: Prettyprinter.sml

 The structure which prettyprints PEPA models
*)

structure Prettyprinter :> Prettyprinter =
struct

  datatype printmode = compressed | uncompressed | verbose
  datatype printstyle = OLD | NEW

  val style = ref OLD

  fun print mode = 
  let 
     fun pp (Pepa.PREFIX ((alpha, rate), P)) 
(* 	     = "("^printid alpha^", "^printid rate^")."^(pp P) *)
	     = "("^printid alpha^", "^(Expressions.toString (Expressions.simplify rate))^")."^(pp P)
       | pp (Pepa.CHOICE (P, Q)) 
	     = (pp P) ^ " + " ^ (pp Q)
       (* gcla - remove later *)
       | pp (Pepa.COOP (P, L)) 
	   = "(" ^ (prettylist P) 
	   ^ ")_{" ^ 
	   (if mode = verbose then " <" ^ (printlist L) ^ "> " else "|")
	       ^ "} "  
(*        | pp (Pepa.COOP (P, Q, L))  *)
(* 	     = (pp P)  *)
(* 	     ^ (if mode = verbose then " <" ^ (printlist L) ^ "> " else "|") *)
(* 	     ^ (pp Q) *)
       | pp (Pepa.HIDING (P, [])) 
	     = (pp P)
       | pp (Pepa.HIDING (P, L)) 
	     = (pp P) ^ "/{" ^ (printlist L) ^ "}"
       | pp (Pepa.VAR I) 
	     = printid I
       | pp (Pepa.CONSTS (I, P, L)) 
	     = printid I ^ " = " ^ (pp P) ^ ";\n" ^ (pp L)

	(* gcla - to restore old style process printing *)
     and pp2 (Pepa.PREFIX ((alpha, rate), P)) 
	     = "("^printid alpha^", "^(Expressions.toString (Expressions.simplify rate))^")."^(pp2 P)
       | pp2 (Pepa.CHOICE (P, Q)) 
	     = (pp2 P) ^ " + " ^ (pp2 Q)
       | pp2 (Pepa.COOP ([], L)) = ""
       | pp2 (Pepa.COOP ([P], L)) =
	 (pp2 P)
       | pp2 (Pepa.COOP ((P::Ps), L)) =
	 (pp2 P) ^ (if mode = verbose then
		       " <" ^ (printlist L) ^ "> "
		    else
		       "|") ^ (pp2 (Pepa.COOP (Ps, L)))

(*        | pp2 (Pepa.COOP (P, L))  *)
(* 	   = "(" ^ (prettylist P)  *)
(* 	   ^ ")_{" ^  *)
(* 	   (if mode = verbose then " <" ^ (printlist L) ^ "> " else "|") *)
(* 	       ^ "} "   *)
(*        | pp2 (Pepa.COOP (P, Q, L))  *)
(* 	     = (pp2 P)  *)
(* 	     ^ (if mode = verbose then " <" ^ (printlist L) ^ "> " else "|") *)
(* 	     ^ (pp2 Q) *)
(*        | pp2 (Pepa.HIDING (P, []))  *)
(* 	     = (pp2 P) *)
       | pp2 (Pepa.HIDING (P, L)) 
	 = (pp2 P) ^ "/{" ^ (printlist L) ^ "}"
       | pp2 (Pepa.VAR I) 
	 = printid I
       | pp2 (Pepa.CONSTS (I, P, (Pepa.VAR S))) 
	 = "#" ^ printid I ^ " = " ^ (pp2 P) ^ ";\n" ^ printid S ^ "\n"
       | pp2 (Pepa.CONSTS (I, P, L)) 
	 = "#" ^ printid I ^ " = " ^ (pp2 P) ^ ";\n" ^ (pp2 L)

     and prettylist [] = ""
       | prettylist [x] = pp x
       | prettylist (h::t) = pp h ^ ", " ^ prettylist t
     and printid s = (case mode of 
			compressed => HashTable.show s 
		      | uncompressed => HashTable.unhash s
		      | verbose => HashTable.unhash s)
     and printlist nil        = ""
       | printlist [x]        = printid x
       | printlist (x::y::z)  = printid x ^ ", " ^ (printlist (y::z))
  in
     fn p => if (!style = OLD) then (pp2 p) else (pp p)
  end

  fun printtransition mode (P, NONE ,Q) =
        (* Note: phantom transition introduced ?? *)
	    (print mode P) ^ 
	    "~~~>" ^ 
	    (print mode Q) ^ "\n"
    | printtransition mode (P, SOME ((a, r), n), Q) =
	    (print mode P) ^ 
	    "~~" ^ HashTable.unhash a ^ "," ^
(*                    HashTable.unhash r ^ "," ^Int.toString n ^ "~>" ^  *)
                   (Expressions.toString (Expressions.simplify r)) ^ "," ^Int.toString n ^ "~>" ^ 
	    (print mode Q) ^ "\n"

end;
