----------------------------------------------------------------------------- -- | -- Module : Data.Eval -- Copyright : (c) 2010 University of Minho -- License : BSD3 -- -- Maintainer : hpacheco@di.uminho.pt -- Stability : experimental -- Portability : non-portable -- -- Pointless Rewrite: -- automatic transformation system for point-free programs -- -- Evaluation of point-free representations. -- ----------------------------------------------------------------------------- module Data.Eval where import Prelude hiding (Functor(..)) import Data.Type import Data.Pf import Data.Spine import Data.Equal import Data.Monoid import Data.Char import Data.List import Generics.Pointless.Combinators import Generics.Pointless.RecursionPatterns import Generics.Pointless.Functors hiding (rep) import qualified Generics.Pointless.Fctrable as F import Generics.Pointless.Lenses import Generics.Pointless.Lenses.Combinators import Generics.Pointless.Lenses.RecursionPatterns import Generics.Pointless.Lenses.Examples.Examples import Generics.Pointless.Lenses.Examples.Recs wrap :: a -> [a] wrap a = [a] fctrT :: Functor f => Fctr f -> F.Fctr f fctrT I = F.I fctrT (K c) = F.K fctrT L = F.L fctrT (f :*!: g) = fctrT f F.:*!: fctrT g fctrT (f :+!: g) = fctrT f F.:+!: fctrT g fctrT (f :@!: g) = fctrT f F.:@!: fctrT g inn_lnsF :: Mu a => Fctr f -> Lens (F a a) a inn_lnsF f = Lens inn (out . fst) out out_lnsF :: Mu a => Fctr f -> Lens a (F a a) out_lnsF f = Lens out (inn . fst) inn fmap_lnsF :: Functor f => Fctr f -> Lens c a -> Lens (Rep f c) (Rep f a) fmap_lnsF (f::Fctr f) l = Lens get' put' create' where get' = fmap fix (get l) put' = fmap fix (put l) . fzip (fixF f) (create l) create' = fmap fix (create l) fix = fixF f ana_lnsF :: (Mu b,Functor (PF b)) => Ann b -> Fctr (PF b) -> Lens a (F b a) -> Lens a b ana_lnsF (b::Ann b) f l = Lens get' put' create' where get' = ana b (get l) put' = accum b (put l) (fzip (fixF g) create' . (id >< get l)) create' = cata b (create l) g = f :: Fctr (PF b) cata_lnsF :: (Mu a,Functor (PF a)) => Ann a -> Fctr (PF a) -> (Lens (F a b) b) -> Lens a b cata_lnsF (a::Ann a) f l = Lens get' put' create' where get' = cata a (get l) put' = ana a (fzip (fixF g) create' . (put l . (id >< fmap (fixF f) get') /\ snd) . (id >< out)) create' = ana a (create l) g = f :: Fctr (PF a) eval :: Type a -> Pf a -> a eval _ BOT = error "_L" eval _ TOP = error "top" eval (Fun _ _) (FUN _ f) = f eval (Fun _ _) (CONV _ f) = error "converse evaluation" eval (Lns _ _) (CONV_LNS _ f) = error "converse evaluation" eval (Lns _ _) (LNS _ l) = l eval (Fun a b) (PROTECT f) = eval (Fun a b) f eval (Lns a b) (PROTECT_LNS f) = eval (Lns a b) f eval _ (VAR s) = error s eval (Fun a b) (PNT v) = const v eval (Fun _ _) BANG = bang eval (Fun a c) (COMP b f g) = eval (Fun b c) f . eval (Fun a b) g eval (Fun _ _) FST = fst eval (Fun _ _) SND = snd eval (Fun a (Prod b c)) (SPLIT f g) = eval (Fun a b) f /\ eval (Fun a c) g eval (Fun (Prod a b) (Prod c d)) (PROD f g) = eval (Fun a c) f >< eval (Fun b d) g eval (Fun _ _) INL = inl eval (Fun _ _) INR = inr eval (Fun (Either a b) c) (EITHER f g) = eval (Fun a c) f \/ eval (Fun b c) g eval (Fun (Either a b) (Either c d)) (SUM f g) = eval (Fun a c) f -|- eval (Fun b d) g eval _ (MKDYN a) = Dyn a eval _ (UNDYN a) = unDyn a eval (Fun b _) (CAST a) = cast a b eval _ ZERO = const mempty eval _ PLUS = uncurry mappend eval _ FOLD = mconcat eval (Fun _ _) ID = id eval (Fun _ _) SWAP = swap eval (Fun _ _) COSWAP = coswap eval (Fun _ _) DISTL = distl eval (Fun _ _) UNDISTL = undistl eval (Fun _ _) DISTR = distr eval (Fun _ _) UNDISTR = undistr eval (Fun _ _) ASSOCL = assocl eval (Fun _ _) ASSOCR = assocr eval (Fun _ _) COASSOCL = coassocl eval (Fun _ _) COASSOCR = coassocr eval (Fun _ _) INN = inn eval (Fun _ _) OUT = out eval (Fun _ _) (FMAP fctr (Fun c a) f) = fmap (fixF fctr) (eval (Fun c a) f) eval (Fun _ _) (FZIP fctr t f) = fzip (fixF fctr) $ eval t f eval (Fun a b@(dataFctr -> Just fctr)) (ANA f) = ana _L (eval (Fun a (rep fctr a)) f) eval (Fun a@(dataFctr -> Just fctr) b) (CATA f) = cata _L (eval (Fun (rep fctr b) b) f) eval (Fun a@(dataFctr -> Just fctr) b) (PARA f) = para _L (eval (Fun (rep fctr (Prod b a)) b) f) eval (Fun a (List b)) (ANA f) = ana _L (eval (Fun a (rep (listfctr b) a)) f) eval (Fun (List a) b) (CATA f) = cata _L (eval (Fun (rep (listfctr a) b) b) f) eval (Fun la@(List a) b) (PARA f) = para _L (eval (Fun (rep (listfctr a) (Prod b la)) b) f) eval (Fun (List a) (List b)) (MAP f) = map (eval (Fun a b) f) eval (Fun _ _) LHEAD = \l -> if (null l) then [] else [head l] eval (Fun _ _) LTAIL = \l -> if (null l) then [] else tail l eval (Fun _ _) WRAP = wrap eval (Fun _ _) LENGTH = get (length_lns _L) eval (Fun _ _) ONE = const (Nat 1) eval (Fun c a) (GET l) = get (eval (Lns c a) l) eval (Fun (Prod a c) _) (PUT l) = put (eval (Lns c a) l) eval (Fun a c) (CREATE l) = create (eval (Lns c a) l) eval (Lns c a) (COMP_LNS b f g) = eval (Lns b a) f .< eval (Lns c b) g eval (Lns (Prod a b) _) (FST_LNS f) = fst_lns $ eval (Fun a b) f eval (Lns (Prod a b) _) (SND_LNS f) = snd_lns $ eval (Fun b a) f eval (Lns (Prod a b) (Prod c d)) (PROD_LNS f g) = eval (Lns a c) f ><< eval (Lns b d) g eval (Lns (Either a b) c) (EITHER_LNS x f g) = (\/<) (eval (Fun c (Either One One)) x) (eval (Lns a c) f) (eval (Lns b c) g) eval (Lns (Either a b) (Either c d)) (SUM_LNS f g) = eval (Lns a c) f -|-< eval (Lns b d) g eval (Lns (Either a b) (Either c d)) (SUMW_LNS f g l1 l2) = sum_lns f' g' (eval (Lns a c) l1) (eval (Lns b d) l2) where f' = eval (Fun (Prod c b) a) f g' = eval (Fun (Prod d a) b) g eval (Lns a One) (BANG_LNS f) = (!<) (eval (Fun One a) f) eval (Lns c _) BANGL_LNS = (!/\<) id_lns eval (Lns c _) BANGR_LNS = (/\!<) id_lns eval (Lns _ _) ID_LNS = id_lns eval (Lns _ _) SWAP_LNS = swap_lns eval (Lns _ _) COSWAP_LNS = coswap_lns eval (Lns _ _) DISTL_LNS = distl_lns eval (Lns _ _) UNDISTL_LNS = undistl_lns eval (Lns _ _) DISTR_LNS = distr_lns eval (Lns _ _) UNDISTR_LNS = undistr_lns eval (Lns _ _) ASSOCL_LNS = assocl_lns eval (Lns _ _) ASSOCR_LNS = assocr_lns eval (Lns _ _) COASSOCL_LNS = coassocl_lns eval (Lns _ _) COASSOCR_LNS = coassocr_lns eval (Lns _ (List a)) INN_LNS = inn_lnsF (listfctr a) eval (Lns (List a) _) OUT_LNS = out_lnsF (listfctr a) eval (Lns _ a@(dataFctr -> Just fctr)) INN_LNS = inn_lnsF fctr eval (Lns a@(dataFctr -> Just fctr) _) OUT_LNS = out_lnsF fctr eval (Lns _ _) (FMAP_LNS fctr (Fun c a) f) = fmap_lnsF fctr (eval (Lns c a) f) eval (Lns a (List b)) (ANA_LNS f) = ana_lnsF _L (listfctr b) (eval (Lns a (rep (listfctr b) a)) f) eval (Lns (List a) b) (CATA_LNS f) = cata_lnsF _L (listfctr a) (eval (Lns (rep (listfctr a) b) b) f) eval (Lns a b@(dataFctr -> Just fctr)) (ANA_LNS f) = ana_lnsF _L fctr (eval (Lns a (rep fctr a)) f) eval (Lns a@(dataFctr -> Just fctr) b) (CATA_LNS f) = cata_lnsF _L fctr (eval (Lns (rep fctr b) b) f) eval (Lns (List a) (List b)) (MAP_LNS l1) = map_pf (eval (Lns a b) l1) eval (Lns (List a) _) (LENGTH_LNS v) = length_lns v eval (Lns _ _) FILTER_LEFT_LNS = filter_left_pf eval (Lns _ _) FILTER_RIGHT_LNS = filter_right_pf eval (Lns _ _) CAT_LNS = cat_pf eval (Lns _ _) CONCAT_LNS = concat_pf eval (Lns _ _) SUMN_LNS = sum_pf eval (Lns _ _) PLUSN_LNS = plus_lns eval p (APPLY Dynamic t) = applyDyn $ \a -> mkDyn a . eval (Fun a a) (APPLY a t) eval p (APPLY a (ALL f)) = eval p (allT a f) eval p (APPLY a (EVERYWHERE f)) = eval p (everywhereEval a f) eval p (APPLY a (EVERYWHERE' f)) = eval p (everywhereEval' a f) eval p (APPLY a (EXTT f t g)) = eval p (extT a f t g) eval p (APPLY a (SEQ f g)) = eval p (APPLY a g) . eval p (APPLY a f) eval p (APPLY a (MKT t f)) = eval p (mkT a t f) eval p (APPLY a NOP) = id eval q@(Fun _ r) (APPLYQ Dynamic f) = applyDyn $ \a -> eval (Fun a r) (APPLYQ a f) eval q@(Fun a r)(APPLYQ _ (GMAPQ f)) = eval q (gmapQ r a f) eval q@(Fun _ r) (APPLYQ a (EVERYTHING f)) = eval q (everythingEval a f) eval q (APPLYQ a (EXTQ f t g)) = eval q (extQ a f t g) eval q (APPLYQ t (UNION f g)) = eval q (APPLYQ t f) `mappend` eval q (APPLYQ t g) eval q (APPLYQ a (MKQ t f)) = eval q (mkQ a t f) eval q (APPLYQ a EMPTYQ) = mempty eval (Fun _ s) (APPLYQ a (SEQQ (q :: Pf (Q r)) f)) = let r = typeof :: Type r in eval (Fun r s) f . eval (Fun a r) (APPLYQ a q) eval _ (f :?: p) = Q (\t x -> let y = unQ (eval (TU (List Dynamic)) f) t x in filter (unQ (eval (TU Bool) p) Dynamic) y) eval (Fun _ _) NONEMPTY = not . null eval q (APPLYQ a SELF) = if isAtt a then mempty else wrap . mkDyn a eval q (APPLYQ a ATT) = if isAtt a then wrap . mkDyn a else mempty eval q (APPLYQ a CHILD) = eval q $ APPLYQ a $ GMAPQ SELF eval q (APPLYQ a ATTRIBUTE) = eval q $ APPLYQ a $ GMAPQ ATT eval q (APPLYQ a DESCENDANT) = eval q $ APPLYQ a $ EVERYTHING CHILD eval q (APPLYQ a DESCSELF) = eval q $ APPLYQ a $ EVERYTHING SELF eval q (APPLYQ a@(dataName -> Just name) (NAME n)) | sameName name n = eval q (APPLYQ a SELF) eval q (APPLYQ a@(dataName -> Just name) (NAME n)) | sameName name ("@"++n) = eval q (APPLYQ a ATT) eval q (APPLYQ a (NAME n)) = mempty eval (Fun t r) (APPLYQ a (f :/: g)) = mconcat . map (eval (Fun Dynamic r) (APPLYQ Dynamic g)) . eval (Fun t (List Dynamic)) (APPLYQ a f) eval (TU (Prod a b)) (f :/\: g) = Q (\t x -> (unQ (eval (TU a) f) t x,unQ (eval (TU b) g) t x)) eval t f = error $ "eval undefined for: " ++ show t everywhereEval t f = APPLY t (ALL (EVERYWHERE f) `SEQ` f) everywhereEval' t f = APPLY t (f `SEQ` ALL (EVERYWHERE' f)) everythingEval t f = APPLYQ t (f `UNION` GMAPQ (EVERYTHING f)) -- ** Type-preserving specialization allTF :: Fctr f -> Type a -> Pf T -> Pf (Rep f a -> Rep f a) allTF I a t = APPLY a t allTF L a t = MAP $ APPLY a t allTF (K c) a t = APPLY c t allTF (f :*!: g) a t = allTF f a t `PROD` allTF g a t allTF (f :+!: g) a t = allTF f a t `SUM` allTF g a t allTF (f :@!: g) a t = let ga = rep g a in COMP (rep f ga) (allTKF f ga t) (FMAP f (Fun ga ga) (allTF g a t)) allTKF :: Fctr f -> Type a -> Pf T -> Pf (Rep f a -> Rep f a) allTKF I a t = ID allTKF L a t = ID allTKF (K c) a t = APPLY c t allTKF (f :*!: g) a t = allTKF f a t `PROD` allTKF g a t allTKF (f :+!: g) a t = allTKF f a t `SUM` allTKF g a t allTKF (f :@!: g) a t = let ga = rep g a in COMP (rep f ga) (allTKF f ga t) (FMAP f (Fun ga ga) (allTKF g a t)) allT :: Type a -> Pf T -> Pf (a -> a) allT a@(Data s fctr) t = allTRec a fctr t allT a@(NewData s fctr) t = allTRec a fctr t allT (List a) t = MAP (APPLY a t) allT (Either a b) t = (APPLY a t) `SUM` (APPLY b t) allT (Prod a b) t = (APPLY a t) `PROD` (APPLY b t) --allT Dynamic allT a t = ID allTRec :: (Functor (PF a),Mu a) => Type a -> Fctr (PF a) -> Pf T -> Pf (a -> a) allTRec a fctr t = let f = rep fctr a in COMP f INN $ COMP f (allTF fctr a t) OUT -- | bottom-up (cata) everywhereT :: Type a -> Pf T -> Pf (a -> a) everywhereT t@(Data n fctr) g = everywhereTRec t fctr g everywhereT t@(NewData n fctr) g = everywhereTRec t fctr g everywhereT t g = APPLY t (ALL (EVERYWHERE g) `SEQ` g) everywhereTRec :: (Functor (PF a),Mu a) => Type a -> Fctr (PF a) -> Pf T -> Pf (a -> a) everywhereTRec t fctr g = let f = rep fctr t in CATA $ COMP t (APPLY t g) $ COMP f INN (allTKF fctr t $ EVERYWHERE g) -- | top-down (ana) everywhereT' :: Type a -> Pf T -> Pf (a -> a) everywhereT' t@(Data n fctr) g = everywhereTRec' t fctr g everywhereT' t@(NewData n fctr) g = everywhereTRec' t fctr g everywhereT' t g = APPLY t (g `SEQ` ALL (EVERYWHERE' g)) everywhereTRec' :: (Functor (PF a),Mu a) => Type a -> Fctr (PF a) -> Pf T -> Pf (a -> a) everywhereTRec' t fctr g = let f = rep fctr t in ANA $ COMP f (allTKF fctr t $ EVERYWHERE' g) $ COMP t OUT $ APPLY t g mkT :: Type a -> Type x -> Pf (x -> x) -> Pf (a -> a) mkT t t' f = case teq t t' of {Just Eq -> f; otherwise -> ID} extT :: Type x -> Pf T -> Type a -> Pf (a -> a) -> Pf (x -> x) extT t f x g = case teq t x of {Just Eq -> g; otherwise -> APPLY t f} -- ** Type-unifying specialization gmapQF :: Monoid r => Type r -> Fctr f -> Type a -> Pf (Q r) -> Pf (Rep f a -> r) gmapQF r I a q = case teq r a of { Just Eq -> ID; otherwise -> APPLYQ a q } gmapQF r L a q = case teq r a of { Just Eq -> FOLD; otherwise -> COMP (List r) FOLD $ MAP $ APPLYQ a q } gmapQF r (K c) a q = APPLYQ c q gmapQF r (f :+!: g) a q = gmapQF r f a q `EITHER` gmapQF r g a q gmapQF r (f :*!: g) a q = COMP (Prod r r) PLUS $ gmapQF r f a q `PROD` gmapQF r g a q gmapQF r (f :@!: g) a q = let ga = rep g a in COMP (rep f r) (gmapQKF r f r q) $ FMAP f (Fun ga r) (gmapQF r g a q) gmapQKF :: Monoid r => Type r -> Fctr f -> Type a -> Pf (Q r) -> Pf (Rep f a -> r) gmapQKF r I a q = case teq r a of { Just Eq -> ID; otherwise -> ZERO } gmapQKF r L a q = case teq r a of { Just Eq -> FOLD; otherwise -> ZERO } gmapQKF r (K c) a q = APPLYQ c q gmapQKF r (f :+!: g) a q = gmapQKF r f a q `EITHER` gmapQKF r g a q gmapQKF r (f :*!: g) a q = COMP (Prod r r) PLUS $ gmapQKF r f a q `PROD` gmapQKF r g a q gmapQKF r (f :@!: g) a q = let ga = rep g a in COMP (rep f r) (gmapQKF r f r q) $ FMAP f (Fun ga r) (gmapQKF r g a q) gmapQ :: (Monoid r) => Type r -> Type a -> Pf (Q r) -> Pf (a -> r) gmapQ r t@(Data _ fctr) g = gmapQRec r t fctr g gmapQ r t@(NewData _ fctr) g = gmapQRec r t fctr g gmapQ r (List a) f = COMP (List r) FOLD $ MAP $ APPLYQ a f gmapQ r (Either a b) f = (APPLYQ a f) `EITHER` (APPLYQ b f) gmapQ r (Prod a b) f = COMP (Prod r r) PLUS $ APPLYQ a f `PROD` APPLYQ b f gmapQ r t f = ZERO gmapQRec :: (Functor (PF a), Mu a,Monoid r) => Type r -> Type a -> Fctr (PF a) -> Pf (Q r) -> Pf (a -> r) gmapQRec r t fctr g = COMP (rep fctr t) (gmapQF r fctr t g) OUT everythingQ :: (Monoid r) => Type r -> Type a -> Pf (Q r) -> Pf (a -> r) everythingQ r t@(Data _ fctr) g = everythingQRec r t fctr g everythingQ r t@(NewData _ fctr) g = everythingQRec r t fctr g --everythingQ r t@(List a) g = everythingQRec r t (listfctr a) g everythingQ r t g = APPLYQ t (g `UNION` GMAPQ (EVERYTHING g)) everythingQRec :: (Functor (PF a), Mu a,Monoid r) => Type r -> Type a -> Fctr (PF a) -> Pf (Q r) -> Pf (a -> r) everythingQRec r t fctr g = let (fr,ft) = (rep fctr r,rep fctr t) (rr,rt) = (Prod r r,Prod r t) in PARA $ COMP rr PLUS $ COMP (Prod fr t) (gmapQKF r fctr r (EVERYTHING g) `PROD` APPLYQ t g) $ FMAP fctr (Fun rt r) FST `SPLIT` (COMP ft INN $ FMAP fctr (Fun rt t) SND) mkQ :: Monoid r => Type a -> Type x -> Pf (x -> r) -> Pf (a -> r) mkQ a x f = case teq a x of {Just Eq -> f; otherwise -> ZERO} extQ :: Type x -> Pf (Q r) -> Type a -> Pf (a -> r) -> Pf (x -> r) extQ t f x g = case teq t x of {Just Eq -> g; otherwise -> APPLYQ t f}