1
1
mirror of https://github.com/github/semantic.git synced 2024-12-25 07:55:12 +03:00
semantic/src/Term.hs

134 lines
4.3 KiB
Haskell
Raw Normal View History

2017-09-08 18:24:11 +03:00
{-# LANGUAGE MultiParamTypeClasses, RankNTypes, TypeFamilies, TypeSynonymInstances, UndecidableInstances #-}
2017-07-28 21:37:02 +03:00
module Term
2017-09-08 18:45:08 +03:00
( Term(..)
, TermF(..)
2017-07-28 21:37:02 +03:00
, SyntaxTerm
, SyntaxTermF
, termSize
2017-09-08 19:23:16 +03:00
, term
2017-09-08 18:46:35 +03:00
, unTerm
2017-09-08 18:24:11 +03:00
, extract
, unwrap
2017-09-08 19:21:39 +03:00
, hoistTerm
2017-07-28 21:37:02 +03:00
) where
2017-09-08 18:24:11 +03:00
import Control.Comonad
import Control.Comonad.Cofree.Class
2017-07-28 21:37:02 +03:00
import Control.DeepSeq
2017-09-08 18:40:23 +03:00
import Data.Bifunctor
2017-09-08 18:55:36 +03:00
import Data.Functor.Classes
import Data.Functor.Classes.Pretty.Generic as Pretty
2017-07-28 21:37:02 +03:00
import Data.Functor.Foldable
import Data.Functor.Listable
import Data.Proxy
import Data.Record
import Data.Union
import Syntax
2016-10-22 01:06:31 +03:00
-- | A Term with an abstract syntax tree and an annotation.
2017-09-08 18:24:11 +03:00
infixr 5 :<
2017-09-08 18:45:08 +03:00
data Term f a = a :< f (Term f a)
2017-09-08 18:56:29 +03:00
infixr 5 :<<
2017-09-08 18:45:08 +03:00
data TermF f a b = (:<<) { headF :: a, tailF :: f b }
2017-09-08 18:40:23 +03:00
deriving (Eq, Foldable, Functor, Show, Traversable)
2017-09-08 18:24:11 +03:00
2016-10-22 00:39:13 +03:00
-- | A Term with a Syntax leaf and a record of fields.
type SyntaxTerm fields = Term Syntax (Record fields)
type SyntaxTermF fields = TermF Syntax (Record fields)
2017-09-08 18:45:08 +03:00
instance (NFData (f (Term f a)), NFData a, Functor f) => NFData (Term f a) where
2017-09-08 18:46:35 +03:00
rnf = rnf . unTerm
2017-09-08 18:45:08 +03:00
instance (NFData a, NFData (f b)) => NFData (TermF f a b) where
2017-09-08 18:40:23 +03:00
rnf (a :<< s) = rnf a `seq` rnf s `seq` ()
2016-04-11 22:06:53 +03:00
-- | Return the node count of a term.
termSize :: (Foldable f, Functor f) => Term f annotation -> Int
2016-01-13 23:32:03 +03:00
termSize = cata size where
2017-09-08 18:40:23 +03:00
size (_ :<< syntax) = 1 + sum syntax
2017-07-28 21:37:02 +03:00
2017-09-08 19:23:16 +03:00
term :: TermF f a (Term f a) -> Term f a
term (a :<< f) = a :< f
2017-07-28 21:37:02 +03:00
2017-09-08 18:46:35 +03:00
unTerm :: Term f a -> TermF f a (Term f a)
unTerm (a :< f) = a :<< f
2017-08-22 19:51:25 +03:00
2017-09-08 19:21:39 +03:00
hoistTerm :: Functor f => (forall a. f a -> g a) -> Term f a -> Term g a
hoistTerm f = go where go (a :< r) = a :< f (fmap go r)
2017-08-22 19:51:25 +03:00
liftPrettyUnion :: Apply1 Pretty1 fs => (a -> Doc ann) -> ([a] -> Doc ann) -> Union fs a -> Doc ann
liftPrettyUnion p pl = apply1 (Proxy :: Proxy Pretty1) (liftPretty p pl)
2017-09-08 18:45:08 +03:00
instance Pretty1 f => Pretty1 (Term f) where
liftPretty p pl = go where go (a :< f) = p a <+> liftPretty go (Pretty.list . map (liftPretty p pl)) f
2017-08-22 19:52:09 +03:00
2017-09-08 18:45:08 +03:00
instance (Pretty1 f, Pretty a) => Pretty (Term f a) where
2017-08-23 18:52:00 +03:00
pretty = liftPretty pretty prettyList
instance Apply1 Pretty1 fs => Pretty1 (Union fs) where
liftPretty = liftPrettyUnion
2017-09-08 18:24:11 +03:00
2017-09-08 18:45:08 +03:00
type instance Base (Term f a) = TermF f a
2017-09-08 18:24:11 +03:00
2017-09-08 18:46:35 +03:00
instance Functor f => Recursive (Term f a) where project = unTerm
2017-09-08 19:23:16 +03:00
instance Functor f => Corecursive (Term f a) where embed = term
2017-09-08 18:24:11 +03:00
2017-09-08 18:45:08 +03:00
instance Functor f => Comonad (Term f) where
2017-09-08 18:24:11 +03:00
extract (a :< _) = a
duplicate w = w :< fmap duplicate (unwrap w)
extend f = go where go w = f w :< fmap go (unwrap w)
2017-09-08 18:45:08 +03:00
instance Functor f => Functor (Term f) where
2017-09-08 18:24:11 +03:00
fmap f = go where go (a :< r) = f a :< fmap go r
2017-09-08 18:45:08 +03:00
instance Functor f => ComonadCofree f (Term f) where
2017-09-08 18:24:11 +03:00
unwrap (_ :< as) = as
{-# INLINE unwrap #-}
2017-09-08 18:55:36 +03:00
instance Eq1 f => Eq1 (Term f) where
liftEq eqA = go where go (a1 :< f1) (a2 :< f2) = eqA a1 a2 && liftEq go f1 f2
instance (Eq1 f, Eq a) => Eq (Term f a) where
(==) = eq1
2017-09-08 18:24:11 +03:00
2017-09-08 18:58:15 +03:00
instance Show1 f => Show1 (Term f) where
liftShowsPrec spA slA = go where go d (a :< f) = showParen (d > 5) $ spA 6 a . showString " :< " . liftShowsPrec go (liftShowList spA slA) 5 f
instance (Show1 f, Show a) => Show (Term f a) where
showsPrec = showsPrec1
2017-09-08 18:40:23 +03:00
2017-09-08 18:45:08 +03:00
instance Functor f => Bifunctor (TermF f) where
2017-09-08 18:40:23 +03:00
bimap f g (a :<< r) = f a :<< fmap g r
instance Listable1 f => Listable2 (TermF f) where
liftTiers2 annotationTiers recurTiers = liftCons2 annotationTiers (liftTiers recurTiers) (:<<)
instance (Listable1 f, Listable a) => Listable1 (TermF f a) where
liftTiers = liftTiers2 tiers
instance (Functor f, Listable1 f) => Listable1 (Term f) where
liftTiers annotationTiers = go
2017-09-08 19:23:16 +03:00
where go = liftCons1 (liftTiers2 annotationTiers go) term
2017-09-08 18:55:36 +03:00
instance Eq1 f => Eq2 (TermF f) where
liftEq2 eqA eqB (a1 :<< f1) (a2 :<< f2) = eqA a1 a2 && liftEq eqB f1 f2
instance (Eq1 f, Eq a) => Eq1 (TermF f a) where
liftEq = liftEq2 (==)
2017-09-08 18:59:40 +03:00
instance Show1 f => Show2 (TermF f) where
liftShowsPrec2 spA _ spB slB d (a :<< f) = showParen (d > 5) $ spA 6 a . showString " :<< " . liftShowsPrec spB slB 5 f
2017-09-08 19:00:09 +03:00
instance (Show1 f, Show a) => Show1 (TermF f a) where
liftShowsPrec = liftShowsPrec2 showsPrec showList
instance Pretty1 f => Pretty2 (TermF f) where
liftPretty2 pA _ pB plB (a :<< f) = pA a <+> liftPretty pB plB f
instance (Pretty1 f, Pretty a) => Pretty1 (TermF f a) where
liftPretty = liftPretty2 pretty prettyList
instance (Pretty1 f, Pretty a, Pretty b) => Pretty (TermF f a b) where
pretty = liftPretty pretty prettyList