{-# OPTIONS_GHC -cpp -fglasgow-exts #-}
{- For Hugs, use the option -F"cpp -P -traditional" -}

module LinearScan.Split where


import Debug.Trace (trace, traceShow)
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 LinearScan.Utils

import qualified LinearScan.Datatypes as Datatypes
import qualified LinearScan.Interval as Interval
import qualified LinearScan.Lib as Lib
import qualified LinearScan.Logic as Logic
import qualified LinearScan.Morph as Morph
import qualified LinearScan.ScanState as ScanState
import qualified LinearScan.Eqtype as Eqtype
import qualified LinearScan.Fintype as Fintype
import qualified LinearScan.Seq as Seq
import qualified LinearScan.Ssrbool as Ssrbool
import qualified LinearScan.Ssrnat as Ssrnat



--unsafeCoerce :: a -> b
#ifdef __GLASGOW_HASKELL__
import qualified GHC.Base as GHC.Base
unsafeCoerce = GHC.Base.unsafeCoerce#
#else
-- HUGS
import qualified LinearScan.IOExts as IOExts
unsafeCoerce = IOExts.unsafeCoerce
#endif

__ :: any
__ = Prelude.error "Logical or arity value used"

type PhysReg = Prelude.Int

data SplitPosition =
   BeforePos Lib.Coq_oddnum
 | EndOfLifetimeHole Lib.Coq_oddnum

splitPosition :: Interval.IntervalDesc -> SplitPosition -> Lib.Coq_oddnum
splitPosition d pos =
  case pos of {
   BeforePos n -> n;
   EndOfLifetimeHole n ->
    Interval.afterLifetimeHole (Interval.getIntervalDesc d) n}

splitUnhandledInterval :: Prelude.Int -> ScanState.ScanStateDesc ->
                          ScanState.IntervalId -> Prelude.Int -> ([]
                          ((,) ScanState.IntervalId Prelude.Int)) ->
                          SplitPosition -> Prelude.Either Morph.SSError
                          (Prelude.Maybe ScanState.ScanStateSig)
splitUnhandledInterval maxReg sd uid beg us pos =
  let {
   _evar_0_ = \_nextInterval_ ints _fixedIntervals_ unh _active_ _inactive_ _handled_ uid0 us0 ->
    let {int = LinearScan.Utils.nth _nextInterval_ ints uid0} in
    let {splitPos = splitPosition ( int) pos} in
    let {
     _evar_0_ = \_ ->
      let {
       _evar_0_ = \iv ib ie rds ->
        let {
         _top_assumption_ = Interval.splitInterval
                              (Interval.Build_IntervalDesc iv ib ie rds)
                              splitPos}
        in
        let {
         _evar_0_ = \i0 i1 ->
          let {
           _evar_0_ = let {
                       _evar_0_ = \_ _ ->
                        let {
                         _evar_0_ = \_discharged_uid_ _discharged_us_ ->
                          Logic.coq_False_rect}
                        in
                        let {
                         _evar_0_0 = \x xs uid1 us1 ->
                          (Prelude.flip (Prelude.$)) __ (\_ ->
                            let {
                             _evar_0_0 = \_ ->
                              (Prelude.flip (Prelude.$)) __
                                (let {
                                  _evar_0_0 = let {
                                               _evar_0_0 = (Prelude.flip (Prelude.$))
                                                             __ (\_ _ ->
                                                             Prelude.Right
                                                             (Prelude.Just
                                                             (ScanState.packScanState
                                                               maxReg
                                                               ScanState.InUse
                                                               (ScanState.Build_ScanStateDesc
                                                               ((Prelude.succ)
                                                               _nextInterval_)
                                                               (LinearScan.Utils.snoc
                                                                 _nextInterval_
                                                                 (LinearScan.Utils.set_nth
                                                                   _nextInterval_
                                                                   ints uid1
                                                                   ( i0))
                                                                 ( i1))
                                                               _fixedIntervals_
                                                               (Lib.insert
                                                                 (Lib.lebf
                                                                   Prelude.snd)
                                                                 ((,)
                                                                 (
                                                                   _nextInterval_)
                                                                 (Interval.ibeg
                                                                   ( i1)))
                                                                 ((:)
                                                                 (Prelude.id
                                                                   ((,) uid1
                                                                   beg))
                                                                 (Prelude.map
                                                                   Prelude.id
                                                                   us1)))
                                                               (Prelude.map
                                                                 Prelude.id
                                                                 _active_)
                                                               (Prelude.map
                                                                 Prelude.id
                                                                 _inactive_)
                                                               (Prelude.map
                                                                 Prelude.id
                                                                 _handled_)))))}
                                              in
                                               _evar_0_0}
                                 in
                                  _evar_0_0)}
                            in
                             _evar_0_0 __)}
                        in
                        case unh of {
                         [] -> _evar_0_ uid0 us0;
                         (:) x x0 -> _evar_0_0 x x0 uid0 us0}}
                      in
                       _evar_0_ __}
          in
           _evar_0_ __}
        in
        case _top_assumption_ of {
         (,) x x0 -> _evar_0_ x x0}}
      in
      case int of {
       Interval.Build_IntervalDesc x x0 x1 x2 -> _evar_0_ x x0 x1 x2}}
    in
    let {
     _evar_0_0 = \_ -> Prelude.Left (Morph.ENoValidSplitPositionUnh ( uid0)
      splitPos)}
    in
    case (Prelude.&&)
           ((Prelude.<=) ((Prelude.succ) (Interval.ibeg ( int))) splitPos)
           ((Prelude.<=) splitPos (Interval.iend ( int))) of {
     Prelude.True -> _evar_0_ __;
     Prelude.False -> _evar_0_0 __}}
  in
  case sd of {
   ScanState.Build_ScanStateDesc x x0 x1 x2 x3 x4 x5 ->
    _evar_0_ x x0 x1 x2 x3 x4 x5 uid us}

splitCurrentInterval :: Prelude.Int -> ScanState.ScanStateDesc ->
                        SplitPosition -> Morph.SState () () ()
splitCurrentInterval maxReg pre pos ssi =
  let {
   _evar_0_ = \desc ->
    let {_evar_0_ = \_ _ _ _ _ -> Logic.coq_False_rect} in
    let {
     _evar_0_0 = \_top_assumption_ ->
      let {
       _evar_0_0 = \uid beg us ->
        let {
         _evar_0_0 = \_nextInterval_ intervals0 _fixedIntervals_ unhandled0 _active_ _inactive_ _handled_ uid0 us0 _top_assumption_0 ->
          let {_evar_0_0 = \err -> Prelude.Left err} in
          let {
           _evar_0_1 = \_top_assumption_1 ->
            let {
             _evar_0_1 = \_top_assumption_2 -> Prelude.Right ((,) ()
              (Morph.Build_SSInfo _top_assumption_2 __))}
            in
            let {
             _evar_0_2 = Prelude.Left (Morph.ECannotSplitSingleton1 ( uid0))}
            in
            case _top_assumption_1 of {
             Prelude.Just x -> _evar_0_1 x;
             Prelude.Nothing -> _evar_0_2}}
          in
          case _top_assumption_0 of {
           Prelude.Left x -> _evar_0_0 x;
           Prelude.Right x -> _evar_0_1 x}}
        in
        case desc of {
         ScanState.Build_ScanStateDesc x x0 x1 x2 x3 x4 x5 ->
          _evar_0_0 x x0 x1 x2 x3 x4 x5 uid us
            (splitUnhandledInterval maxReg desc uid beg us pos)}}
      in
      (\us _ _ _ _ _ ->
      case _top_assumption_ of {
       (,) x x0 -> _evar_0_0 x x0 us})}
    in
    case ScanState.unhandled maxReg desc of {
     [] -> _evar_0_ __ __ __ __;
     (:) x x0 -> _evar_0_0 x x0 __ __ __ __}}
  in
  case ssi of {
   Morph.Build_SSInfo x x0 -> _evar_0_ x __}

splitActiveOrInactiveInterval :: Prelude.Int -> ScanState.ScanStateDesc ->
                                 ScanState.IntervalId -> Prelude.Int -> ([]
                                 ((,) ScanState.IntervalId Prelude.Int)) ->
                                 ScanState.IntervalId -> SplitPosition ->
                                 Prelude.Either Morph.SSError
                                 (Prelude.Maybe ScanState.ScanStateSig)
splitActiveOrInactiveInterval maxReg sd uid beg us xid pos =
  let {
   _evar_0_ = \_nextInterval_ ints _fixedIntervals_ unh _active_ _inactive_ _handled_ uid0 us0 xid0 ->
    let {int = LinearScan.Utils.nth _nextInterval_ ints xid0} in
    let {splitPos = splitPosition ( int) pos} in
    let {
     _evar_0_ = \_ ->
      let {
       _evar_0_ = \iv ib ie rds ->
        let {
         _top_assumption_ = Interval.splitInterval
                              (Interval.Build_IntervalDesc iv ib ie rds)
                              splitPos}
        in
        let {
         _evar_0_ = \i0 i1 ->
          let {
           _evar_0_ = let {
                       _evar_0_ = \_ _ ->
                        let {
                         _evar_0_ = \_top_assumption_0 ->
                          let {
                           _evar_0_ = \_ ->
                            (Prelude.flip (Prelude.$)) __
                              (let {
                                _evar_0_ = let {
                                            _evar_0_ = \_ _ -> Prelude.Left
                                             (Morph.ENoValidSplitPosition
                                             ( xid0) _top_assumption_0)}
                                           in
                                           let {
                                            _evar_0_0 = \_ ->
                                             let {
                                              _evar_0_0 = \_ _ ->
                                               Prelude.Right (Prelude.Just
                                               (ScanState.packScanState
                                                 maxReg ScanState.InUse
                                                 (ScanState.Build_ScanStateDesc
                                                 ((Prelude.succ)
                                                 _nextInterval_)
                                                 (LinearScan.Utils.snoc
                                                   _nextInterval_
                                                   (LinearScan.Utils.set_nth
                                                     _nextInterval_ ints xid0
                                                     ( i0)) ( i1))
                                                 _fixedIntervals_
                                                 (Lib.insert
                                                   (Lib.lebf Prelude.snd)
                                                   ((,) ( _nextInterval_)
                                                   (Interval.ibeg ( i1)))
                                                   ((:)
                                                   (Prelude.id ((,) uid0
                                                     beg))
                                                   (Prelude.map Prelude.id
                                                     us0)))
                                                 (Prelude.map Prelude.id
                                                   _active_)
                                                 (Prelude.map Prelude.id
                                                   _inactive_)
                                                 (Prelude.map Prelude.id
                                                   _handled_))))}
                                             in
                                              _evar_0_0 __}
                                           in
                                           case (Prelude.<=)
                                                  (Interval.ibeg ( i1)) beg of {
                                            Prelude.True -> _evar_0_ __;
                                            Prelude.False -> _evar_0_0 __}}
                               in
                                _evar_0_)}
                          in
                          let {
                           _evar_0_0 = \_ ->
                            (Prelude.flip (Prelude.$)) __ (\_ ->
                              let {
                               _top_assumption_1 = Interval.splitInterval
                                                     ( i1) _top_assumption_0}
                              in
                              let {
                               _evar_0_0 = \i1_0 i1_1 ->
                                (Prelude.flip (Prelude.$)) __
                                  (let {
                                    _evar_0_0 = (Prelude.flip (Prelude.$)) __
                                                  (\_ _ -> Prelude.Right
                                                  (Prelude.Just
                                                  (ScanState.packScanState
                                                    maxReg ScanState.InUse
                                                    (ScanState.Build_ScanStateDesc
                                                    ((Prelude.succ)
                                                    ((Prelude.succ)
                                                    _nextInterval_))
                                                    (LinearScan.Utils.snoc
                                                      ((Prelude.succ)
                                                      _nextInterval_)
                                                      (LinearScan.Utils.snoc
                                                        _nextInterval_
                                                        (LinearScan.Utils.set_nth
                                                          _nextInterval_ ints
                                                          xid0 ( i0))
                                                        ( i1_1)) ( i1_0))
                                                    _fixedIntervals_
                                                    (Prelude.map Prelude.id
                                                      (Lib.insert
                                                        (Lib.lebf
                                                          Prelude.snd) ((,)
                                                        ( _nextInterval_)
                                                        (Interval.ibeg
                                                          ( i1_1))) ((:)
                                                        (Prelude.id ((,) uid0
                                                          beg))
                                                        (Prelude.map
                                                          Prelude.id us0))))
                                                    (Prelude.map Prelude.id
                                                      (Prelude.map Prelude.id
                                                        _active_))
                                                    (Prelude.map Prelude.id
                                                      (Prelude.map Prelude.id
                                                        _inactive_)) ((:)
                                                    ((,)
                                                    ( ((Prelude.succ)
                                                      _nextInterval_))
                                                    Prelude.Nothing)
                                                    (Prelude.map Prelude.id
                                                      (Prelude.map Prelude.id
                                                        _handled_)))))))}
                                   in
                                    _evar_0_0)}
                              in
                              case _top_assumption_1 of {
                               (,) x x0 -> _evar_0_0 x x0})}
                          in
                          case Eqtype.eq_op Ssrnat.nat_eqType
                                 (unsafeCoerce (Interval.ibeg ( i1)))
                                 (unsafeCoerce _top_assumption_0) of {
                           Prelude.True -> _evar_0_ __;
                           Prelude.False -> _evar_0_0 __}}
                        in
                        let {
                         _evar_0_0 = let {
                                      _evar_0_0 = \_ -> Prelude.Right
                                       (Prelude.Just
                                       (ScanState.packScanState maxReg
                                         ScanState.InUse
                                         (ScanState.Build_ScanStateDesc
                                         ((Prelude.succ) _nextInterval_)
                                         (LinearScan.Utils.snoc
                                           _nextInterval_
                                           (LinearScan.Utils.set_nth
                                             _nextInterval_ ints xid0 
                                             ( i0)) ( i1)) _fixedIntervals_
                                         ((:) (Prelude.id ((,) uid0 beg))
                                         (Prelude.map Prelude.id us0))
                                         (Prelude.map Prelude.id _active_)
                                         (Prelude.map Prelude.id _inactive_)
                                         ((:) ((,) ( _nextInterval_)
                                         Prelude.Nothing)
                                         (Prelude.map Prelude.id _handled_)))))}
                                     in
                                      _evar_0_0 __}
                        in
                        case Interval.firstUseReqReg ( i1) of {
                         Prelude.Just x -> _evar_0_ x;
                         Prelude.Nothing -> _evar_0_0}}
                      in
                       _evar_0_ __}
          in
           _evar_0_ __}
        in
        case _top_assumption_ of {
         (,) x x0 -> _evar_0_ x x0}}
      in
      case int of {
       Interval.Build_IntervalDesc x x0 x1 x2 -> _evar_0_ x x0 x1 x2}}
    in
    let {
     _evar_0_0 = \_ -> Prelude.Left (Morph.ENoValidSplitPosition ( xid0)
      splitPos)}
    in
    case (Prelude.&&)
           ((Prelude.<=) ((Prelude.succ) (Interval.ibeg ( int))) splitPos)
           ((Prelude.<=) splitPos (Interval.iend ( int))) of {
     Prelude.True -> _evar_0_ __;
     Prelude.False -> _evar_0_0 __}}
  in
  case sd of {
   ScanState.Build_ScanStateDesc x x0 x1 x2 x3 x4 x5 ->
    _evar_0_ x x0 x1 x2 x3 x4 x5 uid us xid}

splitAssignedIntervalForReg :: Prelude.Int -> ScanState.ScanStateDesc ->
                               PhysReg -> SplitPosition -> Prelude.Bool ->
                               Morph.SState () () ()
splitAssignedIntervalForReg maxReg pre reg pos trueForActives ssi =
  let {
   _evar_0_ = \desc ->
    let {
     intlist = case trueForActives of {
                Prelude.True -> ScanState.active maxReg desc;
                Prelude.False -> ScanState.inactive maxReg desc}}
    in
    (Prelude.flip (Prelude.$)) __ (\_ ->
      let {
       intids = Prelude.map (\i -> Prelude.fst i)
                  (Prelude.filter (\i ->
                    Eqtype.eq_op (Fintype.ordinal_eqType maxReg)
                      (Prelude.snd (unsafeCoerce i)) (unsafeCoerce reg))
                    intlist)}
      in
      (Prelude.flip (Prelude.$)) __ (\_ ->
        let {_evar_0_ = \intlist0 intids0 -> Logic.coq_False_rect} in
        let {
         _evar_0_0 = \_top_assumption_ ->
          let {
           _evar_0_0 = \uid beg us ->
            let {
             _evar_0_0 = \_nextInterval_ intervals0 _fixedIntervals_ _unhandled_ active0 inactive0 _handled_ uid0 us0 intlist0 intids0 ->
              let {
               _evar_0_0 = \_ -> Prelude.Right ((,) () (Morph.Build_SSInfo
                (ScanState.Build_ScanStateDesc _nextInterval_ intervals0
                _fixedIntervals_ _unhandled_ active0 inactive0 _handled_)
                __))}
              in
              let {
               _evar_0_1 = \aid aids iHaids ->
                let {
                 _evar_0_1 = \_ ->
                  let {
                   _top_assumption_0 = \x x0 x1 x2 x3 ->
                    splitActiveOrInactiveInterval maxReg
                      (ScanState.Build_ScanStateDesc _nextInterval_
                      intervals0 _fixedIntervals_ _unhandled_ active0
                      inactive0 _handled_) x x0 x1 x2 x3}
                  in
                  let {
                   _top_assumption_1 = _top_assumption_0 uid0 beg us0 aid pos}
                  in
                  let {_evar_0_1 = \err -> Prelude.Left err} in
                  let {
                   _evar_0_2 = \_top_assumption_2 ->
                    let {
                     _evar_0_2 = \_top_assumption_3 -> Prelude.Right ((,) ()
                      (let {
                        _evar_0_2 = \_ ->
                         (Prelude.flip (Prelude.$)) __
                           (let {
                             act_to_inact = ScanState.Build_ScanStateDesc
                              (ScanState.nextInterval maxReg
                                _top_assumption_3)
                              (ScanState.intervals maxReg _top_assumption_3)
                              (ScanState.fixedIntervals maxReg
                                _top_assumption_3)
                              (ScanState.unhandled maxReg _top_assumption_3)
                              (unsafeCoerce
                                (Seq.rem
                                  (Eqtype.prod_eqType
                                    (Fintype.ordinal_eqType
                                      (ScanState.nextInterval maxReg
                                        _top_assumption_3))
                                    (Fintype.ordinal_eqType maxReg))
                                  (unsafeCoerce ((,) ( aid) reg))
                                  (unsafeCoerce
                                    (ScanState.active maxReg
                                      _top_assumption_3)))) ((:) ((,) 
                              ( aid) reg)
                              (ScanState.inactive maxReg _top_assumption_3))
                              (ScanState.handled maxReg _top_assumption_3)}
                            in
                            \_ ->
                            let {
                             _evar_0_2 = \_ -> Morph.Build_SSInfo
                              act_to_inact __}
                            in
                             _evar_0_2 __)}
                       in
                       let {
                        _evar_0_3 = \_ ->
                         let {
                          _evar_0_3 = \_ -> Morph.Build_SSInfo
                           _top_assumption_3 __}
                         in
                          _evar_0_3 __}
                       in
                       case Ssrbool.in_mem (unsafeCoerce ((,) ( aid) reg))
                              (Ssrbool.mem
                                (Seq.seq_predType
                                  (Eqtype.prod_eqType
                                    (Fintype.ordinal_eqType
                                      (ScanState.nextInterval maxReg
                                        _top_assumption_3))
                                    (Fintype.ordinal_eqType maxReg)))
                                (unsafeCoerce
                                  (ScanState.active maxReg _top_assumption_3))) of {
                        Prelude.True -> _evar_0_2 __;
                        Prelude.False -> _evar_0_3 __}))}
                    in
                    let {
                     _evar_0_3 = Prelude.Left (Morph.ECannotSplitSingleton3
                      ( aid))}
                    in
                    case _top_assumption_2 of {
                     Prelude.Just x -> _evar_0_2 x;
                     Prelude.Nothing -> _evar_0_3}}
                  in
                  case _top_assumption_1 of {
                   Prelude.Left x -> _evar_0_1 x;
                   Prelude.Right x -> _evar_0_2 x}}
                in
                let {
                 _evar_0_2 = \_ -> Prelude.Left (Morph.ECannotSplitSingleton2
                  ( aid))}
                in
                case (Prelude.<=) beg
                       (
                         (splitPosition
                           (
                             (LinearScan.Utils.nth
                               (ScanState.nextInterval maxReg
                                 (ScanState.Build_ScanStateDesc
                                 _nextInterval_ intervals0 _fixedIntervals_
                                 _unhandled_ active0 inactive0 _handled_))
                               (ScanState.intervals maxReg
                                 (ScanState.Build_ScanStateDesc
                                 _nextInterval_ intervals0 _fixedIntervals_
                                 _unhandled_ active0 inactive0 _handled_))
                               aid)) pos)) of {
                 Prelude.True -> _evar_0_1 __;
                 Prelude.False -> _evar_0_2 __}}
              in
              Datatypes.list_rect _evar_0_0 (\aid aids iHaids _ ->
                _evar_0_1 aid aids iHaids) intids0 __}
            in
            (\intlist0 _ intids0 _ _ _ _ _ ->
            case desc of {
             ScanState.Build_ScanStateDesc x x0 x1 x2 x3 x4 x5 ->
              _evar_0_0 x x0 x1 x2 x3 x4 x5 uid us intlist0 intids0})}
          in
          (\us _ ->
          case _top_assumption_ of {
           (,) x x0 -> _evar_0_0 x x0 us})}
        in
        case ScanState.unhandled maxReg desc of {
         [] -> (\_ _ _ _ -> _evar_0_ intlist intids);
         (:) x x0 -> _evar_0_0 x x0 __ intlist __ intids __})) __ __ __}
  in
  case ssi of {
   Morph.Build_SSInfo x x0 -> _evar_0_ x __}

splitActiveIntervalForReg :: Prelude.Int -> ScanState.ScanStateDesc ->
                             PhysReg -> Lib.Coq_oddnum -> Morph.SState 
                             () () ()
splitActiveIntervalForReg maxReg pre reg pos =
  splitAssignedIntervalForReg maxReg pre reg (BeforePos pos) Prelude.True

splitAnyInactiveIntervalForReg :: Prelude.Int -> ScanState.ScanStateDesc ->
                                  PhysReg -> Lib.Coq_oddnum -> Morph.SState
                                  () () ()
splitAnyInactiveIntervalForReg maxReg pre reg pos ss =
  (Prelude.flip (Prelude.$)) (\s ->
    splitAssignedIntervalForReg maxReg s reg (EndOfLifetimeHole pos)
      Prelude.False) (\_top_assumption_ ->
    let {_top_assumption_0 = _top_assumption_ pre ss} in
    let {_evar_0_ = \err -> Prelude.Right ((,) () ss)} in
    let {
     _evar_0_0 = \_top_assumption_1 ->
      let {_evar_0_0 = \_the_1st_wildcard_ ss' -> Prelude.Right ((,) () ss')}
      in
      case _top_assumption_1 of {
       (,) x x0 -> _evar_0_0 x x0}}
    in
    case _top_assumption_0 of {
     Prelude.Left x -> _evar_0_ x;
     Prelude.Right x -> _evar_0_0 x})