{-# LANGUAGE CPP #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
#include "../../ClashDebug.h"
module Clash.Core.Subst
(
TvSubst (..)
, TvSubstEnv
, extendTvSubst
, extendTvSubstList
, substTy
, substTyWith
, substTyInVar
, Subst (..)
, mkSubst
, mkTvSubst
, extendInScopeId
, extendInScopeIdList
, extendIdSubst
, extendIdSubstList
, extendGblSubstList
, substTm
, deShadowTerm
, freshenTm
, aeqType
, aeqTerm
)
where
import Data.Coerce (coerce)
import Data.Text.Prettyprint.Doc
import qualified Data.List as List
import Clash.Core.FreeVars
(noFreeVarsOfType, localFVsOfTerms, tyFVsOfTypes)
import Clash.Core.Pretty (ppr, fromPpr)
import Clash.Core.Term
(LetBinding, Pat (..), Term (..), TickInfo (..))
import Clash.Core.Type (Type (..))
import Clash.Core.VarEnv
import Clash.Core.Var (Id, Var (..), TyVar, isGlobalId)
import Clash.Unique
import Clash.Util
import Clash.Pretty
type TvSubstEnv = VarEnv Type
data TvSubst
= TvSubst InScopeSet
TvSubstEnv
instance ClashPretty TvSubst where
clashPretty :: TvSubst -> Doc ()
clashPretty (TvSubst ins :: InScopeSet
ins tenv :: TvSubstEnv
tenv) =
Doc () -> Doc ()
forall ann. Doc ann -> Doc ann
brackets (Doc () -> Doc ()) -> Doc () -> Doc ()
forall a b. (a -> b) -> a -> b
$ [Doc ()] -> Doc ()
forall ann. [Doc ann] -> Doc ann
sep [ "TvSubst"
, Int -> Doc () -> Doc ()
forall ann. Int -> Doc ann -> Doc ann
nest 2 ("In scope:" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> InScopeSet -> Doc ()
forall a. ClashPretty a => a -> Doc ()
clashPretty InScopeSet
ins)
, Int -> Doc () -> Doc ()
forall ann. Int -> Doc ann -> Doc ann
nest 2 ("Type env:" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> TvSubstEnv -> Doc ()
forall a. ClashPretty a => a -> Doc ()
clashPretty TvSubstEnv
tenv)]
type IdSubstEnv = VarEnv Term
data Subst
= Subst
{ Subst -> InScopeSet
substInScope :: InScopeSet
, Subst -> IdSubstEnv
substTmEnv :: IdSubstEnv
, Subst -> TvSubstEnv
substTyEnv :: TvSubstEnv
, Subst -> IdSubstEnv
substGblEnv :: IdSubstEnv
}
emptySubst
:: Subst
emptySubst :: Subst
emptySubst = InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
emptyInScopeSet IdSubstEnv
forall a. VarEnv a
emptyVarEnv TvSubstEnv
forall a. VarEnv a
emptyVarEnv IdSubstEnv
forall a. VarEnv a
emptyVarEnv
mkSubst
:: InScopeSet
-> Subst
mkSubst :: InScopeSet -> Subst
mkSubst is :: InScopeSet
is = InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is IdSubstEnv
forall a. VarEnv a
emptyVarEnv TvSubstEnv
forall a. VarEnv a
emptyVarEnv IdSubstEnv
forall a. VarEnv a
emptyVarEnv
mkTvSubst
:: InScopeSet
-> VarEnv Type
-> Subst
mkTvSubst :: InScopeSet -> TvSubstEnv -> Subst
mkTvSubst is :: InScopeSet
is env :: TvSubstEnv
env = InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is IdSubstEnv
forall a. VarEnv a
emptyVarEnv TvSubstEnv
env IdSubstEnv
forall a. VarEnv a
emptyVarEnv
zipTvSubst
:: [TyVar]
-> [Type]
-> Subst
zipTvSubst :: [TyVar] -> [Type] -> Subst
zipTvSubst tvs :: [TyVar]
tvs tys :: [Type]
tys
| Bool
debugIsOn
, [TyVar] -> [Type] -> Bool
forall a b. [a] -> [b] -> Bool
neLength [TyVar]
tvs [Type]
tys
= String -> Doc ClashAnnotation -> Subst -> Subst
forall ann a. String -> Doc ann -> a -> a
pprTrace "zipTvSubst" ([TyVar] -> Doc ClashAnnotation
forall p. PrettyPrec p => p -> Doc ClashAnnotation
ppr [TyVar]
tvs Doc ClashAnnotation -> Doc ClashAnnotation -> Doc ClashAnnotation
forall a. Semigroup a => a -> a -> a
<> Doc ClashAnnotation
forall ann. Doc ann
line Doc ClashAnnotation -> Doc ClashAnnotation -> Doc ClashAnnotation
forall a. Semigroup a => a -> a -> a
<> [Type] -> Doc ClashAnnotation
forall p. PrettyPrec p => p -> Doc ClashAnnotation
ppr [Type]
tys) Subst
emptySubst
| Bool
otherwise
= InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst (VarSet -> InScopeSet
mkInScopeSet ([Type] -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes [Type]
tys)) IdSubstEnv
forall a. VarEnv a
emptyVarEnv TvSubstEnv
tenv IdSubstEnv
forall a. VarEnv a
emptyVarEnv
where
tenv :: TvSubstEnv
tenv = [TyVar] -> [Type] -> TvSubstEnv
zipTyEnv [TyVar]
tvs [Type]
tys
zipTyEnv
:: [TyVar]
-> [Type]
-> VarEnv Type
zipTyEnv :: [TyVar] -> [Type] -> TvSubstEnv
zipTyEnv tvs :: [TyVar]
tvs tys :: [Type]
tys = [(TyVar, Type)] -> TvSubstEnv
forall a b. [(Var a, b)] -> VarEnv b
mkVarEnv ([TyVar] -> [Type] -> [(TyVar, Type)]
forall a b. [a] -> [b] -> [(a, b)]
zipEqual [TyVar]
tvs [Type]
tys)
extendIdSubst
:: Subst
-> Id
-> Term
-> Subst
extendIdSubst :: Subst -> Id -> Term -> Subst
extendIdSubst (Subst is :: InScopeSet
is env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) i :: Id
i e :: Term
e =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is (Id -> Term -> IdSubstEnv -> IdSubstEnv
forall b a. Var b -> a -> VarEnv a -> VarEnv a
extendVarEnv Id
i Term
e IdSubstEnv
env) TvSubstEnv
tenv IdSubstEnv
genv
extendIdSubstList
:: Subst
-> [(Id,Term)]
-> Subst
extendIdSubstList :: Subst -> [(Id, Term)] -> Subst
extendIdSubstList (Subst is :: InScopeSet
is env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) es :: [(Id, Term)]
es =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is (IdSubstEnv -> [(Id, Term)] -> IdSubstEnv
forall a b. VarEnv a -> [(Var b, a)] -> VarEnv a
extendVarEnvList IdSubstEnv
env [(Id, Term)]
es) TvSubstEnv
tenv IdSubstEnv
genv
extendGblSubstList
:: Subst
-> [(Id,Term)]
-> Subst
extendGblSubstList :: Subst -> [(Id, Term)] -> Subst
extendGblSubstList (Subst is :: InScopeSet
is env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) es :: [(Id, Term)]
es =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is IdSubstEnv
env TvSubstEnv
tenv (IdSubstEnv -> [(Id, Term)] -> IdSubstEnv
forall a b. VarEnv a -> [(Var b, a)] -> VarEnv a
extendVarEnvList IdSubstEnv
genv [(Id, Term)]
es)
extendTvSubst
:: Subst
-> TyVar
-> Type
-> Subst
extendTvSubst :: Subst -> TyVar -> Type -> Subst
extendTvSubst (Subst is :: InScopeSet
is env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) tv :: TyVar
tv t :: Type
t =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is IdSubstEnv
env (TyVar -> Type -> TvSubstEnv -> TvSubstEnv
forall b a. Var b -> a -> VarEnv a -> VarEnv a
extendVarEnv TyVar
tv Type
t TvSubstEnv
tenv) IdSubstEnv
genv
extendTvSubstList
:: Subst
-> [(TyVar, Type)]
-> Subst
extendTvSubstList :: Subst -> [(TyVar, Type)] -> Subst
extendTvSubstList (Subst is :: InScopeSet
is env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) ts :: [(TyVar, Type)]
ts =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
is IdSubstEnv
env (TvSubstEnv -> [(TyVar, Type)] -> TvSubstEnv
forall a b. VarEnv a -> [(Var b, a)] -> VarEnv a
extendVarEnvList TvSubstEnv
tenv [(TyVar, Type)]
ts) IdSubstEnv
genv
extendInScopeId
:: Subst
-> Id
-> Subst
extendInScopeId :: Subst -> Id -> Subst
extendInScopeId (Subst inScope :: InScopeSet
inScope env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) id' :: Id
id' =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
inScope' IdSubstEnv
env' TvSubstEnv
tenv IdSubstEnv
genv
where
inScope' :: InScopeSet
inScope' = InScopeSet -> Id -> InScopeSet
forall a. InScopeSet -> Var a -> InScopeSet
extendInScopeSet InScopeSet
inScope Id
id'
env' :: IdSubstEnv
env' = IdSubstEnv -> Id -> IdSubstEnv
forall a b. VarEnv a -> Var b -> VarEnv a
delVarEnv IdSubstEnv
env Id
id'
extendInScopeIdList
:: Subst
-> [Id]
-> Subst
extendInScopeIdList :: Subst -> [Id] -> Subst
extendInScopeIdList (Subst inScope :: InScopeSet
inScope env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) ids :: [Id]
ids =
InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
inScope' IdSubstEnv
env' TvSubstEnv
tenv IdSubstEnv
genv
where
inScope' :: InScopeSet
inScope' = InScopeSet -> [Id] -> InScopeSet
forall a. InScopeSet -> [Var a] -> InScopeSet
extendInScopeSetList InScopeSet
inScope [Id]
ids
env' :: IdSubstEnv
env' = IdSubstEnv -> [Id] -> IdSubstEnv
forall a b. VarEnv a -> [Var b] -> VarEnv a
delVarEnvList IdSubstEnv
env [Id]
ids
substTy
:: HasCallStack
=> Subst
-> Type
-> Type
substTy :: Subst -> Type -> Type
substTy (Subst inScope :: InScopeSet
inScope _ tvS :: TvSubstEnv
tvS _) ty :: Type
ty
| TvSubstEnv -> Bool
forall a. VarEnv a -> Bool
nullVarEnv TvSubstEnv
tvS
= Type
ty
| Bool
otherwise
= TvSubst -> [Type] -> Type -> Type
forall a. HasCallStack => TvSubst -> [Type] -> a -> a
checkValidSubst TvSubst
s' [Type
ty] (HasCallStack => TvSubst -> Type -> Type
TvSubst -> Type -> Type
substTy' TvSubst
s' Type
ty)
where
s' :: TvSubst
s' = InScopeSet -> TvSubstEnv -> TvSubst
TvSubst InScopeSet
inScope TvSubstEnv
tvS
substTyInVar
:: HasCallStack
=> Subst
-> Var a
-> Var a
substTyInVar :: Subst -> Var a -> Var a
substTyInVar subst :: Subst
subst tyVar :: Var a
tyVar =
Var a
tyVar { varType :: Type
varType = (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst (Var a -> Type
forall a. Var a -> Type
varType Var a
tyVar)) }
substTyUnchecked
:: HasCallStack
=> TvSubst
-> Type
-> Type
substTyUnchecked :: TvSubst -> Type -> Type
substTyUnchecked subst :: TvSubst
subst@(TvSubst _ tvS :: TvSubstEnv
tvS) ty :: Type
ty
| TvSubstEnv -> Bool
forall a. VarEnv a -> Bool
nullVarEnv TvSubstEnv
tvS
= Type
ty
| Bool
otherwise
= HasCallStack => TvSubst -> Type -> Type
TvSubst -> Type -> Type
substTy' TvSubst
subst Type
ty
checkValidSubst
:: HasCallStack
=> TvSubst
-> [Type]
-> a
-> a
checkValidSubst :: TvSubst -> [Type] -> a -> a
checkValidSubst subst :: TvSubst
subst@(TvSubst inScope :: InScopeSet
inScope tenv :: TvSubstEnv
tenv) tys :: [Type]
tys a :: a
a =
WARN( not (isValidSubst subst),
"inScope" <+> clashPretty inScope <> line <>
"tenv" <+> clashPretty tenv <> line <>
"tenvFVs" <+> clashPretty (tyFVsOfTypes tenv) <> line <>
"tys" <+> fromPpr tys)
WARN( not tysFVsInSope,
"inScope" <+> clashPretty inScope <> line <>
"tenv" <+> clashPretty tenv <> line <>
"tys" <+> fromPpr tys <> line <>
"needsInScope" <+> clashPretty needsInScope)
a
a
where
needsInScope :: VarSet
needsInScope = (Int -> Type -> VarSet -> VarSet) -> VarSet -> TvSubstEnv -> VarSet
forall a b. (Int -> a -> b -> b) -> b -> UniqMap a -> b
foldrWithUnique (\k :: Int
k _ s :: VarSet
s -> Int -> VarSet -> VarSet
delVarSetByKey Int
k VarSet
s)
([Type] -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes [Type]
tys)
TvSubstEnv
tenv
tysFVsInSope :: Bool
tysFVsInSope = VarSet
needsInScope VarSet -> InScopeSet -> Bool
`varSetInScope` InScopeSet
inScope
isValidSubst
:: TvSubst
-> Bool
isValidSubst :: TvSubst -> Bool
isValidSubst (TvSubst inScope :: InScopeSet
inScope tenv :: TvSubstEnv
tenv) = VarSet
tenvFVs VarSet -> InScopeSet -> Bool
`varSetInScope` InScopeSet
inScope
where
tenvFVs :: VarSet
tenvFVs = TvSubstEnv -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes TvSubstEnv
tenv
substTy'
:: HasCallStack
=> TvSubst
-> Type
-> Type
substTy' :: TvSubst -> Type -> Type
substTy' subst :: TvSubst
subst = Type -> Type
go where
go :: Type -> Type
go = \case
VarTy tv :: TyVar
tv -> TvSubst -> TyVar -> Type
substTyVar TvSubst
subst TyVar
tv
ForAllTy tv :: TyVar
tv ty :: Type
ty -> case TvSubst -> TyVar -> (TvSubst, TyVar)
substTyVarBndr TvSubst
subst TyVar
tv of
(subst' :: TvSubst
subst', tv' :: TyVar
tv') -> TyVar -> Type -> Type
ForAllTy TyVar
tv' (HasCallStack => TvSubst -> Type -> Type
TvSubst -> Type -> Type
substTy' TvSubst
subst' Type
ty)
AppTy fun :: Type
fun arg :: Type
arg -> Type -> Type -> Type
AppTy (Type -> Type
go Type
fun) (Type -> Type
go Type
arg)
ty :: Type
ty -> Type
ty
substTyVar
:: TvSubst
-> TyVar
-> Type
substTyVar :: TvSubst -> TyVar -> Type
substTyVar (TvSubst _ tenv :: TvSubstEnv
tenv) tv :: TyVar
tv = case TyVar -> TvSubstEnv -> Maybe Type
forall b a. Var b -> VarEnv a -> Maybe a
lookupVarEnv TyVar
tv TvSubstEnv
tenv of
Just ty :: Type
ty -> Type
ty
_ -> TyVar -> Type
VarTy TyVar
tv
substTyVarBndr
:: TvSubst
-> TyVar
-> (TvSubst, TyVar)
substTyVarBndr :: TvSubst -> TyVar -> (TvSubst, TyVar)
substTyVarBndr subst :: TvSubst
subst@(TvSubst inScope :: InScopeSet
inScope tenv :: TvSubstEnv
tenv) oldVar :: TyVar
oldVar =
ASSERT2( no_capture, clashPretty oldVar <> line
<> clashPretty newVar <> line
<> clashPretty subst )
(InScopeSet -> TvSubstEnv -> TvSubst
TvSubst (InScopeSet
inScope InScopeSet -> TyVar -> InScopeSet
forall a. InScopeSet -> Var a -> InScopeSet
`extendInScopeSet` TyVar
newVar) TvSubstEnv
newEnv, TyVar
newVar)
where
newEnv :: TvSubstEnv
newEnv | Bool
noChange = TvSubstEnv -> TyVar -> TvSubstEnv
forall a b. VarEnv a -> Var b -> VarEnv a
delVarEnv TvSubstEnv
tenv TyVar
oldVar
| Bool
otherwise = TyVar -> Type -> TvSubstEnv -> TvSubstEnv
forall b a. Var b -> a -> VarEnv a -> VarEnv a
extendVarEnv TyVar
oldVar (TyVar -> Type
VarTy TyVar
newVar) TvSubstEnv
tenv
no_capture :: Bool
no_capture = Bool -> Bool
not (TyVar
newVar TyVar -> VarSet -> Bool
forall a. Var a -> VarSet -> Bool
`elemVarSet` TvSubstEnv -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes TvSubstEnv
tenv)
oldKi :: Type
oldKi = TyVar -> Type
forall a. Var a -> Type
varType TyVar
oldVar
noKindChange :: Bool
noKindChange = Type -> Bool
noFreeVarsOfType Type
oldKi
noChange :: Bool
noChange = Bool
noKindChange Bool -> Bool -> Bool
&& (TyVar
newVar TyVar -> TyVar -> Bool
forall a. Eq a => a -> a -> Bool
== TyVar
oldVar)
newVar :: TyVar
newVar | Bool
noKindChange = InScopeSet -> TyVar -> TyVar
forall a. InScopeSet -> Var a -> Var a
uniqAway InScopeSet
inScope TyVar
oldVar
| Bool
otherwise = InScopeSet -> TyVar -> TyVar
forall a. InScopeSet -> Var a -> Var a
uniqAway InScopeSet
inScope
(TyVar
oldVar {varType :: Type
varType = HasCallStack => TvSubst -> Type -> Type
TvSubst -> Type -> Type
substTyUnchecked TvSubst
subst Type
oldKi})
substTm
:: HasCallStack
=> Doc ()
-> Subst
-> Term
-> Term
substTm :: Doc () -> Subst -> Term -> Term
substTm doc :: Doc ()
doc subst :: Subst
subst = Term -> Term
go where
go :: Term -> Term
go = \case
Var v :: Id
v -> HasCallStack => Doc () -> Subst -> Id -> Term
Doc () -> Subst -> Id -> Term
lookupIdSubst (Doc ()
doc Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> Doc ()
forall ann. Doc ann
line Doc () -> Doc () -> Doc ()
forall a. Semigroup a => a -> a -> a
<> "subsTm") Subst
subst Id
v
Lam v :: Id
v e :: Term
e -> case HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst Id
v of
(subst' :: Subst
subst',v' :: Id
v') -> Id -> Term -> Term
Lam Id
v' (HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm Doc ()
doc Subst
subst' Term
e)
TyLam v :: TyVar
v e :: Term
e -> case HasCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
substTyVarBndr' Subst
subst TyVar
v of
(subst' :: Subst
subst',v' :: TyVar
v') -> TyVar -> Term -> Term
TyLam TyVar
v' (HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm Doc ()
doc Subst
subst' Term
e)
App l :: Term
l r :: Term
r -> Term -> Term -> Term
App (Term -> Term
go Term
l) (Term -> Term
go Term
r)
TyApp l :: Term
l r :: Type
r -> Term -> Type -> Term
TyApp (Term -> Term
go Term
l) (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
r)
Letrec bs :: [(Id, Term)]
bs e :: Term
e -> case HasCallStack =>
Doc () -> Subst -> [(Id, Term)] -> (Subst, [(Id, Term)])
Doc () -> Subst -> [(Id, Term)] -> (Subst, [(Id, Term)])
substBind Doc ()
doc Subst
subst [(Id, Term)]
bs of
(subst' :: Subst
subst',bs' :: [(Id, Term)]
bs') -> [(Id, Term)] -> Term -> Term
Letrec [(Id, Term)]
bs' (HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm Doc ()
doc Subst
subst' Term
e)
Case subj :: Term
subj ty :: Type
ty alts :: [Alt]
alts -> Term -> Type -> [Alt] -> Term
Case (Term -> Term
go Term
subj) (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
ty) ((Alt -> Alt) -> [Alt] -> [Alt]
forall a b. (a -> b) -> [a] -> [b]
map Alt -> Alt
goAlt [Alt]
alts)
Cast e :: Term
e t1 :: Type
t1 t2 :: Type
t2 -> Term -> Type -> Type -> Term
Cast (Term -> Term
go Term
e) (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
t1) (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
t2)
Tick tick :: TickInfo
tick e :: Term
e -> TickInfo -> Term -> Term
Tick (TickInfo -> TickInfo
goTick TickInfo
tick) (Term -> Term
go Term
e)
tm :: Term
tm -> Term
tm
goAlt :: Alt -> Alt
goAlt (pat :: Pat
pat,alt :: Term
alt) = case Pat
pat of
DataPat dc :: DataCon
dc tvs :: [TyVar]
tvs ids :: [Id]
ids -> case (Subst -> TyVar -> (Subst, TyVar))
-> Subst -> [TyVar] -> (Subst, [TyVar])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
substTyVarBndr' Subst
subst [TyVar]
tvs of
(subst1 :: Subst
subst1,tvs' :: [TyVar]
tvs') -> case (Subst -> Id -> (Subst, Id)) -> Subst -> [Id] -> (Subst, [Id])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst1 [Id]
ids of
(subst2 :: Subst
subst2,ids' :: [Id]
ids') -> (DataCon -> [TyVar] -> [Id] -> Pat
DataPat DataCon
dc [TyVar]
tvs' [Id]
ids',HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm Doc ()
doc Subst
subst2 Term
alt)
_ -> (Pat
pat,Term -> Term
go Term
alt)
goTick :: TickInfo -> TickInfo
goTick t :: TickInfo
t@(SrcSpan _) = TickInfo
t
goTick (NameMod m :: NameMod
m ty :: Type
ty) = NameMod -> Type -> TickInfo
NameMod NameMod
m (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
ty)
lookupIdSubst
:: HasCallStack
=> Doc ()
-> Subst
-> Id
-> Term
lookupIdSubst :: Doc () -> Subst -> Id -> Term
lookupIdSubst doc :: Doc ()
doc (Subst inScope :: InScopeSet
inScope tmS :: IdSubstEnv
tmS _ genv :: IdSubstEnv
genv) v :: Id
v
| Id -> Bool
forall a. Var a -> Bool
isGlobalId Id
v = case Id -> IdSubstEnv -> Maybe Term
forall b a. Var b -> VarEnv a -> Maybe a
lookupVarEnv Id
v IdSubstEnv
genv of
Just e :: Term
e -> Term
e
_ -> Id -> Term
Var Id
v
| Just e :: Term
e <- Id -> IdSubstEnv -> Maybe Term
forall b a. Var b -> VarEnv a -> Maybe a
lookupVarEnv Id
v IdSubstEnv
tmS = Term
e
| Just v' :: Var Any
v' <- InScopeSet -> Id -> Maybe (Var Any)
forall a. InScopeSet -> Var a -> Maybe (Var Any)
lookupInScope InScopeSet
inScope Id
v = Id -> Term
Var (Var Any -> Id
forall a b. Coercible a b => a -> b
coerce Var Any
v')
| Bool
otherwise = WARN(True, "Subst.lookupIdSubst" <+> doc <+> fromPpr v)
Id -> Term
Var Id
v
substIdBndr
:: HasCallStack
=> Subst
-> Id
-> (Subst,Id)
substIdBndr :: Subst -> Id -> (Subst, Id)
substIdBndr subst :: Subst
subst@(Subst inScope :: InScopeSet
inScope env :: IdSubstEnv
env tenv :: TvSubstEnv
tenv genv :: IdSubstEnv
genv) oldId :: Id
oldId =
(InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst (InScopeSet
inScope InScopeSet -> Id -> InScopeSet
forall a. InScopeSet -> Var a -> InScopeSet
`extendInScopeSet` Id
newId) IdSubstEnv
newEnv TvSubstEnv
tenv IdSubstEnv
genv, Id
newId)
where
id1 :: Id
id1 = InScopeSet -> Id -> Id
forall a. InScopeSet -> Var a -> Var a
uniqAway InScopeSet
inScope Id
oldId
newId :: Id
newId | Bool
noTypeChange = Id
id1
| Bool
otherwise = Id
id1 {varType :: Type
varType = HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst (Id -> Type
forall a. Var a -> Type
varType Id
id1)}
oldTy :: Type
oldTy = Id -> Type
forall a. Var a -> Type
varType Id
oldId
noTypeChange :: Bool
noTypeChange = TvSubstEnv -> Bool
forall a. VarEnv a -> Bool
nullVarEnv TvSubstEnv
tenv Bool -> Bool -> Bool
|| Type -> Bool
noFreeVarsOfType Type
oldTy
newEnv :: IdSubstEnv
newEnv | Bool
noChange = IdSubstEnv -> Id -> IdSubstEnv
forall a b. VarEnv a -> Var b -> VarEnv a
delVarEnv IdSubstEnv
env Id
oldId
| Bool
otherwise = Id -> Term -> IdSubstEnv -> IdSubstEnv
forall b a. Var b -> a -> VarEnv a -> VarEnv a
extendVarEnv Id
oldId (Id -> Term
Var Id
newId) IdSubstEnv
env
noChange :: Bool
noChange = Id
id1 Id -> Id -> Bool
forall a. Eq a => a -> a -> Bool
== Id
oldId
substTyVarBndr'
:: HasCallStack
=> Subst
-> TyVar
-> (Subst,TyVar)
substTyVarBndr' :: Subst -> TyVar -> (Subst, TyVar)
substTyVarBndr' (Subst inScope :: InScopeSet
inScope tmS :: IdSubstEnv
tmS tyS :: TvSubstEnv
tyS tgS :: IdSubstEnv
tgS) tv :: TyVar
tv =
case TvSubst -> TyVar -> (TvSubst, TyVar)
substTyVarBndr (InScopeSet -> TvSubstEnv -> TvSubst
TvSubst InScopeSet
inScope TvSubstEnv
tyS) TyVar
tv of
(TvSubst inScope' :: InScopeSet
inScope' tyS' :: TvSubstEnv
tyS',tv' :: TyVar
tv') -> (InScopeSet -> IdSubstEnv -> TvSubstEnv -> IdSubstEnv -> Subst
Subst InScopeSet
inScope' IdSubstEnv
tmS TvSubstEnv
tyS' IdSubstEnv
tgS, TyVar
tv')
substBind
:: HasCallStack
=> Doc ()
-> Subst
-> [LetBinding]
-> (Subst,[LetBinding])
substBind :: Doc () -> Subst -> [(Id, Term)] -> (Subst, [(Id, Term)])
substBind doc :: Doc ()
doc subst :: Subst
subst xs :: [(Id, Term)]
xs =
(Subst
subst',[Id] -> [Term] -> [(Id, Term)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Id]
bndrs' [Term]
rhss')
where
(bndrs :: [Id]
bndrs,rhss :: [Term]
rhss) = [(Id, Term)] -> ([Id], [Term])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Term)]
xs
(subst' :: Subst
subst',bndrs' :: [Id]
bndrs') = (Subst -> Id -> (Subst, Id)) -> Subst -> [Id] -> (Subst, [Id])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst [Id]
bndrs
rhss' :: [Term]
rhss' = (Term -> Term) -> [Term] -> [Term]
forall a b. (a -> b) -> [a] -> [b]
map (HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm ("substBind" Doc () -> Doc () -> Doc ()
forall ann. Doc ann -> Doc ann -> Doc ann
<+> Doc ()
doc) Subst
subst') [Term]
rhss
substTyWith
:: HasCallStack
=> [TyVar]
-> [Type]
-> Type
-> Type
substTyWith :: [TyVar] -> [Type] -> Type -> Type
substTyWith tvs :: [TyVar]
tvs tys :: [Type]
tys =
ASSERT( tvs `equalLength` tys )
HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy ([TyVar] -> [Type] -> Subst
zipTvSubst [TyVar]
tvs [Type]
tys)
deShadowTerm
:: HasCallStack
=> InScopeSet
-> Term
-> Term
deShadowTerm :: InScopeSet -> Term -> Term
deShadowTerm is :: InScopeSet
is e :: Term
e = HasCallStack => Doc () -> Subst -> Term -> Term
Doc () -> Subst -> Term -> Term
substTm "deShadowTerm" (InScopeSet -> Subst
mkSubst InScopeSet
is) Term
e
freshenTm
:: InScopeSet
-> Term
-> (InScopeSet, Term)
freshenTm :: InScopeSet -> Term -> (InScopeSet, Term)
freshenTm is0 :: InScopeSet
is0 = Subst -> Term -> (InScopeSet, Term)
go (InScopeSet -> Subst
mkSubst InScopeSet
is0) where
go :: Subst -> Term -> (InScopeSet, Term)
go subst0 :: Subst
subst0 = \case
Var v :: Id
v -> (Subst -> InScopeSet
substInScope Subst
subst0, HasCallStack => Doc () -> Subst -> Id -> Term
Doc () -> Subst -> Id -> Term
lookupIdSubst "freshenTm" Subst
subst0 Id
v)
Lam v :: Id
v e :: Term
e -> case HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst0 Id
v of
(subst1 :: Subst
subst1,v' :: Id
v') -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst1 Term
e of
(is2 :: InScopeSet
is2,e' :: Term
e') -> (InScopeSet
is2, Id -> Term -> Term
Lam Id
v' Term
e')
TyLam v :: TyVar
v e :: Term
e -> case HasCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
substTyVarBndr' Subst
subst0 TyVar
v of
(subst1 :: Subst
subst1,v' :: TyVar
v') -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst1 Term
e of
(is2 :: InScopeSet
is2,e' :: Term
e') -> (InScopeSet
is2,TyVar -> Term -> Term
TyLam TyVar
v' Term
e')
App l :: Term
l r :: Term
r -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
l of
(is1 :: InScopeSet
is1,l' :: Term
l') -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 {substInScope :: InScopeSet
substInScope = InScopeSet
is1} Term
r of
(is2 :: InScopeSet
is2,r' :: Term
r') -> (InScopeSet
is2, Term -> Term -> Term
App Term
l' Term
r')
TyApp l :: Term
l r :: Type
r -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
l of
(is1 :: InScopeSet
is1,l' :: Term
l') -> (InScopeSet
is1, Term -> Type -> Term
TyApp Term
l' (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst0 Type
r))
Letrec bs :: [(Id, Term)]
bs e :: Term
e -> case Subst -> [(Id, Term)] -> (Subst, [(Id, Term)])
goBind Subst
subst0 [(Id, Term)]
bs of
(subst1 :: Subst
subst1,bs' :: [(Id, Term)]
bs') -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst1 Term
e of
(is2 :: InScopeSet
is2,e' :: Term
e') -> (InScopeSet
is2,[(Id, Term)] -> Term -> Term
Letrec [(Id, Term)]
bs' Term
e')
Case subj :: Term
subj ty :: Type
ty alts :: [Alt]
alts -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
subj of
(is1 :: InScopeSet
is1,subj' :: Term
subj') -> case (InScopeSet -> Alt -> (InScopeSet, Alt))
-> InScopeSet -> [Alt] -> (InScopeSet, [Alt])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL (\isN :: InScopeSet
isN -> Subst -> Alt -> (InScopeSet, Alt)
goAlt Subst
subst0 {substInScope :: InScopeSet
substInScope = InScopeSet
isN}) InScopeSet
is1 [Alt]
alts of
(is2 :: InScopeSet
is2,alts' :: [Alt]
alts') -> (InScopeSet
is2, Term -> Type -> [Alt] -> Term
Case Term
subj' (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst0 Type
ty) [Alt]
alts')
Cast e :: Term
e t1 :: Type
t1 t2 :: Type
t2 -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
e of
(is1 :: InScopeSet
is1, e' :: Term
e') -> (InScopeSet
is1, Term -> Type -> Type -> Term
Cast Term
e' (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst0 Type
t1) (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst0 Type
t2))
Tick tick :: TickInfo
tick e :: Term
e -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
e of
(is1 :: InScopeSet
is1, e' :: Term
e') -> (InScopeSet
is1, TickInfo -> Term -> Term
Tick (Subst -> TickInfo -> TickInfo
goTick Subst
subst0 TickInfo
tick) Term
e')
tm :: Term
tm -> (Subst -> InScopeSet
substInScope Subst
subst0, Term
tm)
goBind :: Subst -> [(Id, Term)] -> (Subst, [(Id, Term)])
goBind subst0 :: Subst
subst0 xs :: [(Id, Term)]
xs =
let (bndrs :: [Id]
bndrs,rhss :: [Term]
rhss) = [(Id, Term)] -> ([Id], [Term])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Term)]
xs
(subst1 :: Subst
subst1,bndrs' :: [Id]
bndrs') = (Subst -> Id -> (Subst, Id)) -> Subst -> [Id] -> (Subst, [Id])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst0 [Id]
bndrs
(is2 :: InScopeSet
is2,rhss' :: [Term]
rhss') = (InScopeSet -> Term -> (InScopeSet, Term))
-> InScopeSet -> [Term] -> (InScopeSet, [Term])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL (\isN :: InScopeSet
isN -> Subst -> Term -> (InScopeSet, Term)
go Subst
subst1 {substInScope :: InScopeSet
substInScope = InScopeSet
isN})
(Subst -> InScopeSet
substInScope Subst
subst1)
[Term]
rhss
in (Subst
subst1 {substInScope :: InScopeSet
substInScope = InScopeSet
is2},[Id] -> [Term] -> [(Id, Term)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Id]
bndrs' [Term]
rhss')
goAlt :: Subst -> Alt -> (InScopeSet, Alt)
goAlt subst0 :: Subst
subst0 (pat :: Pat
pat,alt :: Term
alt) = case Pat
pat of
DataPat dc :: DataCon
dc tvs :: [TyVar]
tvs ids :: [Id]
ids -> case (Subst -> TyVar -> (Subst, TyVar))
-> Subst -> [TyVar] -> (Subst, [TyVar])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> TyVar -> (Subst, TyVar)
Subst -> TyVar -> (Subst, TyVar)
substTyVarBndr' Subst
subst0 [TyVar]
tvs of
(subst1 :: Subst
subst1,tvs' :: [TyVar]
tvs') -> case (Subst -> Id -> (Subst, Id)) -> Subst -> [Id] -> (Subst, [Id])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
List.mapAccumL HasCallStack => Subst -> Id -> (Subst, Id)
Subst -> Id -> (Subst, Id)
substIdBndr Subst
subst1 [Id]
ids of
(subst2 :: Subst
subst2,ids' :: [Id]
ids') -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst2 Term
alt of
(is3 :: InScopeSet
is3,alt' :: Term
alt') -> (InScopeSet
is3,(DataCon -> [TyVar] -> [Id] -> Pat
DataPat DataCon
dc [TyVar]
tvs' [Id]
ids',Term
alt'))
_ -> case Subst -> Term -> (InScopeSet, Term)
go Subst
subst0 Term
alt of
(is1 :: InScopeSet
is1,alt' :: Term
alt') -> (InScopeSet
is1,(Pat
pat,Term
alt'))
goTick :: Subst -> TickInfo -> TickInfo
goTick subst0 :: Subst
subst0 (NameMod m :: NameMod
m ty :: Type
ty) = NameMod -> Type -> TickInfo
NameMod NameMod
m (HasCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst0 Type
ty)
goTick _ tick :: TickInfo
tick = TickInfo
tick
aeqType
:: Type
-> Type
-> Bool
aeqType :: Type -> Type -> Bool
aeqType t1 :: Type
t1 t2 :: Type
t2 = RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
rnEnv Type
t1 Type
t2 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ
where
rnEnv :: RnEnv
rnEnv = InScopeSet -> RnEnv
mkRnEnv (VarSet -> InScopeSet
mkInScopeSet ([Type] -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes [Type
t1,Type
t2]))
acmpType
:: Type
-> Type
-> Ordering
acmpType :: Type -> Type -> Ordering
acmpType t1 :: Type
t1 t2 :: Type
t2 = RnEnv -> Type -> Type -> Ordering
acmpType' (InScopeSet -> RnEnv
mkRnEnv InScopeSet
inScope) Type
t1 Type
t2
where
inScope :: InScopeSet
inScope = VarSet -> InScopeSet
mkInScopeSet ([Type] -> VarSet
forall (f :: * -> *). Foldable f => f Type -> VarSet
tyFVsOfTypes [Type
t1,Type
t2])
acmpType'
:: RnEnv
-> Type
-> Type
-> Ordering
acmpType' :: RnEnv -> Type -> Type -> Ordering
acmpType' = RnEnv -> Type -> Type -> Ordering
go
where
go :: RnEnv -> Type -> Type -> Ordering
go env :: RnEnv
env (VarTy tv1 :: TyVar
tv1) (VarTy tv2 :: TyVar
tv2) = TyVar -> TyVar -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (RnEnv -> TyVar -> TyVar
rnOccLTy RnEnv
env TyVar
tv1) (RnEnv -> TyVar -> TyVar
rnOccRTy RnEnv
env TyVar
tv2)
go _ (ConstTy c1 :: ConstTy
c1) (ConstTy c2 :: ConstTy
c2) = ConstTy -> ConstTy -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ConstTy
c1 ConstTy
c2
go env :: RnEnv
env (ForAllTy tv1 :: TyVar
tv1 t1 :: Type
t1) (ForAllTy tv2 :: TyVar
tv2 t2 :: Type
t2) =
RnEnv -> Type -> Type -> Ordering
go RnEnv
env (TyVar -> Type
forall a. Var a -> Type
varType TyVar
tv1) (TyVar -> Type
forall a. Var a -> Type
varType TyVar
tv2) Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Type -> Type -> Ordering
go (RnEnv -> TyVar -> TyVar -> RnEnv
rnTyBndr RnEnv
env TyVar
tv1 TyVar
tv2) Type
t1 Type
t2
go env :: RnEnv
env (AppTy s1 :: Type
s1 t1 :: Type
t1) (AppTy s2 :: Type
s2 t2 :: Type
t2) =
RnEnv -> Type -> Type -> Ordering
go RnEnv
env Type
s1 Type
s2 Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Type -> Type -> Ordering
go RnEnv
env Type
t1 Type
t2
go _ (LitTy l1 :: LitTy
l1) (LitTy l2 :: LitTy
l2) = LitTy -> LitTy -> Ordering
forall a. Ord a => a -> a -> Ordering
compare LitTy
l1 LitTy
l2
go _ t1 :: Type
t1 t2 :: Type
t2 = Word -> Word -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Type -> Word
getRank Type
t1) (Type -> Word
getRank Type
t2)
getRank :: Type -> Word
getRank :: Type -> Word
getRank (VarTy {}) = 0
getRank (LitTy {}) = 1
getRank (ConstTy {}) = 2
getRank (AnnType {}) = 3
getRank (AppTy {}) = 4
getRank (ForAllTy {}) = 5
aeqTerm
:: Term
-> Term
-> Bool
aeqTerm :: Term -> Term -> Bool
aeqTerm t1 :: Term
t1 t2 :: Term
t2 = InScopeSet -> Term -> Term -> Bool
aeqTerm' InScopeSet
inScope Term
t1 Term
t2
where
inScope :: InScopeSet
inScope = VarSet -> InScopeSet
mkInScopeSet ([Term] -> VarSet
forall (f :: * -> *). Foldable f => f Term -> VarSet
localFVsOfTerms [Term
t1,Term
t2])
aeqTerm'
:: InScopeSet
-> Term
-> Term
-> Bool
aeqTerm' :: InScopeSet -> Term -> Term -> Bool
aeqTerm' inScope :: InScopeSet
inScope t1 :: Term
t1 t2 :: Term
t2 = InScopeSet -> Term -> Term -> Ordering
acmpTerm' InScopeSet
inScope Term
t1 Term
t2 Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
== Ordering
EQ
acmpTerm
:: Term
-> Term
-> Ordering
acmpTerm :: Term -> Term -> Ordering
acmpTerm t1 :: Term
t1 t2 :: Term
t2 = InScopeSet -> Term -> Term -> Ordering
acmpTerm' InScopeSet
inScope Term
t1 Term
t2
where
inScope :: InScopeSet
inScope = VarSet -> InScopeSet
mkInScopeSet ([Term] -> VarSet
forall (f :: * -> *). Foldable f => f Term -> VarSet
localFVsOfTerms [Term
t1,Term
t2])
acmpTerm'
:: InScopeSet
-> Term
-> Term
-> Ordering
acmpTerm' :: InScopeSet -> Term -> Term -> Ordering
acmpTerm' inScope :: InScopeSet
inScope = RnEnv -> Term -> Term -> Ordering
go (InScopeSet -> RnEnv
mkRnEnv InScopeSet
inScope)
where
thenCmpTm :: Ordering -> Ordering -> Ordering
thenCmpTm EQ rel :: Ordering
rel = Ordering
rel
thenCmpTm rel :: Ordering
rel _ = Ordering
rel
go :: RnEnv -> Term -> Term -> Ordering
go env :: RnEnv
env (Var id1 :: Id
id1) (Var id2 :: Id
id2) = Id -> Id -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (RnEnv -> Id -> Id
rnOccLId RnEnv
env Id
id1) (RnEnv -> Id -> Id
rnOccRId RnEnv
env Id
id2)
go _ (Data dc1 :: DataCon
dc1) (Data dc2 :: DataCon
dc2) = DataCon -> DataCon -> Ordering
forall a. Ord a => a -> a -> Ordering
compare DataCon
dc1 DataCon
dc2
go _ (Literal l1 :: Literal
l1) (Literal l2 :: Literal
l2) = Literal -> Literal -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Literal
l1 Literal
l2
go _ (Prim p1 :: Text
p1 _) (Prim p2 :: Text
p2 _) = Text -> Text -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Text
p1 Text
p2
go env :: RnEnv
env (Lam b1 :: Id
b1 e1 :: Term
e1) (Lam b2 :: Id
b2 e2 :: Term
e2) =
RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
env (Id -> Type
forall a. Var a -> Type
varType Id
b1) (Id -> Type
forall a. Var a -> Type
varType Id
b2) Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Term -> Term -> Ordering
go (RnEnv -> Id -> Id -> RnEnv
rnTmBndr RnEnv
env Id
b1 Id
b2) Term
e1 Term
e2
go env :: RnEnv
env (TyLam b1 :: TyVar
b1 e1 :: Term
e1) (TyLam b2 :: TyVar
b2 e2 :: Term
e2) =
RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
env (TyVar -> Type
forall a. Var a -> Type
varType TyVar
b1) (TyVar -> Type
forall a. Var a -> Type
varType TyVar
b2) Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Term -> Term -> Ordering
go (RnEnv -> TyVar -> TyVar -> RnEnv
rnTyBndr RnEnv
env TyVar
b1 TyVar
b2) Term
e1 Term
e2
go env :: RnEnv
env (App l1 :: Term
l1 r1 :: Term
r1) (App l2 :: Term
l2 r2 :: Term
r2) =
RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
l1 Term
l2 Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
r1 Term
r2
go env :: RnEnv
env (TyApp l1 :: Term
l1 r1 :: Type
r1) (TyApp l2 :: Term
l2 r2 :: Type
r2) =
RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
l1 Term
l2 Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
env Type
r1 Type
r2
go env :: RnEnv
env (Letrec bs1 :: [(Id, Term)]
bs1 e1 :: Term
e1) (Letrec bs2 :: [(Id, Term)]
bs2 e2 :: Term
e2) =
Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ([(Id, Term)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Id, Term)]
bs1) ([(Id, Term)] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Id, Term)]
bs2) Ordering -> Ordering -> Ordering
`thenCompare`
(Ordering -> Ordering -> Ordering)
-> Ordering -> [Ordering] -> Ordering
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Ordering -> Ordering -> Ordering
thenCmpTm Ordering
EQ ((Term -> Term -> Ordering) -> [Term] -> [Term] -> [Ordering]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (RnEnv -> Term -> Term -> Ordering
go RnEnv
env') [Term]
rhs1 [Term]
rhs2) Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Term -> Term -> Ordering
go RnEnv
env' Term
e1 Term
e2
where
(ids1 :: [Id]
ids1,rhs1 :: [Term]
rhs1) = [(Id, Term)] -> ([Id], [Term])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Term)]
bs1
(ids2 :: [Id]
ids2,rhs2 :: [Term]
rhs2) = [(Id, Term)] -> ([Id], [Term])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Term)]
bs2
env' :: RnEnv
env' = RnEnv -> [Id] -> [Id] -> RnEnv
rnTmBndrs RnEnv
env [Id]
ids1 [Id]
ids2
go env :: RnEnv
env (Case e1 :: Term
e1 _ a1 :: [Alt]
a1) (Case e2 :: Term
e2 _ a2 :: [Alt]
a2) =
Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare ([Alt] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Alt]
a1) ([Alt] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Alt]
a2) Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
e1 Term
e2 Ordering -> Ordering -> Ordering
`thenCompare`
(Ordering -> Ordering -> Ordering)
-> Ordering -> [Ordering] -> Ordering
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Ordering -> Ordering -> Ordering
thenCmpTm Ordering
EQ ((Alt -> Alt -> Ordering) -> [Alt] -> [Alt] -> [Ordering]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (RnEnv -> Alt -> Alt -> Ordering
goAlt RnEnv
env) [Alt]
a1 [Alt]
a2)
go env :: RnEnv
env (Cast e1 :: Term
e1 l1 :: Type
l1 r1 :: Type
r1) (Cast e2 :: Term
e2 l2 :: Type
l2 r2 :: Type
r2) =
RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
e1 Term
e2 Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
env Type
l1 Type
l2 Ordering -> Ordering -> Ordering
`thenCompare`
RnEnv -> Type -> Type -> Ordering
acmpType' RnEnv
env Type
r1 Type
r2
go env :: RnEnv
env (Tick _ e1 :: Term
e1) e2 :: Term
e2 = RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
e1 Term
e2
go env :: RnEnv
env e1 :: Term
e1 (Tick _ e2 :: Term
e2) = RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
e1 Term
e2
go _ e1 :: Term
e1 e2 :: Term
e2 = Word -> Word -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Term -> Word
getRank Term
e1) (Term -> Word
getRank Term
e2)
goAlt :: RnEnv -> Alt -> Alt -> Ordering
goAlt env :: RnEnv
env (DataPat c1 :: DataCon
c1 tvs1 :: [TyVar]
tvs1 ids1 :: [Id]
ids1,e1 :: Term
e1) (DataPat c2 :: DataCon
c2 tvs2 :: [TyVar]
tvs2 ids2 :: [Id]
ids2,e2 :: Term
e2) =
DataCon -> DataCon -> Ordering
forall a. Ord a => a -> a -> Ordering
compare DataCon
c1 DataCon
c2 Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Term -> Term -> Ordering
go RnEnv
env' Term
e1 Term
e2
where
env' :: RnEnv
env' = RnEnv -> [Id] -> [Id] -> RnEnv
rnTmBndrs (RnEnv -> [TyVar] -> [TyVar] -> RnEnv
rnTyBndrs RnEnv
env [TyVar]
tvs1 [TyVar]
tvs2) [Id]
ids1 [Id]
ids2
goAlt env :: RnEnv
env (c1 :: Pat
c1,e1 :: Term
e1) (c2 :: Pat
c2,e2 :: Term
e2) =
Pat -> Pat -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Pat
c1 Pat
c2 Ordering -> Ordering -> Ordering
`thenCompare` RnEnv -> Term -> Term -> Ordering
go RnEnv
env Term
e1 Term
e2
getRank :: Term -> Word
getRank :: Term -> Word
getRank = \case
Var {} -> 0
Data {} -> 1
Literal {} -> 2
Prim {} -> 3
Cast {} -> 4
App {} -> 5
TyApp {} -> 6
Lam {} -> 7
TyLam {} -> 8
Letrec {} -> 9
Case {} -> 10
Tick {} -> 11
thenCompare :: Ordering -> Ordering -> Ordering
thenCompare :: Ordering -> Ordering -> Ordering
thenCompare EQ rel :: Ordering
rel = Ordering
rel
thenCompare rel :: Ordering
rel _ = Ordering
rel
instance Eq Type where
== :: Type -> Type -> Bool
(==) = Type -> Type -> Bool
aeqType
instance Ord Type where
compare :: Type -> Type -> Ordering
compare = Type -> Type -> Ordering
acmpType
instance Eq Term where
== :: Term -> Term -> Bool
(==) = Term -> Term -> Bool
aeqTerm
instance Ord Term where
compare :: Term -> Term -> Ordering
compare = Term -> Term -> Ordering
acmpTerm