alms-0.6.0: src/Statics/Env.hs
{-# LANGUAGE TypeFamilies #-}
module Statics.Env (
-- * Type variable environment
Δ,
-- * Main environment
Γ(..), Γv, Γc, Γt, Γm, Γs, R,
-- ** Operations
bumpΓ, sigToEnv, sigItemToEnv, (!.!), (!..!), ExtendRank(..),
-- * Testing
test_g0,
-- * Re-exports
module Statics.Sig,
module Env,
) where
import Util
import qualified AST
import Type
import Statics.Sig
import Statics.Error
import qualified Type.Rank as Rank
import qualified Syntax.Ppr as Ppr
import Env
import Prelude ()
import Data.Generics (Typeable, Data)
import qualified Data.Map as M
type R = AST.Renamed
-- | Mapping from type variable names to type variables
type Δ tv = Env (AST.TyVar R) tv
-- | Mapping variable names to type
type Γv tv = Env VarId (Type tv)
-- | Mapping data constructor names to type constructors or exception
-- parameter types
type Γc tv = Env ConId (Either TyCon (Maybe (Type Empty)))
-- | Mapping type names to type constructors
type Γt tv = Env TypId TyCon
-- | Mapping module names to their signatures and reflection as an environment
type Γm tv = Env ModId (Signature tv, Γ tv)
-- | Mapping signature names to signatures and reflection as an environment
type Γs tv = Env SigId (Signature tv, Γ tv)
-- | An environment
data Γ tv
= Γ {
rankΓ ∷ !Rank.Rank,
varΓ ∷ !(Γv tv),
conΓ ∷ !(Γc tv),
typΓ ∷ !(Γt tv),
modΓ ∷ !(Γm tv),
sigΓ ∷ !(Γs tv)
}
deriving (Functor, Show, Typeable, Data)
instance Monoid (Γ tv) where
mempty = Γ Rank.zero empty empty empty empty empty
Γ rank a b c d e `mappend` Γ rank' a' b' c' d' e'
= Γ (rank `max` rank') (a=+=a') (b=+=b') (c=+=c') (d=+=d') (e=+=e')
-- | Increment the rank of the environment
bumpΓ ∷ Γ tv → Γ tv
bumpΓ γ = γ { rankΓ = Rank.inc (rankΓ γ) }
-- | Reflect a signature as an environment
sigToEnv ∷ Signature tv → Γ tv
sigToEnv = foldMap sigItemToEnv
-- | Reflect a signature item as an environment
sigItemToEnv ∷ SigItem tv → Γ tv
sigItemToEnv (SgVal n τ) = mempty { varΓ = n =:= τ }
sigItemToEnv (SgTyp n tc) =
mempty {
typΓ = n =:= tc,
conΓ = Left tc <$ tcCons tc
}
sigItemToEnv (SgExn n mτ) = mempty { conΓ = n =:= Right mτ }
sigItemToEnv (SgMod n sig) = mempty { modΓ = n =:= (sig, sigToEnv sig) }
sigItemToEnv (SgSig n sig) = mempty { sigΓ = n =:= (sig, sigToEnv sig) }
---
--- INSTANCES
---
instance GenEmpty (Γ tv) where
genEmpty = mempty
instance GenExtend (Γ tv) (Γ tv) where
(=+=) = mappend
instance (v ~ VarId, tv ~ tv') ⇒
GenExtend (Γ tv) (Env v (Type tv')) where -- Γv
e =+= ev' = e { varΓ = varΓ e =+= ev' }
instance (c ~ ConId, tc ~ TyCon, mt ~ Maybe (Type Empty)) ⇒
GenExtend (Γ tv) (Env c (Either tc mt)) where -- Γc
e =+= ec' = e { conΓ = conΓ e =+= ec' }
instance t ~ TypId ⇒
GenExtend (Γ tv) (Env t TyCon) where -- Γt
e =+= et' = e { typΓ = typΓ e =+= et' }
instance (s ~ Signature tv, g ~ Γ tv) ⇒
GenExtend (Γ tv) (Env ModId (s, g)) where -- Γm
e =+= em' = e { modΓ = modΓ e =+= em' }
instance (s ~ Signature tv, g ~ Γ tv) ⇒
GenExtend (Γ tv) (Env SigId (s, g)) where -- Γs
e =+= es' = e { sigΓ = sigΓ e =+= es' }
instance tv ~ tv' ⇒ GenExtend (Γ tv) (Signature tv') where
e =+= sig = e =+= sigToEnv sig
instance GenLookup (Γ tv) VarId (Type tv) where
(=..=) = (=..=) . varΓ
instance GenLookup (Γ tv) ConId (Either TyCon (Maybe (Type Empty))) where
(=..=) = (=..=) . conΓ
instance GenLookup (Γ tv) TypId TyCon where
(=..=) = (=..=) . typΓ
instance GenLookup (Γ tv) ModId (Signature tv, Γ tv) where
(=..=) = (=..=) . modΓ
instance GenLookup (Γ tv) SigId (Signature tv, Γ tv) where
(=..=) = (=..=) . sigΓ
instance GenLookup (Γ tv) k v =>
GenLookup (Γ tv) (Path ModId k) v where
e =..= J [] k = e =..= k
e =..= J (p:ps) k = do
(_, e') <- e =..= p
e' =..= J ps k
(!.!) ∷ (GenLookup e k v, Show k, MonadAlmsError m) ⇒ e → k → m v
e !.! k = case e =..= k of
Just v → return v
Nothing → typeBug "GenLookup" ("unbound identifier: " ++ show k)
(!..!) ∷ (GenLookup e k v, Show k) ⇒ e → k → v
e !..! k = case e =..= k of
Just v → v
Nothing → typeBugError "GenLookup" ("unbound identifier: " ++ show k)
infixl 6 !.!, !..!
-- | Extend the environment and update the ranks of the free type
-- variables of the added types.
class ExtendRank a tv | a → tv where
(!+!) ∷ MonadSubst tv r m ⇒ Γ tv → a → m (Γ tv)
infixl 2 !+!
instance ExtendRank (Γ tv) tv where
γ !+! γ' = do
lowerRank (Rank.inc (rankΓ γ)) =<< subst (range (varΓ γ'))
return (bumpΓ γ =+= γ')
instance ExtendRank (Γv tv) tv where
γ !+! γv = γ !+! mempty { varΓ = γv }
instance ExtendRank (Signature tv) tv where
γ !+! sig = γ !+! sigToEnv sig
instance (Ppr.Ppr k, Ppr.Ppr v) ⇒ Ppr.Ppr (Env k v) where
ppr env = Ppr.braces . Ppr.fsep . Ppr.punctuate Ppr.comma $
[ Ppr.ppr0 k Ppr.<> Ppr.colon Ppr.<+> Ppr.ppr0 v
| (k, v) <- Env.toList env ]
instance Tv tv ⇒ Ppr.Ppr (Γ tv) where
ppr γ = Ppr.char 'Γ' Ppr.<> Ppr.ppr (M.fromList
[ ("rank", Ppr.ppr0 $ rankΓ γ)
, ("typ", Ppr.ppr0 $ typΓ γ)
, ("var", Ppr.ppr0 $ varΓ γ)
, ("con", Ppr.ppr0 $ conΓ γ)
, ("mod", Ppr.ppr0 $ snd <$> modΓ γ)
, ("sig", Ppr.ppr0 $ snd <$> sigΓ γ)
])
test_g0 ∷ ∀ tv. Tv tv ⇒ Γ tv
test_g0 = mempty
=+= AST.ident "->" =:= tcFun
=+= AST.ident "unit" =:= tcUnit
=+= AST.ident "()" =:= Left tcUnit
=+= AST.ident "int" =:= tcInt
=+= AST.ident "exn" =:= tcExn
=+= AST.ident "Failure" =:= Right (Just tyString)
=+= AST.ident "Match" =:= Right Nothing
=+= AST.ident "U" =:= tcUn
=+= AST.ident "A" =:= tcAf
=+= AST.ident "\\/" =:= tcJoin
=+= AST.ident "*" =:= tcTuple
=+= AST.ident "rowend" =:= tcRowEnd
=+= AST.ident "variant" =:= tcVariant
=+= AST.ident "record" =:= tcRecord
=+= AST.ident "nilRecord" =:= TyApp tcRecord [tyUn, tyRowEnd]
=+= AST.ident "rowmap" =:= tcRowMap
=+= AST.ident "rowhole" =:= tcRowHole
=+= AST.ident "option" =:= tcOption
=+= AST.ident "None" =:= Left tcOption
=+= AST.ident "Some" =:= Left tcOption
=+= AST.ident "idfun" =:= tcIdfun
=+= AST.ident "Mono" =:= Left tcIdfun
=+= AST.ident "Poly" =:= Left tcIdfun
=+= AST.ident "ident" =:= tcIdent
=+= AST.ident "const" =:= tcConst
=+= AST.ident "cons" =:= tcConsTup
=+= AST.ident "x" =:= tyInt
=+= AST.ident "bot" =:= TyQu Forall [(Nope, Qa)] (bvTy 0 0 Nope)
=+= AST.ident "botU" =:= TyQu Forall [(Nope, Qu)] (bvTy 0 0 Nope)