packages feed

ADPfusionForest-0.0.0.1: ADP/Fusion/Core/ForestEdit/LeftLinear.hs

module ADP.Fusion.Core.ForestEdit.LeftLinear where

import           Data.Either (either)
import           Data.Graph.Inductive.Basic
import           Data.Strict.Tuple hiding (fst, snd)
import           Data.Traversable (mapAccumL)
import           Data.Vector.Fusion.Stream.Monadic hiding (flatten)
import           Debug.Trace
import           Prelude hiding (map)
import qualified Data.Forest.Static as F
import qualified Data.Tree as T
import qualified Data.Vector as V
import qualified Data.Vector.Fusion.Stream.Monadic as SM
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Unboxed as VU

import           ADP.Fusion.Core
import           Data.Forest.Static
import           Data.PrimitiveArray hiding (map)
import           Math.TriangularNumbers

import           ADP.Fusion.Term.Node.Type



-- | Index for editing purposes into a post-order tree structure
--
-- @
--      6
--    /   \
--   2     5
--  / \   / \
-- 0  1  3   4
-- @
--
-- Cf the tree rooted at @5@. Its bounded by @[3,6)@
--
-- The index @[0,7]@ includes the lower bound, but excludes the bound.
-- Hence, this is the tree from the leaf @0@ to the local root @6@. It
-- implicitly goes down to the leaf @4@ as well.
--
-- The index @[0.6]@ on the other hand describes a forest. This forest
-- contains two full local trees, rooted at @2@ and @5@ respectively.
--
-- We index the left-most lower-most leaf, and the right-most, top-most
-- root (actually the index is the first excluded element, hence @[0,6)@
-- instead of @[0,5]@.
--
-- TODO need to fix @p ~ PostOrder@

data TreeIxL p v a t
  = TreeIxL
      !(Forest p v a)   -- ^ the actual forest we operate on
      !(VU.Vector Int)  -- ^ given a node, gives the index of the left-most leaf of the node
      !Int              -- ^ left-most, lower-most index
      !Int              -- ^ right-most, top-most index

instance Show (TreeIxL p v a t) where
  show (TreeIxL _ _ i j) = show (i,j)

minIx, maxIx :: Forest p v a -> TreeIxL p v a t
minIx f = TreeIxL f (leftMostLeaves f) 0 (VU.length (parent f))

maxIx f = TreeIxL f (leftMostLeaves f) 0 (VU.length (parent f))
{-# Inline minIx #-}
{-# Inline maxIx #-}

instance Index (TreeIxL p v a t) where
  -- | trees @T@ are stored in the first line, i.e. @+0@, forests @F@ (with
  -- @j==u@ are stored in the second line, i.e. @+u+1@ to each index.
  linearIndex _ (TreeIxL _ _ l u) (TreeIxL _ _ i j)
    = linearIndex (subword 0 0) (subword l u) (subword i j)
  {-# Inline linearIndex #-}
  smallestLinearIndex _ = error "still needed?"
  {-# Inline smallestLinearIndex #-}
  largestLinearIndex (TreeIxL _ _ _ u) = (triangularNumber $ u-0+1) - 1
  {-# Inline largestLinearIndex #-}
  size _ (TreeIxL _ _ _ u) = triangularNumber $ u-0+1
  {-# Inline size #-}
  inBounds _ (TreeIxL _ _ _ u) (TreeIxL _ _ i j) = 0 <= i && i <= j && j <= u
  {-# Inline inBounds #-}

streamUpMk l h z = return (z,0,0)  -- start with size 0 and smallest element 0
{-# Inline [0] streamUpMk #-}

-- 0,0 1,1 2,2 ...
-- 0,1 1,2 2,3 ...
-- 0,2 1,3 2,4 ...

streamUpStep p c lf ht (z,s,i)  -- s=size, i=left border
  | s > VG.length c     = return $ SM.Done
  | i + s > VG.length c = return $ SM.Skip (z,s+1,0)
  | otherwise = return $ SM.Yield (z:.TreeIxL p c i (i+s)) (z,s,i+1)
{-# Inline [0] streamUpStep #-}

streamDownMk lf ht z = return (z,ht,0)
{-# Inline [0] streamDownMk #-}

streamDownStep p c lf ht (z,s,i)
  | s < 0     = return $ SM.Done
  | i < 0     = return $ SM.Skip (z,s-1,ht-(s-1))
  | otherwise = return $ SM.Yield (z:.TreeIxL p c i (i+s)) (z,s,i-1)
{-# Inline [0] streamDownStep #-}

instance IndexStream (Z:.TreeIxL p v a t) => IndexStream (TreeIxL p v a t)



-- * Inside



data instance RunningIndex (TreeIxL p v a I) = RiTilI !Int !Int

instance IndexStream z => IndexStream (z:.TreeIxL p v a I) where
  streamUp   (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamUpMk lf  ht) (streamUpStep  p c lf ht) $ streamUp ls hs
  streamDown (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamDownMk lf ht) (streamDownStep p c lf ht) $ streamDown ls hs
  {-# Inline streamUp #-}
  {-# Inline streamDown #-}

instance RuleContext (TreeIxL p v a I) where
  type Context (TreeIxL p v a I) = InsideContext ()
  initialContext _ = IStatic ()
  {-# Inline initialContext #-}



-- Invisible starting symbol

instance (Monad m) => MkStream m S (TreeIxL p v a I) where
  mkStream S (IStatic ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck (i>=0 && i==j && j<=u) . singleton . ElmS $ RiTilI i i
  mkStream S (IVariable ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck (i>=0 && i<=j && j<=u) . singleton . ElmS $ RiTilI i i
  {-# Inline mkStream #-}


instance
  ( Monad m
  , MkStream m S is
  ) => MkStream m S (is:.TreeIxL p v a I) where
  mkStream S (vs:.IStatic()) (lus:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi :.: RiTilI i i)
    . staticCheck (i>=0 && i==j && j<=u)
    $ mkStream S vs lus is
  mkStream S (vs:.IVariable()) (lus:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi :.: RiTilI i i)
    . staticCheck (i>=0 && i<=j && j<=u)
    $ mkStream S vs lus is
  {-# INLINE mkStream #-}



-- * Outside



-- | Running index structure for outside tree-edit algorithms. We
-- explicitly name the indices, to be more sure inside and outside
-- are correctly assigned to.

data instance RunningIndex (TreeIxL p v a O) = RiTilO { iLeft, iRight, oLeft, oRight :: !Int }

instance IndexStream z => IndexStream (z:.TreeIxL Post v a O) where
  streamUp   (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamDownMk lf ht) (streamDownStep p c lf ht) $ streamUp ls hs
  streamDown (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamUpMk   lf ht) (streamUpStep   p c lf ht) $ streamDown ls hs
  {-# Inline streamUp #-}
  {-# Inline streamDown #-}

instance RuleContext (TreeIxL Post v a O) where
  type Context (TreeIxL Post v a O) = OutsideContext ()
  initialContext _ = OStatic ()
  {-# Inline initialContext #-}

instance (Monad m) => MkStream m S (TreeIxL Post v a O) where
  mkStream S (OStatic ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck (i==0 && j==u) . singleton . ElmS $ RiTilO i j i j
  mkStream S (ORightOf ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = error $ "mkStream S / ORightOf should not be happening!"
  mkStream S (OFirstLeft ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck True . singleton . ElmS $ RiTilO i i i j -- TODO ???
  mkStream S (OLeftOf ()) (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck True . singleton . ElmS $ RiTilO 0 i 0 j
  {-# Inline mkStream #-}

instance
  ( Monad m
  , MkStream m S is
  ) => MkStream m S (is:.TreeIxL Post v a O) where
  mkStream S (vs:.OStatic ()) (us:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi:.:RiTilO i j i j)
    . staticCheck (i==0 && j==u)
    $ mkStream S vs us is
  mkStream S (vs:.ORightOf ()) (us:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = error $ "mkStream S / ORightOf should not be happening!"
  mkStream S (vs:.OFirstLeft ()) (us:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi:.:RiTilO i i i j)
    . staticCheck True
    $ mkStream S vs us is
  mkStream S (vs:.OLeftOf ()) (us:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi:.:RiTilO 0 i 0 j)
    . staticCheck True
    $ mkStream S vs us is
  {-# Inline mkStream #-}



-- * Complement

data instance RunningIndex (TreeIxL p v a C) = RiTilC !Int !Int

instance IndexStream z => IndexStream (z:.TreeIxL p v a C) where
  streamUp   (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamUpMk lf  ht) (streamUpStep  p c lf ht) $ streamUp ls hs
  streamDown (ls:.TreeIxL p c lf _) (hs:.TreeIxL _ _ _ ht) = flatten (streamDownMk lf ht) (streamDownStep p c lf ht) $ streamDown ls hs
  {-# Inline streamUp #-}
  {-# Inline streamDown #-}

instance RuleContext (TreeIxL p v a C) where
  type Context (TreeIxL p v a C) = ComplementContext
  initialContext _ = Complemented
  {-# Inline initialContext #-}



-- Invisible starting symbol

instance (Monad m) => MkStream m S (TreeIxL p v a C) where
  mkStream S Complemented (TreeIxL frst _ l u) (TreeIxL _ _ i j)
    = staticCheck (i>=0 && i==j && j<=u) . singleton . ElmS $ RiTilC i j
  {-# Inline mkStream #-}


instance
  ( Monad m
  , MkStream m S is
  ) => MkStream m S (is:.TreeIxL p v a C) where
  mkStream S (vs:.Complemented) (lus:.TreeIxL frst _ l u) (is:.TreeIxL _ _ i j)
    = map (\(ElmS zi) -> ElmS $ zi :.: RiTilC i j)
    . staticCheck (i>=0 && i==j && j<=u)
    $ mkStream S vs lus is
  {-# INLINE mkStream #-}