{-# LANGUAGE DataKinds, TypeFamilies, PolyKinds, DeriveDataTypeable,
StandaloneDeriving, FlexibleInstances, ConstraintKinds #-}
module Data.Singletons.Syntax where
import Prelude hiding ( exp )
import Data.Kind
import Language.Haskell.TH.Syntax hiding (Type)
import Language.Haskell.TH.Desugar
import Data.Map.Strict ( Map )
import qualified Data.Map.Strict as Map
import Data.Semigroup (Semigroup(..))
type VarPromotions = [(Name, Name)]
data DataDecl = DataDecl NewOrData Name [DTyVarBndr] [DCon] [DPred]
data ClassDecl ann = ClassDecl { cd_cxt :: DCxt
, cd_name :: Name
, cd_tvbs :: [DTyVarBndr]
, cd_fds :: [FunDep]
, cd_lde :: LetDecEnv ann }
data InstDecl ann = InstDecl { id_cxt :: DCxt
, id_name :: Name
, id_arg_tys :: [DType]
, id_meths :: [(Name, LetDecRHS ann)] }
type UClassDecl = ClassDecl Unannotated
type UInstDecl = InstDecl Unannotated
type AClassDecl = ClassDecl Annotated
type AInstDecl = InstDecl Annotated
data ADExp = ADVarE Name
| ADConE Name
| ADLitE Lit
| ADAppE ADExp ADExp
| ADLamE [Name]
DType
[Name] ADExp
| ADCaseE ADExp [ADMatch] DType
| ADLetE ALetDecEnv ADExp
| ADSigE ADExp DType
data ADMatch = ADMatch VarPromotions DPat ADExp
data ADClause = ADClause VarPromotions
[DPat] ADExp
data AnnotationFlag = Annotated | Unannotated
type Annotated = 'Annotated
type Unannotated = 'Unannotated
type family IfAnn (ann :: AnnotationFlag) (yes :: k) (no :: k) :: k where
IfAnn Annotated yes no = yes
IfAnn Unannotated yes no = no
data family LetDecRHS (ann :: AnnotationFlag)
data instance LetDecRHS Annotated
= AFunction DType
Int
[ADClause]
| AValue DType
Int
ADExp
data instance LetDecRHS Unannotated = UFunction [DClause]
| UValue DExp
type ALetDecRHS = LetDecRHS Annotated
type ULetDecRHS = LetDecRHS Unannotated
data LetDecEnv ann = LetDecEnv
{ lde_defns :: Map Name (LetDecRHS ann)
, lde_types :: Map Name DType
, lde_infix :: [(Fixity, Name)]
, lde_proms :: IfAnn ann (Map Name DType) ()
}
type ALetDecEnv = LetDecEnv Annotated
type ULetDecEnv = LetDecEnv Unannotated
instance Semigroup ULetDecEnv where
LetDecEnv defns1 types1 infx1 _ <> LetDecEnv defns2 types2 infx2 _ =
LetDecEnv (defns1 <> defns2) (types1 <> types2) (infx1 <> infx2) ()
instance Monoid ULetDecEnv where
mempty = LetDecEnv Map.empty Map.empty [] ()
mappend = (<>)
valueBinding :: Name -> ULetDecRHS -> ULetDecEnv
valueBinding n v = emptyLetDecEnv { lde_defns = Map.singleton n v }
typeBinding :: Name -> DType -> ULetDecEnv
typeBinding n t = emptyLetDecEnv { lde_types = Map.singleton n t }
infixDecl :: Fixity -> Name -> ULetDecEnv
infixDecl f n = emptyLetDecEnv { lde_infix = [(f,n)] }
emptyLetDecEnv :: ULetDecEnv
emptyLetDecEnv = mempty
buildLetDecEnv :: Quasi q => [DLetDec] -> q ULetDecEnv
buildLetDecEnv = go emptyLetDecEnv
where
go acc [] = return acc
go acc (DFunD name clauses : rest) =
go (valueBinding name (UFunction clauses) <> acc) rest
go acc (DValD (DVarPa name) exp : rest) =
go (valueBinding name (UValue exp) <> acc) rest
go acc (dec@(DValD {}) : rest) = do
flattened <- flattenDValD dec
go acc (flattened ++ rest)
go acc (DSigD name ty : rest) =
go (typeBinding name ty <> acc) rest
go acc (DInfixD f n : rest) =
go (infixDecl f n <> acc) rest
go acc (DPragmaD{} : rest) = go acc rest
data DerivedDecl (cls :: Type -> Constraint) = DerivedDecl
{ ded_mb_cxt :: Maybe DCxt
, ded_type :: DType
, ded_cons :: [DCon]
}
type DerivedEqDecl = DerivedDecl Eq
type DerivedShowDecl = DerivedDecl Show