ddc-source-tetra-0.4.3.1: DDC/Source/Tetra/Env.hs
-- | Source Tetra primitive type and kind environments.
module DDC.Source.Tetra.Env
( Env (..)
, Presence (..)
, takePresent
, empty
, union, unions
-- ** Type Variables
, singletonTyVar, singletonTyVar'
, extendTyVar
, extendTyVar', extendsTyVar'
, lookupTyVar
, tyStackDepth
-- ** Data Constructors
, singletonDaCon
, extendDaCon
, lookupDaCon
-- ** Term Variables
, singletonDaVar
, singletonDaVar'
, extendDaVar, extendsDaVar
, extendDaVar'
, extendDaVarMT, extendsDaVarMT
, lookupDaVar
, daStackDepth
-- * Primitive Kinds and Types.
, kindOfPrimType
, typeOfPrimVal
, typeOfPrimLit)
where
import DDC.Source.Tetra.Prim
import DDC.Source.Tetra.Exp.Source
import Data.Map (Map)
import Data.Sequence (Seq)
import Data.Text (Text)
import qualified Data.List as List
import qualified Data.Map.Strict as Map
import qualified Data.Sequence as Seq
---------------------------------------------------------------------------------------------------
data Env
= Env
{ -- | Map names of type constructors to their kinds.
envTyCon :: Map Text Type
-- | Map names of variables to their kinds.
, envTyVar :: Map Text (Maybe Type)
-- | Stack of kinds of deBruijn indexed type variables.
, envTyStack :: Seq (Maybe Type)
-- | Map names of data constructors to their types.
, envDaCon :: Map Text Type
-- | Map names of term variables to their types.
, envDaVar :: Map Text (Maybe Type)
-- | Stack of types of deBruijn indexed term variables.
, envDaStack :: Seq (Maybe Type) }
-- | Presence of a variable in the environment.
data Presence a
-- | Variable is not present in environment.
= Absent
-- | Variable is present but we don't have a type for it.
| Unknown
-- | Variable is present in the environment with this information.
| Present a
deriving Show
-- | Yield `Just` for a `Present` and `Nothing` for the others.
takePresent :: Presence a -> Maybe a
takePresent pp
= case pp of
Absent -> Nothing
Unknown -> Nothing
Present x -> Just x
-- | An empty environment.
empty :: Env
empty
= Env
{ envTyCon = Map.empty
, envTyVar = Map.empty
, envTyStack = Seq.empty
, envDaCon = Map.empty
, envDaVar = Map.empty
, envDaStack = Seq.empty }
-- | Take the right biased union of two environments.
union :: Env -> Env -> Env
union env1 env2
= Env
{ envTyCon = Map.union (envTyCon env1) (envTyCon env2)
, envTyVar = Map.union (envTyVar env1) (envTyVar env2)
, envTyStack = envTyStack env1 Seq.>< envTyStack env2
, envDaCon = Map.union (envDaCon env1) (envDaCon env2)
, envDaVar = Map.union (envDaVar env1) (envDaVar env2)
, envDaStack = envDaStack env1 Seq.>< envDaStack env2 }
-- | Take the right biased union of a list of type environments.
unions :: [Env] -> Env
unions envs
= List.foldl' union empty envs
---------------------------------------------------------------------------------------------------
-- | Extend the environment with the kind for a type variable.
extendTyVar :: Bind -> Type -> Env -> Env
extendTyVar b k env
= case b of
BNone -> env
BAnon -> env { envTyStack = (envTyStack env) Seq.|> (Just k) }
BName n -> env { envTyVar = Map.insert n (Just k) (envTyVar env) }
-- | Extend the environment with a type variable where we don't know its kind.
extendTyVar' :: Bind -> Env -> Env
extendTyVar' b env
= case b of
BNone -> env
BAnon -> env { envTyStack = (envTyStack env) Seq.|> Nothing }
BName n -> env { envTyVar = Map.insert n Nothing (envTyVar env) }
-- | Extend the environment with some type variables where we don't know their kinds.
extendsTyVar' :: [Bind] -> Env -> Env
extendsTyVar' bs env
= List.foldl' (flip extendTyVar') env bs
-- | Yield an environment containing a single type variable.
singletonTyVar' :: Bind -> Env
singletonTyVar' b
= extendTyVar' b empty
-- | Yield an environment containing the kind for a single type variable.
singletonTyVar :: Bind -> Type -> Env
singletonTyVar b t
= extendTyVar b t empty
-- | Lookup the kind of the given type variable.
lookupTyVar :: Env -> Bound -> Presence Type
lookupTyVar env u
= case u of
UName tx
-> case Map.lookup tx (envTyVar env) of
Nothing -> Absent
Just Nothing -> Unknown
Just (Just t) -> Present t
UIx i
| i >= Seq.length (envTyStack env)
-> Absent
| otherwise
-> case Seq.index (envTyStack env) i of
Nothing -> Unknown
Just t -> Present t
UHole
-> Unknown
-- | Get the depth of the type stack.
tyStackDepth :: Env -> Int
tyStackDepth env = Seq.length (envTyStack env)
---------------------------------------------------------------------------------------------------
-- | Extend the environment with the type of a data constructor.
extendDaCon :: DaConBind -> Type -> Env -> Env
extendDaCon (DaConBindName tx) t env
= env { envDaCon = Map.insert tx t (envDaCon env) }
-- | Yield an environment containing the type of a single data constructor.
singletonDaCon :: DaConBind -> Type -> Env
singletonDaCon dc t
= extendDaCon dc t empty
-- | Lookup the type of a data constructor.
lookupDaCon :: DaConBound -> Env -> Maybe Type
lookupDaCon dc env
= case dc of
DaConBoundName tx -> Map.lookup tx (envDaCon env)
DaConBoundLit lit -> Just (typeOfPrimLit lit)
---------------------------------------------------------------------------------------------------
-- | Extend the environment with the type of a term variable.
extendDaVar :: Bind -> Type -> Env -> Env
extendDaVar b t env
= case b of
BNone -> env
BAnon -> env { envDaStack = (envDaStack env) Seq.|> (Just t) }
BName n -> env { envDaVar = Map.insert n (Just t) (envDaVar env) }
-- | Extend the environment with the types of some term variables.
extendsDaVar :: [(Bind, Type)] -> Env -> Env
extendsDaVar bxs env
= List.foldl' (\env' (b, t) -> extendDaVar b t env') env bxs
-- | Extend the environment with a term variable where we don't know it's type.
extendDaVar' :: Bind -> Env -> Env
extendDaVar' b env
= case b of
BNone -> env
BAnon -> env { envDaStack = (envDaStack env) Seq.|> Nothing }
BName n -> env { envDaVar = Map.insert n Nothing (envDaVar env) }
-- | Like `extendDaVar` but take a `BindVarMT`
extendDaVarMT :: BindVarMT -> Env -> Env
extendDaVarMT xb env
= case xb of
XBindVarMT b Nothing -> extendDaVar' b env
XBindVarMT b (Just t) -> extendDaVar b t env
-- | Like `extendDaVarMT` but take a list of `BindVarMT`
extendsDaVarMT :: [BindVarMT] -> Env -> Env
extendsDaVarMT bs env
= List.foldl' (flip extendDaVarMT) env bs
-- | Yield an environment containing the type for a single term variable.
singletonDaVar :: Bind -> Type -> Env
singletonDaVar b t
= extendDaVar b t empty
-- | Yield an environment containing a single term variable where we don't know its type.
singletonDaVar' :: Bind -> Env
singletonDaVar' b
= extendDaVar' b empty
-- | Lookup the kind of the given type variable.
lookupDaVar :: Env -> Bound -> Presence Type
lookupDaVar env u
= case u of
UName tx
-> case Map.lookup tx (envDaVar env) of
Nothing -> Absent
Just Nothing -> Unknown
Just (Just t) -> Present t
UIx i
| i >= Seq.length (envDaStack env)
-> Absent
| otherwise
-> case Seq.index (envDaStack env) i of
Nothing -> Unknown
Just t -> Present t
UHole
-> Unknown
-- | Get the depth of the type stack.
daStackDepth :: Env -> Int
daStackDepth env = Seq.length (envDaStack env)
---------------------------------------------------------------------------------------------------
-- | Take the kind of a primitive type.
kindOfPrimType :: PrimType -> Maybe Type
kindOfPrimType tt
= case tt of
PrimTypeSoCon _ -> Nothing
PrimTypeKiCon _ -> Nothing
PrimTypeTwCon _ -> Nothing
PrimTypeTcCon _ -> Nothing
PrimTypeTyCon tc -> Just (kindPrimTyCon tc)
PrimTypeTyConTetra tc -> Just (kindPrimTyConTetra tc)
-- | Take the type of a primitive name.
typeOfPrimVal :: PrimVal -> Type
typeOfPrimVal dc
= case dc of
PrimValLit l -> typeOfPrimLit l
PrimValArith p -> typePrimArith Source p
PrimValCast p -> typePrimCast Source p
PrimValError p -> typeOpError Source p
PrimValVector p -> typeOpVector Source p
PrimValFun p -> typeOpFun Source p
-- | Take the type of a primitive literal.
typeOfPrimLit :: PrimLit -> Type
typeOfPrimLit pl
= case pl of
PrimLitBool _ -> TBool
PrimLitNat _ -> TNat
PrimLitInt _ -> TInt
PrimLitSize _ -> TSize
PrimLitFloat _ bits -> TFloat bits
PrimLitWord _ bits -> TWord bits
PrimLitChar _ -> TWord 32
PrimLitTextLit _ -> TTextLit