module Language.Symantic.Typing.Variable where
import Data.Proxy (Proxy(..))
import Data.String (IsString(..))
import Data.Text (Text)
import Data.Type.Equality ((:~:)(..))
import qualified Data.Kind as K
import Language.Symantic.Grammar
import Language.Symantic.Typing.List
import Language.Symantic.Typing.Kind
data (:~~:) (a::ka) (b::kb) where
HRefl :: a :~~: a
data Var src (vs::[K.Type]) (v::kv) where
VarZ :: Kind src kv
-> Len (Proxy (v::kv) ': vs)
-> Var src (Proxy (v::kv) ': vs) (v::kv)
VarS :: Var src vs v
-> Var src (not_v ': vs) v
infixr 5 `VarS`
type instance SourceOf (Var src vs t) = src
instance Show (Var src tys v) where
showsPrec p v = showsPrec p (indexVar v)
instance SourceInj (EVar src vs) src => KindOf (Var src vs) where
kindOf v = kindOfVar v `withSource` EVar v
instance LenVars (Var src vs v) where
lenVars (VarZ _k l) = l
lenVars (VarS v) = LenS (lenVars v)
instance AllocVars (Var src) where
allocVarsL LenZ v = v
allocVarsL (LenS len) v = VarS $ allocVarsL len v
allocVarsR len (VarZ k l) = VarZ k (addLen l len)
allocVarsR len (VarS v) = VarS $ allocVarsR len v
varZ ::
forall src vs kv (v::kv).
Source src =>
LenInj vs =>
KindInj kv =>
Var src (Proxy v ': vs) v
varZ = VarZ kindInj lenInj
kindOfVar :: Var src vs (v::kv) -> Kind src kv
kindOfVar (VarZ k _l) = k
kindOfVar (VarS v) = kindOfVar v
eqVar :: Var xs vs x -> Var ys vs y -> Maybe (x:~:y)
eqVar VarZ{} VarZ{} = Just Refl
eqVar (VarS x) (VarS y) = eqVar x y
eqVar _ _ = Nothing
eqVarKi :: Var xs vs x -> Var ys vs y -> Maybe ((x::kx) :~~: (y::ky))
eqVarKi VarZ{} VarZ{} = Just HRefl
eqVarKi (VarS x) (VarS y) = eqVarKi x y
eqVarKi _ _ = Nothing
ordVarKi :: Var xs vs x -> Var ys vs y -> Ordering
ordVarKi VarZ{} VarZ{} = EQ
ordVarKi VarZ{} VarS{} = LT
ordVarKi VarS{} VarZ{} = GT
ordVarKi (VarS x) (VarS y) = ordVarKi x y
data EVar src vs = forall v. EVar (Var src vs v)
type IndexVar = Int
indexVar :: Var src vs v -> Int
indexVar VarZ{} = 0
indexVar (VarS v) = 1 + indexVar v
class LenVars a where
lenVars :: a -> Len (VarsOf a)
class AllocVars (a::[K.Type] -> k -> K.Type) where
allocVarsL :: Len len -> a vs x -> a (len ++ vs) x
allocVarsR :: Len len -> a vs x -> a (vs ++ len) x
appendVars ::
AllocVars a =>
AllocVars b =>
LenVars (a vs_x x) =>
LenVars (b vs_y y) =>
VarsOf (a vs_x x) ~ vs_x =>
VarsOf (b vs_y y) ~ vs_y =>
a vs_x (x::kx) ->
b vs_y (y::ky) ->
( a (vs_x ++ vs_y) x
, b (vs_x ++ vs_y) y )
appendVars x y =
( allocVarsR (lenVars y) x
, allocVarsL (lenVars x) y
)
newtype NameVar = NameVar Text
deriving (Eq, Ord, Show)
instance IsString NameVar where
fromString = NameVar . fromString
class VarOccursIn a where
varOccursIn :: Var src (VarsOf a) v -> a -> Bool
type family VarsOf a :: [K.Type]
type instance VarsOf (Var src vs v) = vs
type instance VarsOf (UsedVars src vs vs') = vs'
data Vars src vs where
VarsZ :: Vars src '[]
VarsS :: NameVar ->
Kind src kv ->
Vars src vs ->
Vars src (Proxy (v::kv) ': vs)
type instance VarsOf (Vars src vs) = vs
instance LenVars (Vars src vs) where
lenVars VarsZ = LenZ
lenVars (VarsS _n _kv vs) = LenS $ lenVars vs
lookupVars ::
NameVar ->
Vars src vs ->
Maybe (EVar src vs)
lookupVars _n VarsZ = Nothing
lookupVars n (VarsS n' kv vs) =
if n == n'
then Just $ EVar $ VarZ kv (LenS $ lenVars vs)
else (\(EVar v) -> EVar $ VarS v) <$> lookupVars n vs
insertVars ::
NameVar ->
Kind src k ->
Vars src vs ->
(forall vs'. Vars src vs' -> ret) -> ret
insertVars n kv vs k =
case lookupVars n vs of
Just{} -> k vs
Nothing -> k $ VarsS n kv vs
data EVars src = forall vs. EVars (Vars src vs)
data UsedVars src vs vs' where
UsedVarsZ :: UsedVars src vs '[]
UsedVarsS :: Var src vs (v::k) ->
UsedVars src vs vs' ->
UsedVars src vs (Proxy v ': vs')
instance LenVars (UsedVars src vs vs') where
lenVars UsedVarsZ = LenZ
lenVars (UsedVarsS _v vs) = LenS $ lenVars vs
lookupUsedVars ::
Var src vs v ->
UsedVars src vs vs' ->
Maybe (Var src vs' v)
lookupUsedVars _v UsedVarsZ = Nothing
lookupUsedVars v (UsedVarsS v' vs) =
case v `eqVarKi` v' of
Just HRefl -> Just $ VarZ (kindOfVar v) (LenS $ lenVars vs)
Nothing -> VarS <$> lookupUsedVars v vs
insertUsedVars ::
Var src vs v ->
UsedVars src vs vs' ->
Maybe (UsedVars src vs (Proxy v ': vs'))
insertUsedVars v vs =
case lookupUsedVars v vs of
Just{} -> Nothing
Nothing -> Just $ UsedVarsS v vs
class UsedVarsOf a where
usedVarsOf ::
UsedVars (SourceOf a) (VarsOf a) vs -> a ->
(forall vs'. UsedVars (SourceOf a) (VarsOf a) vs' -> ret) -> ret
type family UnProxy (x::K.Type) :: k where
UnProxy (Proxy x) = x