{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
{-# OPTIONS_GHC -Wno-incomplete-patterns #-}
module Data.HDiff.Diff.Modes where
import qualified Data.Set as S
import Data.Functor.Const
import Data.Functor.Sum
import Generics.MRSOP.Base
import Generics.MRSOP.Holes
import Generics.MRSOP.HDiff.Digest
import qualified Data.WordTrie as T
import Data.HDiff.Diff.Preprocess
import Data.HDiff.Diff.Types
import Data.HDiff.MetaVar
type CanShare ki codes phi = forall a ix . PrepFix a ki codes phi ix -> Bool
extractHoles :: DiffMode
-> CanShare ki codes phi
-> IsSharedMap
-> Delta (PrepFix a ki codes phi) at
-> Delta (Holes ki codes (Sum phi (MetaVarIK ki))) at
extractHoles DM_NoNested h tr sd
= extractNoNested h tr sd
extractHoles DM_ProperShare h tr (src :*: dst)
= (extractProperShare h tr src :*: extractProperShare h tr dst)
extractHoles DM_Patience h tr (src :*: dst)
= (extractPatience h tr src :*: extractPatience h tr dst)
extractProperShare :: CanShare ki codes phi
-> IsSharedMap
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
extractProperShare h tr a = properShare h tr (tagProperShare tr a)
tagProperShare :: forall a ki codes phi at
. IsSharedMap
-> PrepFix a ki codes phi at
-> PrepFix (Int , Bool) ki codes phi at
tagProperShare ism = holesSynthesize pHole pOpq pPeel
where
myar :: PrepData a -> Int
myar = maybe 0 getArity . flip T.lookup ism . toW64s . treeDigest
pHole :: Const (PrepData a) ix -> phi ix
-> Const (PrepData (Int , Bool)) ix
pHole (Const pd) _ = Const $ pd { treeParm = (myar pd , True) }
pOpq :: Const (PrepData a) ('K k) -> ki k
-> Const (PrepData (Int , Bool)) ('K k)
pOpq (Const pd) _ = Const $ pd { treeParm = (myar pd , True) }
pPeel :: Const (PrepData a) ('I i)
-> Constr sum n
-> NP (Const (PrepData (Int, Bool))) (Lkup n sum)
-> Const (PrepData (Int, Bool)) ('I i)
pPeel (Const pd) _ p
= let maxar = maximum (0 : elimNP (fst . treeParm . getConst) p)
myar' = myar pd
in Const $ pd { treeParm = (max maxar myar' , myar' >= maxar) }
properShare :: forall ki codes phi at
. CanShare ki codes phi
-> IsSharedMap
-> PrepFix (Int , Bool) ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
properShare h tr pr
= let prep = getConst $ holesAnn pr
isPS = snd $ treeParm prep
in if not (isPS && h pr)
then properShare' pr
else case T.lookup (toW64s $ treeDigest prep) tr of
Nothing -> properShare' pr
Just i -> mkHole (getMetavar i) pr
where
properShare' :: PrepFix (Int , Bool) ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
properShare' (Hole _ d) = Hole' (InL d)
properShare' (HOpq _ k) = HOpq' k
properShare' (HPeel _ c d) = HPeel' c (mapNP (properShare h tr) d)
mkHole :: Int
-> PrepFix (Int , Bool) ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
mkHole _ (Hole _ d) = Hole' (InL d)
mkHole v (HPeel _ _ _) = Hole' (InR (NA_I (Const v)))
mkHole v (HOpq _ k) = Hole' (InR (NA_K (Annotate v k)))
extractPatience :: CanShare ki codes phi
-> IsSharedMap
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
extractPatience h tr a = patience h tr a
patience :: forall ki codes phi at a
. CanShare ki codes phi
-> IsSharedMap
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
patience h tr pr
= if not (h pr)
then patience' pr
else case T.lookup (toW64s $ treeDigest $ getConst $ holesAnn pr) tr of
Nothing -> patience' pr
Just i | getArity i == 2 -> mkHole (getMetavar i) pr
| otherwise -> patience' pr
where
patience' :: PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
patience' (Hole _ d) = Hole' (InL d)
patience' (HOpq _ k) = HOpq' k
patience' (HPeel _ c d) = HPeel' c (mapNP (patience h tr) d)
mkMetaVar :: PrepFix a ki codes phi at
-> Int
-> MetaVarIK ki at
mkMetaVar (Hole _ _) _ = error "This should be impossible"
mkMetaVar (HPeel _ _ _) v = NA_I (Const v)
mkMetaVar (HOpq _ k) v = NA_K (Annotate v k)
mkHole :: Int
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (MetaVarIK ki)) at
mkHole _ (Hole _ d) = Hole' (InL d)
mkHole v x = Hole' (InR $ mkMetaVar x v)
extractNoNested :: CanShare ki codes phi
-> IsSharedMap
-> Delta (PrepFix a ki codes phi) at
-> Delta (Holes ki codes (Sum phi (MetaVarIK ki))) at
extractNoNested h tr (src :*: dst)
= let del' = noNested h tr src
ins' = noNested h tr dst
holes = holesGetHolesAnnWith'' getHole del'
`S.intersection`
holesGetHolesAnnWith'' getHole ins'
del = holesRefineAnn (const (refineHole holes)) HOpq del'
ins = holesRefineAnn (const (refineHole holes)) HOpq ins'
in (del :*: ins)
where
getHole :: Sum phi (Const Int :*: f) at -> Maybe Int
getHole (InL _) = Nothing
getHole (InR (Const v :*: _)) = Just v
mkMetaVar :: PrepFix a ki codes phi at
-> Int
-> MetaVarIK ki at
mkMetaVar (Hole _ _) _ = error "This should be impossible"
mkMetaVar (HPeel _ _ _) v = NA_I (Const v)
mkMetaVar (HOpq _ k) v = NA_K (Annotate v k)
refineHole :: S.Set (Maybe Int)
-> Sum phi (Const Int :*: PrepFix a ki codes phi) ix
-> Holes ki codes (Sum phi (MetaVarIK ki)) ix
refineHole _ (InL phi) = Hole' (InL phi)
refineHole s (InR (Const i :*: f))
| Just i `S.member` s = Hole' (InR $ mkMetaVar f i)
| otherwise = holesMapAnn InL (const $ Const ()) f
noNested :: forall ki codes phi at a
. CanShare ki codes phi
-> IsSharedMap
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (Const Int :*: PrepFix a ki codes phi)) at
noNested h tr pr
= if not (h pr)
then noNested' pr
else case T.lookup (toW64s $ treeDigest $ getConst $ holesAnn pr) tr of
Nothing -> noNested' pr
Just i -> mkHole (getMetavar i) pr
where
noNested' :: PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (Const Int :*: PrepFix a ki codes phi)) at
noNested' (Hole _ d) = Hole' (InL d)
noNested' (HOpq _ k) = HOpq' k
noNested' (HPeel _ c d) = HPeel' c (mapNP (noNested h tr) d)
mkHole :: Int
-> PrepFix a ki codes phi at
-> Holes ki codes (Sum phi (Const Int :*: PrepFix a ki codes phi)) at
mkHole _ (Hole _ d) = Hole' (InL d)
mkHole v x = Hole' (InR (Const v :*: x))