{-# LANGUAGE TemplateHaskell, FlexibleContexts #-}
module AST.Unify.Binding.ST.Load
( load
) where
import AST
import AST.Class.Has (HasChild(..))
import AST.Class.Unify (Unify(..), UVarOf, BindingDict(..))
import AST.Recurse
import AST.Unify.Binding (Binding(..), _Binding, UVar(..))
import AST.Unify.Binding.ST (STUVar)
import AST.Unify.Term (UTerm(..), uBody)
import qualified Control.Lens as Lens
import Control.Lens.Operators
import Control.Monad.ST.Class (MonadST(..))
import Data.Array.ST (STArray, newArray, readArray, writeArray)
import Data.Constraint (withDict)
import Data.Proxy (Proxy(..))
import qualified Data.Sequence as Sequence
import Prelude.Compat
newtype ConvertState s t = ConvertState (STArray s Int (Maybe (STUVar s t)))
Lens.makePrisms ''ConvertState
makeConvertState :: MonadST m => Tree Binding t -> m (Tree (ConvertState (World m)) t)
makeConvertState (Binding x) =
newArray (0, Sequence.length x) Nothing & liftST <&> ConvertState
loadUTerm ::
forall m typeVars t.
( MonadST m
, UVarOf m ~ STUVar (World m)
, Unify m t
, Recursively (HasChild typeVars) t
) =>
Tree typeVars Binding -> Tree typeVars (ConvertState (World m)) ->
Tree (UTerm UVar) t -> m (Tree (UTerm (STUVar (World m))) t)
loadUTerm _ _ (UUnbound c) = UUnbound c & pure
loadUTerm _ _ (USkolem c) = USkolem c & pure
loadUTerm src conv (UToVar v) = loadVar src conv v <&> UToVar
loadUTerm src conv (UTerm u) = uBody (loadBody src conv) u <&> UTerm
loadUTerm _ _ UResolving{} = error "converting bindings after resolution"
loadUTerm _ _ UResolved{} = error "converting bindings after resolution"
loadUTerm _ _ UConverted{} = error "loading while saving?"
loadUTerm _ _ UInstantiated{} = error "loading during instantiation"
loadVar ::
forall m t typeVars.
( MonadST m
, UVarOf m ~ STUVar (World m)
, Unify m t
, Recursively (HasChild typeVars) t
) =>
Tree typeVars Binding -> Tree typeVars (ConvertState (World m)) ->
Tree UVar t -> m (Tree (STUVar (World m)) t)
loadVar src conv (UVar v) =
withDict (recursively (Proxy @(HasChild typeVars t))) $
let tConv = conv ^. getChild . _ConvertState
in
readArray tConv v & liftST
>>=
\case
Just x -> pure x
Nothing ->
do
u <-
loadUTerm src conv
(src ^?! getChild . _Binding . Lens.ix v)
r <- newVar binding u
r <$ liftST (writeArray tConv v (Just r))
loadBody ::
forall m typeVars t.
( MonadST m
, UVarOf m ~ STUVar (World m)
, Unify m t
, Recursively (HasChild typeVars) t
) =>
Tree typeVars Binding -> Tree typeVars (ConvertState (World m)) ->
Tree t UVar -> m (Tree t (STUVar (World m)))
loadBody src conv =
withDict (recurse (Proxy @(Unify m t))) $
withDict (recursively (Proxy @(HasChild typeVars t))) $
traverseK
( Proxy @(Unify m) #*# Proxy @(Recursively (HasChild typeVars))
#> loadVar src conv
)
load ::
( MonadST m
, UVarOf m ~ STUVar (World m)
, KTraversable typeVars
, Unify m t
, Recursively (HasChild typeVars) t
) =>
Tree typeVars Binding -> Tree t UVar -> m (Tree t (STUVar (World m)))
load src collection =
do
conv <- traverseK (const makeConvertState) src
loadBody src conv collection