157 lines
3.7 KiB
Haskell
Raw Normal View History

2020-06-01 18:17:33 +04:00
2020-06-04 13:48:04 +04:00
{- | The carrier type for AST.
"Untypedness" of the tree is a payoff to ablity to stop and navigate
anywhere, not just inside the expression context.
Is a `Functor` and `Foldable` over its @info@ parameter.
Is not `Traversable`, because this will definitely not preserve scope.
Use `updateTree` instead of `traverse`/`for`.
-}
2020-06-01 22:02:16 +04:00
module Tree
2020-06-04 17:40:38 +04:00
( -- * Tree type
Tree
2020-06-01 22:02:16 +04:00
, spineTo
, traverseTree
2020-06-01 22:02:16 +04:00
, mk
, infoOf
2020-06-04 17:40:38 +04:00
-- * Callbacks on update
, UpdateOver (..)
, skip
2020-06-01 22:02:16 +04:00
)
where
2020-06-01 18:17:33 +04:00
2020-06-08 01:16:33 +04:00
import Data.Sum
2020-06-01 18:17:33 +04:00
import Lattice
import Comment
2020-06-01 18:17:33 +04:00
import Pretty
import Error
2020-06-01 22:02:16 +04:00
-- | A tree, where each layer is one of @layers@ `Functor`s.
--
-- Is equipped with @info@.
--
-- Can contain `Error` instead of all the above.
--
2020-06-01 18:17:33 +04:00
newtype Tree layers info = Tree
2020-06-08 01:16:33 +04:00
{ unTree :: Either (Error info) (info, Sum layers (Tree layers info))
2020-06-01 18:17:33 +04:00
}
2020-06-08 01:16:33 +04:00
instance Apply Functor layers => Functor (Tree layers) where
fmap f = go
2020-06-01 18:17:33 +04:00
where
go (Tree (Left err)) = Tree $ Left $ fmap f err
go (Tree (Right (a, rest))) = Tree $ Right (f a, fmap go rest)
2020-06-01 18:17:33 +04:00
2020-06-08 01:16:33 +04:00
instance Apply Foldable layers => Foldable (Tree layers) where
foldMap f = go
2020-06-04 13:48:04 +04:00
where
go (Tree (Left err)) = foldMap f err
go (Tree (Right (a, rest))) = f a <> foldMap go rest
2020-06-04 13:48:04 +04:00
2020-06-01 18:17:33 +04:00
instance
2020-06-08 01:16:33 +04:00
( Apply Functor layers
2020-06-01 18:17:33 +04:00
, HasComments info
2020-06-08 01:16:33 +04:00
, Pretty1 (Sum layers)
, Pretty info
2020-06-01 18:17:33 +04:00
)
=>
Show (Tree layers info)
where
show = show . pp
instance {-# OVERLAPS #-}
( HasComments info
2020-06-08 01:16:33 +04:00
, Apply Functor fs
, Pretty1 (Sum fs)
, Pretty info
2020-06-01 18:17:33 +04:00
)
=>
Pretty (Tree fs info)
where
pp = go
2020-06-01 18:17:33 +04:00
where
go (Tree (Left err)) = pp err
go (Tree (Right (info, fTree))) = c info $ pp fTree
2020-06-01 18:17:33 +04:00
2020-06-01 22:02:16 +04:00
-- | Return all subtrees that cover the range, ascending in size.
2020-06-01 18:17:33 +04:00
spineTo
:: ( Lattice info
2020-06-08 01:16:33 +04:00
, Apply Foldable fs
2020-06-01 18:17:33 +04:00
)
=> info
-> Tree fs info
-> [Tree fs info]
spineTo info = reverse . go
2020-06-01 18:17:33 +04:00
where
go tree@(Tree (Right (info', fres))) =
2020-06-01 18:17:33 +04:00
if info <? info'
then tree : foldMap go fres
2020-06-01 18:17:33 +04:00
else []
go _ = []
2020-06-04 13:48:04 +04:00
-- | Traverse the tree over some monad that exports its methods.
2020-06-01 22:02:16 +04:00
--
-- For each tree piece, will call `before` and `after` callbacks.
--
traverseTree
2020-06-08 01:16:33 +04:00
:: ( UpdateOver m (Sum fs) (Tree fs a)
, Apply Foldable fs
, Apply Functor fs
, Apply Traversable fs
2020-06-01 18:17:33 +04:00
)
2020-06-04 13:48:04 +04:00
=> (a -> m b) -> Tree fs a -> m (Tree fs b)
traverseTree act = go
2020-06-01 18:17:33 +04:00
where
go (Tree (Right (a, union))) = do
2020-06-01 18:17:33 +04:00
b <- act a
before union
2020-06-01 18:17:33 +04:00
union' <- traverse go union
after union
return (Tree (Right (b, union')))
2020-06-01 18:17:33 +04:00
go (Tree (Left err)) = do
err' <- traverse act err
return (Tree (Left err'))
2020-06-01 18:17:33 +04:00
-- | Make a tree out of a layer and an info.
2020-06-08 01:16:33 +04:00
mk :: (Functor f, Element f fs) => info -> f (Tree fs info) -> Tree fs info
mk i fx = Tree $ Right (i, inject fx)
2020-06-01 18:17:33 +04:00
2020-06-01 22:02:16 +04:00
-- | Get info from the tree.
2020-06-04 16:34:58 +04:00
infoOf :: Tree fs info -> info
infoOf = either eInfo fst . unTree
2020-06-01 18:17:33 +04:00
instance Stubbed (Tree fs info) info where
stub = Tree . Left
2020-06-01 18:17:33 +04:00
2020-06-08 01:16:33 +04:00
instance Apply Foldable fs => HasErrors (Tree fs info) info where
errors = go
2020-06-01 18:17:33 +04:00
where
go (Tree (Left err)) = pure err
go (Tree (Right (_, rest))) = foldMap go rest
2020-06-04 17:40:38 +04:00
-- | Update callbacks for a @f a@ while working inside monad @m@.
class Monad m => UpdateOver m f a where
before :: f a -> m ()
after :: f a -> m ()
before _ = skip
after _ = skip
-- | Do nothing.
skip :: Monad m => m ()
skip = return ()
2020-06-08 01:16:33 +04:00
instance Monad m => UpdateOver m (Sum '[]) a where
before = error "Sum.empty"
after = error "Sum.empty"
2020-06-04 17:40:38 +04:00
2020-06-08 01:16:33 +04:00
instance (UpdateOver m f a, UpdateOver m (Sum fs) a) => UpdateOver m (Sum (f : fs)) a where
before = either before before . decompose
after = either after after . decompose