X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Ftypecheck%2FTcMatches.lhs;h=29890a21b54973ae4237a74c39a8b515984e4728;hp=60bf7e2c3e5a1af468895d2b8f0395a320b0e6c0;hb=HEAD;hpb=4ac2bb39dffb4b825ece73b349ff0d56d79092d7 diff --git a/compiler/typecheck/TcMatches.lhs b/compiler/typecheck/TcMatches.lhs index 60bf7e2..29890a2 100644 --- a/compiler/typecheck/TcMatches.lhs +++ b/compiler/typecheck/TcMatches.lhs @@ -6,13 +6,14 @@ TcMatches: Typecheck some @Matches@ \begin{code} +{-# OPTIONS_GHC -w #-} -- debugging module TcMatches ( tcMatchesFun, tcGRHSsPat, tcMatchesCase, tcMatchLambda, - TcMatchCtxt(..), - tcStmts, tcDoStmts, tcBody, - tcDoStmt, tcMDoStmt, tcGuardStmt + TcMatchCtxt(..), TcStmtChecker, + tcStmts, tcStmtsAndThen, tcDoStmts, tcBody, + tcDoStmt, tcGuardStmt ) where -import {-# SOURCE #-} TcExpr( tcSyntaxOp, tcInferRhoNC, tcCheckId, +import {-# SOURCE #-} TcExpr( tcSyntaxOp, tcInferRhoNC, tcInferRho, tcCheckId, tcMonoExpr, tcMonoExprNC, tcPolyExpr ) import HsSyn @@ -29,7 +30,7 @@ import TysWiredIn import Id import TyCon import TysPrim -import Coercion ( mkSymCoI ) +import Coercion ( isReflCo, mkSymCo ) import Outputable import Util import SrcLoc @@ -146,7 +147,7 @@ matchFunTys matchFunTys herald arity res_ty thing_inside = do { (coi, pat_tys, res_ty) <- matchExpectedFunTys herald arity res_ty ; res <- thing_inside pat_tys res_ty - ; return (coiToHsWrapper (mkSymCoI coi), res) } + ; return (coToHsWrapper (mkSymCo coi), res) } \end{code} %************************************************************************ @@ -224,7 +225,7 @@ tcGRHSs ctxt (GRHSs grhss binds) res_ty tcGRHS :: TcMatchCtxt -> TcRhoType -> GRHS Name -> TcM (GRHS TcId) tcGRHS ctxt res_ty (GRHS guards rhs) - = do { (guards', rhs') <- tcStmts stmt_ctxt tcGuardStmt guards res_ty $ + = do { (guards', rhs') <- tcStmtsAndThen stmt_ctxt tcGuardStmt guards res_ty $ mc_body ctxt rhs ; return (GRHS guards' rhs') } where @@ -245,15 +246,15 @@ tcDoStmts :: HsStmtContext Name -> TcM (HsExpr TcId) -- Returns a HsDo tcDoStmts ListComp stmts res_ty = do { (coi, elt_ty) <- matchExpectedListTy res_ty - ; stmts' <- tcStmts ListComp (tcLcStmt listTyCon) stmts res_ty - ; return $ mkHsWrapCoI coi - (HsDo ListComp stmts' (mkListTy elt_ty)) } + ; let list_ty = mkListTy elt_ty + ; stmts' <- tcStmts ListComp (tcLcStmt listTyCon) stmts elt_ty + ; return $ mkHsWrapCo coi (HsDo ListComp stmts' list_ty) } tcDoStmts PArrComp stmts res_ty = do { (coi, elt_ty) <- matchExpectedPArrTy res_ty + ; let parr_ty = mkPArrTy elt_ty ; stmts' <- tcStmts PArrComp (tcLcStmt parrTyCon) stmts elt_ty - ; return $ mkHsWrapCoI coi - (HsDo PArrComp stmts' (mkPArrTy elt_ty)) } + ; return $ mkHsWrapCo coi (HsDo PArrComp stmts' parr_ty) } tcDoStmts DoExpr stmts res_ty = do { stmts' <- tcStmts DoExpr tcDoStmt stmts res_ty @@ -267,7 +268,7 @@ tcDoStmts MonadComp stmts res_ty = do { stmts' <- tcStmts MonadComp tcMcStmt stmts res_ty ; return (HsDo MonadComp stmts' res_ty) } -tcDoStmts ctxt _ _ _ _ = pprPanic "tcDoStmts" (pprStmtContext ctxt) +tcDoStmts ctxt _ _ = pprPanic "tcDoStmts" (pprStmtContext ctxt) tcBody :: LHsExpr Name -> TcRhoType -> TcM (LHsExpr TcId) tcBody body res_ty @@ -298,7 +299,7 @@ tcStmts :: HsStmtContext Name -> TcRhoType -> TcM [LStmt TcId] tcStmts ctxt stmt_chk stmts res_ty - = do { (stmts', _) <- tcStmtsAndThen ctxt stmt_check stmts res_ty $ + = do { (stmts', _) <- tcStmtsAndThen ctxt stmt_chk stmts res_ty $ const (return ()) ; return stmts' } @@ -333,8 +334,10 @@ tcStmtsAndThen ctxt stmt_chk (L loc stmt : stmts) res_ty thing_inside thing_inside ; return (L loc stmt' : stmts', thing) } --------------------------------- --- Pattern guards +--------------------------------------------------- +-- Pattern guards +--------------------------------------------------- + tcGuardStmt :: TcStmtChecker tcGuardStmt _ (ExprStmt guard _ _ _) res_ty thing_inside = do { guard' <- tcMonoExpr guard boolTy @@ -351,15 +354,26 @@ tcGuardStmt _ stmt _ _ = pprPanic "tcGuardStmt: unexpected Stmt" (ppr stmt) --------------------------------- --- List comprehensions and PArrays +--------------------------------------------------- +-- List comprehensions and PArrays +-- (no rebindable syntax) +--------------------------------------------------- + +-- Dealt with separately, rather than by tcMcStmt, because +-- a) PArr isn't (yet) an instance of Monad, so the generality seems overkill +-- b) We have special desugaring rules for list comprehensions, +-- which avoid creating intermediate lists. They in turn +-- assume that the bind/return operations are the regular +-- polymorphic ones, and in particular don't have any +-- coercion matching stuff in them. It's hard to avoid the +-- potential for non-trivial coercions in tcMcStmt tcLcStmt :: TyCon -- The list/Parray type constructor ([] or PArray) -> TcStmtChecker -tcLcStmt m_tc ctxt (LastStmt body _) elt_ty thing_inside - = do { body' <- tcMonoExpr body elt_ty - ; thing <- thing_inside elt_ty +tcLcStmt _ _ (LastStmt body _) elt_ty thing_inside + = do { body' <- tcMonoExprNC body elt_ty + ; thing <- thing_inside (panic "tcLcStmt: thing_inside") ; return (LastStmt body' noSyntaxExpr, thing) } -- A generator, pat <- rhs @@ -376,27 +390,7 @@ tcLcStmt _ _ (ExprStmt rhs _ _ _) elt_ty thing_inside ; thing <- thing_inside elt_ty ; return (ExprStmt rhs' noSyntaxExpr noSyntaxExpr boolTy, thing) } --- A parallel set of comprehensions --- [ (g x, h x) | ... ; let g v = ... --- | ... ; let h v = ... ] --- --- It's possible that g,h are overloaded, so we need to feed the LIE from the --- (g x, h x) up through both lots of bindings (so we get the bindLocalMethods). --- Similarly if we had an existential pattern match: --- --- data T = forall a. Show a => C a --- --- [ (show x, show y) | ... ; C x <- ... --- | ... ; C y <- ... ] --- --- Then we need the LIE from (show x, show y) to be simplified against --- the bindings for x and y. --- --- It's difficult to do this in parallel, so we rely on the renamer to --- ensure that g,h and x,y don't duplicate, and simply grow the environment. --- So the binders of the first parallel group will be in scope in the second --- group. But that's fine; there's no shadowing to worry about. - +-- ParStmt: See notes with tcMcStmt tcLcStmt m_tc ctxt (ParStmt bndr_stmts_s _ _ _) elt_ty thing_inside = do { (pairs', thing) <- loop bndr_stmts_s ; return (ParStmt pairs' noSyntaxExpr noSyntaxExpr noSyntaxExpr, thing) } @@ -407,101 +401,90 @@ tcLcStmt m_tc ctxt (ParStmt bndr_stmts_s _ _ _) elt_ty thing_inside loop ((stmts, names) : pairs) = do { (stmts', (ids, pairs', thing)) - <- tcStmts ctxt (tcLcStmt m_tc) stmts elt_ty $ \ _elt_ty' -> + <- tcStmtsAndThen ctxt (tcLcStmt m_tc) stmts elt_ty $ \ _elt_ty' -> do { ids <- tcLookupLocalIds names ; (pairs', thing) <- loop pairs ; return (ids, pairs', thing) } ; return ( (stmts', ids) : pairs', thing ) } -tcLcStmt m_tc ctxt (TransformStmt stmts binders usingExpr maybeByExpr _ _) elt_ty thing_inside = do - (stmts', (binders', usingExpr', maybeByExpr', thing)) <- - tcStmts (TransformStmtCtxt ctxt) (tcLcStmt m_tc) stmts elt_ty $ \elt_ty' -> do - let alphaListTy = mkTyConApp m_tc [alphaTy] - - (usingExpr', maybeByExpr') <- - case maybeByExpr of - Nothing -> do - -- We must validate that usingExpr :: forall a. [a] -> [a] - let using_ty = mkForAllTy alphaTyVar (alphaListTy `mkFunTy` alphaListTy) - usingExpr' <- tcPolyExpr usingExpr using_ty - return (usingExpr', Nothing) - Just byExpr -> do - -- We must infer a type such that e :: t and then check that - -- usingExpr :: forall a. (a -> t) -> [a] -> [a] - (byExpr', tTy) <- tcInferRhoNC byExpr - let using_ty = mkForAllTy alphaTyVar $ - (alphaTy `mkFunTy` tTy) - `mkFunTy` alphaListTy `mkFunTy` alphaListTy - usingExpr' <- tcPolyExpr usingExpr using_ty - return (usingExpr', Just byExpr') - - binders' <- tcLookupLocalIds binders - thing <- thing_inside elt_ty' - - return (binders', usingExpr', maybeByExpr', thing) - - return (TransformStmt stmts' binders' usingExpr' maybeByExpr' noSyntaxExpr noSyntaxExpr, thing) - -tcLcStmt m_tc ctxt (GroupStmt stmts bindersMap by using _ _ _) elt_ty thing_inside - = do { let (bndr_names, list_bndr_names) = unzip bindersMap - - ; (stmts', (bndr_ids, by', using_ty, elt_ty')) <- - tcStmts (TransformStmtCtxt ctxt) (tcLcStmt m_tc) stmts elt_ty $ \elt_ty' -> do - (by', using_ty) <- - case by of - Nothing -> -- check that using :: forall a. [a] -> [[a]] - return (Nothing, mkForAllTy alphaTyVar $ - alphaListTy `mkFunTy` alphaListListTy) - - Just by_e -> -- check that using :: forall a. (a -> t) -> [a] -> [[a]] - -- where by :: t - do { (by_e', t_ty) <- tcInferRhoNC by_e - ; return (Just by_e', mkForAllTy alphaTyVar $ - (alphaTy `mkFunTy` t_ty) - `mkFunTy` alphaListTy - `mkFunTy` alphaListListTy) } - -- Find the Ids (and hence types) of all old binders - bndr_ids <- tcLookupLocalIds bndr_names - - return (bndr_ids, by', using_ty, elt_ty') - - -- Ensure that every old binder of type b is linked up with - -- its new binder which should have type [b] - ; let list_bndr_ids = zipWith mk_list_bndr list_bndr_names bndr_ids - bindersMap' = bndr_ids `zip` list_bndr_ids +tcLcStmt m_tc ctxt (TransStmt { trS_form = form, trS_stmts = stmts + , trS_bndrs = bindersMap + , trS_by = by, trS_using = using }) elt_ty thing_inside + = do { let (bndr_names, n_bndr_names) = unzip bindersMap + unused_ty = pprPanic "tcLcStmt: inner ty" (ppr bindersMap) + -- The inner 'stmts' lack a LastStmt, so the element type + -- passed in to tcStmtsAndThen is never looked at + ; (stmts', (bndr_ids, by')) + <- tcStmtsAndThen (TransStmtCtxt ctxt) (tcLcStmt m_tc) stmts unused_ty $ \_ -> do + { by' <- case by of + Nothing -> return Nothing + Just e -> do { e_ty <- tcInferRho e; return (Just e_ty) } + ; bndr_ids <- tcLookupLocalIds bndr_names + ; return (bndr_ids, by') } + + ; let m_app ty = mkTyConApp m_tc [ty] + + --------------- Typecheck the 'using' function ------------- + -- using :: ((a,b,c)->t) -> m (a,b,c) -> m (a,b,c)m (ThenForm) + -- :: ((a,b,c)->t) -> m (a,b,c) -> m (m (a,b,c))) (GroupForm) + + -- n_app :: Type -> Type -- Wraps a 'ty' into '[ty]' for GroupForm + ; let n_app = case form of + ThenForm -> (\ty -> ty) + _ -> m_app + + by_arrow :: Type -> Type -- Wraps 'ty' to '(a->t) -> ty' if the By is present + by_arrow = case by' of + Nothing -> \ty -> ty + Just (_,e_ty) -> \ty -> (alphaTy `mkFunTy` e_ty) `mkFunTy` ty + + tup_ty = mkBigCoreVarTupTy bndr_ids + poly_arg_ty = m_app alphaTy + poly_res_ty = m_app (n_app alphaTy) + using_poly_ty = mkForAllTy alphaTyVar $ by_arrow $ + poly_arg_ty `mkFunTy` poly_res_ty + + ; using' <- tcPolyExpr using using_poly_ty + ; let final_using = fmap (HsWrap (WpTyApp tup_ty)) using' + + -- 'stmts' returns a result of type (m1_ty tuple_ty), + -- typically something like [(Int,Bool,Int)] + -- We don't know what tuple_ty is yet, so we use a variable + ; let mk_n_bndr :: Name -> TcId -> TcId + mk_n_bndr n_bndr_name bndr_id = mkLocalId n_bndr_name (n_app (idType bndr_id)) + + -- Ensure that every old binder of type `b` is linked up with its + -- new binder which should have type `n b` -- See Note [GroupStmt binder map] in HsExpr - - ; using' <- case using of - Left e -> do { e' <- tcPolyExpr e using_ty; return (Left e') } - Right e -> do { e' <- tcPolyExpr (noLoc e) using_ty; return (Right (unLoc e')) } - - -- Type check the thing in the environment with - -- these new binders and return the result - ; thing <- tcExtendIdEnv list_bndr_ids (thing_inside elt_ty') - ; return (GroupStmt stmts' bindersMap' by' using' noSyntaxExpr noSyntaxExpr noSyntaxExpr, thing) } - where - alphaListTy = mkTyConApp m_tc [alphaTy] - alphaListListTy = mkTyConApp m_tc [alphaListTy] - - mk_list_bndr :: Name -> TcId -> TcId - mk_list_bndr list_bndr_name bndr_id - = mkLocalId list_bndr_name (mkTyConApp m_tc [idType bndr_id]) + n_bndr_ids = zipWith mk_n_bndr n_bndr_names bndr_ids + bindersMap' = bndr_ids `zip` n_bndr_ids + + -- Type check the thing in the environment with + -- these new binders and return the result + ; thing <- tcExtendIdEnv n_bndr_ids (thing_inside elt_ty) + + ; return (emptyTransStmt { trS_stmts = stmts', trS_bndrs = bindersMap' + , trS_by = fmap fst by', trS_using = final_using + , trS_form = form }, thing) } tcLcStmt _ _ stmt _ _ = pprPanic "tcLcStmt: unexpected Stmt" (ppr stmt) - --------------------------------- --- Monad comprehensions + +--------------------------------------------------- +-- Monad comprehensions +-- (supports rebindable syntax) +--------------------------------------------------- tcMcStmt :: TcStmtChecker -tcMcStmt ctxt (LastStmt body return_op) res_ty thing_inside +tcMcStmt _ (LastStmt body return_op) res_ty thing_inside = do { a_ty <- newFlexiTyVarTy liftedTypeKind ; return_op' <- tcSyntaxOp MCompOrigin return_op (a_ty `mkFunTy` res_ty) - ; body' <- tcMonoExpr body a_ty - ; return (body', return_op') } + ; body' <- tcMonoExprNC body a_ty + ; thing <- thing_inside (panic "tcMcStmt: thing_inside") + ; return (LastStmt body' return_op', thing) } -- Generators for monad comprehensions ( pat <- rhs ) -- @@ -549,74 +532,6 @@ tcMcStmt _ (ExprStmt rhs then_op guard_op _) res_ty thing_inside ; thing <- thing_inside new_res_ty ; return (ExprStmt rhs' then_op' guard_op' rhs_ty, thing) } --- Transform statements. --- --- [ body | stmts, then f ] -> f :: forall a. m a -> m a --- [ body | stmts, then f by e ] -> f :: forall a. (a -> t) -> m a -> m a --- -tcMcStmt ctxt (TransformStmt stmts binders usingExpr maybeByExpr return_op bind_op) res_ty thing_inside - = do { - -- We don't know the types of binders yet, so we use this dummy and - -- later unify this type with the `m_bndr_ty` - ty_dummy <- newFlexiTyVarTy liftedTypeKind - - ; (stmts', (binders', usingExpr', maybeByExpr', return_op', bind_op', thing)) <- - tcStmts (TransformStmtCtxt ctxt) tcMcStmt stmts ty_dummy $ \res_ty' -> do - { (_, (m_ty, _)) <- matchExpectedAppTy res_ty' - ; (usingExpr', maybeByExpr') <- - case maybeByExpr of - Nothing -> do - -- We must validate that usingExpr :: forall a. m a -> m a - let using_ty = mkForAllTy alphaTyVar $ - (m_ty `mkAppTy` alphaTy) - `mkFunTy` - (m_ty `mkAppTy` alphaTy) - usingExpr' <- tcPolyExpr usingExpr using_ty - return (usingExpr', Nothing) - Just byExpr -> do - -- We must infer a type such that e :: t and then check that - -- usingExpr :: forall a. (a -> t) -> m a -> m a - (byExpr', tTy) <- tcInferRhoNC byExpr - let using_ty = mkForAllTy alphaTyVar $ - (alphaTy `mkFunTy` tTy) - `mkFunTy` - (m_ty `mkAppTy` alphaTy) - `mkFunTy` - (m_ty `mkAppTy` alphaTy) - usingExpr' <- tcPolyExpr usingExpr using_ty - return (usingExpr', Just byExpr') - - ; bndr_ids <- tcLookupLocalIds binders - - -- `return` and `>>=` are used to pass around/modify our - -- binders, so we know their types: - -- - -- return :: (a,b,c,..) -> m (a,b,c,..) - -- (>>=) :: m (a,b,c,..) - -- -> ( (a,b,c,..) -> m (a,b,c,..) ) - -- -> m (a,b,c,..) - -- - ; let bndr_ty = mkBigCoreVarTupTy bndr_ids - m_bndr_ty = m_ty `mkAppTy` bndr_ty - - ; return_op' <- tcSyntaxOp MCompOrigin return_op - (bndr_ty `mkFunTy` m_bndr_ty) - - ; bind_op' <- tcSyntaxOp MCompOrigin bind_op $ - m_bndr_ty `mkFunTy` (bndr_ty `mkFunTy` res_ty) - `mkFunTy` res_ty - - -- Unify types of the inner comprehension and the binders type - ; _ <- unifyType res_ty' m_bndr_ty - - -- Typecheck the `thing` with out old type (which is the type - -- of the final result of our comprehension) - ; thing <- thing_inside res_ty - - ; return (bndr_ids, usingExpr', maybeByExpr', return_op', bind_op', thing) } - - ; return (TransformStmt stmts' binders' usingExpr' maybeByExpr' return_op' bind_op', thing) } - -- Grouping statements -- -- [ body | stmts, then group by e ] @@ -626,85 +541,90 @@ tcMcStmt ctxt (TransformStmt stmts binders usingExpr maybeByExpr return_op bind_ -- f :: forall a. (a -> t) -> m a -> m (m a) -- [ body | stmts, then group using f ] -- -> f :: forall a. m a -> m (m a) + +-- We type [ body | (stmts, group by e using f), ... ] +-- f [ (a,b,c) | stmts ] >>= \(a,b,c) -> ...body.... -- -tcMcStmt ctxt (GroupStmt stmts bindersMap by using return_op bind_op fmap_op) res_ty thing_inside - = do { m1_ty <- newFlexiTyVarTy liftedTypeKind - ; m2_ty <- newFlexiTyVarTy liftedTypeKind - ; n_ty <- newFlexiTyVarTy liftedTypeKind - ; tup_ty_var <- newFlexiTyVarTy liftedTypeKind - ; new_res_ty <- newFlexiTyVarTy liftedTypeKind - ; let (bndr_names, n_bndr_names) = unzip bindersMap - m1_tup_ty = m1_ty `mkAppTy` tup_ty_var - +-- We type the functions as follows: +-- f :: m1 (a,b,c) -> m2 (a,b,c) (ThenForm) +-- :: m1 (a,b,c) -> m2 (n (a,b,c)) (GroupForm) +-- (>>=) :: m2 (a,b,c) -> ((a,b,c) -> res) -> res (ThenForm) +-- :: m2 (n (a,b,c)) -> (n (a,b,c) -> res) -> res (GroupForm) +-- +tcMcStmt ctxt (TransStmt { trS_stmts = stmts, trS_bndrs = bindersMap + , trS_by = by, trS_using = using, trS_form = form + , trS_ret = return_op, trS_bind = bind_op + , trS_fmap = fmap_op }) res_ty thing_inside + = do { let star_star_kind = liftedTypeKind `mkArrowKind` liftedTypeKind + ; m1_ty <- newFlexiTyVarTy star_star_kind + ; m2_ty <- newFlexiTyVarTy star_star_kind + ; tup_ty <- newFlexiTyVarTy liftedTypeKind + ; by_e_ty <- newFlexiTyVarTy liftedTypeKind -- The type of the 'by' expression (if any) + + -- n_app :: Type -> Type -- Wraps a 'ty' into '(n ty)' for GroupForm + ; n_app <- case form of + ThenForm -> return (\ty -> ty) + _ -> do { n_ty <- newFlexiTyVarTy star_star_kind + ; return (n_ty `mkAppTy`) } + ; let by_arrow :: Type -> Type + -- (by_arrow res) produces ((alpha->e_ty) -> res) ('by' present) + -- or res ('by' absent) + by_arrow = case by of + Nothing -> \res -> res + Just {} -> \res -> (alphaTy `mkFunTy` by_e_ty) `mkFunTy` res + + poly_arg_ty = m1_ty `mkAppTy` alphaTy + using_arg_ty = m1_ty `mkAppTy` tup_ty + poly_res_ty = m2_ty `mkAppTy` n_app alphaTy + using_res_ty = m2_ty `mkAppTy` n_app tup_ty + using_poly_ty = mkForAllTy alphaTyVar $ by_arrow $ + poly_arg_ty `mkFunTy` poly_res_ty + -- 'stmts' returns a result of type (m1_ty tuple_ty), -- typically something like [(Int,Bool,Int)] -- We don't know what tuple_ty is yet, so we use a variable - ; (stmts', (bndr_ids, by_e_ty, return_op')) <- - tcStmts (TransformStmtCtxt ctxt) tcMcStmt stmts m1_tup_ty $ \res_ty' -> do - { by_e_ty <- mapM tcInferRhoNC by_e + ; let (bndr_names, n_bndr_names) = unzip bindersMap + ; (stmts', (bndr_ids, by', return_op')) <- + tcStmtsAndThen (TransStmtCtxt ctxt) tcMcStmt stmts using_arg_ty $ \res_ty' -> do + { by' <- case by of + Nothing -> return Nothing + Just e -> do { e' <- tcMonoExpr e by_e_ty; return (Just e') } -- Find the Ids (and hence types) of all old binders ; bndr_ids <- tcLookupLocalIds bndr_names -- 'return' is only used for the binders, so we know its type. - -- -- return :: (a,b,c,..) -> m (a,b,c,..) ; return_op' <- tcSyntaxOp MCompOrigin return_op $ (mkBigCoreVarTupTy bndr_ids) `mkFunTy` res_ty' - ; return (bndr_ids, by_e_ty, return_op') } - - - - ; let tup_ty = mkBigCoreVarTupTy bndr_ids -- (a,b,c) - using_arg_ty = m1_ty `mkAppTy` tup_ty -- m1 (a,b,c) - n_tup_ty = n_ty `mkAppTy` tup_ty -- n (a,b,c) - using_res_ty = m2_ty `mkAppTy` n_tup_ty -- m2 (n (a,b,c)) - using_fun_ty = using_arg_ty `mkFunTy` using_arg_ty - - -- (>>=) :: m2 (n (a,b,c)) -> ( n (a,b,c) -> new_res_ty ) -> res_ty - -- using :: ((a,b,c)->t) -> m1 (a,b,c) -> m2 (n (a,b,c)) + ; return (bndr_ids, by', return_op') } --------------- Typecheck the 'bind' function ------------- + -- (>>=) :: m2 (n (a,b,c)) -> ( n (a,b,c) -> new_res_ty ) -> res_ty + ; new_res_ty <- newFlexiTyVarTy liftedTypeKind ; bind_op' <- tcSyntaxOp MCompOrigin bind_op $ - using_res_ty `mkFunTy` (n_tup_ty `mkFunTy` new_res_ty) + using_res_ty `mkFunTy` (n_app tup_ty `mkFunTy` new_res_ty) `mkFunTy` res_ty + --------------- Typecheck the 'fmap' function ------------- + ; fmap_op' <- case form of + ThenForm -> return noSyntaxExpr + _ -> fmap unLoc . tcPolyExpr (noLoc fmap_op) $ + mkForAllTy alphaTyVar $ mkForAllTy betaTyVar $ + (alphaTy `mkFunTy` betaTy) + `mkFunTy` (n_app alphaTy) + `mkFunTy` (n_app betaTy) + --------------- Typecheck the 'using' function ------------- - ; let using_fun_ty = (m1_ty `mkAppTy` alphaTy) `mkFunTy` - (m2_ty `mkAppTy` (n_ty `mkAppTy` alphaTy)) - using_poly_ty = case by_e_ty of - Nothing -> mkForAllTy alphaTyVar using_fun_ty - -- using :: forall a. m1 a -> m2 (n a) - - Just (_,t_ty) -> mkForAllTy alphaTyVar $ - (alphaTy `mkFunTy` t_ty) `mkFunTy` using_fun_ty - -- using :: forall a. (a->t) -> m1 a -> m2 (n a) - -- where by :: t - - ; using' <- case using of - Left e -> do { e' <- tcPolyExpr e using_poly_ty - ; return (Left e') } - Right e -> do { e' <- tcPolyExpr (noLoc e) using_poly_ty - ; return (Right (unLoc e')) } - ; coi <- unifyType (applyTy using_poly_ty tup_ty) - (case by_e_ty of - Nothing -> using_fun_ty - Just (_,t_ty) -> (tup_ty `mkFunTy` t_ty) `mkFunTy` using_fun_ty) - ; let final_using = mkHsWrapCoI coi (HsWrap (WpTyApp tup_ty) using') + -- using :: ((a,b,c)->t) -> m1 (a,b,c) -> m2 (n (a,b,c)) - --------------- Typecheck the 'fmap' function ------------- - ; fmap_op' <- fmap unLoc . tcPolyExpr (noLoc fmap_op) $ - mkForAllTy alphaTyVar $ mkForAllTy betaTyVar $ - (alphaTy `mkFunTy` betaTy) - `mkFunTy` - (m_ty `mkAppTy` alphaTy) - `mkFunTy` - (m_ty `mkAppTy` betaTy) + ; using' <- tcPolyExpr using using_poly_ty + ; let final_using = fmap (HsWrap (WpTyApp tup_ty)) using' + --------------- Bulding the bindersMap ---------------- ; let mk_n_bndr :: Name -> TcId -> TcId - mk_n_bndr n_bndr_name bndr_id - = mkLocalId bndr_name (n_ty `mkAppTy` idType bndr_id) + mk_n_bndr n_bndr_name bndr_id = mkLocalId n_bndr_name (n_app (idType bndr_id)) -- Ensure that every old binder of type `b` is linked up with its -- new binder which should have type `n b` @@ -712,16 +632,35 @@ tcMcStmt ctxt (GroupStmt stmts bindersMap by using return_op bind_op fmap_op) re n_bndr_ids = zipWith mk_n_bndr n_bndr_names bndr_ids bindersMap' = bndr_ids `zip` n_bndr_ids - -- Type check the thing in the environment with these new binders and - -- return the result - ; thing <- tcExtendIdEnv n_bndr_ids (thing_inside res_ty) + -- Type check the thing in the environment with + -- these new binders and return the result + ; thing <- tcExtendIdEnv n_bndr_ids (thing_inside new_res_ty) - ; return (GroupStmt stmts' bindersMap' - (fmap fst by_e_ty) final_using - return_op' bind_op' fmap_op', thing) } + ; return (TransStmt { trS_stmts = stmts', trS_bndrs = bindersMap' + , trS_by = by', trS_using = final_using + , trS_ret = return_op', trS_bind = bind_op' + , trS_fmap = fmap_op', trS_form = form }, thing) } --- Typecheck `ParStmt`. See `tcLcStmt` for more informations about typechecking --- of `ParStmt`s. +-- A parallel set of comprehensions +-- [ (g x, h x) | ... ; let g v = ... +-- | ... ; let h v = ... ] +-- +-- It's possible that g,h are overloaded, so we need to feed the LIE from the +-- (g x, h x) up through both lots of bindings (so we get the bindLocalMethods). +-- Similarly if we had an existential pattern match: +-- +-- data T = forall a. Show a => C a +-- +-- [ (show x, show y) | ... ; C x <- ... +-- | ... ; C y <- ... ] +-- +-- Then we need the LIE from (show x, show y) to be simplified against +-- the bindings for x and y. +-- +-- It's difficult to do this in parallel, so we rely on the renamer to +-- ensure that g,h and x,y don't duplicate, and simply grow the environment. +-- So the binders of the first parallel group will be in scope in the second +-- group. But that's fine; there's no shadowing to worry about. -- -- Note: The `mzip` function will get typechecked via: -- @@ -732,67 +671,83 @@ tcMcStmt ctxt (GroupStmt stmts bindersMap by using return_op bind_op fmap_op) re -- -> m (st1, (st2, st3)) -- tcMcStmt ctxt (ParStmt bndr_stmts_s mzip_op bind_op return_op) res_ty thing_inside - = do { (_,(m_ty,_)) <- matchExpectedAppTy res_ty - ; (pairs', thing) <- loop m_ty bndr_stmts_s - - ; let mzip_ty = mkForAllTys [alphaTyVar, betaTyVar] $ - (m_ty `mkAppTy` alphaTy) - `mkFunTy` - (m_ty `mkAppTy` betaTy) - `mkFunTy` - (m_ty `mkAppTy` mkBoxedTupleTy [alphaTy, betaTy]) - ; mzip_op' <- unLoc `fmap` tcPolyExpr (noLoc mzip_op) mzip_ty - - -- Typecheck bind: - ; let tys = map (mkBigCoreVarTupTy . snd) pairs' - tuple_ty = mk_tuple_ty tys - - ; bind_op' <- tcSyntaxOp MCompOrigin bind_op $ - (m_ty `mkAppTy` tuple_ty) - `mkFunTy` - (tuple_ty `mkFunTy` res_ty) - `mkFunTy` - res_ty - - ; return_op' <- fmap unLoc . tcPolyExpr (noLoc return_op) $ - mkForAllTy alphaTyVar $ - alphaTy `mkFunTy` (m_ty `mkAppTy` alphaTy) - ; return_op' <- tcSyntaxOp MCompOrigin return_op - (bndr_ty `mkFunTy` m_bndr_ty) - - ; return (ParStmt pairs' mzip_op' bind_op' return_op', thing) } - - where mk_tuple_ty tys = foldr (\tn tm -> mkBoxedTupleTy [tn, tm]) (last tys) (init tys) + = do { let star_star_kind = liftedTypeKind `mkArrowKind` liftedTypeKind + ; m_ty <- newFlexiTyVarTy star_star_kind + + ; let mzip_ty = mkForAllTys [alphaTyVar, betaTyVar] $ + (m_ty `mkAppTy` alphaTy) + `mkFunTy` + (m_ty `mkAppTy` betaTy) + `mkFunTy` + (m_ty `mkAppTy` mkBoxedTupleTy [alphaTy, betaTy]) + ; mzip_op' <- unLoc `fmap` tcPolyExpr (noLoc mzip_op) mzip_ty + + ; return_op' <- fmap unLoc . tcPolyExpr (noLoc return_op) $ + mkForAllTy alphaTyVar $ + alphaTy `mkFunTy` (m_ty `mkAppTy` alphaTy) + + ; (pairs', thing) <- loop m_ty bndr_stmts_s + + -- Typecheck bind: + ; let tys = map (mkBigCoreVarTupTy . snd) pairs' + tuple_ty = mk_tuple_ty tys + + ; bind_op' <- tcSyntaxOp MCompOrigin bind_op $ + (m_ty `mkAppTy` tuple_ty) + `mkFunTy` (tuple_ty `mkFunTy` res_ty) + `mkFunTy` res_ty + + ; return (ParStmt pairs' mzip_op' bind_op' return_op', thing) } + + where + mk_tuple_ty tys = foldr1 (\tn tm -> mkBoxedTupleTy [tn, tm]) tys -- loop :: Type -- m_ty -- -> [([LStmt Name], [Name])] -- -> TcM ([([LStmt TcId], [TcId])], thing) - loop _ [] = do { thing <- thing_inside res_ty - ; return ([], thing) } -- matching in the branches - - loop m_ty ((stmts, names) : pairs) - = do { -- type dummy since we don't know all binder types yet - ty_dummy <- newFlexiTyVarTy liftedTypeKind - ; (stmts', (ids, pairs', thing)) - <- tcStmts ctxt tcMcStmt stmts ty_dummy $ \res_ty' -> - do { ids <- tcLookupLocalIds names - ; _ <- unifyType res_ty' (m_ty `mkAppTy` mkBigCoreVarTupTy ids) - ; (pairs', thing) <- loop m_ty pairs - ; return (ids, pairs', thing) } - ; return ( (stmts', ids) : pairs', thing ) } + loop _ [] = do { thing <- thing_inside res_ty + ; return ([], thing) } -- matching in the branches + + loop m_ty ((stmts, names) : pairs) + = do { -- type dummy since we don't know all binder types yet + ty_dummy <- newFlexiTyVarTy liftedTypeKind + ; (stmts', (ids, pairs', thing)) + <- tcStmtsAndThen ctxt tcMcStmt stmts ty_dummy $ \res_ty' -> + do { ids <- tcLookupLocalIds names + ; let m_tup_ty = m_ty `mkAppTy` mkBigCoreVarTupTy ids + + ; check_same m_tup_ty res_ty' + ; check_same m_tup_ty ty_dummy + + ; (pairs', thing) <- loop m_ty pairs + ; return (ids, pairs', thing) } + ; return ( (stmts', ids) : pairs', thing ) } + + -- Check that the types match up. + -- This is a grevious hack. They always *will* match + -- If (>>=) and (>>) are polymorpic in the return type, + -- but we don't have any good way to incorporate the coercion + -- so for now we just check that it's the identity + check_same actual expected + = do { coi <- unifyType actual expected + ; unless (isReflCo coi) $ + failWithMisMatch [UnifyOrigin { uo_expected = expected + , uo_actual = actual }] } tcMcStmt _ stmt _ _ = pprPanic "tcMcStmt: unexpected Stmt" (ppr stmt) --------------------------------- --- Do-notation --- The main excitement here is dealing with rebindable syntax + +--------------------------------------------------- +-- Do-notation +-- (supports rebindable syntax) +--------------------------------------------------- tcDoStmt :: TcStmtChecker -tcDoStmt ctxt (LastStmt body _) res_ty thing_inside - = do { body' <- tcMonoExpr body res_ty - ; thing <- thing_inside body_ty +tcDoStmt _ (LastStmt body _) res_ty thing_inside + = do { body' <- tcMonoExprNC body res_ty + ; thing <- thing_inside (panic "tcDoStmt: thing_inside") ; return (LastStmt body' noSyntaxExpr, thing) } tcDoStmt ctxt (BindStmt pat rhs bind_op fail_op) res_ty thing_inside @@ -849,7 +804,7 @@ tcDoStmt ctxt (RecStmt { recS_stmts = stmts, recS_later_ids = later_names ; tcExtendIdEnv tup_ids $ do { stmts_ty <- newFlexiTyVarTy liftedTypeKind ; (stmts', (ret_op', tup_rets)) - <- tcStmts ctxt tcDoStmt stmts stmts_ty $ \ inner_res_ty -> + <- tcStmtsAndThen ctxt tcDoStmt stmts stmts_ty $ \ inner_res_ty -> do { tup_rets <- zipWithM tcCheckId tup_names tup_elt_tys -- Unify the types of the "final" Ids (which may -- be polymorphic) with those of "knot-tied" Ids @@ -865,7 +820,6 @@ tcDoStmt ctxt (RecStmt { recS_stmts = stmts, recS_later_ids = later_names (mkFunTys [mfix_res_ty, mkFunTy tup_ty new_res_ty] res_ty) ; thing <- thing_inside new_res_ty --- ; lie_binds <- bindLocalMethods lie tup_ids ; let rec_ids = takeList rec_names tup_ids ; later_ids <- tcLookupLocalIds later_names @@ -891,53 +845,6 @@ rebindable syntax first, and push that information into (tcMonoExprNC rhs). Otherwise the error shows up when cheking the rebindable syntax, and the expected/inferred stuff is back to front (see Trac #3613). -\begin{code} --------------------------------- --- Mdo-notation --- The distinctive features here are --- (a) RecStmts, and --- (b) no rebindable syntax - -tcMDoStmt :: (LHsExpr Name -> TcM (LHsExpr TcId, TcType)) -- RHS inference - -> TcStmtChecker --- Used only by TcArrows... should be gotten rid of -tcMDoStmt tc_rhs ctxt (BindStmt pat rhs _ _) res_ty thing_inside - = do { (rhs', pat_ty) <- tc_rhs rhs - ; (pat', thing) <- tcPat (StmtCtxt ctxt) pat pat_ty $ - thing_inside res_ty - ; return (BindStmt pat' rhs' noSyntaxExpr noSyntaxExpr, thing) } - -tcMDoStmt tc_rhs _ (ExprStmt rhs _ _ _) res_ty thing_inside - = do { (rhs', elt_ty) <- tc_rhs rhs - ; thing <- thing_inside res_ty - ; return (ExprStmt rhs' noSyntaxExpr noSyntaxExpr elt_ty, thing) } - -tcMDoStmt tc_rhs ctxt (RecStmt { recS_stmts = stmts, recS_later_ids = laterNames - , recS_rec_ids = recNames }) res_ty thing_inside - = do { rec_tys <- newFlexiTyVarTys (length recNames) liftedTypeKind - ; let rec_ids = zipWith mkLocalId recNames rec_tys - ; tcExtendIdEnv rec_ids $ do - { (stmts', (later_ids, rec_rets)) - <- tcStmts ctxt (tcMDoStmt tc_rhs) stmts res_ty $ \ _res_ty' -> - -- ToDo: res_ty not really right - do { rec_rets <- zipWithM tcCheckId recNames rec_tys - ; later_ids <- tcLookupLocalIds laterNames - ; return (later_ids, rec_rets) } - - ; thing <- tcExtendIdEnv later_ids (thing_inside res_ty) - -- NB: The rec_ids for the recursive things - -- already scope over this part. This binding may shadow - -- some of them with polymorphic things with the same Name - -- (see note [RecStmt] in HsExpr) - - ; return (RecStmt stmts' later_ids rec_ids noSyntaxExpr noSyntaxExpr noSyntaxExpr rec_rets, thing) - }} - -tcMDoStmt _ _ stmt _ _ - = pprPanic "tcMDoStmt: unexpected Stmt" (ppr stmt) - -\end{code} - %************************************************************************ %* *