2015-11-18 22:09:18 +03:00
|
|
|
module Interpreter (interpret, Comparable) where
|
2015-11-18 04:05:16 +03:00
|
|
|
|
|
|
|
import Algorithm
|
|
|
|
import Diff
|
2015-11-27 17:51:59 +03:00
|
|
|
import Operation
|
2015-11-18 05:23:53 +03:00
|
|
|
import Patch
|
2015-11-18 18:11:05 +03:00
|
|
|
import SES
|
2015-11-27 17:51:59 +03:00
|
|
|
import Syntax
|
2015-11-18 22:28:16 +03:00
|
|
|
import Term
|
2015-11-27 17:51:59 +03:00
|
|
|
import Control.Monad.Free
|
|
|
|
import Control.Comonad.Cofree
|
|
|
|
import Data.Map
|
2015-11-27 17:53:37 +03:00
|
|
|
import Data.Maybe
|
2015-11-18 04:05:16 +03:00
|
|
|
|
2015-11-19 22:56:35 +03:00
|
|
|
hylo :: Functor f => (t -> f b -> b) -> (a -> (t, f a)) -> a -> b
|
|
|
|
hylo down up a = down annotation $ hylo down up <$> syntax where
|
|
|
|
(annotation, syntax) = up a
|
|
|
|
|
2015-11-19 22:27:31 +03:00
|
|
|
constructAndRun :: (Eq a, Eq annotation) => Comparable a annotation -> Term a annotation -> Term a annotation -> Maybe (Diff a annotation)
|
2015-11-19 22:56:45 +03:00
|
|
|
constructAndRun _ a b | a == b = hylo introduce eliminate <$> zipTerms a b where
|
|
|
|
eliminate :: Cofree f a -> (a, f (Cofree f a))
|
|
|
|
eliminate (extract :< unwrap) = (extract, unwrap)
|
|
|
|
introduce :: (annotation, annotation) -> Syntax a (Diff a annotation) -> Diff a annotation
|
|
|
|
introduce ann syntax = Free $ Annotated ann syntax
|
2015-11-18 22:13:13 +03:00
|
|
|
constructAndRun comparable a b | not $ comparable a b = Nothing
|
2015-11-19 22:36:14 +03:00
|
|
|
constructAndRun comparable (annotation1 :< a) (annotation2 :< b) =
|
2015-11-18 22:09:11 +03:00
|
|
|
run comparable $ algorithm a b where
|
2015-11-19 22:36:14 +03:00
|
|
|
algorithm (Indexed a) (Indexed b) = Free $ ByIndex a b (Pure . Free . Annotated (annotation1, annotation2) . Indexed)
|
|
|
|
algorithm (Keyed a) (Keyed b) = Free $ ByKey a b (Pure . Free . Annotated (annotation1, annotation2) . Keyed)
|
|
|
|
algorithm (Leaf a) (Leaf b) | a == b = Pure . Free . Annotated (annotation1, annotation2) $ Leaf b
|
|
|
|
algorithm a b = Free $ Recursive (annotation1 :< a) (annotation2 :< b) Pure
|
2015-11-18 04:05:16 +03:00
|
|
|
|
2015-11-19 22:27:31 +03:00
|
|
|
run :: (Eq a, Eq annotation) => Comparable a annotation -> Algorithm a annotation (Diff a annotation) -> Maybe (Diff a annotation)
|
2015-11-18 22:09:11 +03:00
|
|
|
run _ (Pure diff) = Just diff
|
2015-11-18 05:26:07 +03:00
|
|
|
|
2015-11-19 22:37:19 +03:00
|
|
|
run comparable (Free (Recursive (annotation1 :< a) (annotation2 :< b) f)) = run comparable . f $ recur a b where
|
2015-11-27 19:46:25 +03:00
|
|
|
recur (Indexed a') (Indexed b') | length a' == length b' = annotate . Indexed $ zipWith (interpret comparable) a' b'
|
|
|
|
recur (Fixed a') (Fixed b') | length a' == length b' = annotate . Fixed $ zipWith (interpret comparable) a' b'
|
|
|
|
recur (Keyed a') (Keyed b') | keys a' == keys b' = annotate . Keyed . fromList . fmap repack $ keys b'
|
2015-11-27 17:55:29 +03:00
|
|
|
where
|
2015-11-18 05:16:39 +03:00
|
|
|
repack key = (key, interpretInBoth key a' b')
|
2015-11-18 04:50:15 +03:00
|
|
|
interpretInBoth key a' b' = maybeInterpret (Data.Map.lookup key a') (Data.Map.lookup key b')
|
2015-11-18 22:09:11 +03:00
|
|
|
maybeInterpret (Just a) (Just b) = interpret comparable a b
|
2015-11-27 18:04:53 +03:00
|
|
|
maybeInterpret _ _ = error "maybeInterpret assumes that its operands are `Just`s."
|
2015-11-19 22:37:19 +03:00
|
|
|
recur _ _ = Pure $ Replace (annotation1 :< a) (annotation2 :< b)
|
2015-11-18 04:13:48 +03:00
|
|
|
|
2015-11-27 19:46:12 +03:00
|
|
|
annotate = Free . Annotated (annotation1, annotation2)
|
|
|
|
|
2015-11-18 22:09:11 +03:00
|
|
|
run comparable (Free (ByKey a b f)) = run comparable $ f byKey where
|
2015-11-18 11:21:27 +03:00
|
|
|
byKey = unions [ deleted, inserted, patched ]
|
|
|
|
deleted = (Pure . Delete) <$> difference a b
|
|
|
|
inserted = (Pure . Insert) <$> difference b a
|
2015-11-18 22:09:11 +03:00
|
|
|
patched = intersectionWith (interpret comparable) a b
|
2015-11-18 11:21:27 +03:00
|
|
|
|
2015-11-27 20:06:14 +03:00
|
|
|
run comparable (Free (ByIndex a b f)) = run comparable . f $ ses (constructAndRun comparable) diffCost a b
|
2015-11-18 18:02:47 +03:00
|
|
|
|
2015-11-19 00:23:47 +03:00
|
|
|
type Comparable a annotation = Term a annotation -> Term a annotation -> Bool
|
2015-11-18 22:09:11 +03:00
|
|
|
|
2015-11-19 22:27:31 +03:00
|
|
|
interpret :: (Eq a, Eq annotation) => Comparable a annotation -> Term a annotation -> Term a annotation -> Diff a annotation
|
2015-11-27 17:53:37 +03:00
|
|
|
interpret comparable a b = fromMaybe (Pure $ Replace a b) $ constructAndRun comparable a b
|