packages feed

yi-0.6.1: Yi/Syntax/BList.hs

{-# LANGUAGE TypeFamilies, UndecidableInstances, DeriveDataTypeable #-}

-- | The BList is like a zipper on lists: it is a list with one point of focus.
-- We provide parsing functions for BLists, and the corresponding traversal functions.
-- When used together, accessing the elements around the last point of modification
-- is fast: they are at the beginning of the lists.

module Yi.Syntax.BList (foldMapAfter, many, some, sepBy, BList, sepBy1, nil) where

import Data.Monoid
import Parser.Incremental 
import Prelude (reverse, takeWhile)
import Yi.Prelude hiding (some, many)
import Yi.Syntax.Tree hiding (sepBy, sepBy1)
import Yi.Lexer.Alex
import Yi.Buffer.Basic
import Data.Data
import Data.Typeable

data BList a = One [a] | Two ([a] -> [a]) [a]
    deriving (Data, Typeable)

instance Show a => Show (BList a) where
    show (One r) =  "[]<>" ++ show r
    show (Two l r) = show (reverse $ l []) ++ "<>" ++ show r

-- Note that consR /must/ be lazy in its rhs argument.
-- It's possible because it /cannot/ take the 'Two' case.
consR, consL :: a -> BList a -> BList a
consR x ~(One r) = One  (x:r)
consL x (One r) = Two (x:) r
consL x (Two l r) = Two (l . (x:))  r

cons :: Parser s (a -> BList a -> BList a)
cons = Pure consL consR

nil :: BList a
nil = One []

many, some :: Parser s a -> Parser s (BList a)
many v = some v <|> pure nil
some v = cons <*> v <*> many v

sepBy :: Parser s a -> Parser s a1 -> Parser s (BList a)
sepBy p q = pure nil <|> sepBy1 p q

sepBy1 :: Parser s a -> Parser s a1 -> Parser s (BList a)
sepBy1 p q = cons <*> p <*> many (q *> p)


instance Foldable BList where
    foldMap f (One r) = foldMap f r
    foldMap f (Two l r) = getDual (foldMap (Dual . f) (l [])) <> foldMap f r

foldMapAfter :: (SubTree a, Element a ~ Tok t, Monoid m) => Point -> (a -> m) -> BList a -> m
foldMapAfter _ f (One r)   = foldMap f r    
foldMapAfter begin f (Two l r) = getDual (foldMap (Dual . f) (takeWhile (\t -> getLastOffset  t > begin) $ l [])) 
                              <> foldMap f r 


instance (Element a ~ Tok t, SubTree a) =>SubTree (BList a) where
    type Element (BList a) = Element a
    foldMapToksAfter begin f t = foldMapAfter begin (foldMapToksAfter begin f) t
    foldMapToks f = foldMap (foldMapToks f)