{-# LANGUAGE CPP #-}
module Rules (
        
        emptyRuleBase, mkRuleBase, extendRuleBaseList,
        unionRuleBase, pprRuleBase,
        
        ruleCheckProgram,
        
        mkRuleInfo, extendRuleInfo, addRuleInfo,
        addIdSpecialisations,
        
        rulesOfBinds, getRules, pprRulesForUser,
        lookupRule, mkRule, roughTopNames
    ) where
#include "HsVersions.h"
import GhcPrelude
import CoreSyn          
import Module           ( Module, ModuleSet, elemModuleSet )
import CoreSubst
import CoreOpt          ( exprIsLambda_maybe )
import CoreFVs          ( exprFreeVars, exprsFreeVars, bindFreeVars
                        , rulesFreeVarsDSet, exprsOrphNames, exprFreeVarsList )
import CoreUtils        ( exprType, eqExpr, mkTick, mkTicks,
                          stripTicksTopT, stripTicksTopE,
                          isJoinBind )
import PprCore          ( pprRules )
import Type             ( Type, Kind, substTy, mkTCvSubst )
import TcType           ( tcSplitTyConApp_maybe )
import TysWiredIn       ( anyTypeOfKind )
import Coercion
import CoreTidy         ( tidyRules )
import Id
import IdInfo           ( RuleInfo( RuleInfo ) )
import Var
import VarEnv
import VarSet
import Name             ( Name, NamedThing(..), nameIsLocalOrFrom )
import NameSet
import NameEnv
import UniqFM
import Unify            ( ruleMatchTyKiX )
import BasicTypes
import DynFlags         ( DynFlags )
import Outputable
import FastString
import Maybes
import Bag
import Util
import Data.List
import Data.Ord
import Control.Monad    ( guard )
mkRule :: Module -> Bool -> Bool -> RuleName -> Activation
       -> Name -> [CoreBndr] -> [CoreExpr] -> CoreExpr -> CoreRule
mkRule :: Module
-> Bool
-> Bool
-> RuleName
-> Activation
-> Name
-> [CoreBndr]
-> [CoreExpr]
-> CoreExpr
-> CoreRule
mkRule this_mod :: Module
this_mod is_auto :: Bool
is_auto is_local :: Bool
is_local name :: RuleName
name act :: Activation
act fn :: Name
fn bndrs :: [CoreBndr]
bndrs args :: [CoreExpr]
args rhs :: CoreExpr
rhs
  = $WRule :: RuleName
-> Activation
-> Name
-> [Maybe Name]
-> [CoreBndr]
-> [CoreExpr]
-> CoreExpr
-> Bool
-> Module
-> IsOrphan
-> Bool
-> CoreRule
Rule { ru_name :: RuleName
ru_name = RuleName
name, ru_fn :: Name
ru_fn = Name
fn, ru_act :: Activation
ru_act = Activation
act,
           ru_bndrs :: [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs, ru_args :: [CoreExpr]
ru_args = [CoreExpr]
args,
           ru_rhs :: CoreExpr
ru_rhs = CoreExpr
rhs,
           ru_rough :: [Maybe Name]
ru_rough = [CoreExpr] -> [Maybe Name]
roughTopNames [CoreExpr]
args,
           ru_origin :: Module
ru_origin = Module
this_mod,
           ru_orphan :: IsOrphan
ru_orphan = IsOrphan
orph,
           ru_auto :: Bool
ru_auto = Bool
is_auto, ru_local :: Bool
ru_local = Bool
is_local }
  where
        
        
        
    lhs_names :: NameSet
lhs_names = NameSet -> Name -> NameSet
extendNameSet ([CoreExpr] -> NameSet
exprsOrphNames [CoreExpr]
args) Name
fn
        
        
        
        
    local_lhs_names :: NameSet
local_lhs_names = (Name -> Bool) -> NameSet -> NameSet
filterNameSet (Module -> Name -> Bool
nameIsLocalOrFrom Module
this_mod) NameSet
lhs_names
    orph :: IsOrphan
orph = NameSet -> IsOrphan
chooseOrphanAnchor NameSet
local_lhs_names
roughTopNames :: [CoreExpr] -> [Maybe Name]
roughTopNames :: [CoreExpr] -> [Maybe Name]
roughTopNames args :: [CoreExpr]
args = (CoreExpr -> Maybe Name) -> [CoreExpr] -> [Maybe Name]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Maybe Name
roughTopName [CoreExpr]
args
roughTopName :: CoreExpr -> Maybe Name
roughTopName :: CoreExpr -> Maybe Name
roughTopName (Type ty :: Type
ty) = case HasCallStack => Type -> Maybe (TyCon, [Type])
Type -> Maybe (TyCon, [Type])
tcSplitTyConApp_maybe Type
ty of
                               Just (tc :: TyCon
tc,_) -> Name -> Maybe Name
forall a. a -> Maybe a
Just (TyCon -> Name
forall a. NamedThing a => a -> Name
getName TyCon
tc)
                               Nothing     -> Maybe Name
forall a. Maybe a
Nothing
roughTopName (Coercion _) = Maybe Name
forall a. Maybe a
Nothing
roughTopName (App f :: CoreExpr
f _) = CoreExpr -> Maybe Name
roughTopName CoreExpr
f
roughTopName (Var f :: CoreBndr
f)   | CoreBndr -> Bool
isGlobalId CoreBndr
f   
                       , CoreBndr -> Bool
isDataConWorkId CoreBndr
f Bool -> Bool -> Bool
|| CoreBndr -> Arity
idArity CoreBndr
f Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
> 0
                       = Name -> Maybe Name
forall a. a -> Maybe a
Just (CoreBndr -> Name
idName CoreBndr
f)
roughTopName (Tick t :: Tickish CoreBndr
t e :: CoreExpr
e) | Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Tickish CoreBndr
t
                        = CoreExpr -> Maybe Name
roughTopName CoreExpr
e
roughTopName _ = Maybe Name
forall a. Maybe a
Nothing
ruleCantMatch :: [Maybe Name] -> [Maybe Name] -> Bool
ruleCantMatch :: [Maybe Name] -> [Maybe Name] -> Bool
ruleCantMatch (Just n1 :: Name
n1 : ts :: [Maybe Name]
ts) (Just n2 :: Name
n2 : as :: [Maybe Name]
as) = Name
n1 Name -> Name -> Bool
forall a. Eq a => a -> a -> Bool
/= Name
n2 Bool -> Bool -> Bool
|| [Maybe Name] -> [Maybe Name] -> Bool
ruleCantMatch [Maybe Name]
ts [Maybe Name]
as
ruleCantMatch (_       : ts :: [Maybe Name]
ts) (_       : as :: [Maybe Name]
as) = [Maybe Name] -> [Maybe Name] -> Bool
ruleCantMatch [Maybe Name]
ts [Maybe Name]
as
ruleCantMatch _              _              = Bool
False
pprRulesForUser :: DynFlags -> [CoreRule] -> SDoc
pprRulesForUser :: DynFlags -> [CoreRule] -> SDoc
pprRulesForUser dflags :: DynFlags
dflags rules :: [CoreRule]
rules
  = PprStyle -> SDoc -> SDoc
withPprStyle (DynFlags -> PprStyle
defaultUserStyle DynFlags
dflags) (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$
    [CoreRule] -> SDoc
pprRules ([CoreRule] -> SDoc) -> [CoreRule] -> SDoc
forall a b. (a -> b) -> a -> b
$
    (CoreRule -> CoreRule -> Ordering) -> [CoreRule] -> [CoreRule]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((CoreRule -> RuleName) -> CoreRule -> CoreRule -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing CoreRule -> RuleName
ruleName) ([CoreRule] -> [CoreRule]) -> [CoreRule] -> [CoreRule]
forall a b. (a -> b) -> a -> b
$
    TidyEnv -> [CoreRule] -> [CoreRule]
tidyRules TidyEnv
emptyTidyEnv [CoreRule]
rules
mkRuleInfo :: [CoreRule] -> RuleInfo
mkRuleInfo :: [CoreRule] -> RuleInfo
mkRuleInfo rules :: [CoreRule]
rules = [CoreRule] -> DVarSet -> RuleInfo
RuleInfo [CoreRule]
rules ([CoreRule] -> DVarSet
rulesFreeVarsDSet [CoreRule]
rules)
extendRuleInfo :: RuleInfo -> [CoreRule] -> RuleInfo
extendRuleInfo :: RuleInfo -> [CoreRule] -> RuleInfo
extendRuleInfo (RuleInfo rs1 :: [CoreRule]
rs1 fvs1 :: DVarSet
fvs1) rs2 :: [CoreRule]
rs2
  = [CoreRule] -> DVarSet -> RuleInfo
RuleInfo ([CoreRule]
rs2 [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
rs1) ([CoreRule] -> DVarSet
rulesFreeVarsDSet [CoreRule]
rs2 DVarSet -> DVarSet -> DVarSet
`unionDVarSet` DVarSet
fvs1)
addRuleInfo :: RuleInfo -> RuleInfo -> RuleInfo
addRuleInfo :: RuleInfo -> RuleInfo -> RuleInfo
addRuleInfo (RuleInfo rs1 :: [CoreRule]
rs1 fvs1 :: DVarSet
fvs1) (RuleInfo rs2 :: [CoreRule]
rs2 fvs2 :: DVarSet
fvs2)
  = [CoreRule] -> DVarSet -> RuleInfo
RuleInfo ([CoreRule]
rs1 [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
rs2) (DVarSet
fvs1 DVarSet -> DVarSet -> DVarSet
`unionDVarSet` DVarSet
fvs2)
addIdSpecialisations :: Id -> [CoreRule] -> Id
addIdSpecialisations :: CoreBndr -> [CoreRule] -> CoreBndr
addIdSpecialisations id :: CoreBndr
id rules :: [CoreRule]
rules
  | [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
rules
  = CoreBndr
id
  | Bool
otherwise
  = CoreBndr -> RuleInfo -> CoreBndr
setIdSpecialisation CoreBndr
id (RuleInfo -> CoreBndr) -> RuleInfo -> CoreBndr
forall a b. (a -> b) -> a -> b
$
    RuleInfo -> [CoreRule] -> RuleInfo
extendRuleInfo (CoreBndr -> RuleInfo
idSpecialisation CoreBndr
id) [CoreRule]
rules
rulesOfBinds :: [CoreBind] -> [CoreRule]
rulesOfBinds :: [CoreBind] -> [CoreRule]
rulesOfBinds binds :: [CoreBind]
binds = (CoreBind -> [CoreRule]) -> [CoreBind] -> [CoreRule]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((CoreBndr -> [CoreRule]) -> [CoreBndr] -> [CoreRule]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap CoreBndr -> [CoreRule]
idCoreRules ([CoreBndr] -> [CoreRule])
-> (CoreBind -> [CoreBndr]) -> CoreBind -> [CoreRule]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBind -> [CoreBndr]
forall b. Bind b -> [b]
bindersOf) [CoreBind]
binds
getRules :: RuleEnv -> Id -> [CoreRule]
getRules :: RuleEnv -> CoreBndr -> [CoreRule]
getRules (RuleEnv { re_base :: RuleEnv -> RuleBase
re_base = RuleBase
rule_base, re_visible_orphs :: RuleEnv -> ModuleSet
re_visible_orphs = ModuleSet
orphs }) fn :: CoreBndr
fn
  = CoreBndr -> [CoreRule]
idCoreRules CoreBndr
fn [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ (CoreRule -> Bool) -> [CoreRule] -> [CoreRule]
forall a. (a -> Bool) -> [a] -> [a]
filter (ModuleSet -> CoreRule -> Bool
ruleIsVisible ModuleSet
orphs) [CoreRule]
imp_rules
  where
    imp_rules :: [CoreRule]
imp_rules = RuleBase -> Name -> Maybe [CoreRule]
forall a. NameEnv a -> Name -> Maybe a
lookupNameEnv RuleBase
rule_base (CoreBndr -> Name
idName CoreBndr
fn) Maybe [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. Maybe a -> a -> a
`orElse` []
ruleIsVisible :: ModuleSet -> CoreRule -> Bool
ruleIsVisible :: ModuleSet -> CoreRule -> Bool
ruleIsVisible _ BuiltinRule{} = Bool
True
ruleIsVisible vis_orphs :: ModuleSet
vis_orphs Rule { ru_orphan :: CoreRule -> IsOrphan
ru_orphan = IsOrphan
orph, ru_origin :: CoreRule -> Module
ru_origin = Module
origin }
    = IsOrphan -> Bool
notOrphan IsOrphan
orph Bool -> Bool -> Bool
|| Module
origin Module -> ModuleSet -> Bool
`elemModuleSet` ModuleSet
vis_orphs
emptyRuleBase :: RuleBase
emptyRuleBase :: RuleBase
emptyRuleBase = RuleBase
forall a. NameEnv a
emptyNameEnv
mkRuleBase :: [CoreRule] -> RuleBase
mkRuleBase :: [CoreRule] -> RuleBase
mkRuleBase rules :: [CoreRule]
rules = RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList RuleBase
emptyRuleBase [CoreRule]
rules
extendRuleBaseList :: RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList :: RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList rule_base :: RuleBase
rule_base new_guys :: [CoreRule]
new_guys
  = (RuleBase -> CoreRule -> RuleBase)
-> RuleBase -> [CoreRule] -> RuleBase
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' RuleBase -> CoreRule -> RuleBase
extendRuleBase RuleBase
rule_base [CoreRule]
new_guys
unionRuleBase :: RuleBase -> RuleBase -> RuleBase
unionRuleBase :: RuleBase -> RuleBase -> RuleBase
unionRuleBase rb1 :: RuleBase
rb1 rb2 :: RuleBase
rb2 = ([CoreRule] -> [CoreRule] -> [CoreRule])
-> RuleBase -> RuleBase -> RuleBase
forall a. (a -> a -> a) -> NameEnv a -> NameEnv a -> NameEnv a
plusNameEnv_C [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
(++) RuleBase
rb1 RuleBase
rb2
extendRuleBase :: RuleBase -> CoreRule -> RuleBase
extendRuleBase :: RuleBase -> CoreRule -> RuleBase
extendRuleBase rule_base :: RuleBase
rule_base rule :: CoreRule
rule
  = (CoreRule -> [CoreRule] -> [CoreRule])
-> (CoreRule -> [CoreRule])
-> RuleBase
-> Name
-> CoreRule
-> RuleBase
forall a b.
(a -> b -> b) -> (a -> b) -> NameEnv b -> Name -> a -> NameEnv b
extendNameEnv_Acc (:) CoreRule -> [CoreRule]
forall a. a -> [a]
singleton RuleBase
rule_base (CoreRule -> Name
ruleIdName CoreRule
rule) CoreRule
rule
pprRuleBase :: RuleBase -> SDoc
pprRuleBase :: RuleBase -> SDoc
pprRuleBase rules :: RuleBase
rules = RuleBase -> ([[CoreRule]] -> SDoc) -> SDoc
forall a. UniqFM a -> ([a] -> SDoc) -> SDoc
pprUFM RuleBase
rules (([[CoreRule]] -> SDoc) -> SDoc) -> ([[CoreRule]] -> SDoc) -> SDoc
forall a b. (a -> b) -> a -> b
$ \rss :: [[CoreRule]]
rss ->
  [SDoc] -> SDoc
vcat [ [CoreRule] -> SDoc
pprRules (TidyEnv -> [CoreRule] -> [CoreRule]
tidyRules TidyEnv
emptyTidyEnv [CoreRule]
rs)
       | [CoreRule]
rs <- [[CoreRule]]
rss ]
lookupRule :: DynFlags -> InScopeEnv
           -> (Activation -> Bool)      
           -> Id -> [CoreExpr]
           -> [CoreRule] -> Maybe (CoreRule, CoreExpr)
lookupRule :: DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> CoreBndr
-> [CoreExpr]
-> [CoreRule]
-> Maybe (CoreRule, CoreExpr)
lookupRule dflags :: DynFlags
dflags in_scope :: InScopeEnv
in_scope is_active :: Activation -> Bool
is_active fn :: CoreBndr
fn args :: [CoreExpr]
args rules :: [CoreRule]
rules
  = 
    case [(CoreRule, CoreExpr)] -> [CoreRule] -> [(CoreRule, CoreExpr)]
go [] [CoreRule]
rules of
        []     -> Maybe (CoreRule, CoreExpr)
forall a. Maybe a
Nothing
        (m :: (CoreRule, CoreExpr)
m:ms :: [(CoreRule, CoreExpr)]
ms) -> (CoreRule, CoreExpr) -> Maybe (CoreRule, CoreExpr)
forall a. a -> Maybe a
Just ((CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest (CoreBndr
fn,[CoreExpr]
args') (CoreRule, CoreExpr)
m [(CoreRule, CoreExpr)]
ms)
  where
    rough_args :: [Maybe Name]
rough_args = (CoreExpr -> Maybe Name) -> [CoreExpr] -> [Maybe Name]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Maybe Name
roughTopName [CoreExpr]
args
    
    
    
    args' :: [CoreExpr]
args' = (CoreExpr -> CoreExpr) -> [CoreExpr] -> [CoreExpr]
forall a b. (a -> b) -> [a] -> [b]
map ((Tickish CoreBndr -> Bool) -> CoreExpr -> CoreExpr
forall b. (Tickish CoreBndr -> Bool) -> Expr b -> Expr b
stripTicksTopE Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable) [CoreExpr]
args
    ticks :: [Tickish CoreBndr]
ticks = (CoreExpr -> [Tickish CoreBndr])
-> [CoreExpr] -> [Tickish CoreBndr]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Tickish CoreBndr -> Bool) -> CoreExpr -> [Tickish CoreBndr]
forall b.
(Tickish CoreBndr -> Bool) -> Expr b -> [Tickish CoreBndr]
stripTicksTopT Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable) [CoreExpr]
args
    go :: [(CoreRule,CoreExpr)] -> [CoreRule] -> [(CoreRule,CoreExpr)]
    go :: [(CoreRule, CoreExpr)] -> [CoreRule] -> [(CoreRule, CoreExpr)]
go ms :: [(CoreRule, CoreExpr)]
ms [] = [(CoreRule, CoreExpr)]
ms
    go ms :: [(CoreRule, CoreExpr)]
ms (r :: CoreRule
r:rs :: [CoreRule]
rs)
      | Just e :: CoreExpr
e <- DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> CoreBndr
-> [CoreExpr]
-> [Maybe Name]
-> CoreRule
-> Maybe CoreExpr
matchRule DynFlags
dflags InScopeEnv
in_scope Activation -> Bool
is_active CoreBndr
fn [CoreExpr]
args' [Maybe Name]
rough_args CoreRule
r
      = [(CoreRule, CoreExpr)] -> [CoreRule] -> [(CoreRule, CoreExpr)]
go ((CoreRule
r,[Tickish CoreBndr] -> CoreExpr -> CoreExpr
mkTicks [Tickish CoreBndr]
ticks CoreExpr
e)(CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)] -> [(CoreRule, CoreExpr)]
forall a. a -> [a] -> [a]
:[(CoreRule, CoreExpr)]
ms) [CoreRule]
rs
      | Bool
otherwise
      = 
        
        
        
        
        [(CoreRule, CoreExpr)] -> [CoreRule] -> [(CoreRule, CoreExpr)]
go [(CoreRule, CoreExpr)]
ms [CoreRule]
rs
findBest :: (Id, [CoreExpr])
         -> (CoreRule,CoreExpr) -> [(CoreRule,CoreExpr)] -> (CoreRule,CoreExpr)
findBest :: (CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest _      (rule :: CoreRule
rule,ans :: CoreExpr
ans)   [] = (CoreRule
rule,CoreExpr
ans)
findBest target :: (CoreBndr, [CoreExpr])
target (rule1 :: CoreRule
rule1,ans1 :: CoreExpr
ans1) ((rule2 :: CoreRule
rule2,ans2 :: CoreExpr
ans2):prs :: [(CoreRule, CoreExpr)]
prs)
  | CoreRule
rule1 CoreRule -> CoreRule -> Bool
`isMoreSpecific` CoreRule
rule2 = (CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest (CoreBndr, [CoreExpr])
target (CoreRule
rule1,CoreExpr
ans1) [(CoreRule, CoreExpr)]
prs
  | CoreRule
rule2 CoreRule -> CoreRule -> Bool
`isMoreSpecific` CoreRule
rule1 = (CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest (CoreBndr, [CoreExpr])
target (CoreRule
rule2,CoreExpr
ans2) [(CoreRule, CoreExpr)]
prs
  | Bool
debugIsOn = let pp_rule :: CoreRule -> SDoc
pp_rule rule :: CoreRule
rule
                      = SDoc -> SDoc -> SDoc
ifPprDebug (CoreRule -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreRule
rule)
                                   (SDoc -> SDoc
doubleQuotes (RuleName -> SDoc
ftext (CoreRule -> RuleName
ruleName CoreRule
rule)))
                in String -> SDoc -> (CoreRule, CoreExpr) -> (CoreRule, CoreExpr)
forall a. String -> SDoc -> a -> a
pprTrace "Rules.findBest: rule overlap (Rule 1 wins)"
                         ([SDoc] -> SDoc
vcat [ SDoc -> SDoc
whenPprDebug (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$
                                 String -> SDoc
text "Expression to match:" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
fn
                                 SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
sep ((CoreExpr -> SDoc) -> [CoreExpr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
args)
                               , String -> SDoc
text "Rule 1:" SDoc -> SDoc -> SDoc
<+> CoreRule -> SDoc
pp_rule CoreRule
rule1
                               , String -> SDoc
text "Rule 2:" SDoc -> SDoc -> SDoc
<+> CoreRule -> SDoc
pp_rule CoreRule
rule2]) ((CoreRule, CoreExpr) -> (CoreRule, CoreExpr))
-> (CoreRule, CoreExpr) -> (CoreRule, CoreExpr)
forall a b. (a -> b) -> a -> b
$
                (CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest (CoreBndr, [CoreExpr])
target (CoreRule
rule1,CoreExpr
ans1) [(CoreRule, CoreExpr)]
prs
  | Bool
otherwise = (CoreBndr, [CoreExpr])
-> (CoreRule, CoreExpr)
-> [(CoreRule, CoreExpr)]
-> (CoreRule, CoreExpr)
findBest (CoreBndr, [CoreExpr])
target (CoreRule
rule1,CoreExpr
ans1) [(CoreRule, CoreExpr)]
prs
  where
    (fn :: CoreBndr
fn,args :: [CoreExpr]
args) = (CoreBndr, [CoreExpr])
target
isMoreSpecific :: CoreRule -> CoreRule -> Bool
isMoreSpecific :: CoreRule -> CoreRule -> Bool
isMoreSpecific (BuiltinRule {}) _                = Bool
False
isMoreSpecific (Rule {})        (BuiltinRule {}) = Bool
True
isMoreSpecific (Rule { ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs1, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args1 })
               (Rule { ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs2, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args2, ru_name :: CoreRule -> RuleName
ru_name = RuleName
rule_name2 })
  = Maybe (CoreExpr -> CoreExpr, [CoreExpr]) -> Bool
forall a. Maybe a -> Bool
isJust (InScopeEnv
-> RuleName
-> [CoreBndr]
-> [CoreExpr]
-> [CoreExpr]
-> Maybe (CoreExpr -> CoreExpr, [CoreExpr])
matchN (InScopeSet
in_scope, CoreBndr -> Unfolding
forall p. p -> Unfolding
id_unfolding_fun) RuleName
rule_name2 [CoreBndr]
bndrs2 [CoreExpr]
args2 [CoreExpr]
args1)
  where
   id_unfolding_fun :: p -> Unfolding
id_unfolding_fun _ = Unfolding
NoUnfolding     
   in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet ([CoreBndr] -> VarSet
mkVarSet [CoreBndr]
bndrs1)
        
        
noBlackList :: Activation -> Bool
noBlackList :: Activation -> Bool
noBlackList _ = Bool
False           
matchRule :: DynFlags -> InScopeEnv -> (Activation -> Bool)
          -> Id -> [CoreExpr] -> [Maybe Name]
          -> CoreRule -> Maybe CoreExpr
matchRule :: DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> CoreBndr
-> [CoreExpr]
-> [Maybe Name]
-> CoreRule
-> Maybe CoreExpr
matchRule dflags :: DynFlags
dflags rule_env :: InScopeEnv
rule_env _is_active :: Activation -> Bool
_is_active fn :: CoreBndr
fn args :: [CoreExpr]
args _rough_args :: [Maybe Name]
_rough_args
          (BuiltinRule { ru_try :: CoreRule -> RuleFun
ru_try = RuleFun
match_fn })
  = case RuleFun
match_fn DynFlags
dflags InScopeEnv
rule_env CoreBndr
fn [CoreExpr]
args of
        Nothing   -> Maybe CoreExpr
forall a. Maybe a
Nothing
        Just expr :: CoreExpr
expr -> CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just CoreExpr
expr
matchRule _ in_scope :: InScopeEnv
in_scope is_active :: Activation -> Bool
is_active _ args :: [CoreExpr]
args rough_args :: [Maybe Name]
rough_args
          (Rule { ru_name :: CoreRule -> RuleName
ru_name = RuleName
rule_name, ru_act :: CoreRule -> Activation
ru_act = Activation
act, ru_rough :: CoreRule -> [Maybe Name]
ru_rough = [Maybe Name]
tpl_tops
                , ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
tpl_vars, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
tpl_args, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs })
  | Bool -> Bool
not (Activation -> Bool
is_active Activation
act)               = Maybe CoreExpr
forall a. Maybe a
Nothing
  | [Maybe Name] -> [Maybe Name] -> Bool
ruleCantMatch [Maybe Name]
tpl_tops [Maybe Name]
rough_args = Maybe CoreExpr
forall a. Maybe a
Nothing
  | Bool
otherwise
  = case InScopeEnv
-> RuleName
-> [CoreBndr]
-> [CoreExpr]
-> [CoreExpr]
-> Maybe (CoreExpr -> CoreExpr, [CoreExpr])
matchN InScopeEnv
in_scope RuleName
rule_name [CoreBndr]
tpl_vars [CoreExpr]
tpl_args [CoreExpr]
args of
        Nothing                       -> Maybe CoreExpr
forall a. Maybe a
Nothing
        Just (bind_wrapper :: CoreExpr -> CoreExpr
bind_wrapper, tpl_vals :: [CoreExpr]
tpl_vals) -> CoreExpr -> Maybe CoreExpr
forall a. a -> Maybe a
Just (CoreExpr -> CoreExpr
bind_wrapper (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$
                                               CoreExpr
rule_fn CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
`mkApps` [CoreExpr]
tpl_vals)
  where
    rule_fn :: CoreExpr
rule_fn = [CoreBndr] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
tpl_vars CoreExpr
rhs
matchN  :: InScopeEnv
        -> RuleName -> [Var] -> [CoreExpr]
        -> [CoreExpr]           
        -> Maybe (BindWrapper,  
                  [CoreExpr])
matchN :: InScopeEnv
-> RuleName
-> [CoreBndr]
-> [CoreExpr]
-> [CoreExpr]
-> Maybe (CoreExpr -> CoreExpr, [CoreExpr])
matchN (in_scope :: InScopeSet
in_scope, id_unf :: CoreBndr -> Unfolding
id_unf) rule_name :: RuleName
rule_name tmpl_vars :: [CoreBndr]
tmpl_vars tmpl_es :: [CoreExpr]
tmpl_es target_es :: [CoreExpr]
target_es
  = do  { RuleSubst
subst <- RuleMatchEnv
-> RuleSubst -> [CoreExpr] -> [CoreExpr] -> Maybe RuleSubst
go RuleMatchEnv
init_menv RuleSubst
emptyRuleSubst [CoreExpr]
tmpl_es [CoreExpr]
target_es
        ; let (_, matched_es :: [CoreExpr]
matched_es) = (RuleSubst -> (CoreBndr, CoreBndr) -> (RuleSubst, CoreExpr))
-> RuleSubst -> [(CoreBndr, CoreBndr)] -> (RuleSubst, [CoreExpr])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL RuleSubst -> (CoreBndr, CoreBndr) -> (RuleSubst, CoreExpr)
lookup_tmpl RuleSubst
subst ([(CoreBndr, CoreBndr)] -> (RuleSubst, [CoreExpr]))
-> [(CoreBndr, CoreBndr)] -> (RuleSubst, [CoreExpr])
forall a b. (a -> b) -> a -> b
$
                                [CoreBndr]
tmpl_vars [CoreBndr] -> [CoreBndr] -> [(CoreBndr, CoreBndr)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [CoreBndr]
tmpl_vars1
        ; (CoreExpr -> CoreExpr, [CoreExpr])
-> Maybe (CoreExpr -> CoreExpr, [CoreExpr])
forall (m :: * -> *) a. Monad m => a -> m a
return (RuleSubst -> CoreExpr -> CoreExpr
rs_binds RuleSubst
subst, [CoreExpr]
matched_es) }
  where
    (init_rn_env :: RnEnv2
init_rn_env, tmpl_vars1 :: [CoreBndr]
tmpl_vars1) = (RnEnv2 -> CoreBndr -> (RnEnv2, CoreBndr))
-> RnEnv2 -> [CoreBndr] -> (RnEnv2, [CoreBndr])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL RnEnv2 -> CoreBndr -> (RnEnv2, CoreBndr)
rnBndrL (InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
in_scope) [CoreBndr]
tmpl_vars
                  
    init_menv :: RuleMatchEnv
init_menv = RV :: RnEnv2
-> VarSet -> Subst -> (CoreBndr -> Unfolding) -> RuleMatchEnv
RV { rv_tmpls :: VarSet
rv_tmpls = [CoreBndr] -> VarSet
mkVarSet [CoreBndr]
tmpl_vars1
                   , rv_lcl :: RnEnv2
rv_lcl   = RnEnv2
init_rn_env
                   , rv_fltR :: Subst
rv_fltR  = InScopeSet -> Subst
mkEmptySubst (RnEnv2 -> InScopeSet
rnInScopeSet RnEnv2
init_rn_env)
                   , rv_unf :: CoreBndr -> Unfolding
rv_unf   = CoreBndr -> Unfolding
id_unf }
    go :: RuleMatchEnv
-> RuleSubst -> [CoreExpr] -> [CoreExpr] -> Maybe RuleSubst
go _    subst :: RuleSubst
subst []     _      = RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
    go _    _     _      []     = Maybe RuleSubst
forall a. Maybe a
Nothing       
    go menv :: RuleMatchEnv
menv subst :: RuleSubst
subst (t :: CoreExpr
t:ts :: [CoreExpr]
ts) (e :: CoreExpr
e:es :: [CoreExpr]
es) = do { RuleSubst
subst1 <- RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
menv RuleSubst
subst CoreExpr
t CoreExpr
e
                                     ; RuleMatchEnv
-> RuleSubst -> [CoreExpr] -> [CoreExpr] -> Maybe RuleSubst
go RuleMatchEnv
menv RuleSubst
subst1 [CoreExpr]
ts [CoreExpr]
es }
    lookup_tmpl :: RuleSubst -> (InVar,OutVar) -> (RuleSubst, CoreExpr)
                   
    lookup_tmpl :: RuleSubst -> (CoreBndr, CoreBndr) -> (RuleSubst, CoreExpr)
lookup_tmpl rs :: RuleSubst
rs@(RS { rs_tv_subst :: RuleSubst -> TvSubstEnv
rs_tv_subst = TvSubstEnv
tv_subst, rs_id_subst :: RuleSubst -> IdSubstEnv
rs_id_subst = IdSubstEnv
id_subst })
                (tmpl_var :: CoreBndr
tmpl_var, tmpl_var1 :: CoreBndr
tmpl_var1)
        | CoreBndr -> Bool
isId CoreBndr
tmpl_var1
        = case IdSubstEnv -> CoreBndr -> Maybe CoreExpr
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv IdSubstEnv
id_subst CoreBndr
tmpl_var1 of
             Just e :: CoreExpr
e -> (RuleSubst
rs, CoreExpr
e)
             Nothing | Just refl_co :: Coercion
refl_co <- CoreBndr -> Maybe Coercion
isReflCoVar_maybe CoreBndr
tmpl_var1
                     , let co_expr :: Expr b
co_expr   = Coercion -> Expr b
forall b. Coercion -> Expr b
Coercion Coercion
refl_co
                           id_subst' :: IdSubstEnv
id_subst' = IdSubstEnv -> CoreBndr -> CoreExpr -> IdSubstEnv
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv IdSubstEnv
id_subst CoreBndr
tmpl_var1 CoreExpr
forall b. Expr b
co_expr
                           rs' :: RuleSubst
rs'       = RuleSubst
rs { rs_id_subst :: IdSubstEnv
rs_id_subst = IdSubstEnv
id_subst' }
                     -> (RuleSubst
rs', CoreExpr
forall b. Expr b
co_expr) 
                     | Bool
otherwise
                     -> CoreBndr -> (RuleSubst, CoreExpr)
forall a. CoreBndr -> a
unbound CoreBndr
tmpl_var
        | Bool
otherwise
        = case TvSubstEnv -> CoreBndr -> Maybe Type
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv TvSubstEnv
tv_subst CoreBndr
tmpl_var1 of
             Just ty :: Type
ty -> (RuleSubst
rs, Type -> CoreExpr
forall b. Type -> Expr b
Type Type
ty)
             Nothing -> (RuleSubst
rs', Type -> CoreExpr
forall b. Type -> Expr b
Type Type
fake_ty) 
        where
          rs' :: RuleSubst
rs'     = RuleSubst
rs { rs_tv_subst :: TvSubstEnv
rs_tv_subst = TvSubstEnv -> CoreBndr -> Type -> TvSubstEnv
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv TvSubstEnv
tv_subst CoreBndr
tmpl_var1 Type
fake_ty }
          fake_ty :: Type
fake_ty = InScopeSet -> RuleSubst -> CoreBndr -> Type
mk_fake_ty InScopeSet
in_scope RuleSubst
rs CoreBndr
tmpl_var1
                    
                    
    unbound :: CoreBndr -> a
unbound tmpl_var :: CoreBndr
tmpl_var
       = String -> SDoc -> a
forall a. HasCallStack => String -> SDoc -> a
pprPanic "Template variable unbound in rewrite rule" (SDoc -> a) -> SDoc -> a
forall a b. (a -> b) -> a -> b
$
         [SDoc] -> SDoc
vcat [ String -> SDoc
text "Variable:" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
tmpl_var SDoc -> SDoc -> SDoc
<+> SDoc
dcolon SDoc -> SDoc -> SDoc
<+> Type -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CoreBndr -> Type
varType CoreBndr
tmpl_var)
              , String -> SDoc
text "Rule" SDoc -> SDoc -> SDoc
<+> RuleName -> SDoc
pprRuleName RuleName
rule_name
              , String -> SDoc
text "Rule bndrs:" SDoc -> SDoc -> SDoc
<+> [CoreBndr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreBndr]
tmpl_vars
              , String -> SDoc
text "LHS args:" SDoc -> SDoc -> SDoc
<+> [CoreExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
tmpl_es
              , String -> SDoc
text "Actual args:" SDoc -> SDoc -> SDoc
<+> [CoreExpr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [CoreExpr]
target_es ]
mk_fake_ty :: InScopeSet -> RuleSubst -> TyVar -> Kind
mk_fake_ty :: InScopeSet -> RuleSubst -> CoreBndr -> Type
mk_fake_ty in_scope :: InScopeSet
in_scope (RS { rs_tv_subst :: RuleSubst -> TvSubstEnv
rs_tv_subst = TvSubstEnv
tv_subst, rs_id_subst :: RuleSubst -> IdSubstEnv
rs_id_subst = IdSubstEnv
id_subst }) tmpl_var1 :: CoreBndr
tmpl_var1
  = Type -> Type
anyTypeOfKind Type
kind
  where
    kind :: Type
kind = HasCallStack => TCvSubst -> Type -> Type
TCvSubst -> Type -> Type
Type.substTy (InScopeSet -> (TvSubstEnv, CvSubstEnv) -> TCvSubst
mkTCvSubst InScopeSet
in_scope (TvSubstEnv
tv_subst, CvSubstEnv
cv_subst))
                        (CoreBndr -> Type
tyVarKind CoreBndr
tmpl_var1)
    cv_subst :: CvSubstEnv
cv_subst = IdSubstEnv -> CvSubstEnv
to_co_env IdSubstEnv
id_subst
    to_co_env :: IdSubstEnv -> CvSubstEnv
    to_co_env :: IdSubstEnv -> CvSubstEnv
to_co_env env :: IdSubstEnv
env = (Unique -> CoreExpr -> CvSubstEnv -> CvSubstEnv)
-> CvSubstEnv -> IdSubstEnv -> CvSubstEnv
forall elt a. (Unique -> elt -> a -> a) -> a -> UniqFM elt -> a
nonDetFoldUFM_Directly Unique -> CoreExpr -> CvSubstEnv -> CvSubstEnv
to_co CvSubstEnv
forall a. NameEnv a
emptyVarEnv IdSubstEnv
env
      
      
    to_co :: Unique -> CoreExpr -> CvSubstEnv -> CvSubstEnv
to_co uniq :: Unique
uniq expr :: CoreExpr
expr env :: CvSubstEnv
env
      = case CoreExpr -> Maybe Coercion
exprToCoercion_maybe CoreExpr
expr of
          Just co :: Coercion
co -> CvSubstEnv -> Unique -> Coercion -> CvSubstEnv
forall a. VarEnv a -> Unique -> a -> VarEnv a
extendVarEnv_Directly CvSubstEnv
env Unique
uniq Coercion
co
          Nothing -> CvSubstEnv
env
data RuleMatchEnv
  = RV { RuleMatchEnv -> RnEnv2
rv_lcl   :: RnEnv2          
                                     
       , RuleMatchEnv -> VarSet
rv_tmpls :: VarSet          
                                     
       , RuleMatchEnv -> Subst
rv_fltR  :: Subst           
                                     
                                     
       , RuleMatchEnv -> CoreBndr -> Unfolding
rv_unf :: IdUnfoldingFun
       }
rvInScopeEnv :: RuleMatchEnv -> InScopeEnv
rvInScopeEnv :: RuleMatchEnv -> InScopeEnv
rvInScopeEnv renv :: RuleMatchEnv
renv = (RnEnv2 -> InScopeSet
rnInScopeSet (RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv), RuleMatchEnv -> CoreBndr -> Unfolding
rv_unf RuleMatchEnv
renv)
data RuleSubst = RS { RuleSubst -> TvSubstEnv
rs_tv_subst :: TvSubstEnv   
                    , RuleSubst -> IdSubstEnv
rs_id_subst :: IdSubstEnv   
                    , RuleSubst -> CoreExpr -> CoreExpr
rs_binds    :: BindWrapper  
                    , RuleSubst -> VarSet
rs_bndrs    :: VarSet       
                    }
type BindWrapper = CoreExpr -> CoreExpr
  
  
emptyRuleSubst :: RuleSubst
emptyRuleSubst :: RuleSubst
emptyRuleSubst = RS :: TvSubstEnv
-> IdSubstEnv -> (CoreExpr -> CoreExpr) -> VarSet -> RuleSubst
RS { rs_tv_subst :: TvSubstEnv
rs_tv_subst = TvSubstEnv
forall a. NameEnv a
emptyVarEnv, rs_id_subst :: IdSubstEnv
rs_id_subst = IdSubstEnv
forall a. NameEnv a
emptyVarEnv
                    , rs_binds :: CoreExpr -> CoreExpr
rs_binds = \e :: CoreExpr
e -> CoreExpr
e, rs_bndrs :: VarSet
rs_bndrs = VarSet
emptyVarSet }
match :: RuleMatchEnv
      -> RuleSubst
      -> CoreExpr               
      -> CoreExpr               
      -> Maybe RuleSubst
match :: RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst e1 :: CoreExpr
e1 (Tick t :: Tickish CoreBndr
t e2 :: CoreExpr
e2)
  | Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Tickish CoreBndr
t
  = RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
subst' CoreExpr
e1 CoreExpr
e2
  where subst' :: RuleSubst
subst' = RuleSubst
subst { rs_binds :: CoreExpr -> CoreExpr
rs_binds = RuleSubst -> CoreExpr -> CoreExpr
rs_binds RuleSubst
subst (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tickish CoreBndr -> CoreExpr -> CoreExpr
mkTick Tickish CoreBndr
t }
match _ _ e :: CoreExpr
e@Tick{} _
  = String -> SDoc -> Maybe RuleSubst
forall a. HasCallStack => String -> SDoc -> a
pprPanic "Tick in rule" (CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreExpr
e)
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Var v1 :: CoreBndr
v1) e2 :: CoreExpr
e2
  = RuleMatchEnv
-> RuleSubst -> CoreBndr -> CoreExpr -> Maybe RuleSubst
match_var RuleMatchEnv
renv RuleSubst
subst CoreBndr
v1 CoreExpr
e2
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst e1 :: CoreExpr
e1 (Var v2 :: CoreBndr
v2)      
  | Bool -> Bool
not (RnEnv2 -> CoreBndr -> Bool
inRnEnvR RnEnv2
rn_env CoreBndr
v2) 
  , Just e2' :: CoreExpr
e2' <- Unfolding -> Maybe CoreExpr
expandUnfolding_maybe (RuleMatchEnv -> CoreBndr -> Unfolding
rv_unf RuleMatchEnv
renv CoreBndr
v2')
  = RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match (RuleMatchEnv
renv { rv_lcl :: RnEnv2
rv_lcl = RnEnv2 -> RnEnv2
nukeRnEnvR RnEnv2
rn_env }) RuleSubst
subst CoreExpr
e1 CoreExpr
e2'
  where
    v2' :: CoreBndr
v2'    = RnEnv2 -> CoreBndr -> CoreBndr
lookupRnInScope RnEnv2
rn_env CoreBndr
v2
    rn_env :: RnEnv2
rn_env = RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv
        
        
        
        
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst e1 :: CoreExpr
e1 (Let bind :: CoreBind
bind e2 :: CoreExpr
e2)
  | 
    Bool -> Bool
not (CoreBind -> Bool
isJoinBind CoreBind
bind) 
  , RnEnv2 -> VarSet -> Bool
okToFloat (RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv) (CoreBind -> VarSet
bindFreeVars CoreBind
bind) 
  = RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match (RuleMatchEnv
renv { rv_fltR :: Subst
rv_fltR = Subst
flt_subst' })
          (RuleSubst
subst { rs_binds :: CoreExpr -> CoreExpr
rs_binds = RuleSubst -> CoreExpr -> CoreExpr
rs_binds RuleSubst
subst (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CoreBind -> CoreExpr -> CoreExpr
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind'
                 , rs_bndrs :: VarSet
rs_bndrs = VarSet -> [CoreBndr] -> VarSet
extendVarSetList (RuleSubst -> VarSet
rs_bndrs RuleSubst
subst) [CoreBndr]
new_bndrs })
          CoreExpr
e1 CoreExpr
e2
  where
    flt_subst :: Subst
flt_subst = Subst -> VarSet -> Subst
addInScopeSet (RuleMatchEnv -> Subst
rv_fltR RuleMatchEnv
renv) (RuleSubst -> VarSet
rs_bndrs RuleSubst
subst)
    (flt_subst' :: Subst
flt_subst', bind' :: CoreBind
bind') = Subst -> CoreBind -> (Subst, CoreBind)
substBind Subst
flt_subst CoreBind
bind
    new_bndrs :: [CoreBndr]
new_bndrs = CoreBind -> [CoreBndr]
forall b. Bind b -> [b]
bindersOf CoreBind
bind'
match _ subst :: RuleSubst
subst (Lit lit1 :: Literal
lit1) (Lit lit2 :: Literal
lit2)
  | Literal
lit1 Literal -> Literal -> Bool
forall a. Eq a => a -> a -> Bool
== Literal
lit2
  = RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (App f1 :: CoreExpr
f1 a1 :: CoreExpr
a1) (App f2 :: CoreExpr
f2 a2 :: CoreExpr
a2)
  = do  { RuleSubst
subst' <- RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
subst CoreExpr
f1 CoreExpr
f2
        ; RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
subst' CoreExpr
a1 CoreExpr
a2 }
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Lam x1 :: CoreBndr
x1 e1 :: CoreExpr
e1) e2 :: CoreExpr
e2
  | Just (x2 :: CoreBndr
x2, e2 :: CoreExpr
e2, ts :: [Tickish CoreBndr]
ts) <- InScopeEnv
-> CoreExpr -> Maybe (CoreBndr, CoreExpr, [Tickish CoreBndr])
exprIsLambda_maybe (RuleMatchEnv -> InScopeEnv
rvInScopeEnv RuleMatchEnv
renv) CoreExpr
e2
  = let renv' :: RuleMatchEnv
renv' = RuleMatchEnv
renv { rv_lcl :: RnEnv2
rv_lcl = RnEnv2 -> CoreBndr -> CoreBndr -> RnEnv2
rnBndr2 (RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv) CoreBndr
x1 CoreBndr
x2
                     , rv_fltR :: Subst
rv_fltR = Subst -> CoreBndr -> Subst
delBndr (RuleMatchEnv -> Subst
rv_fltR RuleMatchEnv
renv) CoreBndr
x2 }
        subst' :: RuleSubst
subst' = RuleSubst
subst { rs_binds :: CoreExpr -> CoreExpr
rs_binds = RuleSubst -> CoreExpr -> CoreExpr
rs_binds RuleSubst
subst (CoreExpr -> CoreExpr)
-> (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CoreExpr -> [Tickish CoreBndr] -> CoreExpr)
-> [Tickish CoreBndr] -> CoreExpr -> CoreExpr
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((Tickish CoreBndr -> CoreExpr -> CoreExpr)
-> CoreExpr -> [Tickish CoreBndr] -> CoreExpr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Tickish CoreBndr -> CoreExpr -> CoreExpr
mkTick) [Tickish CoreBndr]
ts }
    in  RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv' RuleSubst
subst' CoreExpr
e1 CoreExpr
e2
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Case e1 :: CoreExpr
e1 x1 :: CoreBndr
x1 ty1 :: Type
ty1 alts1 :: [Alt CoreBndr]
alts1) (Case e2 :: CoreExpr
e2 x2 :: CoreBndr
x2 ty2 :: Type
ty2 alts2 :: [Alt CoreBndr]
alts2)
  = do  { RuleSubst
subst1 <- RuleMatchEnv -> RuleSubst -> Type -> Type -> Maybe RuleSubst
match_ty RuleMatchEnv
renv RuleSubst
subst Type
ty1 Type
ty2
        ; RuleSubst
subst2 <- RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
subst1 CoreExpr
e1 CoreExpr
e2
        ; let renv' :: RuleMatchEnv
renv' = RuleMatchEnv -> RuleSubst -> CoreBndr -> CoreBndr -> RuleMatchEnv
rnMatchBndr2 RuleMatchEnv
renv RuleSubst
subst CoreBndr
x1 CoreBndr
x2
        ; RuleMatchEnv
-> RuleSubst -> [Alt CoreBndr] -> [Alt CoreBndr] -> Maybe RuleSubst
match_alts RuleMatchEnv
renv' RuleSubst
subst2 [Alt CoreBndr]
alts1 [Alt CoreBndr]
alts2   
        }
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Type ty1 :: Type
ty1) (Type ty2 :: Type
ty2)
  = RuleMatchEnv -> RuleSubst -> Type -> Type -> Maybe RuleSubst
match_ty RuleMatchEnv
renv RuleSubst
subst Type
ty1 Type
ty2
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Coercion co1 :: Coercion
co1) (Coercion co2 :: Coercion
co2)
  = RuleMatchEnv
-> RuleSubst -> Coercion -> Coercion -> Maybe RuleSubst
match_co RuleMatchEnv
renv RuleSubst
subst Coercion
co1 Coercion
co2
match renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (Cast e1 :: CoreExpr
e1 co1 :: Coercion
co1) (Cast e2 :: CoreExpr
e2 co2 :: Coercion
co2)
  = do  { RuleSubst
subst1 <- RuleMatchEnv
-> RuleSubst -> Coercion -> Coercion -> Maybe RuleSubst
match_co RuleMatchEnv
renv RuleSubst
subst Coercion
co1 Coercion
co2
        ; RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
subst1 CoreExpr
e1 CoreExpr
e2 }
match _ _ _e1 :: CoreExpr
_e1 _e2 :: CoreExpr
_e2 = 
                    Maybe RuleSubst
forall a. Maybe a
Nothing
match_co :: RuleMatchEnv
         -> RuleSubst
         -> Coercion
         -> Coercion
         -> Maybe RuleSubst
match_co :: RuleMatchEnv
-> RuleSubst -> Coercion -> Coercion -> Maybe RuleSubst
match_co renv :: RuleMatchEnv
renv subst :: RuleSubst
subst co1 :: Coercion
co1 co2 :: Coercion
co2
  | Just cv :: CoreBndr
cv <- Coercion -> Maybe CoreBndr
getCoVar_maybe Coercion
co1
  = RuleMatchEnv
-> RuleSubst -> CoreBndr -> CoreExpr -> Maybe RuleSubst
match_var RuleMatchEnv
renv RuleSubst
subst CoreBndr
cv (Coercion -> CoreExpr
forall b. Coercion -> Expr b
Coercion Coercion
co2)
  | Just (ty1 :: Type
ty1, r1 :: Role
r1) <- Coercion -> Maybe (Type, Role)
isReflCo_maybe Coercion
co1
  = do { (ty2 :: Type
ty2, r2 :: Role
r2) <- Coercion -> Maybe (Type, Role)
isReflCo_maybe Coercion
co2
       ; Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Role
r1 Role -> Role -> Bool
forall a. Eq a => a -> a -> Bool
== Role
r2)
       ; RuleMatchEnv -> RuleSubst -> Type -> Type -> Maybe RuleSubst
match_ty RuleMatchEnv
renv RuleSubst
subst Type
ty1 Type
ty2 }
match_co renv :: RuleMatchEnv
renv subst :: RuleSubst
subst co1 :: Coercion
co1 co2 :: Coercion
co2
  | Just (tc1 :: TyCon
tc1, cos1 :: [Coercion]
cos1) <- Coercion -> Maybe (TyCon, [Coercion])
splitTyConAppCo_maybe Coercion
co1
  = case Coercion -> Maybe (TyCon, [Coercion])
splitTyConAppCo_maybe Coercion
co2 of
      Just (tc2 :: TyCon
tc2, cos2 :: [Coercion]
cos2)
        |  TyCon
tc1 TyCon -> TyCon -> Bool
forall a. Eq a => a -> a -> Bool
== TyCon
tc2
        -> RuleMatchEnv
-> RuleSubst -> [Coercion] -> [Coercion] -> Maybe RuleSubst
match_cos RuleMatchEnv
renv RuleSubst
subst [Coercion]
cos1 [Coercion]
cos2
      _ -> Maybe RuleSubst
forall a. Maybe a
Nothing
match_co renv :: RuleMatchEnv
renv subst :: RuleSubst
subst co1 :: Coercion
co1 co2 :: Coercion
co2
  | Just (arg1 :: Coercion
arg1, res1 :: Coercion
res1) <- Coercion -> Maybe (Coercion, Coercion)
splitFunCo_maybe Coercion
co1
  = case Coercion -> Maybe (Coercion, Coercion)
splitFunCo_maybe Coercion
co2 of
      Just (arg2 :: Coercion
arg2, res2 :: Coercion
res2)
        -> RuleMatchEnv
-> RuleSubst -> [Coercion] -> [Coercion] -> Maybe RuleSubst
match_cos RuleMatchEnv
renv RuleSubst
subst [Coercion
arg1, Coercion
res1] [Coercion
arg2, Coercion
res2]
      _ -> Maybe RuleSubst
forall a. Maybe a
Nothing
match_co _ _ _co1 :: Coercion
_co1 _co2 :: Coercion
_co2
    
#if defined(DEBUG)
  = pprTrace "match_co: needs more cases" (ppr _co1 $$ ppr _co2) Nothing
#else
  = Maybe RuleSubst
forall a. Maybe a
Nothing
#endif
match_cos :: RuleMatchEnv
         -> RuleSubst
         -> [Coercion]
         -> [Coercion]
         -> Maybe RuleSubst
match_cos :: RuleMatchEnv
-> RuleSubst -> [Coercion] -> [Coercion] -> Maybe RuleSubst
match_cos renv :: RuleMatchEnv
renv subst :: RuleSubst
subst (co1 :: Coercion
co1:cos1 :: [Coercion]
cos1) (co2 :: Coercion
co2:cos2 :: [Coercion]
cos2) =
  do { RuleSubst
subst' <- RuleMatchEnv
-> RuleSubst -> Coercion -> Coercion -> Maybe RuleSubst
match_co RuleMatchEnv
renv RuleSubst
subst Coercion
co1 Coercion
co2
     ; RuleMatchEnv
-> RuleSubst -> [Coercion] -> [Coercion] -> Maybe RuleSubst
match_cos RuleMatchEnv
renv RuleSubst
subst' [Coercion]
cos1 [Coercion]
cos2 }
match_cos _ subst :: RuleSubst
subst [] [] = RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
match_cos _ _ cos1 :: [Coercion]
cos1 cos2 :: [Coercion]
cos2 = String -> SDoc -> Maybe RuleSubst -> Maybe RuleSubst
forall a. String -> SDoc -> a -> a
pprTrace "match_cos: not same length" ([Coercion] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Coercion]
cos1 SDoc -> SDoc -> SDoc
$$ [Coercion] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Coercion]
cos2) Maybe RuleSubst
forall a. Maybe a
Nothing
rnMatchBndr2 :: RuleMatchEnv -> RuleSubst -> Var -> Var -> RuleMatchEnv
rnMatchBndr2 :: RuleMatchEnv -> RuleSubst -> CoreBndr -> CoreBndr -> RuleMatchEnv
rnMatchBndr2 renv :: RuleMatchEnv
renv subst :: RuleSubst
subst x1 :: CoreBndr
x1 x2 :: CoreBndr
x2
  = RuleMatchEnv
renv { rv_lcl :: RnEnv2
rv_lcl  = RnEnv2 -> CoreBndr -> CoreBndr -> RnEnv2
rnBndr2 RnEnv2
rn_env CoreBndr
x1 CoreBndr
x2
         , rv_fltR :: Subst
rv_fltR = Subst -> CoreBndr -> Subst
delBndr (RuleMatchEnv -> Subst
rv_fltR RuleMatchEnv
renv) CoreBndr
x2 }
  where
    rn_env :: RnEnv2
rn_env = RnEnv2 -> VarSet -> RnEnv2
addRnInScopeSet (RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv) (RuleSubst -> VarSet
rs_bndrs RuleSubst
subst)
    
    
match_alts :: RuleMatchEnv
           -> RuleSubst
           -> [CoreAlt]         
           -> [CoreAlt]         
           -> Maybe RuleSubst
match_alts :: RuleMatchEnv
-> RuleSubst -> [Alt CoreBndr] -> [Alt CoreBndr] -> Maybe RuleSubst
match_alts _ subst :: RuleSubst
subst [] []
  = RuleSubst -> Maybe RuleSubst
forall (m :: * -> *) a. Monad m => a -> m a
return RuleSubst
subst
match_alts renv :: RuleMatchEnv
renv subst :: RuleSubst
subst ((c1 :: AltCon
c1,vs1 :: [CoreBndr]
vs1,r1 :: CoreExpr
r1):alts1 :: [Alt CoreBndr]
alts1) ((c2 :: AltCon
c2,vs2 :: [CoreBndr]
vs2,r2 :: CoreExpr
r2):alts2 :: [Alt CoreBndr]
alts2)
  | AltCon
c1 AltCon -> AltCon -> Bool
forall a. Eq a => a -> a -> Bool
== AltCon
c2
  = do  { RuleSubst
subst1 <- RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv' RuleSubst
subst CoreExpr
r1 CoreExpr
r2
        ; RuleMatchEnv
-> RuleSubst -> [Alt CoreBndr] -> [Alt CoreBndr] -> Maybe RuleSubst
match_alts RuleMatchEnv
renv RuleSubst
subst1 [Alt CoreBndr]
alts1 [Alt CoreBndr]
alts2 }
  where
    renv' :: RuleMatchEnv
renv' = (RuleMatchEnv -> (CoreBndr, CoreBndr) -> RuleMatchEnv)
-> RuleMatchEnv -> [(CoreBndr, CoreBndr)] -> RuleMatchEnv
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' RuleMatchEnv -> (CoreBndr, CoreBndr) -> RuleMatchEnv
mb RuleMatchEnv
renv ([CoreBndr]
vs1 [CoreBndr] -> [CoreBndr] -> [(CoreBndr, CoreBndr)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [CoreBndr]
vs2)
    mb :: RuleMatchEnv -> (CoreBndr, CoreBndr) -> RuleMatchEnv
mb renv :: RuleMatchEnv
renv (v1 :: CoreBndr
v1,v2 :: CoreBndr
v2) = RuleMatchEnv -> RuleSubst -> CoreBndr -> CoreBndr -> RuleMatchEnv
rnMatchBndr2 RuleMatchEnv
renv RuleSubst
subst CoreBndr
v1 CoreBndr
v2
match_alts _ _ _ _
  = Maybe RuleSubst
forall a. Maybe a
Nothing
okToFloat :: RnEnv2 -> VarSet -> Bool
okToFloat :: RnEnv2 -> VarSet -> Bool
okToFloat rn_env :: RnEnv2
rn_env bind_fvs :: VarSet
bind_fvs
  = (CoreBndr -> Bool) -> VarSet -> Bool
allVarSet CoreBndr -> Bool
not_captured VarSet
bind_fvs
  where
    not_captured :: CoreBndr -> Bool
not_captured fv :: CoreBndr
fv = Bool -> Bool
not (RnEnv2 -> CoreBndr -> Bool
inRnEnvR RnEnv2
rn_env CoreBndr
fv)
match_var :: RuleMatchEnv
          -> RuleSubst
          -> Var                
          -> CoreExpr        
          -> Maybe RuleSubst
match_var :: RuleMatchEnv
-> RuleSubst -> CoreBndr -> CoreExpr -> Maybe RuleSubst
match_var renv :: RuleMatchEnv
renv@(RV { rv_tmpls :: RuleMatchEnv -> VarSet
rv_tmpls = VarSet
tmpls, rv_lcl :: RuleMatchEnv -> RnEnv2
rv_lcl = RnEnv2
rn_env, rv_fltR :: RuleMatchEnv -> Subst
rv_fltR = Subst
flt_env })
          subst :: RuleSubst
subst v1 :: CoreBndr
v1 e2 :: CoreExpr
e2
  | CoreBndr
v1' CoreBndr -> VarSet -> Bool
`elemVarSet` VarSet
tmpls
  = RuleMatchEnv
-> RuleSubst -> CoreBndr -> CoreExpr -> Maybe RuleSubst
match_tmpl_var RuleMatchEnv
renv RuleSubst
subst CoreBndr
v1' CoreExpr
e2
  | Bool
otherwise   
  = case CoreExpr
e2 of  
       Var v2 :: CoreBndr
v2 | CoreBndr
v1' CoreBndr -> CoreBndr -> Bool
forall a. Eq a => a -> a -> Bool
== RnEnv2 -> CoreBndr -> CoreBndr
rnOccR RnEnv2
rn_env CoreBndr
v2
              -> RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
              | Var v2' :: CoreBndr
v2' <- SDoc -> Subst -> CoreBndr -> CoreExpr
lookupIdSubst (String -> SDoc
text "match_var") Subst
flt_env CoreBndr
v2
              , CoreBndr
v1' CoreBndr -> CoreBndr -> Bool
forall a. Eq a => a -> a -> Bool
== CoreBndr
v2'
              -> RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
       _ -> Maybe RuleSubst
forall a. Maybe a
Nothing
  where
    v1' :: CoreBndr
v1' = RnEnv2 -> CoreBndr -> CoreBndr
rnOccL RnEnv2
rn_env CoreBndr
v1
        
        
        
        
match_tmpl_var :: RuleMatchEnv
               -> RuleSubst
               -> Var                
               -> CoreExpr              
               -> Maybe RuleSubst
match_tmpl_var :: RuleMatchEnv
-> RuleSubst -> CoreBndr -> CoreExpr -> Maybe RuleSubst
match_tmpl_var renv :: RuleMatchEnv
renv@(RV { rv_lcl :: RuleMatchEnv -> RnEnv2
rv_lcl = RnEnv2
rn_env, rv_fltR :: RuleMatchEnv -> Subst
rv_fltR = Subst
flt_env })
               subst :: RuleSubst
subst@(RS { rs_id_subst :: RuleSubst -> IdSubstEnv
rs_id_subst = IdSubstEnv
id_subst, rs_bndrs :: RuleSubst -> VarSet
rs_bndrs = VarSet
let_bndrs })
               v1' :: CoreBndr
v1' e2 :: CoreExpr
e2
  | (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (RnEnv2 -> CoreBndr -> Bool
inRnEnvR RnEnv2
rn_env) (CoreExpr -> [CoreBndr]
exprFreeVarsList CoreExpr
e2)
  = Maybe RuleSubst
forall a. Maybe a
Nothing     
                
  | Just e1' :: CoreExpr
e1' <- IdSubstEnv -> CoreBndr -> Maybe CoreExpr
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv IdSubstEnv
id_subst CoreBndr
v1'
  = if InScopeSet -> CoreExpr -> CoreExpr -> Bool
eqExpr (RnEnv2 -> InScopeSet
rnInScopeSet RnEnv2
rn_env) CoreExpr
e1' CoreExpr
e2'
    then RuleSubst -> Maybe RuleSubst
forall a. a -> Maybe a
Just RuleSubst
subst
    else Maybe RuleSubst
forall a. Maybe a
Nothing
  | Bool
otherwise
  =             
                
                
                
                
                
                
                
                
                
    do { RuleSubst
subst' <- RuleMatchEnv -> RuleSubst -> Type -> Type -> Maybe RuleSubst
match_ty RuleMatchEnv
renv RuleSubst
subst (CoreBndr -> Type
idType CoreBndr
v1') (CoreExpr -> Type
exprType CoreExpr
e2)
       ; RuleSubst -> Maybe RuleSubst
forall (m :: * -> *) a. Monad m => a -> m a
return (RuleSubst
subst' { rs_id_subst :: IdSubstEnv
rs_id_subst = IdSubstEnv
id_subst' }) }
  where
    
    e2' :: CoreExpr
e2' | VarSet -> Bool
isEmptyVarSet VarSet
let_bndrs = CoreExpr
e2
        | Bool
otherwise = SDoc -> Subst -> CoreExpr -> CoreExpr
substExpr (String -> SDoc
text "match_tmpl_var") Subst
flt_env CoreExpr
e2
    id_subst' :: IdSubstEnv
id_subst' = IdSubstEnv -> CoreBndr -> CoreExpr -> IdSubstEnv
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv (RuleSubst -> IdSubstEnv
rs_id_subst RuleSubst
subst) CoreBndr
v1' CoreExpr
e2'
         
         
match_ty :: RuleMatchEnv
         -> RuleSubst
         -> Type                
         -> Type                
         -> Maybe RuleSubst
match_ty :: RuleMatchEnv -> RuleSubst -> Type -> Type -> Maybe RuleSubst
match_ty renv :: RuleMatchEnv
renv subst :: RuleSubst
subst ty1 :: Type
ty1 ty2 :: Type
ty2
  = do  { TvSubstEnv
tv_subst'
            <- VarSet -> RnEnv2 -> TvSubstEnv -> Type -> Type -> Maybe TvSubstEnv
Unify.ruleMatchTyKiX (RuleMatchEnv -> VarSet
rv_tmpls RuleMatchEnv
renv) (RuleMatchEnv -> RnEnv2
rv_lcl RuleMatchEnv
renv) TvSubstEnv
tv_subst Type
ty1 Type
ty2
        ; RuleSubst -> Maybe RuleSubst
forall (m :: * -> *) a. Monad m => a -> m a
return (RuleSubst
subst { rs_tv_subst :: TvSubstEnv
rs_tv_subst = TvSubstEnv
tv_subst' }) }
  where
    tv_subst :: TvSubstEnv
tv_subst = RuleSubst -> TvSubstEnv
rs_tv_subst RuleSubst
subst
ruleCheckProgram :: CompilerPhase               
                 -> String                      
                 -> (Id -> [CoreRule])          
                 -> CoreProgram                 
                 -> SDoc                        
ruleCheckProgram :: CompilerPhase
-> String -> (CoreBndr -> [CoreRule]) -> [CoreBind] -> SDoc
ruleCheckProgram phase :: CompilerPhase
phase rule_pat :: String
rule_pat rules :: CoreBndr -> [CoreRule]
rules binds :: [CoreBind]
binds
  | Bag SDoc -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag SDoc
results
  = String -> SDoc
text "Rule check results: no rule application sites"
  | Bool
otherwise
  = [SDoc] -> SDoc
vcat [String -> SDoc
text "Rule check results:",
          SDoc
line,
          [SDoc] -> SDoc
vcat [ SDoc
p SDoc -> SDoc -> SDoc
$$ SDoc
line | SDoc
p <- Bag SDoc -> [SDoc]
forall a. Bag a -> [a]
bagToList Bag SDoc
results ]
         ]
  where
    env :: RuleCheckEnv
env = RuleCheckEnv :: (Activation -> Bool)
-> (CoreBndr -> Unfolding)
-> String
-> (CoreBndr -> [CoreRule])
-> RuleCheckEnv
RuleCheckEnv { rc_is_active :: Activation -> Bool
rc_is_active = CompilerPhase -> Activation -> Bool
isActive CompilerPhase
phase
                       , rc_id_unf :: CoreBndr -> Unfolding
rc_id_unf    = CoreBndr -> Unfolding
idUnfolding     
                                                        
                       , rc_pattern :: String
rc_pattern   = String
rule_pat
                       , rc_rules :: CoreBndr -> [CoreRule]
rc_rules = CoreBndr -> [CoreRule]
rules }
    results :: Bag SDoc
results = [Bag SDoc] -> Bag SDoc
forall a. [Bag a] -> Bag a
unionManyBags ((CoreBind -> Bag SDoc) -> [CoreBind] -> [Bag SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (RuleCheckEnv -> CoreBind -> Bag SDoc
ruleCheckBind RuleCheckEnv
env) [CoreBind]
binds)
    line :: SDoc
line = String -> SDoc
text (Arity -> Char -> String
forall a. Arity -> a -> [a]
replicate 20 '-')
data RuleCheckEnv = RuleCheckEnv {
    RuleCheckEnv -> Activation -> Bool
rc_is_active :: Activation -> Bool,
    RuleCheckEnv -> CoreBndr -> Unfolding
rc_id_unf  :: IdUnfoldingFun,
    RuleCheckEnv -> String
rc_pattern :: String,
    RuleCheckEnv -> CoreBndr -> [CoreRule]
rc_rules :: Id -> [CoreRule]
}
ruleCheckBind :: RuleCheckEnv -> CoreBind -> Bag SDoc
   
ruleCheckBind :: RuleCheckEnv -> CoreBind -> Bag SDoc
ruleCheckBind env :: RuleCheckEnv
env (NonRec _ r :: CoreExpr
r) = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
r
ruleCheckBind env :: RuleCheckEnv
env (Rec prs :: [(CoreBndr, CoreExpr)]
prs)    = [Bag SDoc] -> Bag SDoc
forall a. [Bag a] -> Bag a
unionManyBags [RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
r | (_,r :: CoreExpr
r) <- [(CoreBndr, CoreExpr)]
prs]
ruleCheck :: RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck :: RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck _   (Var _)       = Bag SDoc
forall a. Bag a
emptyBag
ruleCheck _   (Lit _)       = Bag SDoc
forall a. Bag a
emptyBag
ruleCheck _   (Type _)      = Bag SDoc
forall a. Bag a
emptyBag
ruleCheck _   (Coercion _)  = Bag SDoc
forall a. Bag a
emptyBag
ruleCheck env :: RuleCheckEnv
env (App f :: CoreExpr
f a :: CoreExpr
a)     = RuleCheckEnv -> CoreExpr -> [CoreExpr] -> Bag SDoc
ruleCheckApp RuleCheckEnv
env (CoreExpr -> CoreExpr -> CoreExpr
forall b. Expr b -> Expr b -> Expr b
App CoreExpr
f CoreExpr
a) []
ruleCheck env :: RuleCheckEnv
env (Tick _ e :: CoreExpr
e)  = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
e
ruleCheck env :: RuleCheckEnv
env (Cast e :: CoreExpr
e _)    = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
e
ruleCheck env :: RuleCheckEnv
env (Let bd :: CoreBind
bd e :: CoreExpr
e)    = RuleCheckEnv -> CoreBind -> Bag SDoc
ruleCheckBind RuleCheckEnv
env CoreBind
bd Bag SDoc -> Bag SDoc -> Bag SDoc
forall a. Bag a -> Bag a -> Bag a
`unionBags` RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
e
ruleCheck env :: RuleCheckEnv
env (Lam _ e :: CoreExpr
e)     = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
e
ruleCheck env :: RuleCheckEnv
env (Case e :: CoreExpr
e _ _ as :: [Alt CoreBndr]
as) = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
e Bag SDoc -> Bag SDoc -> Bag SDoc
forall a. Bag a -> Bag a -> Bag a
`unionBags`
                                [Bag SDoc] -> Bag SDoc
forall a. [Bag a] -> Bag a
unionManyBags [RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
r | (_,_,r :: CoreExpr
r) <- [Alt CoreBndr]
as]
ruleCheckApp :: RuleCheckEnv -> Expr CoreBndr -> [Arg CoreBndr] -> Bag SDoc
ruleCheckApp :: RuleCheckEnv -> CoreExpr -> [CoreExpr] -> Bag SDoc
ruleCheckApp env :: RuleCheckEnv
env (App f :: CoreExpr
f a :: CoreExpr
a) as :: [CoreExpr]
as = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
a Bag SDoc -> Bag SDoc -> Bag SDoc
forall a. Bag a -> Bag a -> Bag a
`unionBags` RuleCheckEnv -> CoreExpr -> [CoreExpr] -> Bag SDoc
ruleCheckApp RuleCheckEnv
env CoreExpr
f (CoreExpr
aCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
as)
ruleCheckApp env :: RuleCheckEnv
env (Var f :: CoreBndr
f) as :: [CoreExpr]
as   = RuleCheckEnv -> CoreBndr -> [CoreExpr] -> Bag SDoc
ruleCheckFun RuleCheckEnv
env CoreBndr
f [CoreExpr]
as
ruleCheckApp env :: RuleCheckEnv
env other :: CoreExpr
other _      = RuleCheckEnv -> CoreExpr -> Bag SDoc
ruleCheck RuleCheckEnv
env CoreExpr
other
ruleCheckFun :: RuleCheckEnv -> Id -> [CoreExpr] -> Bag SDoc
ruleCheckFun :: RuleCheckEnv -> CoreBndr -> [CoreExpr] -> Bag SDoc
ruleCheckFun env :: RuleCheckEnv
env fn :: CoreBndr
fn args :: [CoreExpr]
args
  | [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
name_match_rules = Bag SDoc
forall a. Bag a
emptyBag
  | Bool
otherwise             = SDoc -> Bag SDoc
forall a. a -> Bag a
unitBag (RuleCheckEnv -> CoreBndr -> [CoreExpr] -> [CoreRule] -> SDoc
ruleAppCheck_help RuleCheckEnv
env CoreBndr
fn [CoreExpr]
args [CoreRule]
name_match_rules)
  where
    name_match_rules :: [CoreRule]
name_match_rules = (CoreRule -> Bool) -> [CoreRule] -> [CoreRule]
forall a. (a -> Bool) -> [a] -> [a]
filter CoreRule -> Bool
match (RuleCheckEnv -> CoreBndr -> [CoreRule]
rc_rules RuleCheckEnv
env CoreBndr
fn)
    match :: CoreRule -> Bool
match rule :: CoreRule
rule = (RuleCheckEnv -> String
rc_pattern RuleCheckEnv
env) String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` RuleName -> String
unpackFS (CoreRule -> RuleName
ruleName CoreRule
rule)
ruleAppCheck_help :: RuleCheckEnv -> Id -> [CoreExpr] -> [CoreRule] -> SDoc
ruleAppCheck_help :: RuleCheckEnv -> CoreBndr -> [CoreExpr] -> [CoreRule] -> SDoc
ruleAppCheck_help env :: RuleCheckEnv
env fn :: CoreBndr
fn args :: [CoreExpr]
args rules :: [CoreRule]
rules
  =     
    [SDoc] -> SDoc
vcat [String -> SDoc
text "Expression:" SDoc -> SDoc -> SDoc
<+> CoreExpr -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (CoreBndr -> CoreExpr
forall b. CoreBndr -> Expr b
Var CoreBndr
fn) [CoreExpr]
args),
          [SDoc] -> SDoc
vcat ((CoreRule -> SDoc) -> [CoreRule] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map CoreRule -> SDoc
check_rule [CoreRule]
rules)]
  where
    n_args :: Arity
n_args = [CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
args
    i_args :: [(CoreExpr, Arity)]
i_args = [CoreExpr]
args [CoreExpr] -> [Arity] -> [(CoreExpr, Arity)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [1::Int ..]
    rough_args :: [Maybe Name]
rough_args = (CoreExpr -> Maybe Name) -> [CoreExpr] -> [Maybe Name]
forall a b. (a -> b) -> [a] -> [b]
map CoreExpr -> Maybe Name
roughTopName [CoreExpr]
args
    check_rule :: CoreRule -> SDoc
check_rule rule :: CoreRule
rule = (DynFlags -> SDoc) -> SDoc
sdocWithDynFlags ((DynFlags -> SDoc) -> SDoc) -> (DynFlags -> SDoc) -> SDoc
forall a b. (a -> b) -> a -> b
$ \dflags :: DynFlags
dflags ->
                      CoreRule -> SDoc
rule_herald CoreRule
rule SDoc -> SDoc -> SDoc
<> SDoc
colon SDoc -> SDoc -> SDoc
<+> DynFlags -> CoreRule -> SDoc
rule_info DynFlags
dflags CoreRule
rule
    rule_herald :: CoreRule -> SDoc
rule_herald (BuiltinRule { ru_name :: CoreRule -> RuleName
ru_name = RuleName
name })
        = String -> SDoc
text "Builtin rule" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
doubleQuotes (RuleName -> SDoc
ftext RuleName
name)
    rule_herald (Rule { ru_name :: CoreRule -> RuleName
ru_name = RuleName
name })
        = String -> SDoc
text "Rule" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
doubleQuotes (RuleName -> SDoc
ftext RuleName
name)
    rule_info :: DynFlags -> CoreRule -> SDoc
rule_info dflags :: DynFlags
dflags rule :: CoreRule
rule
        | Just _ <- DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> CoreBndr
-> [CoreExpr]
-> [Maybe Name]
-> CoreRule
-> Maybe CoreExpr
matchRule DynFlags
dflags (InScopeSet
emptyInScopeSet, RuleCheckEnv -> CoreBndr -> Unfolding
rc_id_unf RuleCheckEnv
env)
                              Activation -> Bool
noBlackList CoreBndr
fn [CoreExpr]
args [Maybe Name]
rough_args CoreRule
rule
        = String -> SDoc
text "matches (which is very peculiar!)"
    rule_info _ (BuiltinRule {}) = String -> SDoc
text "does not match"
    rule_info _ (Rule { ru_act :: CoreRule -> Activation
ru_act = Activation
act,
                        ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
rule_bndrs, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
rule_args})
        | Bool -> Bool
not (RuleCheckEnv -> Activation -> Bool
rc_is_active RuleCheckEnv
env Activation
act)  = String -> SDoc
text "active only in later phase"
        | Arity
n_args Arity -> Arity -> Bool
forall a. Ord a => a -> a -> Bool
< Arity
n_rule_args        = String -> SDoc
text "too few arguments"
        | Arity
n_mismatches Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== Arity
n_rule_args = String -> SDoc
text "no arguments match"
        | Arity
n_mismatches Arity -> Arity -> Bool
forall a. Eq a => a -> a -> Bool
== 0           = String -> SDoc
text "all arguments match (considered individually), but rule as a whole does not"
        | Bool
otherwise                   = String -> SDoc
text "arguments" SDoc -> SDoc -> SDoc
<+> [Arity] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Arity]
mismatches SDoc -> SDoc -> SDoc
<+> String -> SDoc
text "do not match (1-indexing)"
        where
          n_rule_args :: Arity
n_rule_args  = [CoreExpr] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [CoreExpr]
rule_args
          n_mismatches :: Arity
n_mismatches = [Arity] -> Arity
forall (t :: * -> *) a. Foldable t => t a -> Arity
length [Arity]
mismatches
          mismatches :: [Arity]
mismatches   = [Arity
i | (rule_arg :: CoreExpr
rule_arg, (arg :: CoreExpr
arg,i :: Arity
i)) <- [CoreExpr]
rule_args [CoreExpr]
-> [(CoreExpr, Arity)] -> [(CoreExpr, (CoreExpr, Arity))]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [(CoreExpr, Arity)]
i_args,
                              Bool -> Bool
not (Maybe RuleSubst -> Bool
forall a. Maybe a -> Bool
isJust (CoreExpr -> CoreExpr -> Maybe RuleSubst
match_fn CoreExpr
rule_arg CoreExpr
arg))]
          lhs_fvs :: VarSet
lhs_fvs = [CoreExpr] -> VarSet
exprsFreeVars [CoreExpr]
rule_args     
          match_fn :: CoreExpr -> CoreExpr -> Maybe RuleSubst
match_fn rule_arg :: CoreExpr
rule_arg arg :: CoreExpr
arg = RuleMatchEnv
-> RuleSubst -> CoreExpr -> CoreExpr -> Maybe RuleSubst
match RuleMatchEnv
renv RuleSubst
emptyRuleSubst CoreExpr
rule_arg CoreExpr
arg
                where
                  in_scope :: InScopeSet
in_scope = VarSet -> InScopeSet
mkInScopeSet (VarSet
lhs_fvs VarSet -> VarSet -> VarSet
`unionVarSet` CoreExpr -> VarSet
exprFreeVars CoreExpr
arg)
                  renv :: RuleMatchEnv
renv = RV :: RnEnv2
-> VarSet -> Subst -> (CoreBndr -> Unfolding) -> RuleMatchEnv
RV { rv_lcl :: RnEnv2
rv_lcl   = InScopeSet -> RnEnv2
mkRnEnv2 InScopeSet
in_scope
                            , rv_tmpls :: VarSet
rv_tmpls = [CoreBndr] -> VarSet
mkVarSet [CoreBndr]
rule_bndrs
                            , rv_fltR :: Subst
rv_fltR  = InScopeSet -> Subst
mkEmptySubst InScopeSet
in_scope
                            , rv_unf :: CoreBndr -> Unfolding
rv_unf   = RuleCheckEnv -> CoreBndr -> Unfolding
rc_id_unf RuleCheckEnv
env }