{-# LANGUAGE FlexibleContexts, DefaultSignatures, TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
module AST.Infer.Blame
( blame
, Blame(..)
, BTerm(..), InferOf', bAnn, bRes, bVal
, bTermToAnn
) where
import AST
import AST.Class.Infer
import AST.Class.Infer.InferOf
import AST.Class.Traversable (ContainedK(..))
import AST.Class.Unify (Unify, UVarOf)
import AST.Combinator.Flip
import AST.Infer.Term (ITermVarsConstraint(..))
import AST.Recurse
import AST.TH.Internal.Instances (makeCommonInstances)
import AST.Unify.New (newUnbound)
import AST.Unify.Occurs (occursCheck)
import Control.Lens (makeLenses, from)
import Control.Lens.Operators
import Control.Monad.Except (MonadError(..))
import Data.Constraint (Dict(..), withDict)
import Data.Foldable (traverse_)
import Data.List (sortOn)
import Data.Proxy (Proxy(..))
import GHC.Generics (Generic)
import Prelude.Compat
class
(Infer m t, RTraversable t, KTraversable (InferOf t), KPointed (InferOf t)) =>
Blame m t where
inferOfUnify ::
Proxy t ->
Tree (InferOf t) (UVarOf m) ->
Tree (InferOf t) (UVarOf m) ->
m ()
inferOfMatches ::
Proxy t ->
Tree (InferOf t) (UVarOf m) ->
Tree (InferOf t) (UVarOf m) ->
m Bool
blamableRecursive ::
Proxy m -> Proxy t -> Dict (KNodesConstraint t (Blame m))
{-# INLINE blamableRecursive #-}
default blamableRecursive ::
KNodesConstraint t (Blame m) =>
Proxy m -> Proxy t -> Dict (KNodesConstraint t (Blame m))
blamableRecursive _ _ = Dict
instance Recursive (Blame m) where
recurse p =
blamableRecursive
((const Proxy :: p (b m t) -> Proxy m) p)
((const Proxy :: p (b m t) -> Proxy t) p)
type InferOf' e v = Tree (InferOf (GetKnot e)) v
data PTerm a v e = PTerm
{ pAnn :: a
, pInferResultFromPos :: InferOf' e v
, pInferResultFromSelf :: InferOf' e v
, pBody :: e # PTerm a v
}
prepareH ::
forall m exp a.
Blame m exp =>
Tree (Ann a) exp ->
m (Tree (PTerm a (UVarOf m)) exp)
prepareH t =
withDict (inferContext (Proxy @m) (Proxy @exp)) $
pureK (Proxy @(Unify m) #> MkContainedK newUnbound)
& sequenceK
>>= (`prepare` t)
prepare ::
forall m exp a.
Blame m exp =>
Tree (InferOf exp) (UVarOf m) ->
Tree (Ann a) exp ->
m (Tree (PTerm a (UVarOf m)) exp)
prepare resFromPosition (Ann a x) =
withDict (recurse (Proxy @(Blame m exp))) $
do
(xI, r) <-
mapK
(Proxy @(Blame m) #>
InferChild . fmap (\t -> InferredChild t (pInferResultFromPos t)) . prepareH)
x
& inferBody
pure PTerm
{ pAnn = a
, pInferResultFromPos = resFromPosition
, pInferResultFromSelf = r
, pBody = xI
}
tryUnify ::
forall err m exp.
(MonadError err m, Blame m exp) =>
Proxy exp ->
Tree (InferOf exp) (UVarOf m) ->
Tree (InferOf exp) (UVarOf m) ->
m ()
tryUnify p i0 i1 =
withDict (inferContext (Proxy @m) p) $
do
inferOfUnify p i0 i1
traverseK_ (Proxy @(Unify m) #> occursCheck) i0
& (`catchError` const (pure ()))
toUnifies ::
forall err m exp a.
(MonadError err m, Blame m exp) =>
Tree (PTerm a (UVarOf m)) exp ->
Tree (Ann (a, m ())) exp
toUnifies (PTerm a i0 i1 b) =
withDict (recurse (Proxy @(Blame m exp))) $
mapK (Proxy @(Blame m) #> toUnifies) b
& Ann (a, tryUnify (Proxy @exp) i0 i1)
data BTerm a v e = BTerm
{ _bAnn :: a
, _bRes :: Either (InferOf' e v, InferOf' e v) (InferOf' e v)
, _bVal :: e # BTerm a v
} deriving Generic
makeLenses ''BTerm
makeCommonInstances [''BTerm]
instance KNodes (Flip (BTerm a) e) where
type KNodesConstraint (Flip (BTerm a) e) c = ITermVarsConstraint c e
data KWitness (Flip (BTerm a) e) n where
E_Flip_BTerm_InferOf_e ::
KWitness (InferOf e) n ->
KWitness (Flip (BTerm a) e) n
E_Flip_BTerm_e ::
KWitness e f ->
KWitness (Flip (BTerm a) f) n ->
KWitness (Flip (BTerm a) e) n
{-# INLINE kLiftConstraint #-}
kLiftConstraint w p =
withDict (iTermVarsConstraintCtx p (Proxy @e)) $
case w of
E_Flip_BTerm_InferOf_e w0 -> kLiftConstraint w0 p
E_Flip_BTerm_e w0 w1 ->
kLiftConstraint w0 (p0 p) (kLiftConstraint w1 p)
where
p0 :: Proxy c -> Proxy (ITermVarsConstraint c)
p0 _ = Proxy
instance (Recursively KFunctor e, Recursively KFunctorInferOf e) => KFunctor (Flip (BTerm a) e) where
{-# INLINE mapK #-}
mapK f =
withDict (recursively (Proxy @(KFunctor e))) $
withDict (recursively (Proxy @(KFunctorInferOf e))) $
let mapRes = mapK (f . E_Flip_BTerm_InferOf_e)
in
_Flip %~
\(BTerm pl r x) ->
BTerm pl
( case r of
Left (r0, r1) -> Left (mapRes r0, mapRes r1)
Right r0 -> Right (mapRes r0)
)
( mapK
( Proxy @(Recursively KFunctor) #*# Proxy @(Recursively KFunctorInferOf) #*#
\w -> from _Flip %~ mapK (f . E_Flip_BTerm_e w)
) x
)
instance (Recursively KFoldable e, Recursively KFoldableInferOf e) => KFoldable (Flip (BTerm a) e) where
{-# INLINE foldMapK #-}
foldMapK f (MkFlip (BTerm _ r x)) =
withDict (recursively (Proxy @(KFoldable e))) $
withDict (recursively (Proxy @(KFoldableInferOf e))) $
let foldRes = foldMapK (f . E_Flip_BTerm_InferOf_e)
in
case r of
Left (r0, r1) -> foldRes r0 <> foldRes r1
Right r0 -> foldRes r0
<>
foldMapK
( Proxy @(Recursively KFoldable) #*# Proxy @(Recursively KFoldableInferOf) #*#
\w -> foldMapK (f . E_Flip_BTerm_e w) . (_Flip #)
) x
instance
(RTraversable e, RTraversableInferOf e) =>
KTraversable (Flip (BTerm a) e) where
{-# INLINE sequenceK #-}
sequenceK =
withDict (recurse (Proxy @(RTraversable e))) $
withDict (recurse (Proxy @(RTraversableInferOf e))) $
_Flip
( \(BTerm pl r x) ->
BTerm pl
<$> ( case r of
Left (r0, r1) -> (,) <$> seqRes r0 <*> seqRes r1 <&> Left
Right r0 -> seqRes r0 <&> Right
)
<*> traverseK
( Proxy @RTraversable #*# Proxy @RTraversableInferOf #>
from _Flip sequenceK
) x
)
where
seqRes ::
(KTraversable k, Applicative f) =>
Tree k (ContainedK f p) -> f (Tree k p)
seqRes = traverseK (const runContainedK)
finalize ::
forall a m exp.
Blame m exp =>
Tree (PTerm a (UVarOf m)) exp ->
m (Tree (BTerm a (UVarOf m)) exp)
finalize (PTerm a i0 i1 x) =
withDict (recurse (Proxy @(Blame m exp))) $
do
match <- inferOfMatches (Proxy @exp) i0 i1
let result
| match = Right i0
| otherwise = Left (i0, i1)
traverseK (Proxy @(Blame m) #> finalize) x
<&> BTerm a result
blame ::
forall priority err m exp a.
( Ord priority
, MonadError err m
, Blame m exp
) =>
(a -> priority) ->
Tree (InferOf exp) (UVarOf m) ->
Tree (Ann a) exp ->
m (Tree (BTerm a (UVarOf m)) exp)
blame order topLevelType e =
do
p <- prepare topLevelType e
toUnifies p ^.. annotations & sortOn (order . fst) & traverse_ snd
finalize p
bTermToAnn ::
forall a v e r.
Recursively KFunctor e =>
( forall n.
KRecWitness e n ->
a ->
Either (Tree (InferOf n) v, Tree (InferOf n) v) (Tree (InferOf n) v) ->
r
) ->
Tree (BTerm a v) e ->
Tree (Ann r) e
bTermToAnn f (BTerm pl r x) =
withDict (recursively (Proxy @(KFunctor e))) $
mapK
( Proxy @(Recursively KFunctor) #*#
\w -> bTermToAnn (f . KRecSub w)
) x
& Ann (f KRecSelf pl r)