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

52 lines
2.6 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 Algorithm
import Control.Monad.Free
import Control.Comonad.Cofree
import Operation
import Diff
import Syntax
import Data.Map
2015-11-18 05:23:53 +03:00
import Patch
2015-11-18 18:11:05 +03:00
import SES
import Term
2015-11-18 04:05:16 +03:00
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-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-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)
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
recur (Indexed a') (Indexed b') | length a' == length b' =
2015-11-19 22:27:31 +03:00
Free . Annotated (annotation1, annotation2) . Indexed $ zipWith (interpret comparable) a' b'
2015-11-19 22:37:19 +03:00
recur (Fixed a') (Fixed b') | length a' == length b' =
2015-11-19 22:27:31 +03:00
Free . Annotated (annotation1, annotation2) . Fixed $ zipWith (interpret comparable) a' b'
2015-11-19 22:37:19 +03:00
recur (Keyed a') (Keyed b') | keys a' == keys b' =
2015-11-19 22:27:31 +03:00
Free . Annotated (annotation1, annotation2) . Keyed . fromList . fmap repack $ keys b' where
2015-11-18 05:16:39 +03:00
repack key = (key, interpretInBoth key a' b')
interpretInBoth key a' b' = maybeInterpret (Data.Map.lookup key a') (Data.Map.lookup key b')
maybeInterpret (Just a) (Just b) = interpret comparable a b
2015-11-19 22:37:19 +03:00
recur _ _ = Pure $ Replace (annotation1 :< a) (annotation2 :< b)
2015-11-18 04:13:48 +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
patched = intersectionWith (interpret comparable) a b
2015-11-18 11:21:27 +03:00
run comparable (Free (ByIndex a b f)) = run comparable . f $ ses (constructAndRun comparable) cost 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 = maybeReplace $ constructAndRun comparable a b where
2015-11-18 04:13:48 +03:00
maybeReplace (Just a) = a
2015-11-18 05:44:55 +03:00
maybeReplace Nothing = Pure $ Replace a b