packages feed

yi-0.6.0: Yi/Syntax/BList.hs

{-# LANGUAGE TypeFamilies, UndecidableInstances #-}

-- | 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) where

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

data BList a = One [a] | Two ([a] -> [a]) [a]

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 x ~(One r) = One  (x:r)
consL x (One r) = Two (x:) r
consL x (Two l r) = Two (l . (x:))  r

cons = Pure consL consR
nil = One []

many v = some v <|> pure nil
some v = cons <*> v <*> many v
sepBy p q = pure nil <|> 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 begin 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)