{-# LANGUAGE PatternGuards, ViewPatterns, FlexibleContexts, ScopedTypeVariables, TupleSections #-}
{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveFunctor #-}

module GHC.Util.Unify(
    Subst(..), fromSubst,
    validSubst, removeParens, substitute,
    unifyExp
    ) where

import Control.Applicative
import Control.Monad
import Data.Generics.Uniplate.DataOnly
import Data.Char
import Data.Data
import Data.List.Extra
import Util

import GHC.Hs
import GHC.Types.SrcLoc
import GHC.Utils.Outputable hiding ((<>))
import GHC.Types.Name.Reader

import Language.Haskell.GhclibParserEx.GHC.Hs.Pat
import Language.Haskell.GhclibParserEx.GHC.Hs.Expr
import Language.Haskell.GhclibParserEx.GHC.Utils.Outputable
import Language.Haskell.GhclibParserEx.GHC.Types.Name.Reader
import GHC.Util.HsExpr
import GHC.Util.View
import Data.Maybe
import GHC.Data.FastString

isUnifyVar :: String -> Bool
isUnifyVar :: String -> Bool
isUnifyVar [Char
x] = Char
x forall a. Eq a => a -> a -> Bool
== Char
'?' Bool -> Bool -> Bool
|| Char -> Bool
isAlpha Char
x
isUnifyVar [] = Bool
False
isUnifyVar String
xs = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Eq a => a -> a -> Bool
== Char
'?') String
xs

---------------------------------------------------------------------
-- SUBSTITUTION DATA TYPE

-- A list of substitutions. A key may be duplicated, you need to call
--  'check' to ensure the substitution is valid.
newtype Subst a = Subst [(String, a)]
    deriving (NonEmpty (Subst a) -> Subst a
Subst a -> Subst a -> Subst a
forall b. Integral b => b -> Subst a -> Subst a
forall a. NonEmpty (Subst a) -> Subst a
forall a. Subst a -> Subst a -> Subst a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall a b. Integral b => b -> Subst a -> Subst a
stimes :: forall b. Integral b => b -> Subst a -> Subst a
$cstimes :: forall a b. Integral b => b -> Subst a -> Subst a
sconcat :: NonEmpty (Subst a) -> Subst a
$csconcat :: forall a. NonEmpty (Subst a) -> Subst a
<> :: Subst a -> Subst a -> Subst a
$c<> :: forall a. Subst a -> Subst a -> Subst a
Semigroup, Subst a
[Subst a] -> Subst a
Subst a -> Subst a -> Subst a
forall a. Semigroup (Subst a)
forall a. Subst a
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall a. [Subst a] -> Subst a
forall a. Subst a -> Subst a -> Subst a
mconcat :: [Subst a] -> Subst a
$cmconcat :: forall a. [Subst a] -> Subst a
mappend :: Subst a -> Subst a -> Subst a
$cmappend :: forall a. Subst a -> Subst a -> Subst a
mempty :: Subst a
$cmempty :: forall a. Subst a
Monoid, forall a b. a -> Subst b -> Subst a
forall a b. (a -> b) -> Subst a -> Subst b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Subst b -> Subst a
$c<$ :: forall a b. a -> Subst b -> Subst a
fmap :: forall a b. (a -> b) -> Subst a -> Subst b
$cfmap :: forall a b. (a -> b) -> Subst a -> Subst b
Functor)

-- Unpack the substitution.
fromSubst :: Subst a -> [(String, a)]
fromSubst :: forall a. Subst a -> [(String, a)]
fromSubst (Subst [(String, a)]
xs) = [(String, a)]
xs

instance Outputable a => Show (Subst a) where
    show :: Subst a -> String
show (Subst [(String, a)]
xs) = [String] -> String
unlines [String
a forall a. [a] -> [a] -> [a]
++ String
" = " forall a. [a] -> [a] -> [a]
++ forall a. Outputable a => a -> String
unsafePrettyPrint a
b | (String
a,a
b) <- [(String, a)]
xs]

-- Check the unification is valid and simplify it.
validSubst :: (a -> a -> Bool) -> Subst a -> Maybe (Subst a)
validSubst :: forall a. (a -> a -> Bool) -> Subst a -> Maybe (Subst a)
validSubst a -> a -> Bool
eq = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. [(String, a)] -> Subst a
Subst forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall {a}. (a, [a]) -> Maybe (a, a)
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k v. Ord k => [(k, v)] -> [(k, [v])]
groupSort forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Subst a -> [(String, a)]
fromSubst
    where f :: (a, [a]) -> Maybe (a, a)
f (a
x, a
y : [a]
ys) | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (a -> a -> Bool
eq a
y) [a]
ys = forall a. a -> Maybe a
Just (a
x, a
y)
          f (a, [a])
_ = forall a. Maybe a
Nothing

-- Remove unnecessary brackets from a Subst. The first argument is a list of unification variables
-- for which brackets should be removed from their substitutions.
removeParens :: [String] -> Subst (LHsExpr GhcPs) -> Subst (LHsExpr GhcPs)
removeParens :: [String] -> Subst (LHsExpr GhcPs) -> Subst (LHsExpr GhcPs)
removeParens [String]
noParens (Subst [(String, LHsExpr GhcPs)]
xs) = forall a. [(String, a)] -> Subst a
Subst forall a b. (a -> b) -> a -> b
$
  forall a b. (a -> b) -> [a] -> [b]
map (\(String
x, GenLocated SrcSpanAnnA (HsExpr GhcPs)
y) -> if String
x forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
noParens then (String
x, GenLocated SrcSpanAnnA (HsExpr GhcPs)
-> GenLocated SrcSpanAnnA (HsExpr GhcPs)
fromParen GenLocated SrcSpanAnnA (HsExpr GhcPs)
y) else (String
x, GenLocated SrcSpanAnnA (HsExpr GhcPs)
y)) [(String, LHsExpr GhcPs)]
xs

-- Peform a substition.
-- Returns (suggested replacement, (refactor template, no bracket vars)). It adds/removes brackets
-- for both the suggested replacement and the refactor template appropriately. The "no bracket vars"
-- is a list of substituation variables which, when expanded, should have the brackets stripped.
--
-- Examples:
--   (traverse foo (bar baz), (traverse f (x), []))
--   (zipWith foo bar baz, (f a b, [f]))
substitute :: Subst (LHsExpr GhcPs) -> LHsExpr GhcPs -> (LHsExpr GhcPs, (LHsExpr GhcPs, [String]))
substitute :: Subst (LHsExpr GhcPs)
-> LHsExpr GhcPs -> (LHsExpr GhcPs, (LHsExpr GhcPs, [String]))
substitute (Subst [(String, LHsExpr GhcPs)]
bind) = (LHsExpr GhcPs -> Maybe (LHsExpr GhcPs))
-> LHsExpr GhcPs -> (LHsExpr GhcPs, (LHsExpr GhcPs, [String]))
transformBracketOld LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)
exp forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall from to. Biplate from to => (to -> to) -> from -> from
transformBi LPat GhcPs -> LPat GhcPs
pat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall from to. Biplate from to => (to -> to) -> from -> from
transformBi LHsType GhcPs -> LHsType GhcPs
typ
  where
    exp :: LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)
    -- Variables.
    exp :: LHsExpr GhcPs -> Maybe (LHsExpr GhcPs)
exp (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x)) = forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind
    -- Operator applications.
    exp (L SrcSpanAnnA
loc (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x)) LHsExpr GhcPs
rhs))
      | Just GenLocated SrcSpanAnnA (HsExpr GhcPs)
y <- forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind = forall a. a -> Maybe a
Just (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc (forall p.
XOpApp p -> LHsExpr p -> LHsExpr p -> LHsExpr p -> HsExpr p
OpApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
lhs GenLocated SrcSpanAnnA (HsExpr GhcPs)
y LHsExpr GhcPs
rhs))
    -- Left sections.
    exp (L SrcSpanAnnA
loc (SectionL XSectionL GhcPs
_ LHsExpr GhcPs
exp (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x))))
      | Just GenLocated SrcSpanAnnA (HsExpr GhcPs)
y <- forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind = forall a. a -> Maybe a
Just (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc (forall p. XSectionL p -> LHsExpr p -> LHsExpr p -> HsExpr p
SectionL forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
exp GenLocated SrcSpanAnnA (HsExpr GhcPs)
y))
    -- Right sections.
    exp (L SrcSpanAnnA
loc (SectionR XSectionR GhcPs
_ (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x)) LHsExpr GhcPs
exp))
      | Just GenLocated SrcSpanAnnA (HsExpr GhcPs)
y <- forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind = forall a. a -> Maybe a
Just (forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc (forall p. XSectionR p -> LHsExpr p -> LHsExpr p -> HsExpr p
SectionR forall ann. EpAnn ann
EpAnnNotUsed GenLocated SrcSpanAnnA (HsExpr GhcPs)
y LHsExpr GhcPs
exp))
    exp LHsExpr GhcPs
_ = forall a. Maybe a
Nothing

    pat :: LPat GhcPs -> LPat GhcPs
    -- Pattern variables.
    pat :: LPat GhcPs -> LPat GhcPs
pat (L SrcSpanAnnA
_ (VarPat XVarPat GhcPs
_ LIdP GhcPs
x))
      | Just y :: GenLocated SrcSpanAnnA (HsExpr GhcPs)
y@(L SrcSpanAnnA
_ HsVar{}) <- forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind = String -> LPat GhcPs
strToPat forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> String
varToStr GenLocated SrcSpanAnnA (HsExpr GhcPs)
y
    pat LPat GhcPs
x = LPat GhcPs
x :: LPat GhcPs

    typ :: LHsType GhcPs -> LHsType GhcPs
    -- Type variables.
    typ :: LHsType GhcPs -> LHsType GhcPs
typ (L SrcSpanAnnA
_ (HsTyVar XTyVar GhcPs
_ PromotionFlag
_ LIdP GhcPs
x))
      | Just (L SrcSpanAnnA
_ (HsAppType XAppTypeE GhcPs
_ LHsExpr GhcPs
_ (HsWC XHsWC (NoGhcTc GhcPs) (LHsType (NoGhcTc GhcPs))
_ LHsType (NoGhcTc GhcPs)
y))) <- forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x) [(String, LHsExpr GhcPs)]
bind = LHsType (NoGhcTc GhcPs)
y
    typ LHsType GhcPs
x = LHsType GhcPs
x :: LHsType GhcPs


---------------------------------------------------------------------
-- UNIFICATION

type NameMatch = LocatedN RdrName -> LocatedN RdrName -> Bool

-- | Unification, obeys the property that if @unify a b = s@, then
-- @substitute s a = b@.
unify' :: Data a => NameMatch -> Bool -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unify' :: forall a.
Data a =>
NameMatch -> Bool -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unify' NameMatch
nm Bool
root a
x a
y
    | Just (GenLocated SrcSpanAnnA (HsExpr GhcPs)
x, GenLocated SrcSpanAnnA (HsExpr GhcPs)
y) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (a
x, a
y) = NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
root GenLocated SrcSpanAnnA (HsExpr GhcPs)
x GenLocated SrcSpanAnnA (HsExpr GhcPs)
y
    | Just (GenLocated SrcSpanAnnA (Pat GhcPs)
x, GenLocated SrcSpanAnnA (Pat GhcPs)
y) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (a
x, a
y) = NameMatch
-> LPat GhcPs -> LPat GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyPat' NameMatch
nm GenLocated SrcSpanAnnA (Pat GhcPs)
x GenLocated SrcSpanAnnA (Pat GhcPs)
y
    | Just (GenLocated SrcSpanAnnA (HsType GhcPs)
x, GenLocated SrcSpanAnnA (HsType GhcPs)
y) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (a
x, a
y) = NameMatch
-> LHsType GhcPs -> LHsType GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyType' NameMatch
nm GenLocated SrcSpanAnnA (HsType GhcPs)
x GenLocated SrcSpanAnnA (HsType GhcPs)
y
    | Just (FastString
x, FastString
y) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast (a
x, a
y) = if (FastString
x :: FastString) forall a. Eq a => a -> a -> Bool
== FastString
y then forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty else forall a. Maybe a
Nothing

    -- We need some type magic to reduce this.
    | Just (EpAnn AnnsModule
x :: EpAnn AnnsModule) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn NameAnn
x :: EpAnn NameAnn) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnListItem
x :: EpAnn AnnListItem) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnList
x :: EpAnn AnnList) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnPragma
x :: EpAnn AnnPragma) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnContext
x :: EpAnn AnnContext) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnParen
x :: EpAnn AnnParen) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn Anchor
x :: EpAnn Anchor) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn NoEpAnns
x :: EpAnn NoEpAnns) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn GrhsAnn
x :: EpAnn GrhsAnn) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn [AddEpAnn]
x :: EpAnn [AddEpAnn]) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn EpAnnHsCase
x :: EpAnn EpAnnHsCase) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn EpAnnUnboundVar
x :: EpAnn EpAnnUnboundVar) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnExplicitSum
x :: EpAnn AnnExplicitSum) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnProjection
x :: EpAnn AnnProjection) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn Anchor
x :: EpAnn Anchor) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn EpaLocation
x :: EpAnn EpaLocation) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnFieldLabel
x :: EpAnn AnnFieldLabel) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn EpAnnSumPat
x :: EpAnn EpAnnSumPat) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnSig
x :: EpAnn AnnSig) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn HsRuleAnn
x :: EpAnn HsRuleAnn) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn EpAnnImportDecl
x :: EpAnn EpAnnImportDecl) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn (AddEpAnn, AddEpAnn)
x :: EpAnn (AddEpAnn, AddEpAnn)) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (EpAnn AnnsIf
x :: EpAnn AnnsIf) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
x = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (TokenLocation
x :: TokenLocation) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
y = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty
    | Just (SrcSpan
y :: SrcSpan) <- forall a b. (Typeable a, Typeable b) => a -> Maybe b
cast a
y = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty

    | Bool
otherwise = forall a.
Data a =>
NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' NameMatch
nm a
x a
y

unifyDef' :: Data a => NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' :: forall a.
Data a =>
NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' NameMatch
nm a
x a
y =
  forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a c.
Data a =>
(forall b. Data b => b -> b -> c) -> a -> a -> Maybe [c]
gzip (forall a.
Data a =>
NameMatch -> Bool -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unify' NameMatch
nm Bool
False) a
x a
y

unifyComposed' :: NameMatch
               -> LHsExpr GhcPs
               -> LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
               -> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyComposed' :: NameMatch
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyComposed' NameMatch
nm LHsExpr GhcPs
x1 LHsExpr GhcPs
y11 LHsExpr GhcPs
dot LHsExpr GhcPs
y12 =
  ((, forall a. a -> Maybe a
Just LHsExpr GhcPs
y11) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
x1 LHsExpr GhcPs
y12)
    forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> case LHsExpr GhcPs
y12 of
          (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
y121 LHsExpr GhcPs
dot' LHsExpr GhcPs
y122)) | LHsExpr GhcPs -> Bool
isDot LHsExpr GhcPs
dot' ->
            NameMatch
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyComposed' NameMatch
nm LHsExpr GhcPs
x1 (forall a an. a -> LocatedAn an a
noLocA (forall p.
XOpApp p -> LHsExpr p -> LHsExpr p -> LHsExpr p -> HsExpr p
OpApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
y11 LHsExpr GhcPs
dot LHsExpr GhcPs
y121)) LHsExpr GhcPs
dot' LHsExpr GhcPs
y122
          LHsExpr GhcPs
_ -> forall a. Maybe a
Nothing

-- unifyExp handles the cases where both x and y are HsApp, or y is OpApp. Otherwise,
-- delegate to unifyExp'. These are the cases where we potentially need to call
-- unifyComposed' to handle left composition.
--
-- y is allowed to partially match x (the lhs of the hint), if y is a function application where
-- the function is a composition of functions. In this case the second component of the result is
-- the unmatched part of y, which will be attached to the rhs of the hint after substitution.
--
-- Example:
--   x = head (drop n x)
--   y = foo . bar . baz . head $ drop 2 xs
--   result = (Subst [(n, 2), (x, xs)], Just (foo . bar . baz))
unifyExp :: NameMatch -> Bool -> LHsExpr GhcPs -> LHsExpr GhcPs -> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
-- Match wildcard operators.
unifyExp :: NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs1 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
v))) LHsExpr GhcPs
rhs1))
                 (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs2 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
op2))) LHsExpr GhcPs
rhs2))
    | String -> Bool
isUnifyVar String
v =
        (, forall a. Maybe a
Nothing) forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. [(String, a)] -> Subst a
Subst [(String
v, String -> LHsExpr GhcPs
strToVar String
op2)] forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
lhs1 LHsExpr GhcPs
lhs2) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
rhs1 LHsExpr GhcPs
rhs2)

-- Options: match directly, and expand through '.'
unifyExp NameMatch
nm Bool
root x :: LHsExpr GhcPs
x@(L SrcSpanAnnA
_ (HsApp XApp GhcPs
_ LHsExpr GhcPs
x1 LHsExpr GhcPs
x2)) (L SrcSpanAnnA
_ (HsApp XApp GhcPs
_ LHsExpr GhcPs
y1 LHsExpr GhcPs
y2)) =
    ((, forall a. Maybe a
Nothing) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
x1 LHsExpr GhcPs
y1) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
x2 LHsExpr GhcPs
y2)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Maybe
  (Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs)),
   Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs)))
unifyComposed
  where
    -- Unify a function application where the function is a composition of functions.
    unifyComposed :: Maybe
  (Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs)),
   Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs)))
unifyComposed
      | (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
y11 LHsExpr GhcPs
dot LHsExpr GhcPs
y12)) <- GenLocated SrcSpanAnnA (HsExpr GhcPs)
-> GenLocated SrcSpanAnnA (HsExpr GhcPs)
fromParen LHsExpr GhcPs
y1, LHsExpr GhcPs -> Bool
isDot LHsExpr GhcPs
dot =
          if Bool -> Bool
not Bool
root then
              -- Attempt #1: rewrite '(fun1 . fun2) arg' as 'fun1 (fun2 arg)', and unify it with 'x'.
              -- The guard ensures that you don't get duplicate matches because the matching engine
              -- auto-generates hints in dot-form.
              (, forall a. Maybe a
Nothing) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
root LHsExpr GhcPs
x (forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
y11 (forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
y12 LHsExpr GhcPs
y2))))
          else do
              -- Attempt #2: rewrite '(fun1 . fun2 ... funn) arg' as 'fun1 $ (fun2 ... funn) arg',
              -- 'fun1 . fun2 $ (fun3 ... funn) arg', 'fun1 . fun2 . fun3 $ (fun4 ... funn) arg',
              -- and so on, unify the rhs of '$' with 'x', and store the lhs of '$' into 'extra'.
              -- You can only add to extra if you are at the root (otherwise 'extra' has nowhere to go).
              Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs))
rhs <- NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
x2 LHsExpr GhcPs
y2
              (Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs))
lhs, Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
extra) <- NameMatch
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyComposed' NameMatch
nm LHsExpr GhcPs
x1 LHsExpr GhcPs
y11 LHsExpr GhcPs
dot LHsExpr GhcPs
y12
              forall (f :: * -> *) a. Applicative f => a -> f a
pure (Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs))
lhs forall a. Semigroup a => a -> a -> a
<> Subst (GenLocated SrcSpanAnnA (HsExpr GhcPs))
rhs, Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
extra)
      | Bool
otherwise = forall a. Maybe a
Nothing

-- Options: match directly, then expand through '$', then desugar infix.
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs2 op2 :: LHsExpr GhcPs
op2@(L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
op2')) LHsExpr GhcPs
rhs2))
    | (L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs1 op1 :: LHsExpr GhcPs
op1@(L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
op1')) LHsExpr GhcPs
rhs1)) <- LHsExpr GhcPs
x =
        forall (f :: * -> *). Alternative f => Bool -> f ()
guard (NameMatch
nm LIdP GhcPs
op1' LIdP GhcPs
op2') forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (, forall a. Maybe a
Nothing) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 forall a. Semigroup a => a -> a -> a
(<>) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
lhs1 LHsExpr GhcPs
lhs2) (NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
rhs1 LHsExpr GhcPs
rhs2)
    | LHsExpr GhcPs -> Bool
isDol LHsExpr GhcPs
op2 = NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x forall a b. (a -> b) -> a -> b
$ forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
lhs2 LHsExpr GhcPs
rhs2)
    | LHsExpr GhcPs -> Bool
isAmp LHsExpr GhcPs
op2 = NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x forall a b. (a -> b) -> a -> b
$ forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
rhs2 LHsExpr GhcPs
lhs2)
    | Bool
otherwise  = NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x forall a b. (a -> b) -> a -> b
$ forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed (forall a an. a -> LocatedAn an a
noLocA (forall p. XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
HsApp forall ann. EpAnn ann
EpAnnNotUsed LHsExpr GhcPs
op2 (LHsExpr GhcPs -> LHsExpr GhcPs
addPar LHsExpr GhcPs
lhs2))) (LHsExpr GhcPs -> LHsExpr GhcPs
addPar LHsExpr GhcPs
rhs2))
        where
          -- add parens around when desugaring the expression, if necessary
          addPar :: LHsExpr GhcPs -> LHsExpr GhcPs
          addPar :: LHsExpr GhcPs -> LHsExpr GhcPs
addPar LHsExpr GhcPs
x = if forall a. Brackets a => a -> Bool
isAtom LHsExpr GhcPs
x then LHsExpr GhcPs
x else forall a. Brackets a => a -> a
addParen LHsExpr GhcPs
x

unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y = (, forall a. Maybe a
Nothing) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y

isAmp :: LHsExpr GhcPs -> Bool
isAmp :: LHsExpr GhcPs -> Bool
isAmp (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x)) = LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x forall a. Eq a => a -> a -> Bool
== String
"&"
isAmp LHsExpr GhcPs
_ = Bool
False

-- | If we "throw away" the extra than we have no where to put it, and the substitution is wrong
noExtra :: Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs)) -> Maybe (Subst (LHsExpr GhcPs))
noExtra :: Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
-> Maybe (Subst (LHsExpr GhcPs))
noExtra (Just (Subst (LHsExpr GhcPs)
x, Maybe (LHsExpr GhcPs)
Nothing)) = forall a. a -> Maybe a
Just Subst (LHsExpr GhcPs)
x
noExtra Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
_ = forall a. Maybe a
Nothing

-- App/InfixApp are analysed specially for performance reasons. If
-- 'root = True', this is the outside of the expr. Do not expand out a
-- dot at the root, since otherwise you get two matches because of
-- 'readRule' (Bug #570).
unifyExp' :: NameMatch -> Bool -> LHsExpr GhcPs -> LHsExpr GhcPs -> Maybe (Subst (LHsExpr GhcPs))
-- Don't subsitute for type apps, since no one writes rules imagining
-- they exist.
unifyExp' :: NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
root (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
v))) LHsExpr GhcPs
y | String -> Bool
isUnifyVar String
v, Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ LHsExpr GhcPs -> Bool
isTypeApp LHsExpr GhcPs
y = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. [(String, a)] -> Subst a
Subst [(String
v, LHsExpr GhcPs
y)]
unifyExp' NameMatch
nm Bool
root (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
x)) (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
y)) | NameMatch
nm LIdP GhcPs
x LIdP GhcPs
y = forall a. a -> Maybe a
Just forall a. Monoid a => a
mempty

-- Brackets are not added when expanding '$' in user code, so tolerate
-- them in the match even if they aren't in the user code.
-- Also, allow the user to put in more brackets than they strictly need (e.g. with infix).
unifyExp' NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y | Bool -> Bool
not Bool
root, forall a. Maybe a -> Bool
isJust Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
x2 Bool -> Bool -> Bool
|| forall a. Maybe a -> Bool
isJust Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
y2 = NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
root (forall a. a -> Maybe a -> a
fromMaybe LHsExpr GhcPs
x Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
x2) (forall a. a -> Maybe a -> a
fromMaybe LHsExpr GhcPs
y Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
y2)
    where
        -- Make sure we deal with the weird brackets that can't be removed around sections
        x2 :: Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
x2 = forall a. Brackets a => a -> Maybe a
remParen LHsExpr GhcPs
x
        y2 :: Maybe (GenLocated SrcSpanAnnA (HsExpr GhcPs))
y2 = forall a. Brackets a => a -> Maybe a
remParen LHsExpr GhcPs
y

unifyExp' NameMatch
nm Bool
root x :: LHsExpr GhcPs
x@(L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs1 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
v))) LHsExpr GhcPs
rhs1))
                  y :: LHsExpr GhcPs
y@(L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs2 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
op2)) LHsExpr GhcPs
rhs2)) =
  Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
-> Maybe (Subst (LHsExpr GhcPs))
noExtra forall a b. (a -> b) -> a -> b
$ NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y
unifyExp' NameMatch
nm Bool
root (L SrcSpanAnnA
_ (SectionL XSectionL GhcPs
_ LHsExpr GhcPs
exp1 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
v)))))
                  (L SrcSpanAnnA
_ (SectionL XSectionL GhcPs
_ LHsExpr GhcPs
exp2 (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
op2)))))
    | String -> Bool
isUnifyVar String
v = (forall a. [(String, a)] -> Subst a
Subst [(String
v, String -> LHsExpr GhcPs
strToVar String
op2)] forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
exp1 LHsExpr GhcPs
exp2
unifyExp' NameMatch
nm Bool
root (L SrcSpanAnnA
_ (SectionR XSectionR GhcPs
_ (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
v))) LHsExpr GhcPs
exp1))
                  (L SrcSpanAnnA
_ (SectionR XSectionR GhcPs
_ (L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ (LocatedN RdrName -> String
rdrNameStr -> String
op2))) LHsExpr GhcPs
exp2))
    | String -> Bool
isUnifyVar String
v = (forall a. [(String, a)] -> Subst a
Subst [(String
v, String -> LHsExpr GhcPs
strToVar String
op2)] forall a. Semigroup a => a -> a -> a
<>) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs))
unifyExp' NameMatch
nm Bool
False LHsExpr GhcPs
exp1 LHsExpr GhcPs
exp2

unifyExp' NameMatch
nm Bool
root x :: LHsExpr GhcPs
x@(L SrcSpanAnnA
_ (HsApp XApp GhcPs
_ LHsExpr GhcPs
x1 LHsExpr GhcPs
x2)) y :: LHsExpr GhcPs
y@(L SrcSpanAnnA
_ (HsApp XApp GhcPs
_ LHsExpr GhcPs
y1 LHsExpr GhcPs
y2)) =
  Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
-> Maybe (Subst (LHsExpr GhcPs))
noExtra forall a b. (a -> b) -> a -> b
$ NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y

unifyExp' NameMatch
nm Bool
root LHsExpr GhcPs
x y :: LHsExpr GhcPs
y@(L SrcSpanAnnA
_ (OpApp XOpApp GhcPs
_ LHsExpr GhcPs
lhs2 op2 :: LHsExpr GhcPs
op2@(L SrcSpanAnnA
_ (HsVar XVar GhcPs
_ LIdP GhcPs
op2')) LHsExpr GhcPs
rhs2)) =
  Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
-> Maybe (Subst (LHsExpr GhcPs))
noExtra forall a b. (a -> b) -> a -> b
$ NameMatch
-> Bool
-> LHsExpr GhcPs
-> LHsExpr GhcPs
-> Maybe (Subst (LHsExpr GhcPs), Maybe (LHsExpr GhcPs))
unifyExp NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y

unifyExp' NameMatch
nm Bool
root (L SrcSpanAnnA
_ (HsUntypedBracket XUntypedBracket GhcPs
_ (VarBr XVarBr GhcPs
_ Bool
b0 (RdrName -> String
occNameStr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l e. GenLocated l e -> e
unLoc -> String
v1))))
                  (L SrcSpanAnnA
_ (HsUntypedBracket XUntypedBracket GhcPs
_ (VarBr XVarBr GhcPs
_ Bool
b1 (RdrName -> String
occNameStr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall l e. GenLocated l e -> e
unLoc -> String
v2))))
    | Bool
b0 forall a. Eq a => a -> a -> Bool
== Bool
b1 Bool -> Bool -> Bool
&& String -> Bool
isUnifyVar String
v1 = forall a. a -> Maybe a
Just (forall a. [(String, a)] -> Subst a
Subst [(String
v1, String -> LHsExpr GhcPs
strToVar String
v2)])

unifyExp' NameMatch
nm Bool
root LHsExpr GhcPs
x LHsExpr GhcPs
y | LHsExpr GhcPs -> Bool
isOther LHsExpr GhcPs
x, LHsExpr GhcPs -> Bool
isOther LHsExpr GhcPs
y = forall a.
Data a =>
NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' NameMatch
nm LHsExpr GhcPs
x LHsExpr GhcPs
y
    where
        -- Types that are not already handled in unify.
        {-# INLINE isOther #-}
        isOther :: LHsExpr GhcPs -> Bool
        isOther :: LHsExpr GhcPs -> Bool
isOther (L SrcSpanAnnA
_ HsVar{}) = Bool
False
        isOther (L SrcSpanAnnA
_ HsApp{}) = Bool
False
        isOther (L SrcSpanAnnA
_ OpApp{}) = Bool
False
        isOther LHsExpr GhcPs
_ = Bool
True

unifyExp' NameMatch
_ Bool
_ LHsExpr GhcPs
_ LHsExpr GhcPs
_ = forall a. Maybe a
Nothing


unifyPat' :: NameMatch -> LPat GhcPs -> LPat GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyPat' :: NameMatch
-> LPat GhcPs -> LPat GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyPat' NameMatch
nm (L SrcSpanAnnA
_ (VarPat XVarPat GhcPs
_ LIdP GhcPs
x)) (L SrcSpanAnnA
_ (VarPat XVarPat GhcPs
_ LIdP GhcPs
y)) =
  forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. [(String, a)] -> Subst a
Subst [(LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x, String -> LHsExpr GhcPs
strToVar(LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
y))]
unifyPat' NameMatch
nm (L SrcSpanAnnA
_ (VarPat XVarPat GhcPs
_ LIdP GhcPs
x)) (L SrcSpanAnnA
_ (WildPat XWildPat GhcPs
_)) =
  let s :: String
s = LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x in forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. [(String, a)] -> Subst a
Subst [(String
s, String -> LHsExpr GhcPs
strToVar(String
"_" forall a. [a] -> [a] -> [a]
++ String
s))]
unifyPat' NameMatch
nm (L SrcSpanAnnA
_ (ConPat XConPat GhcPs
_ XRec GhcPs (ConLikeP GhcPs)
x HsConPatDetails GhcPs
_)) (L SrcSpanAnnA
_ (ConPat XConPat GhcPs
_ XRec GhcPs (ConLikeP GhcPs)
y HsConPatDetails GhcPs
_)) | LocatedN RdrName -> String
rdrNameStr XRec GhcPs (ConLikeP GhcPs)
x forall a. Eq a => a -> a -> Bool
/= LocatedN RdrName -> String
rdrNameStr XRec GhcPs (ConLikeP GhcPs)
y =
  forall a. Maybe a
Nothing
unifyPat' NameMatch
nm LPat GhcPs
x LPat GhcPs
y =
  forall a.
Data a =>
NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' NameMatch
nm LPat GhcPs
x LPat GhcPs
y

unifyType' :: NameMatch -> LHsType GhcPs -> LHsType GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyType' :: NameMatch
-> LHsType GhcPs -> LHsType GhcPs -> Maybe (Subst (LHsExpr GhcPs))
unifyType' NameMatch
nm (L SrcSpanAnnA
loc (HsTyVar XTyVar GhcPs
_ PromotionFlag
_ LIdP GhcPs
x)) LHsType GhcPs
y =
  let wc :: HsWildCardBndrs (NoGhcTc GhcPs) (LHsType (NoGhcTc GhcPs))
wc = forall pass thing.
XHsWC pass thing -> thing -> HsWildCardBndrs pass thing
HsWC NoExtField
noExtField LHsType GhcPs
y :: LHsWcType (NoGhcTc GhcPs)
      unused :: LHsExpr GhcPs
unused = String -> LHsExpr GhcPs
strToVar String
"__unused__" :: LHsExpr GhcPs
      appType :: LHsExpr GhcPs
appType = forall l e. l -> e -> GenLocated l e
L SrcSpanAnnA
loc (forall p.
XAppTypeE p -> LHsExpr p -> LHsWcType (NoGhcTc p) -> HsExpr p
HsAppType SrcSpan
noSrcSpan GenLocated SrcSpanAnnA (HsExpr GhcPs)
unused HsWildCardBndrs GhcPs (GenLocated SrcSpanAnnA (HsType GhcPs))
wc) :: LHsExpr GhcPs
 in forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. [(String, a)] -> Subst a
Subst [(LocatedN RdrName -> String
rdrNameStr LIdP GhcPs
x, GenLocated SrcSpanAnnA (HsExpr GhcPs)
appType)]
unifyType' NameMatch
nm LHsType GhcPs
x LHsType GhcPs
y = forall a.
Data a =>
NameMatch -> a -> a -> Maybe (Subst (LHsExpr GhcPs))
unifyDef' NameMatch
nm LHsType GhcPs
x LHsType GhcPs
y