{-# OPTIONS_GHC -cpp -XMagicHash #-} {- For Hugs, use the option -F"cpp -P -traditional" -} module LinearScan.Graph where import Debug.Trace (trace, traceShow, traceShowId) import qualified Prelude import qualified Data.IntMap import qualified Data.IntSet import qualified Data.List import qualified Data.Ord import qualified Data.Functor.Identity import qualified Hask.Utils import qualified LinearScan.Eqtype as Eqtype import qualified LinearScan.Seq as Seq import qualified LinearScan.Ssrbool as Ssrbool import qualified LinearScan.Ssrnat as Ssrnat #ifdef __GLASGOW_HASKELL__ import qualified GHC.Base as GHC.Base import qualified GHC.Prim as GHC.Prim #else -- HUGS import qualified LinearScan.IOExts as IOExts #endif #ifdef __GLASGOW_HASKELL__ --unsafeCoerce :: a -> b unsafeCoerce = GHC.Base.unsafeCoerce# #else -- HUGS --unsafeCoerce :: a -> b unsafeCoerce = IOExts.unsafeCoerce #endif data Graph = Build_Graph ([] Eqtype.Equality__Coq_sort) ([] Eqtype.Equality__Coq_sort) (Eqtype.Equality__Coq_sort -> (,) Eqtype.Equality__Coq_sort Eqtype.Equality__Coq_sort) vertices :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Graph -> [] Eqtype.Equality__Coq_sort vertices a b g = case g of { Build_Graph vertices0 edges0 edge_f0 -> vertices0} edges :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Graph -> [] Eqtype.Equality__Coq_sort edges a b g = case g of { Build_Graph vertices0 edges0 edge_f0 -> edges0} edge_f :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Graph -> Eqtype.Equality__Coq_sort -> (,) Eqtype.Equality__Coq_sort Eqtype.Equality__Coq_sort edge_f a b g = case g of { Build_Graph vertices0 edges0 edge_f0 -> edge_f0} emptyGraph :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> (Eqtype.Equality__Coq_sort -> (,) Eqtype.Equality__Coq_sort Eqtype.Equality__Coq_sort) -> Graph emptyGraph a b f = Build_Graph [] [] f addVertex :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> Graph addVertex a b v g = let {vg = vertices a b g} in Build_Graph (case Ssrbool.in_mem v (Ssrbool.mem (Seq.seq_predType a) (unsafeCoerce vg)) of { Prelude.True -> vg; Prelude.False -> (:) v vg}) (edges a b g) (edge_f a b g) addEdge :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> Graph addEdge a b e g = let { g' = let {eg = edges a b g} in Build_Graph (vertices a b g) (case Ssrbool.in_mem e (Ssrbool.mem (Seq.seq_predType b) (unsafeCoerce eg)) of { Prelude.True -> eg; Prelude.False -> (:) e eg}) (edge_f a b g)} in case edge_f a b g' e of { (,) a0 z -> addVertex a b a0 (addVertex a b z g')} removeEdge :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> Graph removeEdge a b x g = Build_Graph (vertices a b g) (Seq.rem b x (edges a b g)) (edge_f a b g) connections :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> (((,) Eqtype.Equality__Coq_sort Eqtype.Equality__Coq_sort) -> Eqtype.Equality__Coq_sort) -> Eqtype.Equality__Coq_sort -> Graph -> [] Eqtype.Equality__Coq_sort connections a b f x g = Prelude.filter ((Prelude..) ((Prelude..) (\y -> Eqtype.eq_op a y x) f) (edge_f a b g)) (edges a b g) outbound :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> [] Eqtype.Equality__Coq_sort outbound a b = connections a b Prelude.fst inbound :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> [] Eqtype.Equality__Coq_sort inbound a b = connections a b Prelude.snd removeVertex :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_sort -> Graph -> Graph removeVertex a b v g = Prelude.foldr (removeEdge a b) (Build_Graph (Seq.rem a v (vertices a b g)) (edges a b g) (edge_f a b g)) (outbound a b v g) topsort :: Eqtype.Equality__Coq_type -> Eqtype.Equality__Coq_type -> Graph -> (Eqtype.Equality__Coq_sort -> Prelude.Bool) -> (Eqtype.Equality__Coq_sort -> [] Eqtype.Equality__Coq_sort) -> (,) ([] Eqtype.Equality__Coq_sort) ([] ((,) Prelude.Int Eqtype.Equality__Coq_sort)) topsort a b g0 splittable split = let { go fuel depth g = (\fO fS n -> if n Prelude.<= 0 then fO () else fS (n Prelude.- 1)) (\_ -> (,) (vertices a b g) (Prelude.map (\i -> (,) depth i) (edges a b g))) (\fuel0 -> let { noInbound = Prelude.filter (\v -> Seq.nilp (inbound a b v g)) (vertices a b g)} in case noInbound of { [] -> case edges a b g of { [] -> (,) [] []; (:) e l -> let { x = case Prelude.filter (\e0 -> splittable e0) (edges a b g) of { [] -> e; (:) e' l0 -> e'}} in go fuel0 ((Prelude.succ) depth) (Prelude.foldr (addEdge a b) (removeEdge a b x g) (split x))}; (:) s l -> case go fuel0 ((Prelude.succ) depth) (Prelude.foldr (removeVertex a b) g noInbound) of { (,) ns' es' -> (,) ((Prelude.++) noInbound ns') ((Prelude.++) (Prelude.map (\i -> (,) depth i) (Seq.flatten (Prelude.map (\n -> outbound a b n g) noInbound))) es')}}) fuel} in go (Ssrnat.double (Data.List.length (vertices a b g0))) 0 g0