1
1
mirror of https://github.com/github/semantic.git synced 2024-12-22 14:21:31 +03:00
semantic/src/Interpreter.hs

71 lines
3.3 KiB
Haskell
Raw Normal View History

2015-11-18 22:09:18 +03:00
module Interpreter (interpret, Comparable) where
2015-11-18 04:05:16 +03:00
import Prelude hiding (lookup)
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
import Term
2015-11-27 17:51:59 +03:00
import Control.Monad.Free
import Control.Comonad.Cofree hiding (unwrap)
import qualified OrderedMap as Map
import OrderedMap ((!))
2015-12-15 03:10:17 +03:00
import qualified Data.List as List
import Data.List ((\\))
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-27 20:19:24 +03:00
-- | Constructs an algorithm and runs it
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) =
run comparable $ algorithm a b where
2015-11-27 20:10:16 +03:00
algorithm (Indexed a') (Indexed b') = Free $ ByIndex a' b' (annotate . Indexed)
2015-11-27 20:12:49 +03:00
algorithm (Keyed a') (Keyed b') = Free $ ByKey a' b' (annotate . Keyed)
algorithm (Leaf a') (Leaf b') | a' == b' = annotate $ Leaf b'
algorithm a' b' = Free $ Recursive (annotation1 :< a') (annotation2 :< b') Pure
2015-11-27 20:10:16 +03:00
annotate = Pure . Free . Annotated (annotation1, annotation2)
2015-11-18 04:05:16 +03:00
2015-11-27 20:19:24 +03:00
-- | Runs the diff algorithm
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)
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') | Map.keys a' == bKeys = annotate . Keyed . Map.fromList . fmap repack $ bKeys
2015-11-27 17:55:29 +03:00
where
bKeys = Map.keys b'
2015-11-18 05:16:39 +03:00
repack key = (key, interpretInBoth key a' b')
2015-12-15 02:05:00 +03:00
interpretInBoth key x y = interpret comparable (x ! key) (y ! key)
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)
run comparable (Free (ByKey a b f)) = run comparable $ f byKey where
2015-12-15 03:11:40 +03:00
byKey = Map.fromList $ toKeyValue <$> List.union aKeys bKeys
2015-12-15 03:12:03 +03:00
toKeyValue key | List.elem key deleted = (key, Pure . Delete $ a ! key)
2015-12-15 20:42:50 +03:00
toKeyValue key | List.elem key inserted = (key, Pure . Insert $ b ! key)
toKeyValue key = (key, interpret comparable (a ! key) (b ! key))
2015-12-15 03:10:17 +03:00
aKeys = Map.keys a
bKeys = Map.keys b
deleted = aKeys \\ bKeys
inserted = bKeys \\ aKeys
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-19 22:27:31 +03:00
interpret :: (Eq a, Eq annotation) => Comparable a annotation -> Term a annotation -> Term a annotation -> Diff a annotation
interpret comparable a b = fromMaybe (Pure $ Replace a b) $ constructAndRun comparable a b