import Name
import TyCon
import Type
+import TypeRep
import Coercion
import Var
import VarSet
+import VarEnv
import TysWiredIn
-import TysPrim( intPrimTy )
+import TysPrim( intPrimTy, ecKind )
import PrimOp( tagToEnumKey )
import PrelNames
import Module
import Util
import ListSetOps
import Maybes
+import ErrUtils
import Outputable
import FastString
import Control.Monad
%************************************************************************
\begin{code}
+
+updHetMetLevel :: ([TyVar] -> [TyVar]) -> TcM a -> TcM a
+updHetMetLevel f comp =
+ updEnv
+ (\oldenv -> let oldlev = (case oldenv of Env { env_lcl = e' } -> case e' of TcLclEnv { tcl_hetMetLevel = x } -> x)
+ in (oldenv { env_lcl = (env_lcl oldenv) { tcl_hetMetLevel = f oldlev } }))
+
+ comp
+
+addEscapes :: [TyVar] -> HsExpr Name -> HsExpr Name
+addEscapes [] e = e
+addEscapes (t:ts) e = HsHetMetEsc (TyVarTy t) placeHolderType (noLoc (addEscapes ts e))
+
+getIdLevel :: Name -> TcM [TyVar]
+getIdLevel name
+ = do { thing <- tcLookup name
+ ; case thing of
+ ATcId { tct_hetMetLevel = variable_hetMetLevel } -> return $ variable_hetMetLevel
+ _ -> return []
+ }
+
tcExpr :: HsExpr Name -> TcRhoType -> TcM (HsExpr TcId)
tcExpr e res_ty | debugIsOn && isSigmaTy res_ty -- Sanity check
= pprPanic "tcExpr: sigma" (ppr res_ty $$ ppr e)
tcExpr (HsVar name) res_ty = tcCheckId name res_ty
-tcExpr (HsApp e1 e2) res_ty = tcApp e1 [e2] res_ty
+tcExpr (HsHetMetBrak _ e) res_ty =
+ do { (coi, [inferred_name,elt_ty]) <- matchExpectedTyConApp hetMetCodeTypeTyCon res_ty
+ ; fresh_ec_name <- newFlexiTyVar ecKind
+ ; expr' <- updHetMetLevel (\old_lev -> (fresh_ec_name:old_lev))
+ $ tcPolyExpr e elt_ty
+ ; unifyType (TyVarTy fresh_ec_name) inferred_name
+ ; return $ mkHsWrapCo coi (HsHetMetBrak (TyVarTy fresh_ec_name) expr') }
+tcExpr (HsHetMetEsc _ _ e) res_ty =
+ do { cur_level <- getHetMetLevel
+ ; expr' <- updHetMetLevel (\old_lev -> tail old_lev)
+ $ tcExpr (unLoc e) (mkTyConApp hetMetCodeTypeTyCon [(TyVarTy $ head cur_level),res_ty])
+ ; ty' <- zonkTcType res_ty
+ ; return $ HsHetMetEsc (TyVarTy $ head cur_level) ty' (noLoc expr') }
+tcExpr (HsHetMetCSP _ e) res_ty =
+ do { cur_level <- getHetMetLevel
+ ; expr' <- updHetMetLevel (\old_lev -> tail old_lev)
+ $ tcExpr (unLoc e) res_ty
+ ; return $ HsHetMetCSP (TyVarTy $ head cur_level) (noLoc expr') }
+
+tcExpr (HsKappa match) res_ty =
+ do { v1 <- newFlexiTyVar liftedTypeKind
+ ; v2 <- newFlexiTyVar liftedTypeKind
+ ; v3 <- newFlexiTyVar liftedTypeKind
+ ; (_, [ty_ab, ty_c]) <- matchExpectedTyConApp hetMetKappaTyCon res_ty
+ ; (_, [ty_a, ty_b]) <- matchExpectedTyConApp pairTyCon ty_ab
+ ; (co_fn, match') <- tcMatchLambda match (mkFunTy
+ (mkHetMetKappaTy unitTy ty_a)
+ (mkHetMetKappaTy ty_b ty_c))
+ ; return (HsKappa match') }
+
+tcExpr (HsKappaApp e1 e2) res_ty =
+ do { v1 <- newFlexiTyVar liftedTypeKind
+ ; v2 <- newFlexiTyVar liftedTypeKind
+ ; v3 <- newFlexiTyVar liftedTypeKind
+ ; e1' <- tcExpr (unLoc e1) (mkHetMetKappaTy (mkTyConApp pairTyCon [(TyVarTy v1), (TyVarTy v2)]) (TyVarTy v3))
+ ; e2' <- tcExpr (unLoc e2) (mkHetMetKappaTy unitTy (TyVarTy v1))
+ ; unifyType res_ty (mkHetMetKappaTy (TyVarTy v2) (TyVarTy v3))
+ ; return (HsKappaApp (noLoc e1') (noLoc e2')) }
-tcExpr (HsLit lit) res_ty = do { let lit_ty = hsLitType lit
- ; tcWrapResult (HsLit lit) lit_ty res_ty }
+tcExpr (HsApp e1 e2) res_ty = tcApp e1 [e2] res_ty
+tcExpr (HsLit lit) res_ty =
+ getHetMetLevel >>= \lev ->
+ case lev of
+ [] -> do { let lit_ty = hsLitType lit
+ ; tcWrapResult (HsLit lit) lit_ty res_ty }
+ (ec:rest) -> let n = case lit of
+ (HsChar c) -> hetmet_guest_char_literal_name
+ (HsString str) -> hetmet_guest_string_literal_name
+ (HsInteger i _) -> hetmet_guest_integer_literal_name
+ (HsInt i) -> hetmet_guest_integer_literal_name
+ _ -> error "literals of this sort are not allowed at depth >0"
+ in tcExpr (HsHetMetEsc (TyVarTy ec) placeHolderType $ noLoc $
+ (HsApp (noLoc $ HsVar n) (noLoc $ HsLit lit))) res_ty
+
tcExpr (HsPar expr) res_ty = do { expr' <- tcMonoExprNC expr res_ty
; return (HsPar expr') }
= do { expr' <- tcMonoExpr expr res_ty
; return (HsCoreAnn lbl expr') }
-tcExpr (HsOverLit lit) res_ty
- = do { lit' <- newOverloadedLit (LiteralOrigin lit) lit res_ty
- ; return (HsOverLit lit') }
+tcExpr (HsOverLit lit) res_ty =
+ getHetMetLevel >>= \lev ->
+ case lev of
+ [] -> do { lit' <- newOverloadedLit (LiteralOrigin lit) lit res_ty
+ ; return (HsOverLit lit') }
+ (ec:rest) -> let n = case lit of
+ (OverLit { ol_val = HsIntegral i }) -> hetmet_guest_integer_literal_name
+ (OverLit { ol_val = HsIsString fs }) -> hetmet_guest_string_literal_name
+ (OverLit { ol_val = HsFractional f }) -> error "fractional literals not allowed at depth >0"
+ in tcExpr (HsHetMetEsc (TyVarTy ec) placeHolderType $ noLoc $
+ (HsApp (noLoc $ HsVar n) (noLoc $ HsOverLit lit))) res_ty
+
tcExpr (NegApp expr neg_expr) res_ty
= do { neg_expr' <- tcSyntaxOp NegateOrigin neg_expr
-- and it maintains uniformity with other rebindable syntax
; return (HsIf (Just fun') pred' b1' b2') }
-tcExpr (HsDo do_or_lc stmts body _) res_ty
- = tcDoStmts do_or_lc stmts body res_ty
+tcExpr (HsDo do_or_lc stmts _) res_ty
+ = tcDoStmts do_or_lc stmts res_ty
tcExpr (HsProc pat cmd) res_ty
= do { (pat', cmd', coi) <- tcProc pat cmd res_ty
-- Typecheck the result, thereby propagating
-- info (if any) from result into the argument types
-- Both actual_res_ty and res_ty are deeply skolemised
- ; co_res <- addErrCtxt (funResCtxt fun) $
+ ; co_res <- addErrCtxtM (funResCtxt fun actual_res_ty res_ty) $
unifyType actual_res_ty res_ty
-- Typecheck the arguments
tcInferIdWithOrig :: CtOrigin -> Name -> TcM (HsExpr TcId, TcRhoType)
-- Look up an occurrence of an Id, and instantiate it (deeply)
-tcInferIdWithOrig orig id_name
- = do { id <- lookup_id
- ; (id_expr, id_rho) <- instantiateOuter orig id
- ; (wrap, rho) <- deeplyInstantiate orig id_rho
- ; return (mkHsWrap wrap id_expr, rho) }
+tcInferIdWithOrig orig id_name =
+ do { id_level <- getIdLevel id_name
+ ; cur_level <- getHetMetLevel
+ ; if (length id_level < length cur_level)
+ then do { (lhexp, tcrho) <-
+ tcInferRho (noLoc $ addEscapes (take ((length cur_level) - (length id_level)) cur_level) (HsVar id_name))
+ ; return (unLoc lhexp, tcrho)
+ }
+ else tcInferIdWithOrig' orig id_name
+ }
+
+tcInferIdWithOrig' orig id_name =
+ do { id <- lookup_id
+ ; (id_expr, id_rho) <- instantiateOuter orig id
+ ; (wrap, rho) <- deeplyInstantiate orig id_rho
+ ; return (mkHsWrap wrap id_expr, rho) }
where
lookup_id :: TcM TcId
lookup_id
= do { thing <- tcLookup id_name
; case thing of
- ATcId { tct_id = id, tct_level = lvl }
+ ATcId { tct_id = id, tct_level = lvl, tct_hetMetLevel = variable_hetMetLevel }
-> do { check_naughty id -- Note [Local record selectors]
; checkThLocalId id lvl
+ ; current_hetMetLevel <- getHetMetLevel
+ ; mapM
+ (\(name1,name2) -> unifyType (TyVarTy name1) (TyVarTy name2))
+ (zip variable_hetMetLevel current_hetMetLevel)
; return id }
AGlobal (AnId id)
- -> do { check_naughty id; return id }
- -- A global cannot possibly be ill-staged
+ -> do { check_naughty id
+ ; return id }
+ -- A global cannot possibly be ill-staged in Template Haskell
-- nor does it need the 'lifting' treatment
-- hence no checkTh stuff here
quotes (ppr fun) <> text ", namely"])
2 (quotes (ppr arg))
-funResCtxt :: LHsExpr Name -> SDoc
-funResCtxt fun
- = ptext (sLit "In the return type of a call of") <+> quotes (ppr fun)
+funResCtxt :: LHsExpr Name -> TcType -> TcType
+ -> TidyEnv -> TcM (TidyEnv, Message)
+-- When we have a mis-match in the return type of a function
+-- try to give a helpful message about too many/few arguments
+funResCtxt fun fun_res_ty res_ty env0
+ = do { fun_res' <- zonkTcType fun_res_ty
+ ; res' <- zonkTcType res_ty
+ ; let n_fun = length (fst (tcSplitFunTys fun_res'))
+ n_res = length (fst (tcSplitFunTys res'))
+ what | n_fun > n_res = ptext (sLit "few")
+ | otherwise = ptext (sLit "many")
+ extra | n_fun == n_res = empty
+ | otherwise = ptext (sLit "Probable cause:") <+> quotes (ppr fun)
+ <+> ptext (sLit "is applied to too") <+> what
+ <+> ptext (sLit "arguments")
+ msg = ptext (sLit "In the return type of a call of") <+> quotes (ppr fun)
+ ; return (env0, msg $$ extra) }
badFieldTypes :: [(Name,TcType)] -> SDoc
badFieldTypes prs