{-# LANGUAGE TemplateHaskell, TupleSections, ParallelListComp, CPP #-}
module Data.Singletons.Single where
import Prelude hiding ( exp )
import Language.Haskell.TH hiding ( cxt )
import Language.Haskell.TH.Syntax (NameSpace(..), Quasi(..))
import Data.Singletons.Deriving.Infer
import Data.Singletons.Deriving.Ord
import Data.Singletons.Deriving.Bounded
import Data.Singletons.Deriving.Enum
import Data.Singletons.Deriving.Show
import Data.Singletons.Deriving.Util
import Data.Singletons.Util
import Data.Singletons.Promote
import Data.Singletons.Promote.Defun
import Data.Singletons.Promote.Monad ( promoteM )
import Data.Singletons.Promote.Type
import Data.Singletons.Names
import Data.Singletons.Single.Monad
import Data.Singletons.Single.Type
import Data.Singletons.Single.Data
import Data.Singletons.Single.Defun
import Data.Singletons.Single.Fixity
import Data.Singletons.Single.Eq
import Data.Singletons.Syntax
import Data.Singletons.Partition
import Language.Haskell.TH.Desugar
import qualified Data.Map.Strict as Map
import Data.Map.Strict ( Map )
import Data.Maybe
import qualified Data.Set as Set
import Data.Set ( Set )
import Control.Monad
import Data.List
import qualified GHC.LanguageExtensions.Type as LangExt
genSingletons :: DsMonad q => [Name] -> q [Dec]
genSingletons names = do
checkForRep names
ddecs <- concatMapM (singInfo <=< dsInfo <=< reifyWithLocals) names
return $ decsToTH ddecs
singletons :: DsMonad q => q [Dec] -> q [Dec]
singletons qdecs = do
decs <- qdecs
ddecs <- withLocalDeclarations decs $ dsDecs decs
singDecs <- singTopLevelDecs decs ddecs
return (decs ++ decsToTH singDecs)
singletonsOnly :: DsMonad q => q [Dec] -> q [Dec]
singletonsOnly = (>>= wrapDesugar singTopLevelDecs)
singEqInstances :: DsMonad q => [Name] -> q [Dec]
singEqInstances = concatMapM singEqInstance
singEqInstance :: DsMonad q => Name -> q [Dec]
singEqInstance name = do
promotion <- promoteEqInstance name
dec <- singEqualityInstance sEqClassDesc name
return $ dec ++ promotion
singEqInstancesOnly :: DsMonad q => [Name] -> q [Dec]
singEqInstancesOnly = concatMapM singEqInstanceOnly
singEqInstanceOnly :: DsMonad q => Name -> q [Dec]
singEqInstanceOnly name = singEqualityInstance sEqClassDesc name
singDecideInstances :: DsMonad q => [Name] -> q [Dec]
singDecideInstances = concatMapM singDecideInstance
singDecideInstance :: DsMonad q => Name -> q [Dec]
singDecideInstance name = singEqualityInstance sDecideClassDesc name
singEqualityInstance :: DsMonad q => EqualityClassDesc q -> Name -> q [Dec]
singEqualityInstance desc@(_, _, className, _) name = do
(tvbs, cons) <- getDataD ("I cannot make an instance of " ++
show className ++ " for it.") name
dtvbs <- mapM dsTvb tvbs
let data_ty = foldTypeTvbs (DConT name) dtvbs
dcons <- concatMapM (dsCon dtvbs data_ty) cons
let tyvars = map (DVarT . extractTvbName) dtvbs
kind = foldType (DConT name) tyvars
(scons, _) <- singM [] $ mapM singCtor dcons
eqInstance <- mkEqualityInstance Nothing kind dcons scons desc
return $ decToTH eqInstance
singOrdInstances :: DsMonad q => [Name] -> q [Dec]
singOrdInstances = concatMapM singOrdInstance
singOrdInstance :: DsMonad q => Name -> q [Dec]
singOrdInstance = singInstance mkOrdInstance "Ord"
singBoundedInstances :: DsMonad q => [Name] -> q [Dec]
singBoundedInstances = concatMapM singBoundedInstance
singBoundedInstance :: DsMonad q => Name -> q [Dec]
singBoundedInstance = singInstance mkBoundedInstance "Bounded"
singEnumInstances :: DsMonad q => [Name] -> q [Dec]
singEnumInstances = concatMapM singEnumInstance
singEnumInstance :: DsMonad q => Name -> q [Dec]
singEnumInstance = singInstance mkEnumInstance "Enum"
singShowInstance :: DsMonad q => Name -> q [Dec]
singShowInstance = singInstance mkShowInstance "Show"
singShowInstances :: DsMonad q => [Name] -> q [Dec]
singShowInstances = concatMapM singShowInstance
showSingInstance :: DsMonad q => Name -> q [Dec]
showSingInstance name = do
(tvbs, cons) <- getDataD ("I cannot make an instance of Show for it.") name
dtvbs <- mapM dsTvb tvbs
let data_ty = foldTypeTvbs (DConT name) dtvbs
dcons <- concatMapM (dsCon dtvbs data_ty) cons
let tyvars = map (DVarT . extractTvbName) dtvbs
kind = foldType (DConT name) tyvars
data_decl = DataDecl name dtvbs dcons
deriv_show_decl = DerivedDecl { ded_mb_cxt = Nothing
, ded_type = kind
, ded_decl = data_decl }
(show_insts, _) <- singM [] $ singDerivedShowDecs deriv_show_decl
pure $ decsToTH show_insts
showSingInstances :: DsMonad q => [Name] -> q [Dec]
showSingInstances = concatMapM showSingInstance
singInstance :: DsMonad q => DerivDesc q -> String -> Name -> q [Dec]
singInstance mk_inst inst_name name = do
(tvbs, cons) <- getDataD ("I cannot make an instance of " ++ inst_name
++ " for it.") name
dtvbs <- mapM dsTvb tvbs
let data_ty = foldTypeTvbs (DConT name) dtvbs
dcons <- concatMapM (dsCon dtvbs data_ty) cons
let data_decl = DataDecl name dtvbs dcons
raw_inst <- mk_inst Nothing data_ty data_decl
(a_inst, decs) <- promoteM [] $
promoteInstanceDec Map.empty raw_inst
decs' <- singDecsM [] $ (:[]) <$> singInstD a_inst
return $ decsToTH (decs ++ decs')
singInfo :: DsMonad q => DInfo -> q [DDec]
singInfo (DTyConI dec _) =
singTopLevelDecs [] [dec]
singInfo (DPrimTyConI _name _numArgs _unlifted) =
fail "Singling of primitive type constructors not supported"
singInfo (DVarI _name _ty _mdec) =
fail "Singling of value info not supported"
singInfo (DTyVarI _name _ty) =
fail "Singling of type variable info not supported"
singInfo (DPatSynI {}) =
fail "Singling of pattern synonym info not supported"
singTopLevelDecs :: DsMonad q => [Dec] -> [DDec] -> q [DDec]
singTopLevelDecs locals raw_decls = withLocalDeclarations locals $ do
decls <- expand raw_decls
PDecs { pd_let_decs = letDecls
, pd_class_decs = classes
, pd_instance_decs = insts
, pd_data_decs = datas
, pd_ty_syn_decs = ty_syns
, pd_open_type_family_decs = o_tyfams
, pd_closed_type_family_decs = c_tyfams
, pd_derived_eq_decs = derivedEqDecs
, pd_derived_show_decs = derivedShowDecs } <- partitionDecs decls
((letDecEnv, classes', insts'), promDecls) <- promoteM locals $ do
defunTypeDecls ty_syns c_tyfams o_tyfams
promoteDataDecs datas
(_, letDecEnv) <- promoteLetDecs noPrefix letDecls
classes' <- mapM promoteClassDec classes
let meth_sigs = foldMap (lde_types . cd_lde) classes
insts' <- mapM (promoteInstanceDec meth_sigs) insts
mapM_ promoteDerivedEqDec derivedEqDecs
return (letDecEnv, classes', insts')
singDecsM locals $ do
let letBinds = concatMap buildDataLets datas
++ concatMap buildMethLets classes
(newLetDecls, singIDefunDecls, newDecls)
<- bindLets letBinds $
singLetDecEnv letDecEnv $ do
newDataDecls <- concatMapM singDataD datas
newClassDecls <- mapM singClassD classes'
newInstDecls <- mapM singInstD insts'
newDerivedEqDecs <- concatMapM singDerivedEqDecs derivedEqDecs
newDerivedShowDecs <- concatMapM singDerivedShowDecs derivedShowDecs
return $ newDataDecls ++ newClassDecls
++ newInstDecls
++ newDerivedEqDecs
++ newDerivedShowDecs
return $ promDecls ++ (map DLetDec newLetDecls) ++ singIDefunDecls ++ newDecls
buildDataLets :: DataDecl -> [(Name, DExp)]
buildDataLets (DataDecl _name _tvbs cons) =
concatMap con_num_args cons
where
con_num_args :: DCon -> [(Name, DExp)]
con_num_args (DCon _tvbs _cxt name fields _rty) =
(name, wrapSingFun (length (tysOfConFields fields))
(promoteValRhs name) (DConE $ singDataConName name))
: rec_selectors fields
rec_selectors :: DConFields -> [(Name, DExp)]
rec_selectors (DNormalC {}) = []
rec_selectors (DRecC fields) =
let names = map fstOf3 fields in
[ (name, wrapSingFun 1 (promoteValRhs name) (DVarE $ singValName name))
| name <- names ]
buildMethLets :: UClassDecl -> [(Name, DExp)]
buildMethLets (ClassDecl { cd_lde = LetDecEnv { lde_types = meth_sigs } }) =
map mk_bind (Map.toList meth_sigs)
where
mk_bind (meth_name, meth_ty) =
( meth_name
, wrapSingFun (countArgs meth_ty) (promoteValRhs meth_name)
(DVarE $ singValName meth_name) )
singClassD :: AClassDecl -> SgM DDec
singClassD (ClassDecl { cd_cxt = cls_cxt
, cd_name = cls_name
, cd_tvbs = cls_tvbs
, cd_fds = cls_fundeps
, cd_lde = LetDecEnv { lde_defns = default_defns
, lde_types = meth_sigs
, lde_infix = fixities
, lde_proms = promoted_defaults
, lde_bound_kvs = meth_bound_kvs } }) =
bindContext [foldPredTvbs (DConPr cls_name) cls_tvbs] $ do
(sing_sigs, _, tyvar_names, cxts, res_kis, singIDefunss)
<- unzip6 <$> zipWithM (singTySig no_meth_defns meth_sigs meth_bound_kvs)
meth_names (map promoteValRhs meth_names)
emitDecs $ concat singIDefunss
let default_sigs = catMaybes $
zipWith4 mk_default_sig meth_names sing_sigs tyvar_names res_kis
res_ki_map = Map.fromList (zip meth_names
(map (fromMaybe always_sig) res_kis))
sing_meths <- mapM (uncurry (singLetDecRHS (Map.fromList tyvar_names)
(Map.fromList cxts)
res_ki_map))
(Map.toList default_defns)
fixities' <- traverse (uncurry singInfixDecl) $ Map.toList fixities
cls_cxt' <- mapM singPred cls_cxt
return $ DClassD cls_cxt'
(singClassName cls_name)
cls_tvbs
cls_fundeps
(map DLetDec (sing_sigs ++ sing_meths ++ fixities') ++ default_sigs)
where
no_meth_defns = error "Internal error: can't find declared method type"
always_sig = error "Internal error: no signature for default method"
meth_names = Map.keys meth_sigs
mk_default_sig meth_name (DSigD s_name sty) bound_kvs (Just res_ki) =
DDefaultSigD s_name <$> add_constraints meth_name sty bound_kvs res_ki
mk_default_sig _ _ _ _ = error "Internal error: a singled signature isn't a signature."
add_constraints meth_name sty (_, bound_kvs) res_ki = do
prom_dflt <- Map.lookup meth_name promoted_defaults
let default_pred = foldPred (DConPr equalityName)
[ foldApply (promoteValRhs meth_name) tvs `DSigT` res_ki
, foldApply prom_dflt tvs ]
return $ DForallT tvbs (default_pred : cxt) (ravel args res)
where
(tvbs, cxt, args, res) = unravel sty
bound_kv_set = Set.fromList bound_kvs
tvs = map tvbToType $
filter (\tvb -> extractTvbName tvb `Set.member` bound_kv_set) tvbs
singInstD :: AInstDecl -> SgM DDec
singInstD (InstDecl { id_cxt = cxt, id_name = inst_name, id_arg_tys = inst_tys
, id_sigs = inst_sigs, id_meths = ann_meths }) = do
bindContext cxt $ do
cxt' <- mapM singPred cxt
inst_kis <- mapM promoteType inst_tys
meths <- concatMapM (uncurry sing_meth) ann_meths
return (DInstanceD Nothing
cxt'
(foldl DAppT (DConT s_inst_name) inst_kis)
meths)
where
s_inst_name = singClassName inst_name
sing_meth :: Name -> ALetDecRHS -> SgM [DDec]
sing_meth name rhs = do
mb_s_info <- dsReify (singValName name)
inst_kis <- mapM promoteType inst_tys
let mk_subst cls_tvbs = Map.fromList $ zip (map extractTvbName vis_cls_tvbs) inst_kis
where
vis_cls_tvbs = drop (length cls_tvbs - length inst_kis) cls_tvbs
sing_meth_ty :: Set Name -> DType
-> SgM (DType, [Name], DCxt, DKind)
sing_meth_ty bound_kvs inner_ty = do
raw_ty <- expand inner_ty
(s_ty, _num_args, tyvar_names, ctxt, _arg_kis, res_ki)
<- singType bound_kvs (promoteValRhs name) raw_ty
pure (s_ty, tyvar_names, ctxt, res_ki)
(s_ty, tyvar_names, ctxt, m_res_ki) <- case Map.lookup name inst_sigs of
Just inst_sig -> do
let inst_bound = foldMap (fvDType . predToType) cxt <> foldMap fvDType inst_kis
(s_ty, tyvar_names, ctxt, res_ki) <- sing_meth_ty inst_bound inst_sig
pure (s_ty, tyvar_names, ctxt, Just res_ki)
Nothing -> case mb_s_info of
Just (DVarI _ (DForallT cls_tvbs _cls_pred s_ty) _) -> do
let subst = mk_subst cls_tvbs
(sing_tvbs, ctxt, _args, res_ty) = unravel s_ty
m_res_ki = case res_ty of
_sing `DAppT` (_prom_func `DSigT` res_ki) -> Just (substKind subst res_ki)
_ -> Nothing
pure ( substType subst s_ty
, map extractTvbName sing_tvbs
, map (substPred subst) ctxt
, m_res_ki )
_ -> do
mb_info <- dsReify name
case mb_info of
Just (DVarI _ (DForallT cls_tvbs _cls_pred inner_ty) _) -> do
let subst = mk_subst cls_tvbs
cls_kvb_names = foldMap (foldMap fvDType . extractTvbKind) cls_tvbs
cls_tvb_names = Set.fromList $ map extractTvbName cls_tvbs
cls_bound = cls_kvb_names `Set.union` cls_tvb_names
(s_ty, tyvar_names, ctxt, res_ki) <- sing_meth_ty cls_bound inner_ty
pure ( substType subst s_ty
, tyvar_names
, ctxt
, Just (substKind subst res_ki) )
_ -> fail $ "Cannot find type of method " ++ show name
let kind_map = maybe Map.empty (Map.singleton name) m_res_ki
meth' <- singLetDecRHS (Map.singleton name tyvar_names)
(Map.singleton name ctxt)
kind_map name rhs
return $ map DLetDec [DSigD (singValName name) s_ty, meth']
singLetDecEnv :: ALetDecEnv
-> SgM a
-> SgM ([DLetDec], [DDec], a)
singLetDecEnv (LetDecEnv { lde_defns = defns
, lde_types = types
, lde_infix = infix_decls
, lde_proms = proms
, lde_bound_kvs = bound_kvs })
thing_inside = do
let prom_list = Map.toList proms
(typeSigs, letBinds, tyvarNames, cxts, res_kis, singIDefunss)
<- unzip6 <$> mapM (uncurry (singTySig defns types bound_kvs)) prom_list
infix_decls' <- traverse (uncurry singInfixDecl) $ Map.toList infix_decls
let res_ki_map = Map.fromList [ (name, res_ki) | ((name, _), Just res_ki)
<- zip prom_list res_kis ]
bindLets letBinds $ do
let_decs <- mapM (uncurry (singLetDecRHS (Map.fromList tyvarNames)
(Map.fromList cxts)
res_ki_map))
(Map.toList defns)
thing <- thing_inside
return (infix_decls' ++ typeSigs ++ let_decs, concat singIDefunss, thing)
singTySig :: Map Name ALetDecRHS
-> Map Name DType
-> Map Name (Set Name)
-> Name -> DType
-> SgM ( DLetDec
, (Name, DExp)
, (Name, [Name])
, (Name, DCxt)
, Maybe DKind
, [DDec]
)
singTySig defns types bound_kvs name prom_ty =
let sName = singValName name in
case Map.lookup name types of
Nothing -> do
num_args <- guess_num_args
(sty, tyvar_names) <- mk_sing_ty num_args
singIDefuns <- singDefuns name VarName []
(map (const Nothing) tyvar_names) Nothing
return ( DSigD sName sty
, (name, wrapSingFun num_args prom_ty (DVarE sName))
, (name, tyvar_names)
, (name, [])
, Nothing
, singIDefuns )
Just ty -> do
all_bound_kvs <- lookup_bound_kvs
(sty, num_args, tyvar_names, ctxt, arg_kis, res_ki)
<- singType all_bound_kvs prom_ty ty
bound_cxt <- askContext
singIDefuns <- singDefuns name VarName (bound_cxt ++ ctxt)
(map Just arg_kis) (Just res_ki)
return ( DSigD sName sty
, (name, wrapSingFun num_args prom_ty (DVarE sName))
, (name, tyvar_names)
, (name, ctxt)
, Just res_ki
, singIDefuns )
where
guess_num_args :: SgM Int
guess_num_args =
case Map.lookup name defns of
Nothing -> fail "Internal error: promotion known for something not let-bound."
Just (AValue _ n _) -> return n
Just (AFunction _ n _) -> return n
lookup_bound_kvs :: SgM (Set Name)
lookup_bound_kvs =
case Map.lookup name bound_kvs of
Nothing -> fail $ "Internal error: " ++ nameBase name ++ " has no type variable "
++ "bindings, despite having a type signature"
Just kvs -> pure kvs
mk_sing_ty :: Int -> SgM (DType, [Name])
mk_sing_ty n = do
arg_names <- replicateM n (qNewName "arg")
return ( DForallT (map DPlainTV arg_names) []
(ravel (map (\nm -> singFamily `DAppT` DVarT nm) arg_names)
(singFamily `DAppT`
(foldl apply prom_ty (map DVarT arg_names))))
, arg_names )
singLetDecRHS :: Map Name [Name]
-> Map Name DCxt
-> Map Name DKind
-> Name -> ALetDecRHS -> SgM DLetDec
singLetDecRHS bound_names cxts res_kis name ld_rhs =
bindContext (Map.findWithDefault [] name cxts) $
case ld_rhs of
AValue prom num_arrows exp ->
DValD (DVarPa (singValName name)) <$>
(wrapUnSingFun num_arrows prom <$> singExp exp (Map.lookup name res_kis))
AFunction prom_fun num_arrows clauses ->
let tyvar_names = case Map.lookup name bound_names of
Nothing -> []
Just ns -> ns
res_ki = Map.lookup name res_kis
in
DFunD (singValName name) <$>
mapM (singClause prom_fun num_arrows tyvar_names res_ki) clauses
singClause :: DType
-> Int
-> [Name]
-> Maybe DKind
-> ADClause -> SgM DClause
singClause prom_fun num_arrows bound_names res_ki
(ADClause var_proms pats exp) = do
when (num_arrows - length pats < 0) $
fail $ "Function being promoted to " ++ (pprint (typeToTH prom_fun)) ++
" has too many arguments."
(sPats, sigPaExpsSigs) <- evalForPair $ mapM (singPat (Map.fromList var_proms)) pats
sBody <- singExp exp res_ki
let pattern_bound_names = zipWith const bound_names pats
sBody' = wrapUnSingFun (num_arrows - length pats)
(foldl apply prom_fun (map DVarT pattern_bound_names)) sBody
return $ DClause sPats $ mkSigPaCaseE sigPaExpsSigs sBody'
singPat :: Map Name Name
-> ADPat
-> QWithAux SingDSigPaInfos SgM DPat
singPat var_proms = go
where
go :: ADPat -> QWithAux SingDSigPaInfos SgM DPat
go (ADLitPa _lit) =
fail "Singling of literal patterns not yet supported"
go (ADVarPa name) = do
tyname <- case Map.lookup name var_proms of
Nothing ->
fail "Internal error: unknown variable when singling pattern"
Just tyname -> return tyname
pure $ DVarPa (singValName name) `DSigPa` (singFamily `DAppT` DVarT tyname)
go (ADConPa name pats) = DConPa (singDataConName name) <$> mapM go pats
go (ADTildePa pat) = do
qReportWarning
"Lazy pattern converted into regular pattern during singleton generation."
go pat
go (ADBangPa pat) = DBangPa <$> go pat
go (ADSigPa prom_pat pat ty) = do
pat' <- go pat
addElement (dPatToDExp pat', DSigT prom_pat ty)
pure pat'
go ADWildPa = pure DWildPa
mkSigPaCaseE :: SingDSigPaInfos -> DExp -> DExp
mkSigPaCaseE exps_with_sigs exp
| null exps_with_sigs = exp
| otherwise =
let (exps, sigs) = unzip exps_with_sigs
scrutinee = mkTupleDExp exps
pats = map (DSigPa DWildPa . DAppT (DConT singFamilyName)) sigs
in DCaseE scrutinee [DMatch (mkTupleDPat pats) exp]
singExp :: ADExp -> Maybe DKind
-> SgM DExp
singExp (ADVarE err `ADAppE` arg) _res_ki
| err == errorName = DAppE (DVarE (singValName err)) <$>
singExp arg (Just (DConT symbolName))
singExp (ADVarE name) _res_ki = lookupVarE name
singExp (ADConE name) _res_ki = lookupConE name
singExp (ADLitE lit) _res_ki = singLit lit
singExp (ADAppE e1 e2) _res_ki = do
e1' <- singExp e1 Nothing
e2' <- singExp e2 Nothing
if isException e1'
then return $ e1' `DAppE` e2'
else return $ (DVarE applySingName) `DAppE` e1' `DAppE` e2'
singExp (ADLamE ty_names prom_lam names exp) _res_ki = do
let sNames = map singValName names
exp' <- singExp exp Nothing
let caseExp = DCaseE (mkTupleDExp (map DVarE sNames))
[DMatch (mkTupleDPat
(map ((DWildPa `DSigPa`) .
(singFamily `DAppT`) .
DVarT) ty_names)) exp']
return $ wrapSingFun (length names) prom_lam $ DLamE sNames caseExp
singExp (ADCaseE exp matches ret_ty) res_ki =
DSigE <$> (DCaseE <$> singExp exp Nothing <*> mapM (singMatch res_ki) matches)
<*> pure (singFamily `DAppT` (ret_ty `maybeSigT` res_ki))
singExp (ADLetE env exp) res_ki = do
(let_decs, _, exp') <- singLetDecEnv env $ singExp exp res_ki
pure $ DLetE let_decs exp'
singExp (ADSigE prom_exp exp ty) _ = do
exp' <- singExp exp (Just ty)
pure $ DSigE exp' $ DConT singFamilyName `DAppT` DSigT prom_exp ty
singDerivedEqDecs :: DerivedEqDecl -> SgM [DDec]
singDerivedEqDecs (DerivedDecl { ded_mb_cxt = mb_ctxt
, ded_type = ty
, ded_decl = DataDecl _ _ cons }) = do
(scons, _) <- singM [] $ mapM singCtor cons
mb_sctxt <- mapM (mapM singPred) mb_ctxt
kind <- promoteType ty
sEqInst <- mkEqualityInstance mb_sctxt kind cons scons sEqClassDesc
let mb_sctxtDecide = fmap (map sEqToSDecide) mb_sctxt
sDecideInst <- mkEqualityInstance mb_sctxtDecide kind cons scons sDecideClassDesc
return [sEqInst, sDecideInst]
sEqToSDecide :: DPred -> DPred
sEqToSDecide = modifyConNameDPred $ \n ->
if nameBase n == nameBase sEqClassName
then sDecideClassName
else n
singDerivedShowDecs :: DerivedShowDecl -> SgM [DDec]
singDerivedShowDecs (DerivedDecl { ded_mb_cxt = mb_cxt
, ded_type = ty
, ded_decl = DataDecl _ _ cons }) = do
z <- qNewName "z"
show_cxt <- inferConstraintsDef (fmap mkShowSingContext mb_cxt)
(DConPr showSingName)
ty cons
let show_inst = DStandaloneDerivD Nothing show_cxt
(DConT showName `DAppT` (singFamily `DAppT` DSigT (DVarT z) ty))
pure [show_inst]
isException :: DExp -> Bool
isException (DVarE n) = nameBase n == "sUndefined"
isException (DConE {}) = False
isException (DLitE {}) = False
isException (DAppE (DVarE fun) _) | nameBase fun == "sError" = True
isException (DAppE fun _) = isException fun
isException (DAppTypeE e _) = isException e
isException (DLamE _ _) = False
isException (DCaseE e _) = isException e
isException (DLetE _ e) = isException e
isException (DSigE e _) = isException e
isException (DStaticE e) = isException e
singMatch :: Maybe DKind
-> ADMatch -> SgM DMatch
singMatch res_ki (ADMatch var_proms pat exp) = do
(sPat, sigPaExpsSigs) <- evalForPair $ singPat (Map.fromList var_proms) pat
sExp <- singExp exp res_ki
return $ DMatch sPat $ mkSigPaCaseE sigPaExpsSigs sExp
singLit :: Lit -> SgM DExp
singLit (IntegerL n)
| n >= 0 = return $
DVarE sFromIntegerName `DAppE`
(DVarE singMethName `DSigE`
(singFamily `DAppT` DLitT (NumTyLit n)))
| otherwise = do sLit <- singLit (IntegerL (-n))
return $ DVarE sNegateName `DAppE` sLit
singLit (StringL str) = do
let sing_str_lit = DVarE singMethName `DSigE`
(singFamily `DAppT` DLitT (StrTyLit str))
os_enabled <- qIsExtEnabled LangExt.OverloadedStrings
pure $ if os_enabled
then DVarE sFromStringName `DAppE` sing_str_lit
else sing_str_lit
singLit lit =
fail ("Only string and natural number literals can be singled: " ++ show lit)
maybeSigT :: DType -> Maybe DKind -> DType
maybeSigT ty Nothing = ty
maybeSigT ty (Just ki) = ty `DSigT` ki