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 #-}