[project @ 2003-06-24 07:58:18 by simonpj]
authorsimonpj <unknown>
Tue, 24 Jun 2003 07:58:27 +0000 (07:58 +0000)
committersimonpj <unknown>
Tue, 24 Jun 2003 07:58:27 +0000 (07:58 +0000)
----------------------------------------------
Add support for Ross Paterson's arrow notation
----------------------------------------------

Ross Paterson's ICFP'01 paper described syntax to support John Hughes's
"arrows", rather as do-notation supports monads.  Except that do-notation is
relatively modest -- you can write monads by hand without much trouble --
whereas arrow-notation is more-or-less essential for writing arrow programs.
It desugars to a massive pile of tuple construction and selection!

For some time, Ross has had a pre-processor for arrow notation, but the
resulting type error messages (reported in terms of the desugared code)
are impenetrable.  This commit integrates the syntax into GHC.  The
type error messages almost certainly still require tuning, but they should
be better than with the pre-processor.

Main syntactic changes (enabled with -farrows)

   exp ::= ... | proc pat -> cmd

   cmd ::= exp1 -<  exp2   |  exp1 >-  exp2
|  exp1 -<< exp2   |  exp1 >>- exp2
| \ pat1 .. patn -> cmd
| let decls in cmd
| if exp then cmd1 else cmd2
| do { cstmt1 .. cstmtn ; cmd }
| (| exp |) cmd1 .. cmdn
| cmd1 qop cmd2
| case exp of { calts }

   cstmt :: = let decls
 |   pat <- cmd
 |   rec { cstmt1 .. cstmtn }
 |   cmd

New keywords and symbols:
proc rec
-<   >-   -<<   >>-
(|  |)

The do-notation in cmds was not described in Ross's ICFP'01 paper; instead
it's in his chapter in The Fun of Programming (Plagrave 2003).

The four arrow-tail forms (-<) etc cover
  (a) which order the pices come in (-<  vs  >-), and
  (b) whether the locally bound variables can be used in the
arrow part (-<  vs  -<<) .
In previous presentations, the higher-order-ness (b) was inferred,
but it makes a big difference to the typing required so it seems more
consistent to be explicit.

The 'rec' form is also available in do-notation:
  * you can use 'rec' in an ordinary do, with the obvious meaning
  * using 'mdo' just says "infer the minimal recs"

Still to do
~~~~~~~~~~~
Top priority is the user manual.

The implementation still lacks an implementation of
the case form of cmd.

Implementation notes
~~~~~~~~~~~~~~~~~~~~
Cmds are parsed, and indeed renamed, as expressions.  The type checker
distinguishes the two.

33 files changed:
ghc/compiler/deSugar/DsArrows.lhs [new file with mode: 0644]
ghc/compiler/deSugar/DsExpr.lhs
ghc/compiler/deSugar/DsListComp.lhs
ghc/compiler/deSugar/DsMonad.lhs
ghc/compiler/deSugar/DsUtils.lhs
ghc/compiler/hsSyn/Convert.lhs
ghc/compiler/hsSyn/HsExpr.lhs
ghc/compiler/hsSyn/HsSyn.lhs
ghc/compiler/main/CmdLineOpts.lhs
ghc/compiler/main/DriverFlags.hs
ghc/compiler/main/HscMain.lhs
ghc/compiler/main/ParsePkgConf.y
ghc/compiler/parser/Lex.lhs
ghc/compiler/parser/Parser.y
ghc/compiler/parser/RdrHsSyn.lhs
ghc/compiler/prelude/PrelNames.lhs
ghc/compiler/rename/RnEnv.lhs
ghc/compiler/rename/RnExpr.lhs
ghc/compiler/rename/RnHiFiles.lhs
ghc/compiler/rename/RnHsSyn.lhs
ghc/compiler/typecheck/Inst.lhs
ghc/compiler/typecheck/TcArrows.lhs [new file with mode: 0644]
ghc/compiler/typecheck/TcEnv.lhs
ghc/compiler/typecheck/TcExpr.lhs
ghc/compiler/typecheck/TcHsSyn.lhs
ghc/compiler/typecheck/TcMType.lhs
ghc/compiler/typecheck/TcMatches.lhs
ghc/compiler/typecheck/TcMonoType.lhs
ghc/compiler/typecheck/TcPat.lhs
ghc/compiler/typecheck/TcRnDriver.lhs
ghc/compiler/typecheck/TcRnMonad.lhs
ghc/compiler/typecheck/TcRnTypes.lhs
ghc/compiler/typecheck/TcUnify.lhs

diff --git a/ghc/compiler/deSugar/DsArrows.lhs b/ghc/compiler/deSugar/DsArrows.lhs
new file mode 100644 (file)
index 0000000..3c4be07
--- /dev/null
@@ -0,0 +1,960 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section[DsArrows]{Desugaring arrow commands}
+
+\begin{code}
+module DsArrows ( dsProcExpr ) where
+
+#include "HsVersions.h"
+
+import Match           ( matchSimply )
+import DsUtils         ( mkErrorAppDs,
+                         mkCoreTupTy, mkCoreTup, selectMatchVar,
+                         mkTupleExpr, mkTupleSelector,
+                         dsReboundNames, lookupReboundName )
+import DsMonad
+
+import HsSyn           ( HsExpr(..), Pat(..),
+                         Stmt(..), HsMatchContext(..), HsStmtContext(..), 
+                         Match(..), GRHSs(..), GRHS(..),
+                         HsCmdTop(..), HsArrAppType(..),
+                         ReboundNames,
+                         collectHsBinders,
+                         collectStmtBinders, collectStmtsBinders,
+                         matchContextErrString
+                       )
+import TcHsSyn         ( TypecheckedHsCmd, TypecheckedHsCmdTop,
+                         TypecheckedHsExpr, TypecheckedHsBinds,
+                         TypecheckedPat,
+                         TypecheckedMatch, TypecheckedGRHSs, TypecheckedGRHS,
+                         TypecheckedStmt, hsPatType,
+                         TypecheckedMatchContext )
+
+-- NB: The desugarer, which straddles the source and Core worlds, sometimes
+--     needs to see source types (newtypes etc), and sometimes not
+--     So WATCH OUT; check each use of split*Ty functions.
+-- Sigh.  This is a pain.
+
+import {-# SOURCE #-} DsExpr ( dsExpr, dsLet )
+
+import TcType          ( Type, tcSplitAppTy )
+import Type            ( mkTyConApp )
+import CoreSyn
+import CoreFVs         ( exprFreeVars )
+import CoreUtils       ( exprType, mkIfThenElse, bindNonRec )
+
+import Id              ( Id, idType )
+import PrelInfo                ( pAT_ERROR_ID )
+import DataCon         ( DataCon, dataConWrapId )
+import TysWiredIn      ( tupleCon, mkTupleTy )
+import BasicTypes      ( Boxity(..) )
+import PrelNames       ( eitherTyConName, leftDataConName, rightDataConName,
+                         arrAName, composeAName, firstAName,
+                         appAName, choiceAName, loopAName )
+import Util            ( mapAccumL )
+import Outputable
+
+import HsPat           ( collectPatBinders, collectPatsBinders )
+import VarSet          ( IdSet, emptyVarSet, mkVarSet, varSetElems,
+                         intersectVarSet, minusVarSet, 
+                         unionVarSet, unionVarSets, elemVarSet )
+import SrcLoc          ( SrcLoc )
+\end{code}
+
+\begin{code}
+data DsCmdEnv = DsCmdEnv {
+       meth_binds :: [CoreBind],
+       arr_id, compose_id, first_id, app_id, choice_id, loop_id :: CoreExpr
+    }
+
+mkCmdEnv :: ReboundNames Id -> DsM DsCmdEnv
+mkCmdEnv ids
+  = dsReboundNames ids                 `thenDs` \ (meth_binds, ds_meths) ->
+    return $ DsCmdEnv {
+               meth_binds = meth_binds,
+               arr_id     = lookupReboundName ds_meths arrAName,
+               compose_id = lookupReboundName ds_meths composeAName,
+               first_id   = lookupReboundName ds_meths firstAName,
+               app_id     = lookupReboundName ds_meths appAName,
+               choice_id  = lookupReboundName ds_meths choiceAName,
+               loop_id    = lookupReboundName ds_meths loopAName
+           }
+
+bindCmdEnv :: DsCmdEnv -> CoreExpr -> CoreExpr
+bindCmdEnv ids body = foldr Let body (meth_binds ids)
+
+-- arr :: forall b c. (b -> c) -> a b c
+do_arr :: DsCmdEnv -> Type -> Type -> CoreExpr -> CoreExpr
+do_arr ids b_ty c_ty f = mkApps (arr_id ids) [Type b_ty, Type c_ty, f]
+
+-- (>>>) :: forall b c d. a b c -> a c d -> a b d
+do_compose :: DsCmdEnv -> Type -> Type -> Type ->
+               CoreExpr -> CoreExpr -> CoreExpr
+do_compose ids b_ty c_ty d_ty f g
+  = mkApps (compose_id ids) [Type b_ty, Type c_ty, Type d_ty, f, g]
+
+-- first :: forall b c d. a b c -> a (b,d) (c,d)
+do_first :: DsCmdEnv -> Type -> Type -> Type -> CoreExpr -> CoreExpr
+do_first ids b_ty c_ty d_ty f
+  = mkApps (first_id ids) [Type b_ty, Type c_ty, Type d_ty, f]
+
+-- app :: forall b c. a (a b c, b) c
+do_app :: DsCmdEnv -> Type -> Type -> CoreExpr
+do_app ids b_ty c_ty = mkApps (app_id ids) [Type b_ty, Type c_ty]
+
+-- (|||) :: forall b d c. a b d -> a c d -> a (Either b c) d
+-- note the swapping of d and c
+do_choice :: DsCmdEnv -> Type -> Type -> Type ->
+               CoreExpr -> CoreExpr -> CoreExpr
+do_choice ids b_ty c_ty d_ty f g
+  = mkApps (choice_id ids) [Type b_ty, Type d_ty, Type c_ty, f, g]
+
+-- loop :: forall b d c. a (b,d) (c,d) -> a b c
+-- note the swapping of d and c
+do_loop :: DsCmdEnv -> Type -> Type -> Type -> CoreExpr -> CoreExpr
+do_loop ids b_ty c_ty d_ty f
+  = mkApps (loop_id ids) [Type b_ty, Type d_ty, Type c_ty, f]
+
+-- map_arrow (f :: b -> c) (g :: a c d) = arr f >>> g :: a b d
+do_map_arrow :: DsCmdEnv -> Type -> Type -> Type ->
+               CoreExpr -> CoreExpr -> CoreExpr
+do_map_arrow ids b_ty c_ty d_ty f c
+  = do_compose ids b_ty c_ty d_ty (do_arr ids b_ty c_ty f) c
+
+mkFailExpr :: TypecheckedMatchContext -> Type -> DsM CoreExpr
+mkFailExpr ctxt ty
+  = mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt)
+
+-- construct CoreExpr for \ (a :: a_ty, b :: b_ty) -> b
+mkSndExpr :: Type -> Type -> DsM CoreExpr
+mkSndExpr a_ty b_ty
+  = newSysLocalDs a_ty                 `thenDs` \a_var ->
+    newSysLocalDs b_ty                 `thenDs` \b_var ->
+    newSysLocalDs (mkCorePairTy a_ty b_ty)     `thenDs` \pair_var ->
+    returnDs (coreCaseSmallTuple pair_var [a_var, b_var] (Var b_var))
+\end{code}
+
+Build case analysis of a tuple.  This cannot be done in the DsM monad,
+because the list of variables is typically not yet defined.
+
+\begin{code}
+-- coreCaseTuple [u1..] v [x1..xn] body
+--     = case v of v { (x1, .., xn) -> body }
+-- But the matching may be nested if the tuple is very big
+
+coreCaseTuple :: UniqSupply -> Id -> [Id] -> CoreExpr -> CoreExpr
+coreCaseTuple uniqs = coreCaseSmallTuple       -- TODO: do this right
+
+-- same, but with a tuple small enough not to need nesting
+
+coreCaseSmallTuple :: Id -> [Id] -> CoreExpr -> CoreExpr
+coreCaseSmallTuple scrut_var [var] body
+  = bindNonRec var (Var scrut_var) body
+coreCaseSmallTuple scrut_var vars body
+  = Case (Var scrut_var) scrut_var
+         [(DataAlt (tupleCon Boxed (length vars)), vars, body)]
+\end{code}
+
+\begin{code}
+-- Not right: doesn't handle nested tuples
+tupleType :: [Id] -> Type
+tupleType vars = mkCoreTupTy (map idType vars)
+
+mkCorePairTy :: Type -> Type -> Type
+mkCorePairTy t1 t2 = mkCoreTupTy [t1, t2]
+
+mkCorePairExpr :: CoreExpr -> CoreExpr -> CoreExpr
+mkCorePairExpr e1 e2 = mkCoreTup [e1, e2]
+\end{code}
+
+The input is divided into a local environment, which is a flat tuple
+(unless it's too big), and a stack, each element of which is paired
+with the stack in turn.  In general, the input has the form
+
+       (...((x1,...,xn),s1),...sk)
+
+where xi are the environment values, and si the ones on the stack,
+with s1 being the "top", the first one to be matched with a lambda.
+
+\begin{code}
+envStackType :: [Id] -> [Type] -> Type
+envStackType ids stack_tys = foldl mkCorePairTy (tupleType ids) stack_tys
+
+----------------------------------------------
+--             buildEnvStack
+--
+--     (...((x1,...,xn),s1),...sn)
+
+buildEnvStack :: [Id] -> [Id] -> CoreExpr
+buildEnvStack env_ids stack_ids
+  = envStackExpr (mkTupleExpr env_ids) (map Var stack_ids)
+
+envStackExpr :: CoreExpr -> [CoreExpr] -> CoreExpr
+envStackExpr core_ids core_exprs = foldl mkCorePairExpr core_ids core_exprs
+
+----------------------------------------------
+--             matchEnvStack
+--
+--     \ (...((x1,...,xm),s1),...sn) -> e
+--     =>
+--     \ zn ->
+--     case zn of (zn-1,sn) ->
+--     ...
+--     case z1 of (z0,s1) ->
+--     case z0 of (x1,...,xm) ->
+--     e
+
+matchEnvStack  :: [Id]         -- x1..xm
+               -> [Id]         -- s1..sn
+               -> CoreExpr     -- e
+               -> DsM CoreExpr
+matchEnvStack env_ids stack_ids body
+  = getUniqSupplyDs                    `thenDs` \ uniqs ->
+    newSysLocalDs (tupleType env_ids)  `thenDs` \ tup_var ->
+    matchVarStack tup_var stack_ids 
+                 (coreCaseTuple uniqs tup_var env_ids body)
+
+
+----------------------------------------------
+--             matchVarStack
+--
+--     \ (...(z0,s1),...sn) -> e
+--     =>
+--     \ zn ->
+--     case zn of (zn-1,sn) ->
+--     ...
+--     case z1 of (z0,s1) ->
+--     e
+
+matchVarStack :: Id            -- z0
+             -> [Id]           -- s1..sn
+             -> CoreExpr       -- e
+             -> DsM CoreExpr
+matchVarStack env_id [] body
+  = returnDs (Lam env_id body)
+matchVarStack env_id (stack_id:stack_ids) body
+  = let
+       pair_ids = [env_id, stack_id]
+    in
+    newSysLocalDs (tupleType pair_ids) `thenDs` \ pair_id ->
+    matchVarStack pair_id stack_ids 
+                 (coreCaseSmallTuple pair_id pair_ids body)
+\end{code}
+
+\begin{code}
+mkHsTupleExpr :: [TypecheckedHsExpr] -> TypecheckedHsExpr
+mkHsTupleExpr [e] = e
+mkHsTupleExpr es = ExplicitTuple es Unboxed
+
+mkHsPairExpr :: TypecheckedHsExpr -> TypecheckedHsExpr -> TypecheckedHsExpr
+mkHsPairExpr e1 e2 = mkHsTupleExpr [e1, e2]
+
+mkHsEnvStackExpr :: [Id] -> [Id] -> TypecheckedHsExpr
+mkHsEnvStackExpr env_ids stack_ids
+  = foldl mkHsPairExpr (mkHsTupleExpr (map HsVar env_ids)) (map HsVar stack_ids)
+\end{code}
+
+Translation of arrow abstraction
+
+\begin{code}
+
+--     A | xs |- c :: [] t'        ---> c'
+--     --------------------------
+--     A |- proc p -> c :: a t t'  ---> arr (\ p -> (xs)) >>> c'
+--
+--             where (xs) is the tuple of variables bound by p
+
+dsProcExpr
+       :: TypecheckedPat
+       -> TypecheckedHsCmdTop
+       -> SrcLoc
+       -> DsM CoreExpr
+dsProcExpr pat (HsCmdTop cmd [] cmd_ty ids) locn
+  = putSrcLocDs locn $
+    mkCmdEnv ids                       `thenDs` \ meth_ids ->
+    let
+       locals = mkVarSet (collectPatBinders pat)
+    in
+    dsfixCmd meth_ids locals [] cmd_ty cmd
+                               `thenDs` \ (core_cmd, free_vars, env_ids) ->
+    let
+       env_ty = tupleType env_ids
+    in
+    mkFailExpr ProcExpr env_ty         `thenDs` \ fail_expr ->
+    selectMatchVar pat                 `thenDs` \ var ->
+    matchSimply (Var var) ProcExpr pat (mkTupleExpr env_ids) fail_expr
+                                       `thenDs` \ match_code ->
+    let
+       pat_ty = hsPatType pat
+       proc_code = do_map_arrow meth_ids pat_ty env_ty cmd_ty
+               (Lam var match_code)
+               core_cmd
+    in
+    returnDs (bindCmdEnv meth_ids proc_code)
+
+\end{code}
+
+Translation of command judgements of the form
+
+       A | xs |- c :: [ts] t
+
+\begin{code}
+
+dsCmd :: DsCmdEnv              -- arrow combinators
+       -> IdSet                -- set of local vars available to this command
+       -> [Id]                 -- list of vars in the input to this command
+                               -- This is typically fed back,
+                               -- so don't pull on it too early
+       -> [Type]               -- type of the stack
+       -> Type                 -- return type of the command
+       -> TypecheckedHsCmd     -- command to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet)          -- set of local vars that occur free
+
+--     A |- f :: a t t'
+--     A, xs |- arg :: t
+--     ---------------------------
+--     A | xs |- f -< arg :: [] t'     ---> arr (\ (xs) -> arg) >>> f
+
+dsCmd ids local_vars env_ids [] res_ty
+       (HsArrApp arrow arg arrow_ty HsFirstOrderApp _ _)
+  = let
+       (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
+        (a_ty, arg_ty) = tcSplitAppTy a_arg_ty
+       env_ty = tupleType env_ids
+    in
+    dsExpr arrow                       `thenDs` \ core_arrow ->
+    dsExpr arg                         `thenDs` \ core_arg ->
+    matchEnvStack env_ids [] core_arg  `thenDs` \ core_make_arg ->
+    returnDs (do_map_arrow ids env_ty arg_ty res_ty
+               core_make_arg
+               core_arrow,
+             exprFreeVars core_arg `intersectVarSet` local_vars)
+
+--     A, xs |- f :: a t t'
+--     A, xs |- arg :: t
+--     ---------------------------
+--     A | xs |- f -<< arg :: [] t'    ---> arr (\ (xs) -> (f,arg)) >>> app
+
+dsCmd ids local_vars env_ids [] res_ty
+       (HsArrApp arrow arg arrow_ty HsHigherOrderApp _ _)
+  = let
+       (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
+        (a_ty, arg_ty) = tcSplitAppTy a_arg_ty
+       env_ty = tupleType env_ids
+    in
+    dsExpr arrow                       `thenDs` \ core_arrow ->
+    dsExpr arg                         `thenDs` \ core_arg ->
+    matchEnvStack env_ids [] (mkCoreTup [core_arrow, core_arg])
+                                       `thenDs` \ core_make_pair ->
+    returnDs (do_map_arrow ids env_ty (mkCorePairTy arrow_ty arg_ty) res_ty
+               core_make_pair
+               (do_app ids arg_ty res_ty),
+             (exprFreeVars core_arrow `unionVarSet` exprFreeVars core_arg)
+               `intersectVarSet` local_vars)
+
+--     A | ys |- c :: [ts] t'
+--     -----------------------------------------------
+--     A | xs |- \ p1 ... pk -> c :: [t1:...:tk:ts] t'
+--
+--             ---> arr (\ ((((xs), p1), ... pk)*ts) -> ((ys)*ts)) >>> c
+
+dsCmd ids local_vars env_ids stack res_ty
+    (HsLam (Match pats _ (GRHSs [GRHS [ResultStmt body _] loc] _ _cmd_ty)))
+  = let
+       pat_vars = mkVarSet (collectPatsBinders pats)
+       local_vars' = local_vars `unionVarSet` pat_vars
+       stack' = drop (length pats) stack
+    in
+    dsfixCmd ids local_vars' stack' res_ty body
+                               `thenDs` \ (core_body, free_vars, env_ids') ->
+    mapDs newSysLocalDs stack  `thenDs` \ stack_ids ->
+
+    -- the expression is built from the inside out, so the actions
+    -- are presented in reverse order
+
+    let
+        (actual_ids, stack_ids') = splitAt (length pats) stack_ids
+       -- build a new environment, plus what's left of the stack
+       core_expr = buildEnvStack env_ids' stack_ids'
+       in_ty = envStackType env_ids stack
+       in_ty' = envStackType env_ids' stack'
+    in
+    mkFailExpr LambdaExpr in_ty'       `thenDs` \ fail_expr ->
+    -- match the patterns against the top of the old stack
+    matchSimplys (map Var actual_ids) LambdaExpr pats core_expr fail_expr
+                                       `thenDs` \ match_code ->
+    -- match the old environment and stack against the input
+    matchEnvStack env_ids stack_ids match_code
+                                       `thenDs` \ select_code ->
+    returnDs (do_map_arrow ids in_ty in_ty' res_ty select_code core_body,
+            free_vars `minusVarSet` pat_vars)
+
+dsCmd ids local_vars env_ids stack res_ty (HsPar cmd)
+  = dsCmd ids local_vars env_ids stack res_ty cmd
+
+dsCmd ids local_vars env_ids stack res_ty (HsCase exp matches src_loc)
+  = dsExpr exp                         `thenDs` \ core_exp ->
+    mapDs newSysLocalDs stack          `thenDs` \ stack_ids ->
+
+    -- Extract and desugar the leaf commands in the case, building tuple
+    -- expressions that will (after tagging) replace these leaves
+
+    let
+        leaves = concatMap leavesMatch matches
+       make_branch (leaf, bound_vars)
+         = dsfixCmd ids (local_vars `unionVarSet` bound_vars) stack res_ty leaf
+                                       `thenDs` \ (core_leaf, fvs, leaf_ids) ->
+           returnDs (fvs `minusVarSet` bound_vars,
+                     [mkHsEnvStackExpr leaf_ids stack_ids],
+                     envStackType leaf_ids stack,
+                     core_leaf)
+    in
+    mapDs make_branch leaves           `thenDs` \ branches ->
+    dsLookupTyCon eitherTyConName      `thenDs` \ either_con ->
+    dsLookupDataCon leftDataConName    `thenDs` \ left_con ->
+    dsLookupDataCon rightDataConName   `thenDs` \ right_con ->
+    let
+       left_id = HsVar (dataConWrapId left_con)
+       right_id = HsVar (dataConWrapId right_con)
+       left_expr ty1 ty2 e = HsApp (TyApp left_id [ty1, ty2]) e
+       right_expr ty1 ty2 e = HsApp (TyApp right_id [ty1, ty2]) e
+
+       -- Prefix each tuple with a distinct series of Left's and Right's,
+       -- in a balanced way, keeping track of the types.
+
+        merge_branches (fvs1, builds1, in_ty1, core_exp1)
+                      (fvs2, builds2, in_ty2, core_exp2) 
+         = (fvs1 `unionVarSet` fvs2,
+            map (left_expr in_ty1 in_ty2) builds1 ++
+               map (right_expr in_ty1 in_ty2) builds2,
+            mkTyConApp either_con [in_ty1, in_ty2],
+            do_choice ids in_ty1 in_ty2 res_ty core_exp1 core_exp2)
+       (fvs, leaves', sum_ty, core_choices) = foldb merge_branches branches
+
+       -- Replace the commands in the case with these tagged tuples,
+       -- yielding a TypecheckedHsExpr we can feed to dsExpr.
+
+       (_, matches') = mapAccumL (replaceLeavesMatch res_ty) leaves' matches
+       in_ty = envStackType env_ids stack
+    in
+    dsExpr (HsCase exp matches' src_loc) `thenDs` \ core_matches ->
+    returnDs(do_map_arrow ids in_ty sum_ty res_ty core_matches core_choices,
+       exprFreeVars core_exp `unionVarSet` fvs)
+
+--     A, xs |- e :: Bool
+--     A | xs1 |- c1 :: [ts] t
+--     A | xs2 |- c2 :: [ts] t
+--     ----------------------------------------
+--     A | xs |- if e then c1 else c2 :: [ts] t
+--
+--             ---> arr (\ ((xs)*ts) ->
+--                     if e then Left ((xs1)*ts) else Right ((xs2)*ts)) >>>
+--                  c1 ||| c2
+
+dsCmd ids local_vars env_ids stack res_ty (HsIf cond then_cmd else_cmd src_loc)
+  = dsExpr cond                        `thenDs` \ core_cond ->
+    dsfixCmd ids local_vars stack res_ty then_cmd
+                               `thenDs` \ (core_then, fvs_then, then_ids) ->
+    dsfixCmd ids local_vars stack res_ty else_cmd
+                               `thenDs` \ (core_else, fvs_else, else_ids) ->
+    mapDs newSysLocalDs stack          `thenDs` \ stack_ids ->
+    dsLookupTyCon eitherTyConName      `thenDs` \ either_con ->
+    dsLookupDataCon leftDataConName    `thenDs` \ left_con ->
+    dsLookupDataCon rightDataConName   `thenDs` \ right_con ->
+    let
+       left_expr ty1 ty2 e = mkConApp left_con [Type ty1, Type ty2, e]
+       right_expr ty1 ty2 e = mkConApp right_con [Type ty1, Type ty2, e]
+
+       in_ty = envStackType env_ids stack
+       then_ty = envStackType then_ids stack
+       else_ty = envStackType else_ids stack
+       sum_ty = mkTyConApp either_con [then_ty, else_ty]
+    in
+    matchEnvStack env_ids stack_ids
+       (mkIfThenElse core_cond
+           (left_expr then_ty else_ty (buildEnvStack then_ids stack_ids))
+           (right_expr then_ty else_ty (buildEnvStack else_ids stack_ids)))
+                                       `thenDs` \ core_if ->
+    returnDs(do_map_arrow ids in_ty sum_ty res_ty
+               core_if
+               (do_choice ids then_ty else_ty res_ty core_then core_else),
+       exprFreeVars core_cond `unionVarSet` fvs_then `unionVarSet` fvs_else)
+
+--     A | ys |- c :: [ts] t
+--     ----------------------------------
+--     A | xs |- let binds in c :: [ts] t
+--
+--             ---> arr (\ ((xs)*ts) -> let binds in ((ys)*ts)) >>> c
+
+dsCmd ids local_vars env_ids stack res_ty (HsLet binds body)
+  = let
+       defined_vars = mkVarSet (collectHsBinders binds)
+       local_vars' = local_vars `unionVarSet` defined_vars
+    in
+    dsfixCmd ids local_vars' stack res_ty body
+                               `thenDs` \ (core_body, free_vars, env_ids') ->
+    mapDs newSysLocalDs stack          `thenDs` \ stack_ids ->
+    -- build a new environment, plus the stack, using the let bindings
+    dsLet binds (buildEnvStack env_ids' stack_ids)
+                                       `thenDs` \ core_binds ->
+    -- match the old environment and stack against the input
+    matchEnvStack env_ids stack_ids core_binds
+                                       `thenDs` \ core_map ->
+    returnDs (do_map_arrow ids
+                       (envStackType env_ids stack)
+                       (envStackType env_ids' stack)
+                       res_ty
+                       core_map
+                       core_body,
+       exprFreeVars core_binds `intersectVarSet` local_vars)
+
+dsCmd ids local_vars env_ids [] res_ty (HsDo ctxt stmts _ _ src_loc)
+  = dsCmdDo ids local_vars env_ids res_ty stmts
+
+--     A |- e :: forall e. a1 (e*ts1) t1 -> ... an (e*tsn) tn -> a (e*ts) t
+--     A | xs |- ci :: [tsi] ti
+--     -----------------------------------
+--     A | xs |- (|e|) c1 ... cn :: [ts] t     ---> e [t_xs] c1 ... cn
+
+dsCmd ids local_vars env_ids _stack _res_ty (HsArrForm op _ args _)
+  = let
+       env_ty = tupleType env_ids
+    in
+    dsExpr op                          `thenDs` \ core_op ->
+    mapAndUnzipDs (dsTrimCmdArg local_vars env_ids) args
+                                       `thenDs` \ (core_args, fv_sets) ->
+    returnDs (mkApps (App core_op (Type env_ty)) core_args,
+             unionVarSets fv_sets)
+
+--     A | ys |- c :: [ts] t   (ys <= xs)
+--     ---------------------
+--     A | xs |- c :: [ts] t   ---> arr_ts (\ (xs) -> (ys)) >>> c
+
+dsTrimCmdArg
+       :: IdSet                -- set of local vars available to this command
+       -> [Id]                 -- list of vars in the input to this command
+       -> TypecheckedHsCmdTop  -- command argument to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet)          -- set of local vars that occur free
+dsTrimCmdArg local_vars env_ids (HsCmdTop cmd stack cmd_ty ids)
+  = mkCmdEnv ids                       `thenDs` \ meth_ids ->
+    dsfixCmd meth_ids local_vars stack cmd_ty cmd
+                               `thenDs` \ (core_cmd, free_vars, env_ids') ->
+    mapDs newSysLocalDs stack          `thenDs` \ stack_ids ->
+    matchEnvStack env_ids stack_ids (buildEnvStack env_ids' stack_ids)
+                                       `thenDs` \ trim_code ->
+    let
+       in_ty = envStackType env_ids stack
+       in_ty' = envStackType env_ids' stack
+       arg_code = if env_ids' == env_ids then core_cmd else
+               do_map_arrow meth_ids in_ty in_ty' cmd_ty trim_code core_cmd
+    in
+    returnDs (bindCmdEnv meth_ids arg_code, free_vars)
+
+-- Given A | xs |- c :: [ts] t, builds c with xs fed back.
+-- Typically needs to be prefixed with arr (\p -> ((xs)*ts))
+
+dsfixCmd
+       :: DsCmdEnv             -- arrow combinators
+       -> IdSet                -- set of local vars available to this command
+       -> [Type]               -- type of the stack
+       -> Type                 -- return type of the command
+       -> TypecheckedHsCmd     -- command to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet,          -- set of local vars that occur free
+               [Id])           -- set as a list, fed back
+dsfixCmd ids local_vars stack cmd_ty cmd
+  = fixDs (\ ~(_,_,env_ids') ->
+       dsCmd ids local_vars env_ids' stack cmd_ty cmd
+                                       `thenDs` \ (core_cmd, free_vars) ->
+       returnDs (core_cmd, free_vars, varSetElems free_vars))
+
+\end{code}
+
+Translation of command judgements of the form
+
+       A | xs |- do { ss } :: [] t
+
+\begin{code}
+
+dsCmdDo :: DsCmdEnv            -- arrow combinators
+       -> IdSet                -- set of local vars available to this statement
+       -> [Id]                 -- list of vars in the input to this statement
+                               -- This is typically fed back,
+                               -- so don't pull on it too early
+       -> Type                 -- return type of the statement
+       -> [TypecheckedStmt]    -- statements to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet)          -- set of local vars that occur free
+
+--     A | xs |- c :: [] t
+--     --------------------------
+--     A | xs |- do { c } :: [] t
+
+dsCmdDo ids local_vars env_ids res_ty [ResultStmt cmd _locn]
+  = dsCmd ids local_vars env_ids [] res_ty cmd
+
+dsCmdDo ids local_vars env_ids res_ty (stmt:stmts)
+  = let
+       bound_vars = mkVarSet (collectStmtBinders stmt)
+       local_vars' = local_vars `unionVarSet` bound_vars
+    in
+    fixDs (\ ~(_,_,env_ids') ->
+       dsCmdDo ids local_vars' env_ids' res_ty stmts
+                                       `thenDs` \ (core_stmts, fv_stmts) ->
+       returnDs (core_stmts, fv_stmts, varSetElems fv_stmts))
+                               `thenDs` \ (core_stmts, fv_stmts, env_ids') ->
+    dsCmdStmt ids local_vars env_ids env_ids' stmt
+                               `thenDs` \ (core_stmt, fv_stmt) ->
+    returnDs (do_compose ids
+               (tupleType env_ids)
+               (tupleType env_ids')
+               res_ty
+               core_stmt
+               core_stmts,
+             fv_stmt)
+
+dsCmdStmt
+       :: DsCmdEnv             -- arrow combinators
+       -> IdSet                -- set of local vars available to this statement
+       -> [Id]                 -- list of vars in the input to this statement
+                               -- This is typically fed back,
+                               -- so don't pull on it too early
+       -> [Id]                 -- list of vars in the output of this statement
+       -> TypecheckedStmt      -- statement to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet)          -- set of local vars that occur free
+
+--     A | xs1 |- c :: [] t
+--     A | xs' |- do { ss } :: [] t
+--     ------------------------------
+--     A | xs |- do { c; ss } :: [] t
+--
+--             ---> arr (\ (xs) -> ((xs1),(xs'))) >>> first c >>>
+--                     arr snd >>> ss
+
+dsCmdStmt ids local_vars env_ids out_ids (ExprStmt cmd c_ty locn)
+  = dsfixCmd ids local_vars [] c_ty cmd
+                               `thenDs` \ (core_cmd, fv_cmd, env_ids1) ->
+    matchEnvStack env_ids []
+       (mkCorePairExpr (mkTupleExpr env_ids1) (mkTupleExpr out_ids))
+                                       `thenDs` \ core_mux ->
+    let
+       in_ty = tupleType env_ids
+       in_ty1 = tupleType env_ids1
+       out_ty = tupleType out_ids
+       before_c_ty = mkCorePairTy in_ty1 out_ty
+       after_c_ty = mkCorePairTy c_ty out_ty
+    in
+    mkSndExpr c_ty out_ty              `thenDs` \ snd_fn ->
+    returnDs (do_map_arrow ids in_ty before_c_ty out_ty core_mux $
+               do_compose ids before_c_ty after_c_ty out_ty
+                       (do_first ids in_ty1 c_ty out_ty core_cmd) $
+               do_arr ids after_c_ty out_ty snd_fn,
+             fv_cmd `unionVarSet` mkVarSet out_ids)
+  where
+
+--     A | xs1 |- c :: [] t
+--     A | xs' |- do { ss } :: [] t            xs2 = xs' - defs(p)
+--     -----------------------------------
+--     A | xs |- do { p <- c; ss } :: [] t
+--
+--             ---> arr (\ (xs) -> ((xs1),(xs2))) >>> first c >>>
+--                     arr (\ (p, (xs2)) -> (xs')) >>> ss
+--
+-- It would be simpler and more consistent to do this using second,
+-- but that's likely to be defined in terms of first.
+
+dsCmdStmt ids local_vars env_ids out_ids (BindStmt pat cmd locn)
+  = dsfixCmd ids local_vars [] (hsPatType pat) cmd
+                               `thenDs` \ (core_cmd, fv_cmd, env_ids1) ->
+    let
+       pat_vars = mkVarSet (collectPatBinders pat)
+       env_ids2 = varSetElems (mkVarSet out_ids `minusVarSet` pat_vars)
+    in
+
+    -- multiplexing function
+    --         \ (xs) -> ((xs1),(xs2))
+
+    matchEnvStack env_ids []
+       (mkCorePairExpr (mkTupleExpr env_ids1) (mkTupleExpr env_ids2))
+                                       `thenDs` \ core_mux ->
+
+    -- projection function
+    --         \ (p, (xs2)) -> (zs)
+
+    selectMatchVar pat                 `thenDs` \ pat_id ->
+    newSysLocalDs (tupleType env_ids2) `thenDs` \ env_id ->
+    getUniqSupplyDs                    `thenDs` \ uniqs ->
+    let
+       pair_ids = [pat_id, env_id]
+       after_c_ty = tupleType pair_ids
+       out_ty = tupleType out_ids
+       body_expr = coreCaseTuple uniqs env_id env_ids2 (mkTupleExpr out_ids)
+    in
+    mkFailExpr (StmtCtxt DoExpr) out_ty        `thenDs` \ fail_expr ->
+    matchSimply (Var pat_id) (StmtCtxt DoExpr) pat body_expr fail_expr
+                                       `thenDs` \ match_code ->
+    newSysLocalDs after_c_ty           `thenDs` \ pair_id ->
+    let
+       proj_expr = Lam pair_id (coreCaseSmallTuple pair_id pair_ids match_code)
+    in
+
+    -- put it all togther
+    let
+       pat_ty = hsPatType pat
+       in_ty = tupleType env_ids
+       in_ty1 = tupleType env_ids1
+       in_ty2 = tupleType env_ids2
+       before_c_ty = mkCorePairTy in_ty1 in_ty2
+    in
+    returnDs (do_map_arrow ids in_ty before_c_ty out_ty core_mux $
+               do_compose ids before_c_ty after_c_ty out_ty
+                       (do_first ids in_ty1 pat_ty in_ty2 core_cmd) $
+               do_arr ids after_c_ty out_ty proj_expr,
+             fv_cmd `unionVarSet` (mkVarSet out_ids `minusVarSet` pat_vars))
+
+--     A | xs' |- do { ss } :: [] t
+--     --------------------------------------
+--     A | xs |- do { let binds; ss } :: [] t
+--
+--             ---> arr (\ (xs) -> let binds in (xs')) >>> ss
+
+dsCmdStmt ids local_vars env_ids out_ids (LetStmt binds)
+    -- build a new environment using the let bindings
+  = dsLet binds (mkTupleExpr out_ids)  `thenDs` \ core_binds ->
+    -- match the old environment against the input
+    matchEnvStack env_ids [] core_binds        `thenDs` \ core_map ->
+    returnDs (do_arr ids
+                       (tupleType env_ids)
+                       (tupleType out_ids)
+                       core_map,
+       exprFreeVars core_binds `intersectVarSet` local_vars)
+
+--     A | ys |- do { ss; returnA -< ((xs1), (ys2)) } :: [] ...
+--     A | xs' |- do { ss' } :: [] t
+--     ------------------------------------
+--     A | xs |- do { rec ss; ss' } :: [] t
+--
+--                     xs1 = xs' /\ defs(ss)
+--                     xs2 = xs' - defs(ss)
+--                     ys1 = ys - defs(ss)
+--                     ys2 = ys /\ defs(ss)
+--
+--             ---> arr (\(xs) -> ((ys1),(xs2))) >>>
+--                     first (loop (arr (\((ys1),~(ys2)) -> (ys)) >>> ss)) >>>
+--                     arr (\((xs1),(xs2)) -> (xs')) >>> ss'
+
+dsCmdStmt ids local_vars env_ids out_ids' (RecStmt stmts later_ids rec_ids rhss)
+  = let
+       rec_id_set = mkVarSet rec_ids
+       out_ids = varSetElems (mkVarSet later_ids `unionVarSet` rec_id_set)
+       out_ty = tupleType out_ids
+       local_vars' = local_vars `unionVarSet` rec_id_set
+    in
+
+    -- mk_pair_fn = \ (out_ids) -> ((later_ids),(rhss))
+
+    mapDs dsExpr rhss          `thenDs` \ core_rhss ->
+    let
+       later_tuple = mkTupleExpr later_ids
+       later_ty = tupleType later_ids
+       rec_tuple = mkCoreTup core_rhss
+       rec_ty = tupleType rec_ids
+       out_pair = mkCoreTup [later_tuple, rec_tuple]
+       out_pair_ty = mkCoreTupTy [later_ty, rec_ty]
+    in
+       matchEnvStack out_ids [] out_pair
+                               `thenDs` \ mk_pair_fn ->
+
+    dsfixCmdStmts ids local_vars' out_ids stmts
+                               `thenDs` \ (core_stmts, fv_stmts, env_ids') ->
+
+    -- squash_pair_fn = \ ((env1_ids), ~(rec_ids)) -> (env_ids')
+
+    newSysLocalDs rec_ty       `thenDs` \ rec_id ->
+    let
+       env1_id_set = fv_stmts `minusVarSet` rec_id_set
+       env1_ids = varSetElems env1_id_set
+       env1_ty = tupleType env1_ids
+       in_pair_ty = mkCoreTupTy [env1_ty, rec_ty]
+       core_body = mkCoreTup (map selectVar env_ids')
+         where
+           selectVar v
+               | v `elemVarSet` rec_id_set
+                 = mkTupleSelector rec_ids v rec_id (Var rec_id)
+               | otherwise = Var v
+    in
+    matchEnvStack env1_ids [rec_id] core_body
+                               `thenDs` \ squash_pair_fn ->
+
+    -- loop (arr squash_pair_fn >>> ss >>> arr mk_pair_fn)
+
+    let
+       env_ty' = tupleType env_ids'
+       core_loop = do_loop ids env1_ty later_ty rec_ty
+               (do_map_arrow ids in_pair_ty env_ty' out_pair_ty
+                       squash_pair_fn
+                       (do_compose ids env_ty' out_ty out_pair_ty
+                               core_stmts
+                               (do_arr ids out_ty out_pair_ty mk_pair_fn)))
+    in
+
+    -- pre_loop_fn = \(env_ids) -> ((env1_ids),(env2_ids))
+
+    let
+       env_ty = tupleType env_ids
+       env2_id_set = mkVarSet out_ids' `minusVarSet` mkVarSet later_ids
+       env2_ids = varSetElems env2_id_set
+       env2_ty = tupleType env2_ids
+       pre_pair_ty = mkCoreTupTy [env1_ty, env2_ty]
+       pre_loop_body = mkCoreTup [mkTupleExpr env1_ids, mkTupleExpr env2_ids]
+
+    in
+    matchEnvStack env_ids [] pre_loop_body
+                               `thenDs` \ pre_loop_fn ->
+
+    -- post_loop_fn = \((later_ids),(env2_ids)) -> (out_ids')
+
+    getUniqSupplyDs            `thenDs` \ uniqs ->
+    newSysLocalDs env2_ty      `thenDs` \ env2_id ->
+    let
+       out_ty' = tupleType out_ids'
+       post_pair_ty = mkCoreTupTy [later_ty, env2_ty]
+       post_loop_body = coreCaseTuple uniqs env2_id env2_ids (mkTupleExpr out_ids')
+    in
+    matchEnvStack later_ids [env2_id] post_loop_body
+                               `thenDs` \ post_loop_fn ->
+       
+    -- arr pre_loop_fn >>> first (loop (...)) >>> arr post_loop_fn
+
+    let
+       core_body = do_map_arrow ids env_ty pre_pair_ty out_ty'
+               pre_loop_fn
+               (do_compose ids pre_pair_ty post_pair_ty out_ty'
+                       (do_first ids env1_ty later_ty env2_ty
+                               core_loop)
+                       (do_arr ids post_pair_ty out_ty'
+                               post_loop_fn))
+    in
+    returnDs (core_body, env1_id_set `unionVarSet` env2_id_set)
+
+\end{code}
+A sequence of statements (as is a rec) is desugared to an arrow between
+two environments
+\begin{code}
+
+dsfixCmdStmts
+       :: DsCmdEnv             -- arrow combinators
+       -> IdSet                -- set of local vars available to this statement
+       -> [Id]                 -- output vars of these statements
+       -> [TypecheckedStmt]    -- statements to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet,          -- set of local vars that occur free
+               [Id])           -- input vars
+
+dsfixCmdStmts ids local_vars out_ids stmts
+  = fixDs (\ ~(_,_,env_ids) ->
+       dsCmdStmts ids local_vars env_ids out_ids stmts
+                                       `thenDs` \ (core_stmts, fv_stmts) ->
+       returnDs (core_stmts, fv_stmts, varSetElems fv_stmts))
+
+dsCmdStmts
+       :: DsCmdEnv             -- arrow combinators
+       -> IdSet                -- set of local vars available to this statement
+       -> [Id]                 -- list of vars in the input to these statements
+       -> [Id]                 -- output vars of these statements
+       -> [TypecheckedStmt]    -- statements to desugar
+       -> DsM (CoreExpr,       -- desugared expression
+               IdSet)          -- set of local vars that occur free
+
+dsCmdStmts ids local_vars env_ids out_ids [stmt]
+  = dsCmdStmt ids local_vars env_ids out_ids stmt
+
+dsCmdStmts ids local_vars env_ids out_ids (stmt:stmts)
+  = let
+       bound_vars = mkVarSet (collectStmtBinders stmt)
+       local_vars' = local_vars `unionVarSet` bound_vars
+    in
+    dsfixCmdStmts ids local_vars' out_ids stmts
+                               `thenDs` \ (core_stmts, fv_stmts, env_ids') ->
+    dsCmdStmt ids local_vars env_ids env_ids' stmt
+                               `thenDs` \ (core_stmt, fv_stmt) ->
+    returnDs (do_compose ids
+               (tupleType env_ids)
+               (tupleType env_ids')
+               (tupleType out_ids)
+               core_stmt
+               core_stmts,
+             fv_stmt)
+
+\end{code}
+
+Match a list of expressions against a list of patterns, left-to-right.
+
+\begin{code}
+matchSimplys :: [CoreExpr]               -- Scrutinees
+            -> TypecheckedMatchContext  -- Match kind
+            -> [TypecheckedPat]         -- Patterns they should match
+            -> CoreExpr                 -- Return this if they all match
+            -> CoreExpr                 -- Return this if they don't
+            -> DsM CoreExpr
+matchSimplys [] _ctxt [] result_expr fail_expr = returnDs result_expr
+matchSimplys (exp:exps) ctxt (pat:pats) result_expr fail_expr
+  = matchSimplys exps ctxt pats result_expr fail_expr
+                                       `thenDs` \ match_code ->
+    matchSimply exp ctxt pat match_code fail_expr
+\end{code}
+
+\begin{code}
+
+-- list of leaf expressions, with set of variables bound in each
+leavesMatch :: TypecheckedMatch -> [(TypecheckedHsExpr, IdSet)]
+leavesMatch (Match pats _ (GRHSs grhss binds _ty))
+  = let
+       defined_vars = mkVarSet (collectPatsBinders pats) `unionVarSet`
+                      mkVarSet (collectHsBinders binds)
+    in
+    [(expr, mkVarSet (collectStmtsBinders stmts) `unionVarSet` defined_vars) |
+       GRHS stmts _locn <- grhss,
+       let ResultStmt expr _ = last stmts]
+
+-- Replace the leaf commands in a match
+
+replaceLeavesMatch
+       :: Type                 -- new result type
+       -> [TypecheckedHsExpr]  -- replacement leaf expressions of that type
+       -> TypecheckedMatch     -- the matches of a case command
+       -> ([TypecheckedHsExpr],-- remaining leaf expressions
+           TypecheckedMatch)   -- updated match
+replaceLeavesMatch res_ty leaves (Match pat mt (GRHSs grhss binds _ty))
+  = let
+       (leaves', grhss') = mapAccumL (replaceLeavesGRHS res_ty) leaves grhss
+    in
+    (leaves', Match pat mt (GRHSs grhss' binds res_ty))
+
+replaceLeavesGRHS
+       :: Type                 -- new result type
+       -> [TypecheckedHsExpr]  -- replacement leaf expressions of that type
+       -> TypecheckedGRHS      -- rhss of a case command
+       -> ([TypecheckedHsExpr],-- remaining leaf expressions
+           TypecheckedGRHS)    -- updated GRHS
+replaceLeavesGRHS res_ty (leaf:leaves) (GRHS stmts srcloc)
+  = (leaves, GRHS (init stmts ++ [ResultStmt leaf srcloc]) srcloc)
+
+\end{code}
+
+Balanced fold of a non-empty list.
+
+\begin{code}
+foldb :: (a -> a -> a) -> [a] -> a
+foldb f [] = error "foldb of empty list"
+foldb f [x] = x
+foldb f xs = foldb f (fold_pairs xs)
+  where
+    fold_pairs [] = []
+    fold_pairs [x] = [x]
+    fold_pairs (x1:x2:xs) = f x1 x2:fold_pairs xs
+\end{code}
index 20414c0..f9d0a6c 100644 (file)
@@ -15,7 +15,10 @@ import DsBinds               ( dsMonoBinds, AutoScc(..) )
 import DsGRHSs         ( dsGuarded )
 import DsCCall         ( dsCCall )
 import DsListComp      ( dsListComp, dsPArrComp )
-import DsUtils         ( mkErrorAppDs, mkStringLit, mkConsExpr, mkNilExpr, mkCoreTupTy, selectMatchVar )
+import DsUtils         ( mkErrorAppDs, mkStringLit, mkConsExpr, mkNilExpr,
+                         mkCoreTupTy, selectMatchVar,
+                         dsReboundNames, lookupReboundName )
+import DsArrows                ( dsProcExpr )
 import DsMonad
 
 #ifdef GHCI
@@ -26,6 +29,7 @@ import DsMeta         ( dsBracket, dsReify )
 import HsSyn           ( HsExpr(..), Pat(..), ArithSeqInfo(..),
                          Stmt(..), HsMatchContext(..), HsStmtContext(..), 
                          Match(..), HsBinds(..), MonoBinds(..), HsConDetails(..),
+                         ReboundNames,
                          mkSimpleMatch, isDoExpr
                        )
 import TcHsSyn         ( TypecheckedHsExpr, TypecheckedHsBinds, TypecheckedStmt, hsPatType )
@@ -52,7 +56,9 @@ import Name           ( Name )
 import TyCon           ( tyConDataCons )
 import TysWiredIn      ( tupleCon, mkTupleTy )
 import BasicTypes      ( RecFlag(..), Boxity(..), ipNameName )
-import PrelNames       ( toPName )
+import PrelNames       ( toPName,
+                         returnMName, bindMName, thenMName, failMName,
+                         mfixName )
 import SrcLoc          ( noSrcLoc )
 import Util            ( zipEqual, zipWithEqual )
 import Outputable
@@ -559,6 +565,8 @@ dsExpr (HsReify r)     = dsReify r
 dsExpr (HsSplice n e _)    = pprPanic "dsExpr:splice" (ppr e)
 #endif
 
+-- Arrow notation extension
+dsExpr (HsProc pat cmd src_loc) = dsProcExpr pat cmd src_loc
 \end{code}
 
 
@@ -580,13 +588,18 @@ Basically does the translation given in the Haskell~1.3 report:
 \begin{code}
 dsDo   :: HsStmtContext Name
        -> [TypecheckedStmt]
-       -> [Id]         -- id for: [return,fail,>>=,>>] and possibly mfixName
-       -> Type         -- Element type; the whole expression has type (m t)
+       -> ReboundNames Id      -- id for: [return,fail,>>=,>>] and possibly mfixName
+       -> Type                 -- Element type; the whole expression has type (m t)
        -> DsM CoreExpr
 
 dsDo do_or_lc stmts ids result_ty
-  = let
-       (return_id : fail_id : bind_id : then_id : _) = ids
+  = dsReboundNames ids         `thenDs` \ (meth_binds, ds_meths) ->
+    let
+       return_id = lookupReboundName ds_meths returnMName
+       fail_id   = lookupReboundName ds_meths failMName
+       bind_id   = lookupReboundName ds_meths bindMName
+       then_id   = lookupReboundName ds_meths thenMName
+
        (m_ty, b_ty) = tcSplitAppTy result_ty   -- result_ty must be of the form (m b)
        is_do        = isDoExpr do_or_lc        -- True for both MDo and Do
        
@@ -598,13 +611,13 @@ dsDo do_or_lc stmts ids result_ty
        go [ResultStmt expr locn]
          | is_do     = do_expr expr locn
          | otherwise = do_expr expr locn       `thenDs` \ expr2 ->
-                       returnDs (mkApps (Var return_id) [Type b_ty, expr2])
+                       returnDs (mkApps return_id [Type b_ty, expr2])
 
        go (ExprStmt expr a_ty locn : stmts)
          | is_do       -- Do expression
          = do_expr expr locn           `thenDs` \ expr2 ->
            go stmts                    `thenDs` \ rest  ->
-           returnDs (mkApps (Var then_id) [Type a_ty, Type b_ty, expr2, rest])
+           returnDs (mkApps then_id [Type a_ty, Type b_ty, expr2, rest])
 
           | otherwise  -- List comprehension
          = do_expr expr locn                   `thenDs` \ expr2 ->
@@ -614,7 +627,7 @@ dsDo do_or_lc stmts ids result_ty
            in
            mkStringLit msg                     `thenDs` \ core_msg ->
            returnDs (mkIfThenElse expr2 rest 
-                                  (App (App (Var fail_id) (Type b_ty)) core_msg))
+                                  (App (App fail_id (Type b_ty)) core_msg))
     
        go (LetStmt binds : stmts )
          = go stmts            `thenDs` \ rest   ->
@@ -628,21 +641,22 @@ dsDo do_or_lc stmts ids result_ty
            let
                -- In a do expression, pattern-match failure just calls
                -- the monadic 'fail' rather than throwing an exception
-               fail_expr  = mkApps (Var fail_id) [Type b_ty, core_msg]
+               fail_expr  = mkApps fail_id [Type b_ty, core_msg]
                a_ty       = hsPatType pat
            in
            selectMatchVar pat                                  `thenDs` \ var ->
            matchSimply (Var var) (StmtCtxt do_or_lc) pat
                        body fail_expr                          `thenDs` \ match_code ->
-           returnDs (mkApps (Var bind_id) [Type a_ty, Type b_ty, rhs, Lam var match_code])
+           returnDs (mkApps bind_id [Type a_ty, Type b_ty, rhs, Lam var match_code])
 
-       go (RecStmt rec_vars rec_stmts rec_rets : stmts)
+       go (RecStmt rec_stmts later_vars rec_vars rec_rets : stmts)
          = go (bind_stmt : stmts)
          where
-           bind_stmt = dsRecStmt m_ty ids rec_vars rec_stmts rec_rets
+           bind_stmt = dsRecStmt m_ty ds_meths rec_stmts later_vars rec_vars rec_rets
            
     in
-    go stmts
+    go stmts                           `thenDs` \ stmts_code ->
+    returnDs (foldr Let stmts_code meth_binds)
 
   where
     do_expr expr locn = putSrcLocDs locn (dsExpr expr)
@@ -658,16 +672,17 @@ We turn (RecStmt [v1,..vn] stmts) into:
 
 \begin{code}
 dsRecStmt :: Type              -- Monad type constructor :: * -> *
-         -> [Id]               -- Ids for: [return,fail,>>=,>>,mfix]
-         -> [Id] -> [TypecheckedStmt]  -> [TypecheckedHsExpr]  -- Guts of the RecStmt
+         -> [(Name,Id)]        -- Rebound Ids
+         -> [TypecheckedStmt]
+         -> [Id] -> [Id] -> [TypecheckedHsExpr]
          -> TypecheckedStmt
-dsRecStmt m_ty ids@[return_id, _, _, _, mfix_id] vars stmts rets
+dsRecStmt m_ty ds_meths stmts later_vars rec_vars rec_rets
   = ASSERT( length vars == length rets )
     BindStmt tup_pat mfix_app noSrcLoc
   where 
-       (var1:rest) = vars              -- Always at least one
-       (ret1:_)    = rets
-       one_var     = null rest
+       vars@(var1:rest) = later_vars           ++ rec_vars             -- Always at least one
+       rets@(ret1:_)    = map HsVar later_vars ++ rec_rets
+       one_var          = null rest
 
        mfix_app = HsApp (TyApp (HsVar mfix_id) [tup_ty]) mfix_arg
        mfix_arg = HsLam (mkSimpleMatch [tup_pat] body tup_ty noSrcLoc)
@@ -680,10 +695,13 @@ dsRecStmt m_ty ids@[return_id, _, _, _, mfix_id] vars stmts rets
                 | otherwise = LazyPat (TuplePat (map VarPat vars) Boxed)
 
        body = HsDo DoExpr (stmts ++ [return_stmt]) 
-                          ids  -- Don't need the mfix, but it does no harm
+                          [(n, HsVar id) | (n,id) <- ds_meths] -- A bit of a hack
                           (mkAppTy m_ty tup_ty)
                           noSrcLoc
 
+       Var return_id = lookupReboundName ds_meths returnMName
+       Var mfix_id   = lookupReboundName ds_meths mfixName
+
        return_stmt = ResultStmt return_app noSrcLoc
        return_app  = HsApp (TyApp (HsVar return_id) [tup_ty]) tup_expr
 \end{code}
index 7c2343d..e9c455d 100644 (file)
@@ -67,8 +67,8 @@ dsListComp quals elt_ty
     returnDs (Var build_id `App` Type elt_ty 
                           `App` mkLams [n_tyvar, c, n] result)
 
-  where isParallelComp (ParStmtOut bndrstmtss : _) = True
-       isParallelComp _                           = False
+  where isParallelComp (ParStmt bndrstmtss : _) = True
+       isParallelComp _                        = False
 \end{code}
 
 %************************************************************************
@@ -125,7 +125,7 @@ comprehensions.  The translation goes roughly as follows:
 where (x1, .., xn) are the variables bound in p1, v1, p2
       (y1, .., ym) are the variables bound in q1, v2, q2
 
-In the translation below, the ParStmtOut branch translates each parallel branch
+In the translation below, the ParStmt branch translates each parallel branch
 into a sub-comprehension, and desugars each independently.  The resulting lists
 are fed to a zip function, we create a binding for all the variables bound in all
 the comprehensions, and then we hand things off the the desugarer for bindings.
@@ -139,22 +139,25 @@ with the Unboxed variety.
 
 deListComp :: [TypecheckedStmt] -> CoreExpr -> DsM CoreExpr
 
-deListComp (ParStmtOut bndrstmtss : quals) list
-  = mapDs do_list_comp bndrstmtss      `thenDs` \ exps ->
+deListComp (ParStmt stmtss_w_bndrs : quals) list
+  = mapDs do_list_comp stmtss_w_bndrs  `thenDs` \ exps ->
     mkZipBind qual_tys                 `thenDs` \ (zip_fn, zip_rhs) ->
 
        -- Deal with [e | pat <- zip l1 .. ln] in example above
     deBindComp pat (Let (Rec [(zip_fn, zip_rhs)]) (mkApps (Var zip_fn) exps)) 
                   quals list
 
-  where -- pat is the pattern ((x1,..,xn), (y1,..,ym)) in the example above
-       pat            = TuplePat pats Boxed
-       pats           = map (\(bs,_) -> mk_hs_tuple_pat bs) bndrstmtss
+  where 
+       bndrs_s = map snd stmtss_w_bndrs
+
+       -- pat is the pattern ((x1,..,xn), (y1,..,ym)) in the example above
+       pat      = TuplePat pats Boxed
+       pats     = map mk_hs_tuple_pat bndrs_s
 
        -- Types of (x1,..,xn), (y1,..,yn) etc
-       qual_tys = [ mk_bndrs_tys bndrs | (bndrs,_) <- bndrstmtss ]
+       qual_tys = map mk_bndrs_tys bndrs_s
 
-       do_list_comp (bndrs, stmts)
+       do_list_comp (stmts, bndrs)
          = dsListComp (stmts ++ [ResultStmt (mk_hs_tuple_expr bndrs) noSrcLoc])
                       (mk_bndrs_tys bndrs)
 
@@ -428,8 +431,8 @@ dePArrComp (LetStmt ds : qs) pa cea =
 --    where
 --      {x_1, ..., x_n} = DV (qs)
 --
-dePArrComp (ParStmtOut []             : qss2) pa cea = dePArrComp qss2 pa cea
-dePArrComp (ParStmtOut ((xs, qs):qss) : qss2) pa cea =
+dePArrComp (ParStmt []             : qss2) pa cea = dePArrComp qss2 pa cea
+dePArrComp (ParStmt ((qs, xs):qss) : qss2) pa cea =
   dsLookupGlobalId zipPName                              `thenDs` \zipP    ->
   let pa'     = TuplePat [pa, TuplePat (map VarPat xs) Boxed] Boxed
       ty'cea  = parrElemType cea
@@ -439,7 +442,7 @@ dePArrComp (ParStmtOut ((xs, qs):qss) : qss2) pa cea =
   let ty'cqs = parrElemType cqs
       cea'   = mkApps (Var zipP) [Type ty'cea, Type ty'cqs, cea, cqs]
   in
-  dePArrComp (ParStmtOut qss : qss2) pa' cea'
+  dePArrComp (ParStmt qss : qss2) pa' cea'
 
 -- generate Core corresponding to `\p -> e'
 --
index 904d575..0889109 100644 (file)
@@ -6,7 +6,7 @@
 \begin{code}
 module DsMonad (
        DsM,
-       initDs, returnDs, thenDs, mapDs, listDs,
+       initDs, returnDs, thenDs, mapDs, listDs, fixDs,
        mapAndUnzipDs, zipWithDs, foldlDs,
        uniqSMtoDsM,
        newTyVarsDs, cloneTyVarsDs,
@@ -15,8 +15,9 @@ module DsMonad (
        getSrcLocDs, putSrcLocDs,
        getModuleDs,
        getUniqueDs, getUniquesDs,
+       UniqSupply, getUniqSupplyDs,
        getDOptsDs,
-       dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon,
+       dsLookupGlobal, dsLookupGlobalId, dsLookupTyCon, dsLookupDataCon,
 
        DsMetaEnv, DsMetaVal(..), dsLookupMetaEnv, dsExtendMetaEnv,
 
@@ -30,7 +31,9 @@ module DsMonad (
 import TcHsSyn         ( TypecheckedPat, TypecheckedMatchContext, TypecheckedHsExpr )
 import HscTypes                ( TyThing(..) )
 import Bag             ( emptyBag, snocBag, Bag )
+import DataCon         ( DataCon )
 import TyCon           ( TyCon )
+import DataCon         ( DataCon )
 import Id              ( mkSysLocal, setIdUnique, Id )
 import Module          ( Module )
 import Var             ( TyVar, setTyVarUnique )
@@ -38,7 +41,7 @@ import Outputable
 import SrcLoc          ( noSrcLoc, SrcLoc )
 import Type             ( Type )
 import UniqSupply      ( initUs_, getUniqueUs, getUniquesUs, thenUs, returnUs, 
-                         UniqSM, UniqSupply )
+                         fixUs, UniqSM, UniqSupply, getUs )
 import Unique          ( Unique ) 
 import Name            ( Name, nameOccName )
 import NameEnv
@@ -113,6 +116,9 @@ thenDs (DsM m1) m2 = DsM( \ env warns ->
 returnDs :: a -> DsM a
 returnDs result = DsM (\ env warns -> returnUs (result, warns))
 
+fixDs :: (a -> DsM a) -> DsM a
+fixDs f = DsM (\env warns -> fixUs (\ ~(a, _warns') -> unDsM (f a) env warns))
+
 listDs :: [DsM a] -> DsM [a]
 listDs []     = returnDs []
 listDs (x:xs)
@@ -173,6 +179,11 @@ getUniquesDs = DsM(\ env warns ->
     getUniquesUs               `thenUs` \ uniqs -> 
     returnUs (uniqs, warns))
 
+getUniqSupplyDs :: DsM UniqSupply
+getUniqSupplyDs = DsM(\ env warns -> 
+    getUs              `thenUs` \ uniqs -> 
+    returnUs (uniqs, warns))
+
 -- Make a new Id with the same print name, but different type, and new unique
 newUniqueId :: Name -> Type -> DsM Id
 newUniqueId id ty
@@ -238,18 +249,23 @@ dsLookupGlobal name
 dsLookupGlobalId :: Name -> DsM Id
 dsLookupGlobalId name 
   = dsLookupGlobal name                `thenDs` \ thing ->
-    returnDs (get_id name thing)
+    returnDs $ case thing of
+               AnId id -> id
+               other   -> pprPanic "dsLookupGlobalId" (ppr name)
 
 dsLookupTyCon :: Name -> DsM TyCon
 dsLookupTyCon name
   = dsLookupGlobal name                `thenDs` \ thing ->
-    returnDs (get_tycon name thing)
+    returnDs $ case thing of
+                ATyCon tc -> tc
+                other     -> pprPanic "dsLookupTyCon" (ppr name)
 
-get_id name (AnId id) = id
-get_id name other     = pprPanic "dsLookupGlobalId" (ppr name)
-
-get_tycon name (ATyCon tc) = tc
-get_tycon name other       = pprPanic "dsLookupTyCon" (ppr name)
+dsLookupDataCon :: Name -> DsM DataCon
+dsLookupDataCon name
+  = dsLookupGlobal name                `thenDs` \ thing ->
+    returnDs $ case thing of
+                ADataCon dc -> dc
+                other       -> pprPanic "dsLookupDataCon" (ppr name)
 \end{code}
 
 \begin{code}
index 4556b0a..4705082 100644 (file)
@@ -26,13 +26,16 @@ module DsUtils (
 
        mkSelectorBinds, mkTupleExpr, mkTupleSelector, 
        mkCoreTup, mkCoreSel, mkCoreTupTy,
+       
+       dsReboundNames, lookupReboundName,
 
        selectMatchVar
     ) where
 
 #include "HsVersions.h"
 
-import {-# SOURCE #-} Match ( matchSimply )
+import {-# SOURCE #-}  Match ( matchSimply )
+import {-# SOURCE #-}  DsExpr( dsExpr )
 
 import HsSyn
 import TcHsSyn         ( TypecheckedPat, hsPatType )
@@ -43,6 +46,7 @@ import DsMonad
 import CoreUtils       ( exprType, mkIfThenElse, mkCoerce )
 import MkId            ( iRREFUT_PAT_ERROR_ID, mkReboxingAlt, mkNewTypeBody )
 import Id              ( idType, Id, mkWildId, mkTemplateLocals )
+import Name            ( Name )
 import Literal         ( Literal(..), inIntRange, tARGET_MAX_INT )
 import TyCon           ( isNewTyCon, tyConDataCons )
 import DataCon         ( DataCon, dataConSourceArity )
@@ -65,6 +69,7 @@ import PrelNames      ( unpackCStringName, unpackCStringUtf8Name,
 import Outputable
 import UnicodeUtil      ( intsToUtf8, stringToUtf8 )
 import Util             ( isSingleton, notNull, zipEqual )
+import ListSetOps      ( assocDefault )
 import FastString
 \end{code}
 
@@ -72,6 +77,36 @@ import FastString
 
 %************************************************************************
 %*                                                                     *
+               Rebindable syntax
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+dsReboundNames :: ReboundNames Id 
+              -> DsM ([CoreBind],      -- Auxiliary bindings
+                      [(Name,Id)])     -- Maps the standard name to its value
+
+dsReboundNames rebound_ids
+  = mapAndUnzipDs mk_bind rebound_ids  `thenDs` \ (binds_s, prs) ->
+    return (concat binds_s, prs)
+  where
+       -- The cheapo special case can happen when we 
+       -- make an intermediate HsDo when desugaring a RecStmt
+    mk_bind (std_name, HsVar id) = return ([], (std_name, id))
+    mk_bind (std_name, expr)    = dsExpr expr                          `thenDs` \ rhs ->
+                                  newSysLocalDs (exprType rhs)         `thenDs` \ id ->
+                                  return ([NonRec id rhs], (std_name, id))
+
+lookupReboundName :: [(Name,Id)] -> Name -> CoreExpr
+lookupReboundName prs std_name
+  = Var (assocDefault (mk_panic std_name) prs std_name)
+  where
+    mk_panic std_name = pprPanic "dsReboundNames" (ptext SLIT("Not found:") <+> ppr std_name)
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
 \subsection{Tidying lit pats}
 %*                                                                     *
 %************************************************************************
index db6c7ad..a5f6994 100644 (file)
@@ -237,13 +237,12 @@ cvtdd (FromThenToR x y z) = (FromThenTo (cvt x) (cvt y) (cvt z))
 
 
 cvtstmts :: [Meta.Stmt] -> [Hs.Stmt RdrName]
-cvtstmts [] = [] -- this is probably an error as every [stmt] should end with ResultStmt
-cvtstmts [NoBindS e]      = [ResultStmt (cvt e) loc0]      -- when its the last element use ResultStmt
-cvtstmts (NoBindS e : ss) = ExprStmt (cvt e) void loc0     : cvtstmts ss
+cvtstmts []                   = [] -- this is probably an error as every [stmt] should end with ResultStmt
+cvtstmts [NoBindS e]           = [ResultStmt (cvt e) loc0]      -- when its the last element use ResultStmt
+cvtstmts (NoBindS e : ss)      = ExprStmt (cvt e) void loc0     : cvtstmts ss
 cvtstmts (Meta.BindS p e : ss) = BindStmt (cvtp p) (cvt e) loc0 : cvtstmts ss
 cvtstmts (Meta.LetS ds : ss)   = LetStmt (cvtdecs ds)      : cvtstmts ss
-cvtstmts (Meta.ParS dss : ss)  = ParStmt(map cvtstmts dss)      : cvtstmts ss
-
+cvtstmts (Meta.ParS dss : ss)  = ParStmt [(cvtstmts ds, undefined) | ds <- dss] : cvtstmts ss
 
 cvtm :: Meta.Match -> Hs.Match RdrName
 cvtm (Meta.Match p body wheres)
index a735195..d34d4b9 100644 (file)
@@ -22,6 +22,7 @@ import PprType                ( pprParendType )
 import Type            ( Type )
 import Var             ( TyVar, Id )
 import Name            ( Name )
+import NameSet         ( FreeVars )
 import DataCon         ( DataCon )
 import CStrings                ( CLabelString, pprCLabelString )
 import BasicTypes      ( IPName, Boxity, tupleParens, Fixity(..) )
@@ -86,11 +87,9 @@ data HsExpr id
   | HsDo       (HsStmtContext Name)    -- The parameterisation is unimportant
                                        -- because in this context we never use
                                        -- the PatGuard or ParStmt variant
-               [Stmt id]       -- "do":one or more stmts
-               [id]            -- Ids for [return,fail,>>=,>>]
-                               --      Brutal but simple
-                               -- Before type checking, used for rebindable syntax
-               PostTcType      -- Type of the whole expression
+               [Stmt id]               -- "do":one or more stmts
+               (ReboundNames id)       -- Ids for [return,fail,>>=,>>]
+                       PostTcType      -- Type of the whole expression
                SrcLoc
 
   | ExplicitList               -- syntactic list
@@ -161,6 +160,7 @@ data HsExpr id
   | HsCoreAnn   FastString      -- hdaume: core annotation
                 (HsExpr id)
                
+  -----------------------------------------------------------
   -- MetaHaskell Extensions
   | HsBracket    (HsBracket id) SrcLoc
 
@@ -173,6 +173,37 @@ data HsExpr id
                                        -- identify this splice point
 
   | HsReify (HsReify id)               -- reifyType t, reifyDecl i, reifyFixity
+
+  -----------------------------------------------------------
+  -- Arrow notation extension
+
+  | HsProc     (Pat id)                -- arrow abstraction, proc
+               (HsCmdTop id)           -- body of the abstraction
+                                       -- always has an empty stack
+               SrcLoc
+
+  ---------------------------------------
+  -- The following are commands, not expressions proper
+
+  | HsArrApp   -- Arrow tail, or arrow application (f -< arg)
+       (HsExpr id)     -- arrow expression, f
+       (HsExpr id)     -- input expression, arg
+       PostTcType      -- type of the arrow expressions f,
+                       -- of the form a t t', where arg :: t
+       HsArrAppType    -- higher-order (-<<) or first-order (-<)
+       Bool            -- True => right-to-left (f -< arg)
+                       -- False => left-to-right (arg >- f)
+       SrcLoc
+
+  | HsArrForm  -- Command formation,  (| e |) cmd1 .. cmdn
+       (HsExpr id)     -- the operator
+                       -- after type-checking, a type abstraction to be
+                       -- applied to the type of the local environment tuple
+       (Maybe Fixity)  -- fixity (filled in by the renamer), for forms that
+                       -- were converted from OpApp's by the renamer
+       [HsCmdTop id]   -- argument commands
+       SrcLoc
+
 \end{code}
 
 
@@ -212,6 +243,22 @@ type PendingSplice = (Name, HsExpr Id)     -- Typechecked splices, waiting to be
                                        -- pasted back in by the desugarer
 \end{code}
 
+Table of bindings of names used in rebindable syntax.
+This gets filled in by the renamer.
+
+\begin{code}
+type ReboundNames id = [(Name, HsExpr id)]
+-- * Before the renamer, this list is empty
+--
+-- * After the renamer, it takes the form [(std_name, HsVar actual_name)]
+--   For example, for the 'return' op of a monad
+--     normal case:            (GHC.Base.return, HsVar GHC.Base.return)
+--     with rebindable syntax: (GHC.Base.return, return_22)
+--             where return_22 is whatever "return" is in scope
+--
+-- * After the type checker, it takes the form [(std_name, <expression>)]
+--     where <expression> is the evidence for the method
+\end{code}
 
 A @Dictionary@, unless of length 0 or 1, becomes a tuple.  A
 @ClassDictLam dictvars methods expr@ is, therefore:
@@ -256,12 +303,7 @@ ppr_expr (OpApp e1 op fixity e2)
       = hang (pprExpr op) 4 (sep [pp_e1, pp_e2])
 
     pp_infixly v
-      = sep [pp_e1, hsep [pp_v_op, pp_e2]]
-      where
-       ppr_v = ppr v
-        pp_v_op | isOperator ppr_v = ppr_v
-               | otherwise        = char '`' <> ppr_v <> char '`'
-               -- Put it in backquotes if it's not an operator already
+      = sep [pp_e1, hsep [pprInfix v, pp_e2]]
 
 ppr_expr (NegApp e _) = char '-' <+> pprParendExpr e
 
@@ -390,6 +432,35 @@ ppr_expr (HsBracket b _)     = pprHsBracket b
 ppr_expr (HsBracketOut e ps) = ppr e $$ ptext SLIT("where") <+> ppr ps
 ppr_expr (HsReify r)        = ppr r
 
+ppr_expr (HsProc pat (HsCmdTop cmd _ _ _) _)
+  = hsep [ptext SLIT("proc"), ppr pat, ptext SLIT("->"), pprExpr cmd]
+
+ppr_expr (HsArrApp arrow arg _ HsFirstOrderApp True _)
+  = hsep [pprExpr arrow, ptext SLIT("-<"), pprExpr arg]
+ppr_expr (HsArrApp arrow arg _ HsFirstOrderApp False _)
+  = hsep [pprExpr arg, ptext SLIT(">-"), pprExpr arrow]
+ppr_expr (HsArrApp arrow arg _ HsHigherOrderApp True _)
+  = hsep [pprExpr arrow, ptext SLIT("-<<"), pprExpr arg]
+ppr_expr (HsArrApp arrow arg _ HsHigherOrderApp False _)
+  = hsep [pprExpr arg, ptext SLIT(">>-"), pprExpr arrow]
+
+ppr_expr (HsArrForm (HsVar v) (Just _) [arg1, arg2] _)
+  = sep [pprCmdArg arg1, hsep [pprInfix v, pprCmdArg arg2]]
+ppr_expr (HsArrForm op _ args _)
+  = hang (ptext SLIT("(|") <> pprExpr op <> ptext SLIT("|)"))
+        4 (sep (map pprCmdArg args))
+
+pprCmdArg :: OutputableBndr id => HsCmdTop id -> SDoc
+pprCmdArg (HsCmdTop cmd@(HsArrForm _ Nothing [] _) _ _ _) = pprExpr cmd
+pprCmdArg (HsCmdTop cmd _ _ _) = parens (pprExpr cmd)
+
+-- Put a var in backquotes if it's not an operator already
+pprInfix :: Outputable name => name -> SDoc
+pprInfix v | isOperator ppr_v = ppr_v
+          | otherwise        = char '`' <> ppr_v <> char '`'
+          where
+            ppr_v = ppr v
+
 -- add parallel array brackets around a document
 --
 pa_brackets :: SDoc -> SDoc
@@ -420,6 +491,70 @@ pprParendExpr expr
 
 %************************************************************************
 %*                                                                     *
+\subsection{Commands (in arrow abstractions)}
+%*                                                                     *
+%************************************************************************
+
+We re-use HsExpr to represent these.
+
+\begin{code}
+type HsCmd id = HsExpr id
+
+data HsArrAppType = HsHigherOrderApp | HsFirstOrderApp
+\end{code}
+
+The legal constructors for commands are:
+
+  = HsArrApp ...               -- as above
+
+  | HsArrForm ...              -- as above
+
+  | HsLam      (Match  id)     -- kappa
+
+  -- the renamer turns this one into HsArrForm
+  | OpApp      (HsExpr id)     -- left operand
+               (HsCmd id)      -- operator
+               Fixity          -- Renamer adds fixity; bottom until then
+               (HsCmd id)      -- right operand
+
+  | HsPar      (HsCmd id)      -- parenthesised command
+
+  | HsCase     (HsExpr id)
+               [Match id]      -- bodies are HsCmd's
+               SrcLoc
+
+  | HsIf       (HsExpr id)     --  predicate
+               (HsCmd id)      --  then part
+               (HsCmd id)      --  else part
+               SrcLoc
+
+  | HsLet      (HsBinds id)    -- let(rec)
+               (HsCmd  id)
+
+  | HsDo       (HsStmtContext Name)    -- The parameterisation is unimportant
+                                       -- because in this context we never use
+                                       -- the PatGuard or ParStmt variant
+               [Stmt id]       -- HsExpr's are really HsCmd's
+               (ReboundNames id)
+               PostTcType      -- Type of the whole expression
+               SrcLoc
+
+Top-level command, introducing a new arrow.
+This may occur inside a proc (where the stack is empty) or as an
+argument of a command-forming operator.
+
+\begin{code}
+data HsCmdTop id
+  = HsCmdTop   (HsCmd id)
+               [PostTcType]    -- types of inputs on the command's stack
+               PostTcType      -- return type of the command
+               (ReboundNames id)
+                               -- after type checking:
+                               -- names used in the command's desugaring
+\end{code}
+
+%************************************************************************
+%*                                                                     *
 \subsection{Record binds}
 %*                                                                     *
 %************************************************************************
@@ -486,6 +621,11 @@ mkSimpleMatch pats rhs rhs_ty locn
 
 unguardedRHS :: HsExpr id -> SrcLoc -> [GRHS id]
 unguardedRHS rhs loc = [GRHS [ResultStmt rhs loc] loc]
+
+glueBindsOnGRHSs :: HsBinds id -> GRHSs id -> GRHSs id
+glueBindsOnGRHSs EmptyBinds grhss = grhss
+glueBindsOnGRHSs binds1 (GRHSs grhss binds2 ty)
+  = GRHSs grhss (binds1 `ThenBinds` binds2) ty
 \end{code}
 
 @getMatchLoc@ takes a @Match@ and returns the
@@ -568,21 +708,25 @@ data Stmt id
        -- The type is the *element type* of the expression
 
        -- ParStmts only occur in a list comprehension
-  | ParStmt    [[Stmt id]]             -- List comp only: parallel set of quals
-  | ParStmtOut [([id], [Stmt id])]     -- PLC after renaming; the ids are the binders
-                                       -- bound by the stmts
-
-       -- mdo-notation (only exists after renamer)
-       -- The ids are a subset of the variables bound by the stmts that
-       -- either (a) are used before they are bound in the stmts
-       -- or     (b) are used in stmts that follow the RecStmt
-  | RecStmt  [id]
-            [Stmt id] 
-            [HsExpr id]        -- Post type-checking only; these expressions correspond
-                               -- 1-to-1 with the [id], and are the expresions that should
-                               -- be returned by the recursion.  They may not quite be the
-                               -- Ids themselves, because the Id may be polymorphic, but
-                               -- the returned thing has to be monomorphic.
+  | ParStmt    [([Stmt id], [id])]     -- After remaing, the ids are the binders
+                                       -- bound by the stmts and used subsequently
+
+       -- Recursive statement
+  | RecStmt  [Stmt id] 
+               --- The next two fields are only valid after renaming
+            [id]       -- The ids are a subset of the variables bound by the stmts
+                       -- that are used in stmts that follow the RecStmt
+
+            [id]       -- Ditto, but these variables are the "recursive" ones, that 
+                       -- are used before they are bound in the stmts of the RecStmt
+                       -- From a type-checking point of view, these ones have to be monomorphic
+
+               --- This field is only valid after typechecking
+            [HsExpr id]        -- These expressions correspond
+                               -- 1-to-1 with the "recursive" [id], and are the expresions that 
+                               -- should be returned by the recursion.  They may not quite be the
+                               -- Ids themselves, because the Id may be *polymorphic*, but
+                               -- the returned thing has to be *monomorphic*.
 \end{code}
 
 ExprStmts and ResultStmts are a bit tricky, because what they mean
@@ -632,15 +776,12 @@ consLetStmt binds      stmts = LetStmt binds : stmts
 instance OutputableBndr id => Outputable (Stmt id) where
     ppr stmt = pprStmt stmt
 
-pprStmt (BindStmt pat expr _) = hsep [ppr pat, ptext SLIT("<-"), ppr expr]
-pprStmt (LetStmt binds)       = hsep [ptext SLIT("let"), pprBinds binds]
-pprStmt (ExprStmt expr _ _)   = ppr expr
-pprStmt (ResultStmt expr _)   = ppr expr
-pprStmt (ParStmt stmtss)
- = hsep (map (\stmts -> ptext SLIT("| ") <> ppr stmts) stmtss)
-pprStmt (ParStmtOut stmtss)
- = hsep (map (\stmts -> ptext SLIT("| ") <> ppr stmts) stmtss)
-pprStmt (RecStmt _ segment _) = vcat (map ppr segment)
+pprStmt (BindStmt pat expr _)  = hsep [ppr pat, ptext SLIT("<-"), ppr expr]
+pprStmt (LetStmt binds)        = hsep [ptext SLIT("let"), pprBinds binds]
+pprStmt (ExprStmt expr _ _)    = ppr expr
+pprStmt (ResultStmt expr _)    = ppr expr
+pprStmt (ParStmt stmtss)        = hsep (map (\stmts -> ptext SLIT("| ") <> ppr stmts) stmtss)
+pprStmt (RecStmt segment _ _ _) = ptext SLIT("rec") <+> braces (vcat (map ppr segment))
 
 pprDo :: OutputableBndr id => HsStmtContext any -> [Stmt id] -> SDoc
 pprDo DoExpr stmts   = hang (ptext SLIT("do")) 2 (vcat (map ppr stmts))
@@ -740,6 +881,7 @@ data HsMatchContext id      -- Context of a Match
   = FunRhs id                  -- Function binding for f
   | CaseAlt                    -- Guard on a case alternative
   | LambdaExpr                 -- Pattern of a lambda
+  | ProcExpr                   -- Pattern of a proc
   | PatBindRhs                 -- Pattern binding
   | RecUpd                     -- Record update [used only in DsExpr to tell matchWrapper
                                --      what sort of runtime error message to generate]
@@ -766,6 +908,7 @@ isDoExpr other   = False
 matchSeparator (FunRhs _)   = ptext SLIT("=")
 matchSeparator CaseAlt      = ptext SLIT("->") 
 matchSeparator LambdaExpr   = ptext SLIT("->") 
+matchSeparator ProcExpr     = ptext SLIT("->") 
 matchSeparator PatBindRhs   = ptext SLIT("=") 
 matchSeparator (StmtCtxt _) = ptext SLIT("<-")  
 matchSeparator RecUpd       = panic "unused"
@@ -777,12 +920,14 @@ pprMatchContext CaseAlt             = ptext SLIT("a case alternative")
 pprMatchContext RecUpd           = ptext SLIT("a record-update construct")
 pprMatchContext PatBindRhs       = ptext SLIT("a pattern binding")
 pprMatchContext LambdaExpr       = ptext SLIT("a lambda abstraction")
+pprMatchContext ProcExpr         = ptext SLIT("an arrow abstraction")
 pprMatchContext (StmtCtxt ctxt)   = ptext SLIT("a pattern binding in") $$ pprStmtContext ctxt
 
 pprMatchRhsContext (FunRhs fun) = ptext SLIT("a right-hand side of function") <+> quotes (ppr fun)
 pprMatchRhsContext CaseAlt     = ptext SLIT("the body of a case alternative")
 pprMatchRhsContext PatBindRhs  = ptext SLIT("the right-hand side of a pattern binding")
 pprMatchRhsContext LambdaExpr  = ptext SLIT("the body of a lambda")
+pprMatchRhsContext ProcExpr    = ptext SLIT("the body of a proc")
 pprMatchRhsContext RecUpd      = panic "pprMatchRhsContext"
 
 pprStmtContext (ParStmtCtxt c) = sep [ptext SLIT("a parallel branch of"), pprStmtContext c]
@@ -805,6 +950,7 @@ matchContextErrString CaseAlt                        = "case"
 matchContextErrString PatBindRhs                = "pattern binding"
 matchContextErrString RecUpd                    = "record update"
 matchContextErrString LambdaExpr                = "lambda"
+matchContextErrString ProcExpr                  = "proc"
 matchContextErrString (StmtCtxt (ParStmtCtxt c)) = matchContextErrString (StmtCtxt c)
 matchContextErrString (StmtCtxt (PatGuard _))   = "pattern guard"
 matchContextErrString (StmtCtxt DoExpr)         = "'do' expression"
index 887bc69..9f6b534 100644 (file)
@@ -22,7 +22,7 @@ module HsSyn (
        Fixity, NewOrData, 
 
        HsModule(..), 
-       collectStmtsBinders,
+       collectStmtsBinders, collectStmtBinders,
        collectHsBinders,   collectLocatedHsBinders, 
        collectMonoBinders, collectLocatedMonoBinders,
        collectSigTysFromHsBinds, collectSigTysFromMonoBinds
@@ -148,6 +148,9 @@ collectMonoBinders binds
     go (PatMonoBind pat _ loc) acc = collectPatBinders pat ++ acc
     go (FunMonoBind f _ _ loc) acc = f : acc
     go (AndMonoBinds bs1 bs2)  acc = go bs1 (go bs2 acc)
+    go (VarMonoBind v _)       acc = v : acc
+    go (AbsBinds _ _ dbinds _ binds) acc
+      = [dp | (_,dp,_) <- dbinds] ++ go binds acc
 \end{code}
 
 
@@ -195,6 +198,7 @@ collectStmtBinders (BindStmt pat _ _) = collectPatBinders pat
 collectStmtBinders (LetStmt binds)    = collectHsBinders binds
 collectStmtBinders (ExprStmt _ _ _)   = []
 collectStmtBinders (ResultStmt _ _)   = []
+collectStmtBinders (RecStmt ss _ _ _) = collectStmtsBinders ss
 collectStmtBinders other              = panic "collectStmtBinders"
 \end{code}
 
index 19f027d..ed8e99b 100644 (file)
@@ -293,6 +293,7 @@ data DynFlag
    | Opt_FFI
    | Opt_PArr                         -- syntactic support for parallel arrays
    | Opt_With                         -- deprecated keyword for implicit parms
+   | Opt_Arrows                               -- Arrow-notation syntax
    | Opt_Generics
    | Opt_NoImplicitPrelude 
 
index 378265e..c4a3e96 100644 (file)
@@ -1,5 +1,5 @@
 -----------------------------------------------------------------------------
--- $Id: DriverFlags.hs,v 1.116 2003/06/23 10:35:17 simonpj Exp $
+-- $Id: DriverFlags.hs,v 1.117 2003/06/24 07:58:20 simonpj Exp $
 --
 -- Driver flags
 --
@@ -455,6 +455,7 @@ fFlags = [
   ( "fi",                              Opt_FFI ),  -- support `-ffi'...
   ( "ffi",                             Opt_FFI ),  -- ...and also `-fffi'
   ( "with",                            Opt_With ), -- with keyword
+  ( "arrows",                          Opt_Arrows ), -- arrow syntax
   ( "parr",                            Opt_PArr ),
   ( "allow-overlapping-instances",     Opt_AllowOverlappingInstances ),
   ( "allow-undecidable-instances",     Opt_AllowUndecidableInstances ),
index d76027d..8bcd749 100644 (file)
@@ -387,10 +387,7 @@ myParseModule dflags src_filename
       _scc_  "Parser" do
       buf <- hGetStringBuffer src_filename
 
-      let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags,
-                          ffiEF         = dopt Opt_FFI         dflags,
-                          withEF        = dopt Opt_With        dflags,
-                          parrEF        = dopt Opt_PArr        dflags}
+      let exts = mkExtFlags dflags
          loc  = mkSrcLoc (mkFastString src_filename) 1
 
       case parseModule buf (mkPState loc exts) of {
@@ -513,10 +510,7 @@ hscParseStmt dflags str
 
       buf <- stringToStringBuffer str
 
-      let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags,
-                          ffiEF         = dopt Opt_FFI         dflags,
-                          withEF        = dopt Opt_With        dflags,
-                          parrEF        = dopt Opt_PArr        dflags}
+      let exts = mkExtFlags dflags 
          loc  = mkSrcLoc FSLIT("<interactive>") 1
 
       case parseStmt buf (mkPState loc exts) of {
@@ -574,10 +568,7 @@ hscThing hsc_env pcs0 ic str
 myParseIdentifier dflags str
   = do buf <- stringToStringBuffer str
  
-       let exts = ExtFlags {glasgowExtsEF = dopt Opt_GlasgowExts dflags,
-                           ffiEF         = dopt Opt_FFI         dflags,
-                           withEF        = dopt Opt_With        dflags,
-                           parrEF        = dopt Opt_PArr        dflags}
+       let exts = mkExtFlags dflags
           loc  = mkSrcLoc FSLIT("<interactive>") 1
 
        case parseIdentifier buf (mkPState loc exts) of
@@ -683,4 +674,11 @@ initExternalPackageState
 
 initOrigNames :: OrigNameCache
 initOrigNames = foldl extendOrigNameCache emptyModuleEnv knownKeyNames 
+
+mkExtFlags dflags
+  = ExtFlags { glasgowExtsEF = dopt Opt_GlasgowExts dflags,
+              ffiEF         = dopt Opt_FFI      dflags,
+              withEF        = dopt Opt_With     dflags,
+              arrowsEF      = dopt Opt_Arrows   dflags,
+              parrEF        = dopt Opt_PArr     dflags}
 \end{code}
index 1c94edc..f83dd58 100644 (file)
@@ -98,6 +98,7 @@ loadPackageConfig conf_filename = do
    let loc  = mkSrcLoc (mkFastString conf_filename) 1
        exts = ExtFlags {glasgowExtsEF = False,
                        ffiEF         = False,
+                       arrowsEF      = False,
                        withEF        = False,
                        parrEF        = False}
    case parse buf (mkPState loc exts) of
index c8126ce..33a9594 100644 (file)
@@ -210,6 +210,16 @@ data Token
   | ITreifyDecl
   | ITreifyFixity
 
+  -- Arrow notation extension
+  | ITproc
+  | ITrec
+  | IToparenbar                        -- (|
+  | ITcparenbar                        -- |)
+  | ITlarrowtail               -- -<
+  | ITrarrowtail               -- >-
+  | ITLarrowtail               -- -<<
+  | ITRarrowtail               -- >>-
+
   | ITunknown String           -- Used when the lexer can't make sense of it
   | ITeof                      -- end of file token
   deriving Show -- debugging
@@ -295,6 +305,13 @@ isSpecial _             = False
 ghcExtensionKeywordsFM = listToUFM $
        map (\(x, y, z) -> (mkFastString x, (y, z)))
      [ ( "forall",     ITforall,        bit glaExtsBit),
+       ( "mdo",        ITmdo,           bit glaExtsBit),
+       ( "reifyDecl",  ITreifyDecl,     bit glaExtsBit),
+       ( "reifyType",  ITreifyType,     bit glaExtsBit),
+       ( "reifyFixity",ITreifyFixity,   bit glaExtsBit),
+
+       ( "rec",        ITrec,           bit glaExtsBit .|. bit arrowsBit),
+
        ( "foreign",    ITforeign,       bit ffiBit),
        ( "export",     ITexport,        bit ffiBit),
        ( "label",      ITlabel,         bit ffiBit),
@@ -302,14 +319,15 @@ ghcExtensionKeywordsFM = listToUFM $
        ( "safe",       ITsafe,          bit ffiBit),
        ( "threadsafe", ITthreadsafe,    bit ffiBit),
        ( "unsafe",     ITunsafe,        bit ffiBit),
-       ( "with",       ITwith,          bit withBit),
-       ( "mdo",        ITmdo,           bit glaExtsBit),
        ( "stdcall",    ITstdcallconv,   bit ffiBit),
        ( "ccall",      ITccallconv,     bit ffiBit),
        ( "dotnet",     ITdotnet,        bit ffiBit),
-       ( "reifyDecl",  ITreifyDecl,     bit glaExtsBit),
-       ( "reifyType",  ITreifyType,     bit glaExtsBit),
-       ( "reifyFixity",ITreifyFixity,   bit glaExtsBit),
+
+       ( "with",       ITwith,          bit withBit),
+
+       ( "proc",       ITproc,          bit arrowsBit),
+
+       -- On death row
         ("_ccall_",    ITccall (False, False, PlayRisky),
                                         bit glaExtsBit),
         ("_ccall_GC_", ITccall (False, False, PlaySafe False),
@@ -321,23 +339,29 @@ ghcExtensionKeywordsFM = listToUFM $
      ]
 
 haskellKeySymsFM = listToUFM $
-       map (\ (x,y) -> (mkFastString x,y))
-      [ ("..",         ITdotdot)
-       ,(":",          ITcolon)        -- (:) is a reserved op, 
+       map (\ (x,y,z) -> (mkFastString x,(y,z)))
+      [ ("..", ITdotdot,       Nothing)
+       ,(":",  ITcolon,        Nothing)        -- (:) is a reserved op, 
                                        -- meaning only list cons
-       ,("::",         ITdcolon)
-       ,("=",          ITequal)
-       ,("\\",         ITlam)
-       ,("|",          ITvbar)
-       ,("<-",         ITlarrow)
-       ,("->",         ITrarrow)
-       ,("@",          ITat)
-       ,("~",          ITtilde)
-       ,("=>",         ITdarrow)
-       ,("-",          ITminus)
-       ,("!",          ITbang)
-       ,("*",          ITstar)
-       ,(".",          ITdot)          -- sadly, for 'forall a . t'
+       ,("::", ITdcolon,       Nothing)
+       ,("=",  ITequal,        Nothing)
+       ,("\\", ITlam,          Nothing)
+       ,("|",  ITvbar,         Nothing)
+       ,("<-", ITlarrow,       Nothing)
+       ,("->", ITrarrow,       Nothing)
+       ,("@",  ITat,           Nothing)
+       ,("~",  ITtilde,        Nothing)
+       ,("=>", ITdarrow,       Nothing)
+       ,("-",  ITminus,        Nothing)
+       ,("!",  ITbang,         Nothing)
+
+       ,("*",  ITstar,         Just (bit glaExtsBit))  -- For data T (a::*) = MkT
+       ,(".",  ITdot,          Just (bit glaExtsBit))  -- For 'forall a . t'
+
+       ,("-<", ITlarrowtail,   Just (bit arrowsBit))
+       ,(">-", ITrarrowtail,   Just (bit arrowsBit))
+       ,("-<<",        ITLarrowtail,   Just (bit arrowsBit))
+       ,(">>-",        ITRarrowtail,   Just (bit arrowsBit))
        ]
 
 \end{code}
@@ -537,8 +561,14 @@ lexToken cont exts buf =
   case currentChar# buf of
 
     -- special symbols ----------------------------------------------------
-    '('# | glaExtsEnabled exts && lookAhead# buf 1# `eqChar#` '#'# 
+    '('# | glaExtsEnabled exts && lookAhead# buf 1# `eqChar#` '#'# &&
+        -- Unboxed tules: '(#' but not '(##'
+          not (lookAhead# buf 2# `eqChar#` '#'#)
                -> cont IToubxparen (addToCurrentPos buf 2#)
+        -- Arrow notation extension: '(|' but not '(||'
+        | arrowsEnabled exts && lookAhead# buf 1# `eqChar#` '|'# &&
+          not (lookAhead# buf 2# `eqChar#` '|'#)
+               -> cont IToparenbar (addToCurrentPos buf 2#)
         | otherwise
                -> cont IToparen (incCurrentPos buf)
 
@@ -572,12 +602,15 @@ lexToken cont exts buf =
                 '}'#  | glaExtsEnabled exts -> cont ITccurlybar 
                                                      (addToCurrentPos buf 2#)
                  -- MetaHaskell extension 
-                 ']'#  |  glaExtsEnabled exts -> cont ITcloseQuote (addToCurrentPos buf 2#)
-                 other -> lex_sym cont (incCurrentPos buf)
+                 ']'#  | glaExtsEnabled exts -> cont ITcloseQuote (addToCurrentPos buf 2#)
+                -- arrow notation extension
+                ')'#  | arrowsEnabled exts -> cont ITcparenbar 
+                                                     (addToCurrentPos buf 2#)
+                 other -> lex_sym cont exts (incCurrentPos buf)
     ':'# -> case lookAhead# buf 1# of
                 ']'#  | parrEnabled exts    -> cont ITcpabrack
                                                      (addToCurrentPos buf 2#)
-                 _                           -> lex_sym cont (incCurrentPos buf)
+                 _                           -> lex_sym cont exts (incCurrentPos buf)
 
                 
     '#'# -> case lookAhead# buf 1# of
@@ -585,8 +618,8 @@ lexToken cont exts buf =
                     -> cont ITcubxparen (addToCurrentPos buf 2#)
                '-'# -> case lookAhead# buf 2# of
                           '}'# -> cont ITclose_prag (addToCurrentPos buf 3#)
-                          _    -> lex_sym cont (incCurrentPos buf)
-               _    -> lex_sym cont (incCurrentPos buf)
+                          _    -> lex_sym cont exts (incCurrentPos buf)
+               _    -> lex_sym cont exts (incCurrentPos buf)
 
     '`'# | glaExtsEnabled exts && lookAhead# buf 1# `eqChar#` '`'#
                -> lex_cstring cont (addToCurrentPos buf 2#)
@@ -637,7 +670,7 @@ lexToken cont exts buf =
            ((lookAhead# buf 1#) `eqChar#` '('#) -> cont ITparenEscape (addToCurrentPos buf 2#)
           
     c | is_digit  c -> lex_num cont exts 0 buf
-      | is_symbol c -> lex_sym cont buf
+      | is_symbol c -> lex_sym cont exts buf
       | is_upper  c -> lex_con cont exts buf
       | is_lower  c -> lex_id  cont exts buf
       | otherwise   -> lexError "illegal character" buf
@@ -964,14 +997,16 @@ lex_id cont exts buf =
 
  }}}
 
-lex_sym cont buf =
+lex_sym cont exts buf =
  -- trace "lex_sym" $
  case expandWhile# is_symbol buf of
    buf' -> case lookupUFM haskellKeySymsFM lexeme of {
-               Just kwd_token -> --trace ("keysym: "++unpackFS lexeme) $
-                                 cont kwd_token buf' ;
-               Nothing        -> --trace ("sym: "++unpackFS lexeme) $ 
-                         cont (mk_var_token lexeme) buf'
+               Just (kwd_token, Nothing) 
+                       -> cont kwd_token buf' ;
+               Just (kwd_token, Just validExts) 
+                       | validExts .&. toInt32 exts /= 0
+                       -> cont kwd_token buf' ;
+               other   -> cont (mk_var_token lexeme) buf'
            }
        where lexeme = lexemeToFastString buf'
 
@@ -1275,12 +1310,14 @@ glaExtsBit = 0
 ffiBit    = 1
 parrBit           = 2
 withBit           = 3
+arrowsBit  = 4
 
 glaExtsEnabled, ffiEnabled, parrEnabled :: Int# -> Bool
 glaExtsEnabled flags = testBit (toInt32 flags) glaExtsBit
 ffiEnabled     flags = testBit (toInt32 flags) ffiBit
 withEnabled    flags = testBit (toInt32 flags) withBit
 parrEnabled    flags = testBit (toInt32 flags) parrBit
+arrowsEnabled  flags = testBit (toInt32 flags) arrowsBit
 
 toInt32 :: Int# -> Int32
 toInt32 x# = fromIntegral (I# x#)
@@ -1293,7 +1330,8 @@ data ExtFlags = ExtFlags {
                  glasgowExtsEF :: Bool,
                  ffiEF         :: Bool,
                  withEF        :: Bool,
-                 parrEF        :: Bool
+                 parrEF        :: Bool,
+                 arrowsEF      :: Bool
                }
 
 -- create a parse state
@@ -1313,6 +1351,7 @@ mkPState loc exts  =
                                          || glasgowExtsEF exts)
               .|. withBit    `setBitIf` withEF            exts
               .|. parrBit    `setBitIf` parrEF            exts
+              .|. arrowsBit  `setBitIf` arrowsEF          exts
       --
       setBitIf :: Int -> Bool -> Int32
       b `setBitIf` cond | cond      = bit b
index 11dc6dc..9e4c660 100644 (file)
@@ -1,6 +1,6 @@
 {-                                                             -*-haskell-*-
 -----------------------------------------------------------------------------
-$Id: Parser.y,v 1.119 2003/06/23 10:35:22 simonpj Exp $
+$Id: Parser.y,v 1.120 2003/06/24 07:58:22 simonpj Exp $
 
 Haskell grammar.
 
@@ -130,6 +130,8 @@ Conflicts: 29 shift/reduce, [SDM 19/9/2002]
  'stdcall'      { ITstdcallconv }
  'ccall'        { ITccallconv }
  'dotnet'       { ITdotnet }
+ 'proc'                { ITproc }              -- for arrow notation extension
+ 'rec'         { ITrec }               -- for arrow notation extension
  '_ccall_'     { ITccall (False, False, PlayRisky) }
  '_ccall_GC_'  { ITccall (False, False, PlaySafe False) }
  '_casm_'      { ITccall (False, True,  PlayRisky) }
@@ -189,6 +191,10 @@ Conflicts: 29 shift/reduce, [SDM 19/9/2002]
  '-'           { ITminus }
  '!'           { ITbang }
  '*'           { ITstar }
+ '-<'          { ITlarrowtail }                -- for arrow notation
+ '>-'          { ITrarrowtail }                -- for arrow notation
+ '-<<'         { ITLarrowtail }                -- for arrow notation
+ '>>-'         { ITRarrowtail }                -- for arrow notation
  '.'           { ITdot }
 
  '{'           { ITocurly }                    -- special symbols
@@ -204,6 +210,8 @@ Conflicts: 29 shift/reduce, [SDM 19/9/2002]
  ')'           { ITcparen }
  '(#'          { IToubxparen }
  '#)'          { ITcubxparen }
+ '(|'          { IToparenbar }
+ '|)'          { ITcparenbar }
  ';'           { ITsemi }
  ','           { ITcomma }
  '`'           { ITbackquote }
@@ -927,6 +935,10 @@ sigdecl :: { RdrBinding }
 exp   :: { RdrNameHsExpr }
        : infixexp '::' sigtype         { ExprWithTySig $1 $3 }
        | infixexp 'with' dbinding      { HsLet (IPBinds $3 True{-not a let-}) $1 }
+       | fexp srcloc '-<' exp          { HsArrApp $1 $4 placeHolderType HsFirstOrderApp True $2 }
+       | fexp srcloc '>-' exp          { HsArrApp $4 $1 placeHolderType HsFirstOrderApp False $2 }
+       | fexp srcloc '-<<' exp         { HsArrApp $1 $4 placeHolderType HsHigherOrderApp True $2 }
+       | fexp srcloc '>>-' exp         { HsArrApp $4 $1 placeHolderType HsHigherOrderApp False $2 }
        | infixexp                      { $1 }
 
 infixexp :: { RdrNameHsExpr }
@@ -958,6 +970,12 @@ exp10 :: { RdrNameHsExpr }
                                                        then HsSCC $1 $2
                                                        else HsPar $2 }
 
+       | 'proc' srcloc aexp '->' srcloc exp    
+                       {% checkPattern $2 $3 `thenP` \ p -> 
+                          returnP (HsProc p (HsCmdTop $6 [] placeHolderType undefined) $5) }
+
+       | srcloc operator cmdargs               { HsArrForm $2 Nothing (reverse $3) $1 }
+
         | '{-# CORE' STRING '#-}' exp           { HsCoreAnn $2 $4 }    -- hdaume: core annotation
 
        | reifyexp                              { HsReify $1 }
@@ -1026,6 +1044,17 @@ aexp2    :: { RdrNameHsExpr }
                                           returnP (HsBracket (PatBr p) $1) }
        | srcloc '[d|' cvtopbody '|]'   { HsBracket (DecBr (mkGroup $3)) $1 }
 
+cmdargs        :: { [RdrNameHsCmdTop] }
+       : cmdargs acmd                  { HsCmdTop $2 [] placeHolderType undefined : $1 }
+       | {- empty -}                   { [] }
+
+acmd   :: { RdrNameHsExpr }
+       : '(' exp ')'                   { HsPar $2 }
+       | srcloc operator               { HsArrForm $2 Nothing [] $1 }
+
+operator :: { RdrNameHsExpr }
+       : '(|' exp '|)'                 { $2 }
+
 cvtopbody :: { [RdrNameHsDecl] }
        :  '{'            cvtopdecls '}'                { $2 }
        |      layout_on  cvtopdecls close              { $2 }
@@ -1048,13 +1077,9 @@ list :: { RdrNameHsExpr }
        | exp ',' exp '..'              { ArithSeqIn (FromThen $1 $3) }
        | exp '..' exp                  { ArithSeqIn (FromTo $1 $3) }
        | exp ',' exp '..' exp          { ArithSeqIn (FromThenTo $1 $3 $5) }
-       | exp srcloc pquals             {% let { body [qs] = qs;
-                                                body  qss = [ParStmt (map reverse qss)] }
-                                          in
-                                          returnP ( mkHsDo ListComp
-                                                           (reverse (ResultStmt $1 $2 : body $3))
-                                                           $2
-                                                 )
+       | exp srcloc pquals             { mkHsDo ListComp
+                                                (reverse (ResultStmt $1 $2 : $3))
+                                                $2
                                        }
 
 lexps :: { [RdrNameHsExpr] }
@@ -1064,8 +1089,17 @@ lexps :: { [RdrNameHsExpr] }
 -----------------------------------------------------------------------------
 -- List Comprehensions
 
-pquals :: { [[RdrNameStmt]] }
-       : pquals '|' quals              { $3 : $1 }
+pquals :: { [RdrNameStmt] }    -- Either a singleton ParStmt, or a reversed list of Stmts
+       : pquals1                       { case $1 of
+                                           [qs] -> qs
+                                           qss  -> [ParStmt stmtss]
+                                                where
+                                                   stmtss = [ (reverse qs, undefined) 
+                                                            | qs <- qss ]
+                                       }
+                       
+pquals1 :: { [[RdrNameStmt]] }
+       : pquals1 '|' quals             { $3 : $1 }
        | '|' quals                     { [$2] }
 
 quals :: { [RdrNameStmt] }
@@ -1087,16 +1121,9 @@ parr :: { RdrNameHsExpr }
                                                       (reverse $1) }
        | exp '..' exp                  { PArrSeqIn (FromTo $1 $3) }
        | exp ',' exp '..' exp          { PArrSeqIn (FromThenTo $1 $3 $5) }
-       | exp srcloc pquals             {% let {
-                                            body [qs] = qs;
-                                            body  qss = [ParStmt 
-                                                          (map reverse qss)]}
-                                          in
-                                          returnP $ 
-                                            mkHsDo PArrComp 
-                                                   (reverse (ResultStmt $1 $2 
-                                                            : body $3))
-                                                   $2
+       | exp srcloc pquals             {  mkHsDo PArrComp 
+                                                 (reverse (ResultStmt $1 $2 : $3))
+                                                 $2
                                        }
 
 -- We are reusing `lexps' and `pquals' from the list case.
@@ -1166,6 +1193,7 @@ stmt  :: { RdrNameStmt }
                                           returnP (BindStmt p $4 $1) }
        | srcloc exp                    { ExprStmt $2 placeHolderType $1 }
        | srcloc 'let' binds            { LetStmt $3 }
+       | srcloc 'rec' stmtlist         { RecStmt $3 undefined undefined undefined }
 
 -----------------------------------------------------------------------------
 -- Record Field Update/Construction
index f07c989..101ada1 100644 (file)
@@ -20,6 +20,8 @@ module RdrHsSyn (
        RdrNameGRHS,
        RdrNameGRHSs,
        RdrNameHsBinds,
+       RdrNameHsCmd,
+       RdrNameHsCmdTop,
        RdrNameHsDecl,
        RdrNameHsExpr,
        RdrNameHsModule,
@@ -134,6 +136,8 @@ type RdrNameGRHS            = GRHS                  RdrName
 type RdrNameGRHSs              = GRHSs                 RdrName
 type RdrNameHsBinds            = HsBinds               RdrName
 type RdrNameHsExpr             = HsExpr                RdrName
+type RdrNameHsCmd              = HsCmd                 RdrName
+type RdrNameHsCmdTop           = HsCmdTop              RdrName
 type RdrNameHsModule           = HsModule              RdrName
 type RdrNameIE                 = IE                    RdrName
 type RdrNameImportDecl                 = ImportDecl            RdrName
index d65c9f1..2ecfaa5 100644 (file)
@@ -175,6 +175,10 @@ basicKnownKeyNames
        -- MonadRec stuff
        mfixName,
 
+       -- Arrow stuff
+       arrAName, composeAName, firstAName,
+       appAName, choiceAName, loopAName,
+
        -- Ix stuff
        ixClassName, 
 
@@ -215,6 +219,9 @@ basicKnownKeyNames
        -- Booleans
        andName, orName
        
+       -- The Either type
+       , eitherTyConName, leftDataConName, rightDataConName
+
        -- dotnet interop
        , objectTyConName, marshalObjectName, unmarshalObjectName
        , marshalStringName, unmarshalStringName, checkDotnetResName
@@ -244,6 +251,7 @@ pREL_NUM_Name     = mkModuleName "GHC.Num"
 pREL_LIST_Name    = mkModuleName "GHC.List"
 pREL_PARR_Name    = mkModuleName "GHC.PArr"
 pREL_TUP_Name     = mkModuleName "Data.Tuple"
+pREL_EITHER_Name  = mkModuleName "Data.Either"
 pREL_PACK_Name    = mkModuleName "GHC.Pack"
 pREL_CONC_Name    = mkModuleName "GHC.Conc"
 pREL_IO_BASE_Name = mkModuleName "GHC.IOBase"
@@ -270,6 +278,7 @@ mAIN_Name     = mkModuleName "Main"
 pREL_INT_Name    = mkModuleName "GHC.Int"
 pREL_WORD_Name   = mkModuleName "GHC.Word"
 mONAD_FIX_Name   = mkModuleName "Control.Monad.Fix"
+aRROW_Name       = mkModuleName "Control.Arrow"
 aDDR_Name        = mkModuleName "Addr"
 
 gLA_EXTS_Name   = mkModuleName "GHC.Exts"
@@ -358,6 +367,9 @@ false_RDR           = nameRdrName falseDataConName
 true_RDR               = nameRdrName trueDataConName
 and_RDR                        = nameRdrName andName
 
+left_RDR               = nameRdrName leftDataConName
+right_RDR              = nameRdrName rightDataConName
+
 error_RDR              = nameRdrName errorName
 
 fromEnum_RDR           = varQual_RDR pREL_ENUM_Name FSLIT("fromEnum")
@@ -521,6 +533,10 @@ consDataConName      = wDataQual pREL_BASE_Name FSLIT(":") consDataConKey
 eqName           = varQual  pREL_BASE_Name FSLIT("==") eqClassOpKey
 geName           = varQual  pREL_BASE_Name FSLIT(">=") geClassOpKey
 
+eitherTyConName          = tcQual   pREL_EITHER_Name FSLIT("Either") eitherTyConKey
+leftDataConName   = dataQual pREL_EITHER_Name FSLIT("Left")   leftDataConKey
+rightDataConName  = dataQual pREL_EITHER_Name FSLIT("Right")  rightDataConKey
+
 -- Generics
 crossTyConName     = tcQual   pREL_BASE_Name FSLIT(":*:") crossTyConKey
 crossDataConName   = dataQual pREL_BASE_Name FSLIT(":*:") crossDataConKey
@@ -699,6 +715,14 @@ splitName          = varQual gLA_EXTS_Name FSLIT("split") splitIdKey
 -- Recursive-do notation
 mfixName          = varQual mONAD_FIX_Name FSLIT("mfix") mfixIdKey
 
+-- Arrow notation
+arrAName          = varQual aRROW_Name FSLIT("arr")    arrAIdKey
+composeAName      = varQual aRROW_Name FSLIT(">>>")    composeAIdKey
+firstAName        = varQual aRROW_Name FSLIT("first")  firstAIdKey
+appAName          = varQual aRROW_Name FSLIT("app")    appAIdKey
+choiceAName       = varQual aRROW_Name FSLIT("|||")    choiceAIdKey
+loopAName         = varQual aRROW_Name FSLIT("loop")   loopAIdKey
+
 -- dotnet interop
 objectTyConName            = wTcQual  dOTNET_Name FSLIT("Object") objectTyConKey
 unmarshalObjectName = varQual  dOTNET_Name FSLIT("unmarshalObject") unmarshalObjectIdKey
@@ -851,6 +875,8 @@ parrTyConKey                                = mkPreludeTyConUnique 82
 -- dotnet interop
 objectTyConKey                         = mkPreludeTyConUnique 83
 
+eitherTyConKey                         = mkPreludeTyConUnique 84
+
 ---------------- Template Haskell -------------------
 --     USES TyConUniques 100-119
 -----------------------------------------------------
@@ -888,6 +914,9 @@ genUnitDataConKey                   = mkPreludeDataConUnique 23
 
 -- Data constructor for parallel arrays
 parrDataConKey                         = mkPreludeDataConUnique 24
+
+leftDataConKey                         = mkPreludeDataConUnique 25
+rightDataConKey                                = mkPreludeDataConUnique 26
 \end{code}
 
 %************************************************************************
@@ -1009,6 +1038,14 @@ returnMClassOpKey              = mkPreludeMiscIdUnique 117
 -- Recursive do notation
 mfixIdKey      = mkPreludeMiscIdUnique 118
 
+-- Arrow notation
+arrAIdKey      = mkPreludeMiscIdUnique 119
+composeAIdKey  = mkPreludeMiscIdUnique 120 -- >>>
+firstAIdKey    = mkPreludeMiscIdUnique 121
+appAIdKey      = mkPreludeMiscIdUnique 122
+choiceAIdKey   = mkPreludeMiscIdUnique 123 -- |||
+loopAIdKey     = mkPreludeMiscIdUnique 124
+
 ---------------- Template Haskell -------------------
 --     USES IdUniques 200-299
 -----------------------------------------------------
index 270f509..68b09c6 100644 (file)
@@ -648,21 +648,34 @@ checks the type of the user thing against the type of the standard thing.
 lookupSyntaxName :: Name                       -- The standard name
                 -> RnM (Name, FreeVars)        -- Possibly a non-standard name
 lookupSyntaxName std_name
-  = getModeRn                          `thenM` \ mode ->
-    if isInterfaceMode mode then
-       returnM (std_name, unitFV std_name)
-                               -- Happens for 'derived' code
-                               -- where we don't want to rebind
+  = doptM Opt_NoImplicitPrelude                `thenM` \ no_prelude -> 
+    if not no_prelude then normal_case
     else
-
-    doptM Opt_NoImplicitPrelude                `thenM` \ no_prelude -> 
-    if not no_prelude then
-       returnM (std_name, unitFV std_name)     -- Normal case
-
+    getModeRn                          `thenM` \ mode ->
+    if isInterfaceMode mode then normal_case
+       -- Happens for 'derived' code where we don't want to rebind
     else
        -- Get the similarly named thing from the local environment
     lookupOccRn (mkRdrUnqual (nameOccName std_name)) `thenM` \ usr_name ->
     returnM (usr_name, mkFVs [usr_name, std_name])
+  where
+    normal_case = returnM (std_name, unitFV std_name)
+
+lookupSyntaxNames :: [Name]                            -- Standard names
+                 -> RnM (ReboundNames Name, FreeVars)  -- See comments with HsExpr.ReboundNames
+lookupSyntaxNames std_names
+  = doptM Opt_NoImplicitPrelude                `thenM` \ no_prelude -> 
+    if not no_prelude then normal_case 
+    else
+    getModeRn                          `thenM` \ mode ->
+    if isInterfaceMode mode then normal_case
+    else
+       -- Get the similarly named thing from the local environment
+    mappM (lookupOccRn . mkRdrUnqual . nameOccName) std_names  `thenM` \ usr_names ->
+
+    returnM (std_names `zip` map HsVar usr_names, mkFVs std_names `plusFV` mkFVs usr_names)
+  where
+    normal_case = returnM (std_names `zip` map HsVar std_names, mkFVs std_names)
 \end{code}
 
 
index 5e18d67..e926ef0 100644 (file)
@@ -38,6 +38,7 @@ import PrelNames      ( hasKey, assertIdKey,
                          foldrName, buildName, 
                          cCallableClassName, cReturnableClassName, 
                          enumClassName, 
+                         loopAName, choiceAName, appAName, arrAName, composeAName, firstAName,
                          splitName, fstName, sndName, ioDataConName, 
                          replicatePName, mapPName, filterPName,
                          crossPName, zipPName, toPName,
@@ -48,10 +49,11 @@ import NameSet
 import UnicodeUtil     ( stringToUtf8 )
 import UniqFM          ( isNullUFM )
 import UniqSet         ( emptyUniqSet )
-import Util            ( isSingleton )
+import Util            ( isSingleton, mapAndUnzip )
 import List            ( intersectBy, unzip4 )
 import ListSetOps      ( removeDups )
 import Outputable
+import SrcLoc          ( noSrcLoc )
 import FastString
 \end{code}
 
@@ -295,20 +297,20 @@ rnExpr e@(HsDo do_or_lc stmts _ _ src_loc)
     }                                  `thenM_`
 
        -- Generate the rebindable syntax for the monad
-    mapAndUnzipM lookupSyntaxName 
-        (syntax_names do_or_lc)        `thenM` \ (monad_names', monad_fvs) ->
+    lookupSyntaxNames syntax_names     `thenM` \ (syntax_names', monad_fvs) ->
 
-    returnM (HsDo do_or_lc stmts' monad_names' placeHolderType src_loc, 
-            fvs `plusFV` implicit_fvs do_or_lc `plusFV` plusFVs monad_fvs)
+    returnM (HsDo do_or_lc stmts' syntax_names' placeHolderType src_loc, 
+            fvs `plusFV` implicit_fvs do_or_lc `plusFV` monad_fvs)
   where
     implicit_fvs PArrComp = mkFVs [replicatePName, mapPName, filterPName, crossPName, zipPName]
     implicit_fvs ListComp = mkFVs [foldrName, buildName]
     implicit_fvs DoExpr   = emptyFVs
     implicit_fvs MDoExpr  = emptyFVs
 
-    syntax_names DoExpr  = monadNames
-    syntax_names MDoExpr = monadNames ++ [mfixName]
-    syntax_names other   = []
+    syntax_names = case do_or_lc of
+                       DoExpr  -> monadNames
+                       MDoExpr -> monadNames ++ [mfixName]
+                       other   -> []
 
 rnExpr (ExplicitList _ exps)
   = rnExprs exps                       `thenM` \ (exps', fvs) ->
@@ -384,6 +386,212 @@ rnExpr e@(ELazyPat _) = addErr (patSynErr e)      `thenM_`
 
 %************************************************************************
 %*                                                                     *
+       Arrow notation
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+rnExpr (HsProc pat body src_loc)
+  = addSrcLoc src_loc $
+    rnPatsAndThen ProcExpr [pat] $ \ [pat'] ->
+    rnCmdTop body      `thenM` \ (body',fvBody) ->
+    returnM (HsProc pat' body' src_loc, fvBody)
+
+rnExpr (HsArrApp arrow arg _ ho rtl srcloc)
+  = rnExpr arrow       `thenM` \ (arrow',fvArrow) ->
+    rnExpr arg         `thenM` \ (arg',fvArg) ->
+    returnM (HsArrApp arrow' arg' placeHolderType ho rtl srcloc,
+            fvArrow `plusFV` fvArg)
+
+-- infix form
+rnExpr (HsArrForm op (Just _) [arg1, arg2] srcloc)
+  = rnExpr op          `thenM` \ (op'@(HsVar op_name),fv_op) ->
+    rnCmdTop arg1      `thenM` \ (arg1',fv_arg1) ->
+    rnCmdTop arg2      `thenM` \ (arg2',fv_arg2) ->
+
+       -- Deal with fixity
+
+    lookupFixityRn op_name             `thenM` \ fixity ->
+    mkOpFormRn arg1' op' fixity arg2'  `thenM` \ final_e -> 
+
+    returnM (final_e,
+             fv_arg1 `plusFV` fv_op `plusFV` fv_arg2)
+
+rnExpr (HsArrForm op fixity cmds srcloc)
+  = rnExpr op          `thenM` \ (op',fvOp) ->
+    rnCmdArgs cmds     `thenM` \ (cmds',fvCmds) ->
+    returnM (HsArrForm op' fixity cmds' srcloc,
+            fvOp `plusFV` fvCmds)
+
+---------------------------
+-- Deal with fixity (cf mkOpAppRn for the method)
+
+mkOpFormRn :: RenamedHsCmdTop          -- Left operand; already rearranged
+         -> RenamedHsExpr -> Fixity    -- Operator and fixity
+         -> RenamedHsCmdTop            -- Right operand (not an infix)
+         -> RnM RenamedHsCmd
+
+---------------------------
+-- (e11 `op1` e12) `op2` e2
+mkOpFormRn a1@(HsCmdTop (HsArrForm op1 (Just fix1) [a11,a12] loc1) _ _ _) op2 fix2 a2
+  | nofix_error
+  = addErr (precParseErr (ppr_op op1,fix1) (ppr_op op2,fix2))  `thenM_`
+    returnM (HsArrForm op2 (Just fix2) [a1, a2] loc1)
+
+  | associate_right
+  = mkOpFormRn a12 op2 fix2 a2         `thenM` \ new_c ->
+    returnM (HsArrForm op1 (Just fix1)
+       [a11, HsCmdTop new_c [] placeHolderType []] loc1)
+  where
+    (nofix_error, associate_right) = compareFixity fix1 fix2
+
+---------------------------
+--     Default case
+mkOpFormRn arg1 op fix arg2                    -- Default case, no rearrangment
+  = returnM (HsArrForm op (Just fix) [arg1, arg2] noSrcLoc)
+
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+       Arrow commands
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+rnCmdArgs [] = returnM ([], emptyFVs)
+rnCmdArgs (arg:args)
+  = rnCmdTop arg       `thenM` \ (arg',fvArg) ->
+    rnCmdArgs args     `thenM` \ (args',fvArgs) ->
+    returnM (arg':args', fvArg `plusFV` fvArgs)
+
+rnCmdTop (HsCmdTop cmd _ _ _) 
+  = rnExpr (convertOpFormsCmd cmd)     `thenM` \ (cmd', fvCmd) ->
+    let 
+       cmd_names = [arrAName, composeAName, firstAName] ++
+                   nameSetToList (methodNamesCmd cmd')
+    in
+       -- Generate the rebindable syntax for the monad
+    lookupSyntaxNames cmd_names                `thenM` \ (cmd_names', cmd_fvs) ->
+
+    returnM (HsCmdTop cmd' [] placeHolderType cmd_names', 
+            fvCmd `plusFV` cmd_fvs)
+
+---------------------------------------------------
+-- convert OpApp's in a command context to HsArrForm's
+
+convertOpFormsCmd :: HsCmd id -> HsCmd id
+
+convertOpFormsCmd (HsLam match) = HsLam (convertOpFormsMatch match)
+
+convertOpFormsCmd (OpApp c1 op fixity c2)
+  = let
+       arg1 = HsCmdTop (convertOpFormsCmd c1) [] placeHolderType []
+       arg2 = HsCmdTop (convertOpFormsCmd c2) [] placeHolderType []
+    in
+    HsArrForm op (Just fixity) [arg1, arg2] noSrcLoc
+
+convertOpFormsCmd (HsPar c) = HsPar (convertOpFormsCmd c)
+
+convertOpFormsCmd (HsCase exp matches locn)
+  = HsCase exp (map convertOpFormsMatch matches) locn
+
+convertOpFormsCmd (HsIf exp c1 c2 locn)
+  = HsIf exp (convertOpFormsCmd c1) (convertOpFormsCmd c2) locn
+
+convertOpFormsCmd (HsLet binds cmd)
+  = HsLet binds (convertOpFormsCmd cmd)
+
+convertOpFormsCmd (HsDo ctxt stmts ids ty locn)
+  = HsDo ctxt (map convertOpFormsStmt stmts) ids ty locn
+
+-- Anything else is unchanged.  This includes HsArrForm (already done),
+-- things with no sub-commands, and illegal commands (which will be
+-- caught by the type checker)
+convertOpFormsCmd c = c
+
+convertOpFormsStmt (BindStmt pat cmd locn)
+  = BindStmt pat (convertOpFormsCmd cmd) locn
+convertOpFormsStmt (ResultStmt cmd locn)
+  = ResultStmt (convertOpFormsCmd cmd) locn
+convertOpFormsStmt (ExprStmt cmd ty locn)
+  = ExprStmt (convertOpFormsCmd cmd) ty locn
+convertOpFormsStmt (RecStmt stmts lvs rvs es)
+  = RecStmt (map convertOpFormsStmt stmts) lvs rvs es
+convertOpFormsStmt stmt = stmt
+
+convertOpFormsMatch (Match pat mty grhss)
+  = Match pat mty (convertOpFormsGRHSs grhss)
+
+convertOpFormsGRHSs (GRHSs grhss binds ty)
+  = GRHSs (map convertOpFormsGRHS grhss) binds ty
+
+convertOpFormsGRHS (GRHS stmts locn)
+  = let
+       (ResultStmt cmd locn') = last stmts
+    in
+    GRHS (init stmts ++ [ResultStmt (convertOpFormsCmd cmd) locn']) locn
+
+---------------------------------------------------
+type CmdNeeds = FreeVars       -- Only inhabitants are 
+                               --      appAName, choiceAName, loopAName
+
+-- find what methods the Cmd needs (loop, choice, apply)
+methodNamesCmd :: HsCmd Name -> CmdNeeds
+
+methodNamesCmd cmd@(HsArrApp _arrow _arg _ HsFirstOrderApp _rtl _srcloc)
+  = emptyFVs
+methodNamesCmd cmd@(HsArrApp _arrow _arg _ HsHigherOrderApp _rtl _srcloc)
+  = unitFV appAName
+methodNamesCmd cmd@(HsArrForm {}) = emptyFVs
+
+methodNamesCmd (HsPar c) = methodNamesCmd c
+
+methodNamesCmd (HsIf p c1 c2 loc)
+  = methodNamesCmd c1 `plusFV` methodNamesCmd c2 `addOneFV` choiceAName
+
+methodNamesCmd (HsLet b c) = methodNamesCmd c
+
+methodNamesCmd (HsDo sc stmts rbs ty loc) = methodNamesStmts stmts
+
+methodNamesCmd (HsLam match) = methodNamesMatch match
+
+methodNamesCmd (HsCase scrut matches loc)
+  = plusFVs (map methodNamesMatch matches) `addOneFV` choiceAName
+
+methodNamesCmd other = emptyFVs
+   -- Other forms can't occur in commands, but it's not convenient 
+   -- to error here so we just do what's convenient.
+   -- The type checker will complain later
+
+---------------------------------------------------
+methodNamesMatch (Match pats sig_ty grhss) = methodNamesGRHSs grhss
+
+-------------------------------------------------
+methodNamesGRHSs (GRHSs grhss binds ty) = plusFVs (map methodNamesGRHS grhss)
+
+-------------------------------------------------
+methodNamesGRHS (GRHS stmts loc) = methodNamesStmt (last stmts)
+
+---------------------------------------------------
+methodNamesStmts stmts = plusFVs (map methodNamesStmt stmts)
+
+---------------------------------------------------
+methodNamesStmt (ResultStmt cmd loc) = methodNamesCmd cmd
+methodNamesStmt (ExprStmt cmd ty loc) = methodNamesCmd cmd
+methodNamesStmt (BindStmt pat cmd loc) = methodNamesCmd cmd
+methodNamesStmt (RecStmt stmts lvs rvs es)
+  = methodNamesStmts stmts `addOneFV` loopAName
+methodNamesStmt (LetStmt b)  = emptyFVs
+methodNamesStmt (ParStmt ss) = emptyFVs
+   -- ParStmt can't occur in commands, but it's not convenient to error 
+   -- here so we just do what's convenient
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
        Arithmetic sequences
 %*                                                                     *
 %************************************************************************
@@ -517,59 +725,80 @@ rnNormalStmts ctxt (LetStmt binds : stmts)
 rnNormalStmts ctxt (ParStmt stmtss : stmts)
   = doptM Opt_GlasgowExts              `thenM` \ opt_GlasgowExts ->
     checkM opt_GlasgowExts parStmtErr  `thenM_`
-    mapFvRn (rnNormalStmts (ParStmtCtxt ctxt)) stmtss  `thenM` \ (stmtss', fv_stmtss) ->
+    mapFvRn rn_branch stmtss           `thenM` \ (stmtss', fv_stmtss) ->
     let
-       bndrss = map collectStmtsBinders stmtss'
+       bndrss :: [[Name]]      -- NB: Name, not RdrName
+       bndrss        = map collectStmtsBinders stmtss'
+       (bndrs, dups) = removeDups cmpByOcc (concat bndrss)
     in
-    foldlM checkBndrs [] bndrss                `thenM` \ new_binders ->
-    bindLocalNamesFV new_binders       $
+    mappM dupErr dups                  `thenM` \ _ ->
+    bindLocalNamesFV bndrs             $
        -- Note: binders are returned in scope order, so one may
        --       shadow the next; e.g. x <- xs; x <- ys
     rnNormalStmts ctxt stmts                   `thenM` \ (stmts', fvs) ->
-    returnM (ParStmtOut (bndrss `zip` stmtss') : stmts', 
+
+       -- Cut down the exported binders to just the ones neede in the body
+    let
+       used_bndrs_s = map (filter (`elemNameSet` fvs)) bndrss
+    in
+    returnM (ParStmt (stmtss' `zip` used_bndrs_s) : stmts', 
             fv_stmtss `plusFV` fvs)
             
   where
-    checkBndrs all_bndrs bndrs
-         = checkErr (null common) (err (head common)) `thenM_`
-           returnM (bndrs ++ all_bndrs)
-       where
-         common = intersectBy eqOcc all_bndrs bndrs
+    rn_branch (stmts, _) = rnNormalStmts (ParStmtCtxt ctxt) stmts
 
-    eqOcc n1 n2 = nameOccName n1 == nameOccName n2
-    err v = ptext SLIT("Duplicate binding in parallel list comprehension for:")
-           <+> quotes (ppr v)
+    cmpByOcc n1 n2 = nameOccName n1 `compare` nameOccName n2
+    dupErr (v:_) = addErr (ptext SLIT("Duplicate binding in parallel list comprehension for:")
+                           <+> quotes (ppr v))
 
-rnNormalStmts ctxt stmts = pprPanic "rnNormalStmts" (ppr stmts)
+rnNormalStmts ctxt (RecStmt rec_stmts _ _ _ : stmts)
+  = bindLocalsRn doc (collectStmtsBinders rec_stmts)   $ \ _ ->
+    rn_rec_stmts rec_stmts                             `thenM` \ segs ->
+    rnNormalStmts ctxt stmts                           `thenM` \ (stmts', fvs) ->
+    let
+       segs_w_fwd_refs          = addFwdRefs segs
+       (ds, us, fs, rec_stmts') = unzip4 segs_w_fwd_refs
+       later_vars = nameSetToList (plusFVs ds `intersectNameSet` fvs)
+       fwd_vars   = nameSetToList (plusFVs fs)
+       uses       = plusFVs us
+    in 
+    returnM (RecStmt rec_stmts' later_vars fwd_vars [] : stmts', uses `plusFV` fvs)
+  where
+    doc = text "In a recursive do statement"
 \end{code}
 
 
 %************************************************************************
 %*                                                                     *
-\subsubsection{Precedence Parsing}
+\subsubsection{mdo expressions}
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
 type FwdRefs = NameSet
-type Segment = (Defs,
-               Uses,           -- May include defs
-               FwdRefs,        -- A subset of uses that are 
+type Segment stmts = (Defs,
+                     Uses,     -- May include defs
+                     FwdRefs,  -- A subset of uses that are 
                                --   (a) used before they are bound in this segment, or 
                                --   (b) used here, and bound in subsequent segments
-               [RenamedStmt])
+                     stmts)    -- Either Stmt or [Stmt]
+
 
 ----------------------------------------------------
 rnMDoStmts :: [RdrNameStmt] -> RnM ([RenamedStmt], FreeVars)
 rnMDoStmts stmts
   =    -- Step1: bring all the binders of the mdo into scope
+       -- Remember that this also removes the binders from the
+       -- finally-returned free-vars
     bindLocalsRn doc (collectStmtsBinders stmts)       $ \ _ ->
        
        -- Step 2: Rename each individual stmt, making a
        --         singleton segment.  At this stage the FwdRefs field
        --         isn't finished: it's empty for all except a BindStmt
        --         for which it's the fwd refs within the bind itself
-    mappM rn_mdo_stmt stmts                            `thenM` \ segs ->
+       --         (This set may not be empty, because we're in a recursive 
+       --          context.)
+    rn_rec_stmts stmts                                 `thenM` \ segs ->
     let
        -- Step 3: Fill in the fwd refs.
        --         The segments are all singletons, but their fwd-ref
@@ -593,22 +822,24 @@ rnMDoStmts stmts
   where
     doc = text "In a mdo-expression"
 
+
 ----------------------------------------------------
-rn_mdo_stmt :: RdrNameStmt -> RnM Segment
+rn_rec_stmt :: RdrNameStmt -> RnM [Segment RenamedStmt]
+       -- Rename a Stmt that is inside a RecStmt (or mdo)
        -- Assumes all binders are already in scope
        -- Turns each stmt into a singleton Stmt
 
-rn_mdo_stmt (ExprStmt expr _ src_loc)
+rn_rec_stmt (ExprStmt expr _ src_loc)
   = addSrcLoc src_loc (rnExpr expr)    `thenM` \ (expr', fvs) ->
-    returnM (emptyNameSet, fvs, emptyNameSet,
-            [ExprStmt expr' placeHolderType src_loc])
+    returnM [(emptyNameSet, fvs, emptyNameSet,
+             ExprStmt expr' placeHolderType src_loc)]
 
-rn_mdo_stmt (ResultStmt expr src_loc)
+rn_rec_stmt (ResultStmt expr src_loc)
   = addSrcLoc src_loc (rnExpr expr)    `thenM` \ (expr', fvs) ->
-    returnM (emptyNameSet, fvs, emptyNameSet,
-            [ResultStmt expr' src_loc])
+    returnM [(emptyNameSet, fvs, emptyNameSet,
+             ResultStmt expr' src_loc)]
 
-rn_mdo_stmt (BindStmt pat expr src_loc)
+rn_rec_stmt (BindStmt pat expr src_loc)
   = addSrcLoc src_loc  $
     rnExpr expr                `thenM` \ (expr', fv_expr) ->
     rnPat pat          `thenM` \ (pat', fv_pat) ->
@@ -616,19 +847,28 @@ rn_mdo_stmt (BindStmt pat expr src_loc)
        bndrs = mkNameSet (collectPatBinders pat')
        fvs   = fv_expr `plusFV` fv_pat
     in
-    returnM (bndrs, fvs, bndrs `intersectNameSet` fvs,
-            [BindStmt pat' expr' src_loc])
+    returnM [(bndrs, fvs, bndrs `intersectNameSet` fvs,
+             BindStmt pat' expr' src_loc)]
 
-rn_mdo_stmt (LetStmt binds)
+rn_rec_stmt (LetStmt binds)
   = rnBinds binds              `thenM` \ (binds', du_binds) ->
-    returnM (duDefs du_binds, duUses du_binds, 
-            emptyNameSet, [LetStmt binds'])
+    returnM [(duDefs du_binds, duUses du_binds, 
+             emptyNameSet, LetStmt binds')]
+
+rn_rec_stmt (RecStmt stmts _ _ _)      -- Flatten Rec inside Rec
+  = rn_rec_stmts stmts
+
+rn_rec_stmt stmt@(ParStmt _)   -- Syntactically illegal in mdo
+  = pprPanic "rn_rec_stmt" (ppr stmt)
 
-rn_mdo_stmt stmt@(ParStmt _)   -- Syntactically illegal in mdo
-  = pprPanic "rn_mdo_stmt" (ppr stmt)
+---------------------------------------------
+rn_rec_stmts :: [RdrNameStmt] -> RnM [Segment RenamedStmt]
+rn_rec_stmts stmts = mappM rn_rec_stmt stmts   `thenM` \ segs_s ->
+                    returnM (concat segs_s)
 
 
-addFwdRefs :: [Segment] -> [Segment]
+---------------------------------------------
+addFwdRefs :: [Segment a] -> [Segment a]
 -- So far the segments only have forward refs *within* the Stmt
 --     (which happens for bind:  x <- ...x...)
 -- This function adds the cross-seg fwd ref info
@@ -636,12 +876,12 @@ addFwdRefs :: [Segment] -> [Segment]
 addFwdRefs pairs 
   = fst (foldr mk_seg ([], emptyNameSet) pairs)
   where
-    mk_seg (defs, uses, fwds, stmts) (segs, seg_defs)
+    mk_seg (defs, uses, fwds, stmts) (segs, later_defs)
        = (new_seg : segs, all_defs)
        where
          new_seg = (defs, uses, new_fwds, stmts)
-         all_defs = seg_defs `unionNameSets` defs
-         new_fwds = fwds `unionNameSets` (uses `intersectNameSet` seg_defs)
+         all_defs = later_defs `unionNameSets` defs
+         new_fwds = fwds `unionNameSets` (uses `intersectNameSet` later_defs)
                -- Add the downstream fwd refs here
 
 ----------------------------------------------------
@@ -679,10 +919,10 @@ addFwdRefs pairs
 --             q <- x ; z <- y } ; 
 --       r <- x }
 
-glomSegments :: [Segment] -> [Segment]
+glomSegments :: [Segment RenamedStmt] -> [Segment [RenamedStmt]]
 
-glomSegments [seg] = [seg]
-glomSegments ((defs,uses,fwds,stmts) : segs)
+glomSegments [] = []
+glomSegments ((defs,uses,fwds,stmt) : segs)
        -- Actually stmts will always be a singleton
   = (seg_defs, seg_uses, seg_fwds, seg_stmts)  : others
   where
@@ -693,12 +933,12 @@ glomSegments ((defs,uses,fwds,stmts) : segs)
     seg_defs  = plusFVs ds `plusFV` defs
     seg_uses  = plusFVs us `plusFV` uses
     seg_fwds  = plusFVs fs `plusFV` fwds
-    seg_stmts = stmts ++ concat ss
+    seg_stmts = stmt : concat ss
 
     grab :: NameSet            -- The client
-        -> [Segment]
-        -> ([Segment],         -- Needed by the 'client'
-            [Segment])         -- Not needed by the client
+        -> [Segment a]
+        -> ([Segment a],       -- Needed by the 'client'
+            [Segment a])       -- Not needed by the client
        -- The result is simply a split of the input
     grab uses dus 
        = (reverse yeses, reverse noes)
@@ -708,7 +948,7 @@ glomSegments ((defs,uses,fwds,stmts) : segs)
 
 
 ----------------------------------------------------
-segsToStmts :: [Segment] -> ([RenamedStmt], FreeVars)
+segsToStmts :: [Segment [RenamedStmt]] -> ([RenamedStmt], FreeVars)
 
 segsToStmts [] = ([], emptyFVs)
 segsToStmts ((defs, uses, fwds, ss) : segs)
@@ -716,13 +956,11 @@ segsToStmts ((defs, uses, fwds, ss) : segs)
   where
     (later_stmts, later_uses) = segsToStmts segs
     new_stmt | non_rec  = head ss
-            | otherwise = RecStmt rec_names ss []
+            | otherwise = RecStmt ss (nameSetToList used_later) (nameSetToList fwds) []
             where
-              non_rec   = isSingleton ss && isEmptyNameSet fwds
-              rec_names = nameSetToList (fwds `plusFV` (defs `intersectNameSet` later_uses))
-               -- The names for the fixpoint are
-               --      (a) the ones needed after the RecStmt
-               --      (b) the forward refs within the fixpoint
+              non_rec    = isSingleton ss && isEmptyNameSet fwds
+              used_later = defs `intersectNameSet` later_uses
+                               -- The ones needed after the RecStmt
 \end{code}
 
 %************************************************************************
index e5fbb17..82512dc 100644 (file)
@@ -665,6 +665,7 @@ read_iface mod file_path is_hi_boot_file
  where
     exts = ExtFlags {glasgowExtsEF = True,
                     ffiEF         = True,
+                    arrowsEF      = True,
                     withEF        = True,
                     parrEF        = True}
     loc  = mkSrcLoc (mkFastString file_path) 1
index 83a098a..5c959d2 100644 (file)
@@ -47,6 +47,8 @@ type RenamedSig                       = Sig                   Name
 type RenamedStmt               = Stmt                  Name
 type RenamedFixitySig          = FixitySig             Name
 type RenamedDeprecation                = DeprecDecl            Name
+type RenamedHsCmd              = HsCmd                 Name
+type RenamedHsCmdTop           = HsCmdTop              Name
 \end{code}
 
 %************************************************************************
index 19c484f..5790e7b 100644 (file)
@@ -360,7 +360,7 @@ newOverloadedLit orig lit@(HsIntegral i fi) expected_ty
   | fi /= fromIntegerName      -- Do not generate a LitInst for rebindable
                                -- syntax.  Reason: tcSyntaxName does unification
                                -- which is very inconvenient in tcSimplify
-  = tcSyntaxName orig expected_ty fromIntegerName fi   `thenM` \ (expr, _) ->
+  = tcSyntaxName orig expected_ty (fromIntegerName, HsVar fi)  `thenM` \ (_,expr) ->
     returnM (HsApp expr (HsLit (HsInteger i)))
 
   | Just expr <- shortCutIntLit i expected_ty 
@@ -371,8 +371,8 @@ newOverloadedLit orig lit@(HsIntegral i fi) expected_ty
 
 newOverloadedLit orig lit@(HsFractional r fr) expected_ty
   | fr /= fromRationalName     -- c.f. HsIntegral case
-  = tcSyntaxName orig expected_ty fromRationalName fr  `thenM` \ (expr, _) ->
-    mkRatLit r                                         `thenM` \ rat_lit ->
+  = tcSyntaxName orig expected_ty (fromRationalName, HsVar fr) `thenM` \ (_,expr) ->
+    mkRatLit r                                                 `thenM` \ rat_lit ->
     returnM (HsApp expr rat_lit)
 
   | Just expr <- shortCutFracLit r expected_ty 
@@ -645,18 +645,18 @@ just use the expression inline.
 \begin{code}
 tcSyntaxName :: InstOrigin
             -> TcType                  -- Type to instantiate it at
-            -> Name -> Name            -- (Standard name, user name)
-            -> TcM (TcExpr, TcType)    -- Suitable expression with its type
+            -> (Name, HsExpr Name)     -- (Standard name, user name)
+            -> TcM (Name, TcExpr)      -- (Standard name, suitable expression)
 
 -- NB: tcSyntaxName calls tcExpr, and hence can do unification.
 -- So we do not call it from lookupInst, which is called from tcSimplify
 
-tcSyntaxName orig ty std_nm user_nm
+tcSyntaxName orig ty (std_nm, HsVar user_nm)
   | std_nm == user_nm
   = newMethodFromName orig ty std_nm   `thenM` \ id ->
-    returnM (HsVar id, idType id)
+    returnM (std_nm, HsVar id)
 
-  | otherwise
+tcSyntaxName orig ty (std_nm, user_nm_expr)
   = tcLookupId std_nm          `thenM` \ std_id ->
     let        
        -- C.f. newMethodAtLoc
@@ -665,9 +665,9 @@ tcSyntaxName orig ty std_nm user_nm
        -- Actually, the "tau-type" might be a sigma-type in the
        -- case of locally-polymorphic methods.
     in
-    addErrCtxtM (syntaxNameCtxt user_nm orig tau1)     $
-    tcCheckSigma (HsVar user_nm) tau1                  `thenM` \ user_fn ->
-    returnM (user_fn, tau1)
+    addErrCtxtM (syntaxNameCtxt user_nm_expr orig tau1)        $
+    tcCheckSigma user_nm_expr tau1                     `thenM` \ expr ->
+    returnM (std_nm, expr)
 
 syntaxNameCtxt name orig ty tidy_env
   = getInstLoc orig            `thenM` \ inst_loc ->
diff --git a/ghc/compiler/typecheck/TcArrows.lhs b/ghc/compiler/typecheck/TcArrows.lhs
new file mode 100644 (file)
index 0000000..026c006
--- /dev/null
@@ -0,0 +1,324 @@
+%
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
+%
+\section{Typecheck arrow notation}
+
+\begin{code}
+module TcArrows ( tcProc ) where
+
+#include "HsVersions.h"
+
+import {-# SOURCE #-}  TcExpr( tcCheckRho )
+
+import HsSyn
+import TcHsSyn ( TcCmd, TcCmdTop, TcExpr, TcPat, mkHsLet )
+
+import TcMatches ( TcStmtCtxt(..), tcMatchPats, matchCtxt, tcStmts )
+
+import TcType  ( TcType, TcTauType, TcRhoType, mkFunTys, mkTyConApp,
+                 mkTyVarTy, mkAppTys, tcSplitTyConApp_maybe, tcEqType )
+import TcMType ( newTyVar, newTyVarTy, newTyVarTys, newSigTyVar, zonkTcType )
+import TcBinds ( tcBindsAndThen )
+import TcSimplify ( tcSimplifyCheck )
+import TcUnify ( Expected(..), checkSigTyVarsWrt, zapExpectedTo )
+import TcRnMonad
+import Inst    ( tcSyntaxName )
+import TysWiredIn ( boolTy, pairTyCon )
+import VarSet 
+import Type    ( Kind,
+                 mkArrowKinds, liftedTypeKind, openTypeKind, tyVarsOfTypes )
+import RnHsSyn ( RenamedHsExpr, RenamedPat, RenamedHsCmd, RenamedHsCmdTop )
+
+import Outputable
+import Util    ( lengthAtLeast )
+
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+               Proc    
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+tcProc :: RenamedPat -> RenamedHsCmdTop                -- proc pat -> expr
+       -> Expected TcRhoType                   -- Expected type of whole proc expression
+       -> TcM (TcPat, TcCmdTop)
+
+tcProc pat cmd exp_ty
+ = do  { arr_ty <- newTyVarTy arrowTyConKind
+       ; [arg_ty, res_ty] <- newTyVarTys 2 liftedTypeKind
+       ; zapExpectedTo exp_ty (mkAppTys arr_ty [arg_ty,res_ty])
+
+       ; let cmd_env = CmdEnv { cmd_arr = arr_ty }
+       ; ([pat'], cmd', ex_binds) <- incProcLevel $
+                                     tcMatchPats [(pat, Check arg_ty)] (Check res_ty) $
+                                     tcCmdTop cmd_env cmd ([], res_ty)
+
+       ; return (pat', glueBindsOnCmd ex_binds cmd') }
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+               Commands
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+type CmdStack = [TcTauType]
+data CmdEnv   = CmdEnv { cmd_arr   :: TcType }         -- The arrow type constructor, of kind *->*->*
+
+mkCmdArrTy :: CmdEnv -> TcTauType -> TcTauType -> TcTauType
+mkCmdArrTy env t1 t2 = mkAppTys (cmd_arr env) [t1, t2]
+
+---------------------------------------
+tcCmdTop :: CmdEnv 
+        -> RenamedHsCmdTop 
+        -> (CmdStack, TcTauType)       -- Expected result type; always a monotype
+                                       -- We know exactly how many cmd args are expected,
+                                       -- albeit perhaps not their types; so we can pass 
+                                       -- in a CmdStack
+        -> TcM TcCmdTop
+
+tcCmdTop env (HsCmdTop cmd _ _ names) (cmd_stk, res_ty)
+  = do { cmd'   <- tcCmd env cmd (cmd_stk, res_ty)
+       ; names' <- mapM (tcSyntaxName ProcOrigin (cmd_arr env)) names
+       ; return (HsCmdTop cmd' cmd_stk res_ty names') }
+
+
+----------------------------------------
+tcCmd :: CmdEnv -> RenamedHsExpr -> (CmdStack, TcTauType) -> TcM TcExpr
+       -- The main recursive function
+
+tcCmd env (HsPar cmd) res_ty
+  = do { cmd' <- tcCmd env cmd res_ty
+       ; return (HsPar cmd') }
+
+tcCmd env (HsLet binds body) res_ty
+  = tcBindsAndThen HsLet binds $
+    tcCmd env body res_ty
+
+tcCmd env (HsIf pred b1 b2 src_loc) res_ty
+  = addSrcLoc src_loc  $ 
+    do         { pred' <- tcCheckRho pred boolTy
+       ; b1'   <- tcCmd env b1 res_ty
+       ; b2'   <- tcCmd env b2 res_ty
+       ; return (HsIf pred' b1' b2' src_loc)
+    }
+
+-------------------------------------------
+--             Arrow application
+--                 (f -< a)   or   (f =< a)
+
+tcCmd env cmd@(HsArrApp fun arg _ ho_app lr src_loc) (cmd_stk, res_ty)
+  = addSrcLoc src_loc          $ 
+    addErrCtxt (cmdCtxt cmd)   $
+    do  { arg_ty <- newTyVarTy openTypeKind
+       ; let fun_ty = mkCmdArrTy env arg_ty res_ty
+
+       ; checkTc (null cmd_stk) (nonEmptyCmdStkErr cmd)
+
+       ; fun' <- pop_arrow_binders (tcCheckRho fun fun_ty)
+
+       ; arg' <- tcCheckRho arg arg_ty
+
+       ; return (HsArrApp fun' arg' fun_ty ho_app lr src_loc) }
+  where
+       -- Before type-checking f, remove the "arrow binders" from the 
+       -- environment in the (-<) case.  
+       -- Local bindings, inside the enclosing proc, are not in scope 
+       -- inside f.  In the higher-order case (--<), they are.
+    pop_arrow_binders tc = case ho_app of
+       HsHigherOrderApp -> tc
+       HsFirstOrderApp  -> popArrowBinders tc
+
+
+-------------------------------------------
+--             Lambda
+
+tcCmd env cmd@(HsLam match@(Match pats maybe_rhs_sig grhss)) (cmd_stk, res_ty)
+  = addSrcLoc (getMatchLoc match)              $
+    addErrCtxt (matchCtxt match_ctxt match)    $
+
+    do {       -- Check the cmd stack is big enough
+       ; checkTc (lengthAtLeast cmd_stk n_pats)
+                 (kappaUnderflow cmd)
+       ; let pats_w_tys = zip pats (map Check cmd_stk)
+
+               -- Check the patterns, and the GRHSs inside
+       ; (pats', grhss', ex_binds) <- tcMatchPats pats_w_tys (Check res_ty) $
+                                      tc_grhss grhss
+
+       ; return (HsLam (Match pats' Nothing (glueBindsOnGRHSs ex_binds grhss')))
+       }
+
+  where
+    n_pats     = length pats
+    stk'       = drop n_pats cmd_stk
+    match_ctxt = LambdaExpr    -- Maybe KappaExpr?
+
+    tc_grhss (GRHSs grhss binds _)
+       = tcBindsAndThen glueBindsOnGRHSs binds         $
+         do { grhss' <- mappM tc_grhs grhss
+            ; return (GRHSs grhss' EmptyBinds res_ty) }
+
+    stmt_ctxt = SC { sc_what = PatGuard match_ctxt, 
+                    sc_rhs  = tcCheckRho, 
+                    sc_body = \ body -> tcCmd env body (stk', res_ty),
+                    sc_ty   = res_ty } -- ToDo: Is this right?
+    tc_grhs (GRHS guarded locn)
+       = addSrcLoc locn        $
+         do { guarded' <- tcStmts stmt_ctxt guarded    
+            ; return (GRHS guarded' locn) }
+
+-------------------------------------------
+--             Do notation
+
+tcCmd env cmd@(HsDo do_or_lc stmts _ ty src_loc) (cmd_stk, res_ty)
+  = do         { checkTc (null cmd_stk) (nonEmptyCmdStkErr cmd)
+       ; stmts' <- tcStmts stmt_ctxt stmts 
+       ; return (HsDo do_or_lc stmts' [] res_ty src_loc) }
+       -- The 'methods' needed for the HsDo are in the enclosing HsCmd
+       -- hence the empty list here
+  where
+    stmt_ctxt = SC { sc_what = do_or_lc,
+                    sc_rhs  = tc_rhs,
+                    sc_body = tc_ret,
+                    sc_ty   = res_ty }
+
+    tc_rhs rhs ty = tcCmd env rhs  ([], ty)
+    tc_ret body   = tcCmd env body ([], res_ty)
+
+
+-----------------------------------------------------------------
+--     Arrow ``forms''       (| e |) c1 .. cn
+--
+--     G      |-b  c : [s1 .. sm] s
+--     pop(G) |-   e : forall w. b ((w,s1) .. sm) s
+--                             -> a ((w,t1) .. tn) t
+--     e \not\in (s, s1..sm, t, t1..tn)
+--     ----------------------------------------------
+--     G |-a  (| e |) c  :  [t1 .. tn] t
+
+tcCmd env cmd@(HsArrForm expr fixity cmd_args src_loc) (cmd_stk, res_ty)       
+  = addSrcLoc src_loc          $ 
+    addErrCtxt (cmdCtxt cmd)   $
+    do { cmds_w_tys <- mapM new_cmd_ty (cmd_args `zip` [1..])
+       ; w_tv       <- newSigTyVar liftedTypeKind
+       ; let w_ty = mkTyVarTy w_tv
+
+               --  a ((w,t1) .. tn) t
+       ; let e_res_ty = mkCmdArrTy env (foldl mkPairTy w_ty cmd_stk) res_ty
+
+               --   b ((w,s1) .. sm) s
+               --   -> a ((w,t1) .. tn) t
+       ; let e_ty = mkFunTys [mkAppTys b [tup,s] | (_,_,b,tup,s) <- cmds_w_tys] 
+                             e_res_ty
+
+               -- Check expr
+       ; (expr', lie) <- getLIE (tcCheckRho expr e_ty)
+       ; inst_binds <- tcSimplifyCheck sig_msg [w_tv] [] lie
+
+               -- Check that the polymorphic variable hasn't been unified with anything
+               -- and is not free in res_ty or the cmd_stk  (i.e.  t, t1..tn)
+       ; [w_tv'] <- checkSigTyVarsWrt (tyVarsOfTypes (res_ty:cmd_stk)) 
+                                      [w_tv] 
+
+               -- OK, now we are in a position to unscramble 
+               -- the s1..sm and check each cmd
+       ; cmds' <- mapM (tc_cmd w_tv') cmds_w_tys
+
+       ; returnM (HsArrForm (TyLam [w_tv'] (mkHsLet inst_binds expr')) fixity cmds' src_loc)
+       }
+  where
+       -- Make the types       
+       --      b, ((e,s1) .. sm), s
+    new_cmd_ty :: (RenamedHsCmdTop, Int)
+              -> TcM (RenamedHsCmdTop, Int, TcType, TcType, TcType)
+    new_cmd_ty (cmd,i)
+         = do  { b_ty   <- newTyVarTy arrowTyConKind
+               ; tup_ty <- newTyVarTy liftedTypeKind
+                       -- We actually make a type variable for the tuple
+                       -- because we don't know how deeply nested it is yet    
+               ; s_ty   <- newTyVarTy liftedTypeKind
+               ; return (cmd, i, b_ty, tup_ty, s_ty)
+               }
+
+    tc_cmd w_tv (cmd, i, b, tup_ty, s)
+      = do { tup_ty' <- zonkTcType tup_ty
+          ; let (corner_ty, arg_tys) = unscramble tup_ty'
+
+               -- Check that it has the right shape:
+               --      ((w,s1) .. sn)
+               -- where the si do not mention w
+          ; checkTc (corner_ty `tcEqType` mkTyVarTy w_tv && 
+                     not (w_tv `elemVarSet` tyVarsOfTypes arg_tys))
+                    (badFormFun i tup_ty')
+
+          ; tcCmdTop (CmdEnv { cmd_arr = b }) cmd (arg_tys, s) }
+
+    unscramble :: TcType -> (TcType, [TcType])
+    -- unscramble ((w,s1) .. sn)       =  (w, [s1..sn])
+    unscramble ty
+       = case tcSplitTyConApp_maybe ty of
+           Just (tc, [t,s]) | tc == pairTyCon 
+              ->  let 
+                     (w,ss) = unscramble t  
+                  in (w, s:ss)
+                                   
+           other -> (ty, [])
+
+    sig_msg  = ptext SLIT("expected type of a command form")
+
+-----------------------------------------------------------------
+--             Base case for illegal commands
+-- This is where expressions that aren't commands get rejected
+
+tcCmd env cmd _
+  = failWithTc (vcat [ptext SLIT("The expression"), nest 2 (ppr cmd), 
+                     ptext SLIT("was found where an arrow command was expected")])
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+               Helpers
+%*                                                                     *
+%************************************************************************
+
+
+\begin{code}
+glueBindsOnCmd EmptyBinds cmd                            = cmd
+glueBindsOnCmd binds      (HsCmdTop cmd stk res_ty names) = HsCmdTop (HsLet binds cmd) stk res_ty names
+       -- Existential bindings become local bindings in the command
+
+
+mkPairTy t1 t2 = mkTyConApp pairTyCon [t1,t2]
+
+arrowTyConKind :: Kind         -- *->*->*
+arrowTyConKind = mkArrowKinds [liftedTypeKind, liftedTypeKind] liftedTypeKind
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+               Errors
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+cmdCtxt cmd = ptext SLIT("In the command:") <+> ppr cmd
+
+nonEmptyCmdStkErr cmd
+  = hang (ptext SLIT("Non-empty command stack at command:"))
+        4 (ppr cmd)
+
+kappaUnderflow cmd
+  = hang (ptext SLIT("Command stack underflow at command:"))
+        4 (ppr cmd)
+
+badFormFun i tup_ty'
+ = hang (ptext SLIT("The type of the") <+> speakNth i <+> ptext SLIT("argument of a command form has the wrong shape"))
+       4 (ptext SLIT("Argument type:") <+> ppr tup_ty')
+\end{code}
index f8ad79c..5360887 100644 (file)
@@ -21,7 +21,7 @@ module TcEnv(
        tcExtendTyVarEnv,    tcExtendTyVarEnv2, 
        tcExtendLocalValEnv, tcExtendLocalValEnv2, 
        tcLookup, tcLookupLocalIds, tcLookup_maybe, 
-       tcLookupId, tcLookupIdLvl, 
+       tcLookupId, 
        lclEnvElts, getInLocalScope, findGlobals, 
 
        -- Instance environment
@@ -34,9 +34,12 @@ module TcEnv(
        tcGetGlobalTyVars,
 
        -- Template Haskell stuff
-       checkWellStaged, spliceOK, bracketOK, tcMetaTy, metaLevel, 
+       checkWellStaged, spliceOK, bracketOK, tcMetaTy, thLevel, 
        topIdLvl, 
 
+       -- Arrow stuff
+       checkProcLevel,
+
        -- New Ids
        newLocalName, newDFunName,
 
@@ -85,26 +88,45 @@ import List         ( partition )
 
 %************************************************************************
 %*                                                                     *
+               Arrow notation proc levels
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+checkProcLevel :: TcId -> ProcLevel -> TcM ()
+checkProcLevel id id_lvl
+  = do { banned <- getBannedProcLevels
+       ; checkTc (not (id_lvl `elem` banned))
+                 (procLevelErr id id_lvl) }
+
+procLevelErr id id_lvl
+  = hang (ptext SLIT("Command-bound variable") <+> quotes (ppr id) <+> ptext SLIT("is not in scope here"))
+        4 (ptext SLIT("Reason: it is used in the left argument of (-<)"))
+\end{code}
+               
+
+%************************************************************************
+%*                                                                     *
                Meta level
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
-instance Outputable Stage where
+instance Outputable ThStage where
    ppr Comp         = text "Comp"
    ppr (Brack l _ _) = text "Brack" <+> int l
    ppr (Splice l)    = text "Splice" <+> int l
 
 
-metaLevel :: Stage -> Level
-metaLevel Comp         = topLevel
-metaLevel (Splice l)    = l
-metaLevel (Brack l _ _) = l
+thLevel :: ThStage -> ThLevel
+thLevel Comp         = topLevel
+thLevel (Splice l)    = l
+thLevel (Brack l _ _) = l
 
 
 checkWellStaged :: SDoc                -- What the stage check is for
-               -> Level        -- Binding level
-               -> Stage        -- Use stage
+               -> ThLevel      -- Binding level
+               -> ThStage      -- Use stage
                -> TcM ()       -- Fail if badly staged, adding an error
 checkWellStaged pp_thing bind_lvl use_stage
   | bind_lvl <= use_lvl        -- OK!
@@ -121,10 +143,10 @@ checkWellStaged pp_thing bind_lvl use_stage
        hsep   [ptext SLIT("is bound at stage") <+> ppr bind_lvl,
                ptext SLIT("but used at stage") <+> ppr use_lvl]
   where
-    use_lvl = metaLevel use_stage
+    use_lvl = thLevel use_stage
 
 
-topIdLvl :: Id -> Level
+topIdLvl :: Id -> ThLevel
 -- Globals may either be imported, or may be from an earlier "chunk" 
 -- (separated by declaration splices) of this module.  The former
 -- *can* be used inside a top-level splice, but the latter cannot.
@@ -138,14 +160,14 @@ topIdLvl id | isLocalId id = topLevel
            | otherwise    = impLevel
 
 -- Indicates the legal transitions on bracket( [| |] ).
-bracketOK :: Stage -> Maybe Level
+bracketOK :: ThStage -> Maybe ThLevel
 bracketOK (Brack _ _ _) = Nothing      -- Bracket illegal inside a bracket
-bracketOK stage         = (Just (metaLevel stage + 1))
+bracketOK stage         = (Just (thLevel stage + 1))
 
 -- Indicates the legal transitions on splice($).
-spliceOK :: Stage -> Maybe Level
+spliceOK :: ThStage -> Maybe ThLevel
 spliceOK (Splice _) = Nothing  -- Splice illegal inside splice
-spliceOK stage      = Just (metaLevel stage - 1)
+spliceOK stage      = Just (thLevel stage - 1)
 
 tcMetaTy :: Name -> TcM Type
 -- Given the name of a Template Haskell data type, 
@@ -354,30 +376,21 @@ tcLookupId :: Name -> TcM Id
 tcLookupId name
   = tcLookup name      `thenM` \ thing -> 
     case thing of
-       ATcId tc_id lvl   -> returnM tc_id
+       ATcId tc_id _ _   -> returnM tc_id
        AGlobal (AnId id) -> returnM id
        other             -> pprPanic "tcLookupId" (ppr name)
 
-tcLookupIdLvl :: Name -> TcM (Id, Level)
--- DataCons dealt with separately
-tcLookupIdLvl name
-  = tcLookup name      `thenM` \ thing -> 
-    case thing of
-       ATcId tc_id lvl   -> returnM (tc_id, lvl)
-       AGlobal (AnId id) -> returnM (id, topIdLvl id)
-       other             -> pprPanic "tcLookupIdLvl" (ppr name)
-
 tcLookupLocalIds :: [Name] -> TcM [TcId]
 -- We expect the variables to all be bound, and all at
 -- the same level as the lookup.  Only used in one place...
 tcLookupLocalIds ns
   = getLclEnv          `thenM` \ env ->
-    returnM (map (lookup (tcl_env env) (metaLevel (tcl_level env))) ns)
+    returnM (map (lookup (tcl_env env) (thLevel (tcl_th_ctxt env))) ns)
   where
     lookup lenv lvl name 
        = case lookupNameEnv lenv name of
-               Just (ATcId id lvl1) -> ASSERT( lvl == lvl1 ) id
-               other                -> pprPanic "tcLookupLocalIds" (ppr name)
+               Just (ATcId id lvl1 _) -> ASSERT( lvl == lvl1 ) id
+               other                  -> pprPanic "tcLookupLocalIds" (ppr name)
 
 lclEnvElts :: TcLclEnv -> [TcTyThing]
 lclEnvElts env = nameEnvElts (tcl_env env)
@@ -433,8 +446,9 @@ tcExtendLocalValEnv ids thing_inside
   = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | id <- ids]
-       lvl                 = metaLevel (tcl_level env)
-       extra_env           = [(idName id, ATcId id lvl) | id <- ids]
+       th_lvl              = thLevel (tcl_th_ctxt env)
+       proc_lvl            = proc_level (tcl_arrow_ctxt env)
+       extra_env           = [(idName id, ATcId id th_lvl proc_lvl) | id <- ids]
        le'                 = extendNameEnvList (tcl_env env) extra_env
     in
     tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
@@ -445,8 +459,9 @@ tcExtendLocalValEnv2 names_w_ids thing_inside
   = getLclEnv          `thenM` \ env ->
     let
        extra_global_tyvars = tyVarsOfTypes [idType id | (name,id) <- names_w_ids]
-       lvl                 = metaLevel (tcl_level env)
-       extra_env           = [(name, ATcId id lvl) | (name,id) <- names_w_ids]
+       th_lvl              = thLevel    (tcl_th_ctxt   env)
+       proc_lvl            = proc_level (tcl_arrow_ctxt env)
+       extra_env           = [(name, ATcId id th_lvl proc_lvl) | (name,id) <- names_w_ids]
        le'                 = extendNameEnvList (tcl_env env) extra_env
     in
     tc_extend_gtvs (tcl_tyvars env) extra_global_tyvars        `thenM` \ gtvs' ->
@@ -479,7 +494,7 @@ findGlobals tvs tidy_env
     ignore_it ty = not (tvs `intersectsVarSet` tyVarsOfType ty)
 
 -----------------------
-find_thing ignore_it tidy_env (ATcId id _)
+find_thing ignore_it tidy_env (ATcId id _ _)
   = zonkTcType  (idType id)    `thenM` \ id_ty ->
     if ignore_it id_ty then
        returnM (tidy_env, Nothing)
index f44b757..f889697 100644 (file)
@@ -12,7 +12,7 @@ module TcExpr ( tcCheckSigma, tcCheckRho, tcInferRho, tcMonoExpr ) where
 import {-# SOURCE #-}  TcSplice( tcSpliceExpr, tcBracket )
 import HsSyn           ( HsReify(..), ReifyFlavour(..) )
 import TcType          ( isTauTy )
-import TcEnv           ( bracketOK, tcMetaTy, checkWellStaged, metaLevel )
+import TcEnv           ( bracketOK, tcMetaTy, checkWellStaged )
 import Name            ( isExternalName )
 import qualified DsMeta
 #endif
@@ -30,9 +30,10 @@ import Inst          ( InstOrigin(..),
                          instToId, tcInstCall, tcInstDataCon
                        )
 import TcBinds         ( tcBindsAndThen )
-import TcEnv           ( tcLookupClass, tcLookupGlobal_maybe, tcLookupIdLvl,
-                         tcLookupTyCon, tcLookupDataCon, tcLookupId
+import TcEnv           ( tcLookupClass, tcLookupGlobal_maybe, tcLookup,
+                         tcLookupTyCon, tcLookupDataCon, tcLookupId, checkProcLevel
                        )
+import TcArrows                ( tcProc )
 import TcMatches       ( tcMatchesCase, tcMatchLambda, tcDoStmts, tcThingWithSig )
 import TcMonoType      ( tcHsSigType, UserTypeCtxt(..) )
 import TcPat           ( badFieldCon )
@@ -281,8 +282,8 @@ tcMonoExpr (HsDo do_or_lc stmts method_names _ src_loc) res_ty
   = addSrcLoc src_loc                                  $
     zapExpectedType res_ty                             `thenM` \ res_ty' ->
        -- All comprehensions yield a monotype
-    tcDoStmts do_or_lc stmts method_names res_ty'      `thenM` \ (binds, stmts', methods') ->
-    returnM (mkHsLet binds (HsDo do_or_lc stmts' methods' res_ty' src_loc))
+    tcDoStmts do_or_lc stmts method_names res_ty'      `thenM` \ (stmts', methods') ->
+    returnM (HsDo do_or_lc stmts' methods' res_ty' src_loc)
 
 tcMonoExpr in_expr@(ExplicitList _ exprs) res_ty       -- Non-empty list
   = zapToListTy res_ty                `thenM` \ elt_ty ->  
@@ -306,6 +307,11 @@ tcMonoExpr (ExplicitTuple exprs boxity) res_ty
   = zapToTupleTy boxity (length exprs) res_ty  `thenM` \ arg_tys ->
     tcCheckRhos exprs arg_tys                  `thenM` \ exprs' ->
     returnM (ExplicitTuple exprs' boxity)
+
+tcMonoExpr (HsProc pat cmd loc) res_ty
+  = addSrcLoc loc $
+    tcProc pat cmd res_ty                      `thenM` \ (pat', cmd') ->
+    returnM (HsProc pat' cmd' loc)
 \end{code}
 
 
@@ -786,64 +792,65 @@ tcId name -- Look up the Id and instantiate its type
   =    -- First check whether it's a DataCon
        -- Reason: we must not forget to chuck in the
        --         constraints from their "silly context"
-    tcLookupGlobal_maybe name          `thenM` \ maybe_thing ->
+    tcLookup name              `thenM` \ maybe_thing ->
     case maybe_thing of {
-       Just (ADataCon data_con) -> inst_data_con data_con ;
-       other                    ->
+       AGlobal (ADataCon data_con)  -> inst_data_con data_con 
+    ;  AGlobal (AnId id)            -> loop (HsVar id) (idType id)
+               -- A global cannot possibly be ill-staged
+               -- nor does it need the 'lifting' treatment
 
-       -- OK, so now look for ordinary Ids
-    tcLookupIdLvl name                 `thenM` \ (id, bind_lvl) ->
+    ;  ATcId id th_level proc_level -> tc_local_id id th_level proc_level
+    ;  other                        -> pprPanic "tcId" (ppr name)
+    }
+  where
 
 #ifndef GHCI
-    loop (HsVar id) (idType id)                -- Non-TH case
+    tc_local_id id th_bind_lvl proc_lvl                        -- Non-TH case
+       = checkProcLevel id proc_lvl    `thenM_`
+         loop (HsVar id) (idType id)
+
+#else /* GHCI and TH is on */
+    tc_local_id id th_bind_lvl proc_lvl                        -- TH case
+       = checkProcLevel id proc_lvl    `thenM_`
 
-#else /* GHCI is on */
        -- Check for cross-stage lifting
-    getStage                           `thenM` \ use_stage -> 
-    case use_stage of
-      Brack use_lvl ps_var lie_var
-       | use_lvl > bind_lvl && not (isExternalName name)
-       ->      -- E.g. \x -> [| h x |]
+         getStage                              `thenM` \ use_stage -> 
+         case use_stage of
+             Brack use_lvl ps_var lie_var
+               | use_lvl > th_bind_lvl 
+               ->      -- E.g. \x -> [| h x |]
                -- We must behave as if the reference to x was
+
                --      h $(lift x)     
                -- We use 'x' itself as the splice proxy, used by 
                -- the desugarer to stitch it all back together.
                -- If 'x' occurs many times we may get many identical
                -- bindings of the same splice proxy, but that doesn't
                -- matter, although it's a mite untidy.
-               --
-               -- NB: During type-checking, isExernalName is true of 
-               -- top level things, and false of nested bindings
-               -- Top-level things don't need lifting.
-       
-       let
-           id_ty = idType id
-       in
-       checkTc (isTauTy id_ty) (polySpliceErr id)      `thenM_` 
+               let
+                   id_ty = idType id
+               in
+               checkTc (isTauTy id_ty) (polySpliceErr id)      `thenM_` 
                    -- If x is polymorphic, its occurrence sites might
                    -- have different instantiations, so we can't use plain
                    -- 'x' as the splice proxy name.  I don't know how to 
                    -- solve this, and it's probably unimportant, so I'm
                    -- just going to flag an error for now
 
-       setLIEVar lie_var       (
-       newMethodFromName orig id_ty DsMeta.liftName    `thenM` \ lift ->
-               -- Put the 'lift' constraint into the right LIE
+               setLIEVar lie_var       (
+               newMethodFromName orig id_ty DsMeta.liftName    `thenM` \ lift ->
+                       -- Put the 'lift' constraint into the right LIE
        
-       -- Update the pending splices
-        readMutVar ps_var                      `thenM` \ ps ->
-        writeMutVar ps_var ((name, HsApp (HsVar lift) (HsVar id)) : ps)        `thenM_`
-
-       returnM (HsVar id, id_ty))
-
-      other -> 
-       checkWellStaged (quotes (ppr id)) bind_lvl use_stage    `thenM_`
-       loop (HsVar id) (idType id)
-#endif
-    }
+               -- Update the pending splices
+               readMutVar ps_var                       `thenM` \ ps ->
+               writeMutVar ps_var ((name, HsApp (HsVar lift) (HsVar id)) : ps) `thenM_`
+       
+               returnM (HsVar id, id_ty))
 
-  where
-    orig = OccurrenceOf name
+             other -> 
+               checkWellStaged (quotes (ppr id)) th_bind_lvl use_stage `thenM_`
+               loop (HsVar id) (idType id)
+#endif /* GHCI */
 
     loop (HsVar fun_id) fun_ty
        | want_method_inst fun_ty
@@ -885,6 +892,8 @@ tcId name   -- Look up the Id and instantiate its type
        returnM (mkHsDictApp (mkHsTyApp (HsVar (dataConWrapId data_con)) ty_args) 
                             (map instToId ex_dicts), 
                 mkFunTys arg_tys result_ty)
+
+    orig = OccurrenceOf name
 \end{code}
 
 %************************************************************************
index 24dc515..2b30c3c 100644 (file)
@@ -13,6 +13,7 @@ module TcHsSyn (
        TcStmt, TcArithSeqInfo, TcRecordBinds,
        TcHsModule, TcDictBinds,
        TcForeignDecl,
+       TcCmd, TcCmdTop,
        
        TypecheckedHsBinds, TypecheckedRuleDecl,
        TypecheckedMonoBinds, TypecheckedPat,
@@ -22,6 +23,7 @@ module TcHsSyn (
        TypecheckedGRHSs, TypecheckedGRHS,
        TypecheckedRecordBinds, TypecheckedDictBinds,
        TypecheckedMatchContext, TypecheckedCoreBind,
+       TypecheckedHsCmd, TypecheckedHsCmdTop,
 
        mkHsTyApp, mkHsDictApp, mkHsConApp,
        mkHsTyLam, mkHsDictLam, mkHsLet,
@@ -103,6 +105,8 @@ type TcRecordBinds  = HsRecordBinds TcId
 type TcHsModule                = HsModule      TcId
 type TcForeignDecl      = ForeignDecl  TcId
 type TcRuleDecl        = RuleDecl     TcId
+type TcCmd             = HsCmd         TcId 
+type TcCmdTop          = HsCmdTop      TcId 
 
 type TypecheckedPat            = OutPat        Id
 type TypecheckedMonoBinds      = MonoBinds     Id
@@ -119,6 +123,8 @@ type TypecheckedHsModule    = HsModule      Id
 type TypecheckedForeignDecl     = ForeignDecl   Id
 type TypecheckedRuleDecl       = RuleDecl      Id
 type TypecheckedCoreBind        = (Id, CoreExpr)
+type TypecheckedHsCmd          = HsCmd         Id
+type TypecheckedHsCmdTop       = HsCmdTop      Id
 
 type TypecheckedMatchContext   = HsMatchContext Name   -- Keeps consistency with 
                                                        -- HsDo arg StmtContext
@@ -553,9 +559,9 @@ zonkExpr env (HsLet binds expr)
 zonkExpr env (HsDo do_or_lc stmts ids ty src_loc)
   = zonkStmts env stmts        `thenM` \ new_stmts ->
     zonkTcTypeToType env ty    `thenM` \ new_ty   ->
-    returnM (HsDo do_or_lc new_stmts 
-                     (zonkIdOccs env ids) 
-                     new_ty src_loc)
+    zonkReboundNames env ids   `thenM` \ new_ids ->
+    returnM (HsDo do_or_lc new_stmts new_ids
+                 new_ty src_loc)
 
 zonkExpr env (ExplicitList ty exprs)
   = zonkTcTypeToType env ty    `thenM` \ new_ty ->
@@ -637,6 +643,42 @@ zonkExpr env (DictApp expr dicts)
   = zonkExpr env expr                  `thenM` \ new_expr ->
     returnM (DictApp new_expr (zonkIdOccs env dicts))
 
+-- arrow notation extensions
+zonkExpr env (HsProc pat body src_loc)
+  = zonkPat env pat                    `thenM` \ (new_pat, new_ids) ->
+    let
+       env1 = extendZonkEnv env (bagToList new_ids)
+    in
+    zonkCmdTop env1 body               `thenM` \ new_body ->
+    returnM (HsProc new_pat new_body src_loc)
+
+zonkExpr env (HsArrApp e1 e2 ty ho rl src_loc)
+  = zonkExpr env e1                    `thenM` \ new_e1 ->
+    zonkExpr env e2                    `thenM` \ new_e2 ->
+    zonkTcTypeToType env ty            `thenM` \ new_ty ->
+    returnM (HsArrApp new_e1 new_e2 new_ty ho rl src_loc)
+
+zonkExpr env (HsArrForm op fixity args src_loc)
+  = zonkExpr env op                    `thenM` \ new_op ->
+    mappM (zonkCmdTop env) args                `thenM` \ new_args ->
+    returnM (HsArrForm new_op fixity new_args src_loc)
+
+zonkCmdTop :: ZonkEnv -> TcCmdTop -> TcM TypecheckedHsCmdTop
+zonkCmdTop env (HsCmdTop cmd stack_tys ty ids)
+  = zonkExpr env cmd                   `thenM` \ new_cmd ->
+    mappM (zonkTcTypeToType env) stack_tys
+                                       `thenM` \ new_stack_tys ->
+    zonkTcTypeToType env ty            `thenM` \ new_ty ->
+    zonkReboundNames env ids           `thenM` \ new_ids ->
+    returnM (HsCmdTop new_cmd new_stack_tys new_ty new_ids)
+
+-------------------------------------------------------------------------
+zonkReboundNames :: ZonkEnv -> ReboundNames Id -> TcM (ReboundNames Id)
+zonkReboundNames env prs 
+  = mapM zonk prs
+  where
+    zonk (n, e) = zonkExpr env e `thenM` \ new_e ->
+                 returnM (n, new_e)
 
 
 -------------------------------------------------------------------------
@@ -673,29 +715,33 @@ zonk_stmts :: ZonkEnv -> [TcStmt] -> TcM (ZonkEnv, [TypecheckedStmt])
 
 zonk_stmts env [] = returnM (env, [])
 
-zonk_stmts env (ParStmtOut bndrstmtss : stmts)
-  = mappM (mappM zonkId) bndrss                `thenM` \ new_bndrss ->
-    mappM (zonkStmts env) stmtss       `thenM` \ new_stmtss ->
+zonk_stmts env (ParStmt stmts_w_bndrs : stmts)
+  = mappM zonk_branch stmts_w_bndrs    `thenM` \ new_stmts_w_bndrs ->
     let 
-       new_binders = concat new_bndrss
+       new_binders = concat (map snd new_stmts_w_bndrs)
        env1 = extendZonkEnv env new_binders
     in
     zonk_stmts env1 stmts              `thenM` \ (env2, new_stmts) ->
-    returnM (env2, ParStmtOut (zip new_bndrss new_stmtss) : new_stmts)
+    returnM (env2, ParStmt new_stmts_w_bndrs : new_stmts)
   where
-    (bndrss, stmtss) = unzip bndrstmtss
+    zonk_branch (stmts, bndrs) = zonk_stmts env stmts  `thenM` \ (env1, new_stmts) ->
+                                returnM (new_stmts, zonkIdOccs env1 bndrs)
 
-zonk_stmts env (RecStmt vs segStmts rets : stmts)
-  = mappM zonkId vs            `thenM` \ new_vs ->
+zonk_stmts env (RecStmt segStmts lvs rvs rets : stmts)
+  = zonkIdBndrs env rvs                `thenM` \ new_rvs ->
     let
-       env1 = extendZonkEnv env new_vs
+       env1 = extendZonkEnv env new_rvs
     in
     zonk_stmts env1 segStmts   `thenM` \ (env2, new_segStmts) ->
        -- Zonk the ret-expressions in an envt that 
        -- has the polymorphic bindings in the envt
     zonkExprs env2 rets                `thenM` \ new_rets ->
-    zonk_stmts env1 stmts      `thenM` \ (env3, new_stmts) ->
-    returnM (env3, RecStmt new_vs new_segStmts new_rets : new_stmts)
+    let
+       new_lvs = zonkIdOccs env2 lvs
+       env3 = extendZonkEnv env new_lvs        -- Only the lvs are needed
+    in
+    zonk_stmts env3 stmts      `thenM` \ (env4, new_stmts) ->
+    returnM (env4, RecStmt new_segStmts new_lvs new_rvs new_rets : new_stmts)
 
 zonk_stmts env (ResultStmt expr locn : stmts)
   = ASSERT( null stmts )
index f2c900b..207411c 100644 (file)
@@ -11,7 +11,7 @@ module TcMType (
 
   --------------------------------
   -- Creating new mutable type variables
-  newTyVar, 
+  newTyVar, newSigTyVar,
   newTyVarTy,          -- Kind -> TcM TcType
   newTyVarTys,         -- Int -> Kind -> TcM [TcType]
   newKindVar, newKindVars, newOpenTypeKind,
@@ -112,6 +112,11 @@ newTyVar kind
   = newUnique  `thenM` \ uniq ->
     newMutTyVar (mkSystemTvNameEncoded uniq FSLIT("t")) kind VanillaTv
 
+newSigTyVar :: Kind -> TcM TcTyVar
+newSigTyVar kind
+  = newUnique  `thenM` \ uniq ->
+    newMutTyVar (mkSystemTvNameEncoded uniq FSLIT("s")) kind SigTv
+
 newTyVarTy  :: Kind -> TcM TcType
 newTyVarTy kind
   = newTyVar kind      `thenM` \ tc_tyvar ->
index 64a4505..269abde 100644 (file)
@@ -4,8 +4,10 @@
 \section[TcMatches]{Typecheck some @Matches@}
 
 \begin{code}
-module TcMatches ( tcMatchesFun, tcMatchesCase, tcMatchLambda, 
-                  tcDoStmts, tcStmtsAndThen, tcGRHSs, tcThingWithSig
+module TcMatches ( tcMatchesFun, tcMatchesCase, tcMatchLambda, matchCtxt,
+                  tcDoStmts, tcStmtsAndThen, tcStmts, tcGRHSs, tcThingWithSig,
+                  tcMatchPats,
+                  TcStmtCtxt(..)
        ) where
 
 #include "HsVersions.h"
@@ -14,13 +16,14 @@ import {-# SOURCE #-}       TcExpr( tcCheckRho, tcMonoExpr )
 
 import HsSyn           ( HsExpr(..), HsBinds(..), Match(..), GRHSs(..), GRHS(..),
                          MonoBinds(..), Stmt(..), HsMatchContext(..), HsStmtContext(..),
+                         ReboundNames,
                          pprMatch, getMatchLoc, isDoExpr,
                          pprMatchContext, pprStmtContext, pprStmtResultContext,
-                         mkMonoBind, collectSigTysFromPats, andMonoBindList
+                         mkMonoBind, collectSigTysFromPats, andMonoBindList, glueBindsOnGRHSs
                        )
-import RnHsSyn         ( RenamedMatch, RenamedGRHSs, RenamedStmt, 
+import RnHsSyn         ( RenamedMatch, RenamedGRHSs, RenamedStmt, RenamedHsExpr,
                          RenamedPat, RenamedMatchContext )
-import TcHsSyn         ( TcMatch, TcGRHSs, TcStmt, TcDictBinds, TcHsBinds, 
+import TcHsSyn         ( TcMatch, TcGRHSs, TcStmt, TcDictBinds, TcHsBinds, TcExpr,
                          TcMonoBinds, TcPat, TcStmt, ExprCoFn,
                          isIdCoercion, (<$>), (<.>) )
 
@@ -31,12 +34,12 @@ import TcEnv                ( TcId, tcLookupLocalIds, tcLookupId, tcExtendLocalValEnv, tcExten
 import TcPat           ( tcPat, tcMonoPatBndr )
 import TcMType         ( newTyVarTy, newTyVarTys, zonkTcType ) 
 import TcType          ( TcType, TcTyVar, TcSigmaType, TcRhoType,
-                         tyVarsOfType, tidyOpenTypes, tidyOpenType, isSigmaTy,
+                         tyVarsOfTypes, tidyOpenTypes, tidyOpenType, isSigmaTy,
                          mkFunTy, isOverloadedTy, liftedTypeKind, openTypeKind, 
                          mkArrowKind, mkAppTy )
 import TcBinds         ( tcBindsAndThen )
 import TcUnify         ( Expected(..), newHole, zapExpectedType, zapExpectedBranches, readExpectedType,
-                         unifyTauTy, subFunTy, unifyPArrTy, unifyListTy, unifyFunTy,
+                         unifyTauTy, subFunTys, unifyPArrTy, unifyListTy, unifyFunTy,
                          checkSigTyVarsWrt, tcSubExp, tcGen )
 import TcSimplify      ( tcSimplifyCheck, bindInstsOfLocalFuns )
 import Name            ( Name )
@@ -87,7 +90,7 @@ tcMatchesFun fun_name matches@(first_match:_) expected_ty
        -- because inconsistency between branches
        -- may show up as something wrong with the (non-existent) type signature
 
-       -- No need to zonk expected_ty, because subFunTy does that on the fly
+       -- No need to zonk expected_ty, because subFunTys does that on the fly
     tcMatches (FunRhs fun_name) matches expected_ty
 \end{code}
 
@@ -159,14 +162,17 @@ tcMatch :: RenamedMatchContext
 tcMatch ctxt match@(Match pats maybe_rhs_sig grhss) expected_ty
   = addSrcLoc (getMatchLoc match)              $       -- At one stage I removed this;
     addErrCtxt (matchCtxt ctxt match)          $       -- I'm not sure why, so I put it back
-    tcMatchPats pats expected_ty tc_grhss      `thenM` \ (pats', grhss', ex_binds) ->
-    returnM (Match pats' Nothing (glue_on ex_binds grhss'))
+    subFunTys pats expected_ty                 $ \ pats_w_tys rhs_ty ->
+       -- This is the unique place we call subFunTys
+       -- The point is that if expected_y is a "hole", we want 
+       -- to make arg_ty and rest_ty as "holes" too.
+    tcMatchPats pats_w_tys rhs_ty (tc_grhss rhs_ty)    `thenM` \ (pats', grhss', ex_binds) ->
+    returnM (Match pats' Nothing (glueBindsOnGRHSs ex_binds grhss'))
 
   where
     tc_grhss rhs_ty 
-       =       -- Deal with the result signature
-         case maybe_rhs_sig of
-           Nothing ->  tcGRHSs ctxt grhss rhs_ty
+       = case maybe_rhs_sig of  -- Deal with the result signature
+           Nothing  ->  tcGRHSs ctxt grhss rhs_ty
 
            Just sig ->  tcAddScopedTyVars [sig]        $
                                -- Bring into scope the type variables in the signature
@@ -189,12 +195,6 @@ lift_grhss co_fn rhs_ty (GRHSs grhss binds ty)
     lift_stmt (ResultStmt e l) = ResultStmt (co_fn <$> e) l
     lift_stmt stmt            = stmt
    
--- glue_on just avoids stupid dross
-glue_on EmptyBinds grhss = grhss               -- The common case
-glue_on binds1 (GRHSs grhss binds2 ty)
-  = GRHSs grhss (binds1 `ThenBinds` binds2) ty
-
-
 tcGRHSs :: RenamedMatchContext -> RenamedGRHSs
        -> Expected TcRhoType
        -> TcM TcGRHSs
@@ -206,24 +206,27 @@ tcGRHSs :: RenamedMatchContext -> RenamedGRHSs
   -- This is a consequence of the fact that tcStmts takes a TcType,
   -- not a Expected TcType, a decision we could revisit if necessary
 tcGRHSs ctxt (GRHSs [GRHS [ResultStmt rhs loc1] loc2] binds _) exp_ty
-  = tcBindsAndThen glue_on binds       $
-    tcMonoExpr rhs exp_ty              `thenM` \ rhs' ->
-    readExpectedType exp_ty            `thenM` \ exp_ty' ->
+  = tcBindsAndThen glueBindsOnGRHSs binds      $
+    tcMonoExpr rhs exp_ty                      `thenM` \ rhs' ->
+    readExpectedType exp_ty                    `thenM` \ exp_ty' ->
     returnM (GRHSs [GRHS [ResultStmt rhs' loc1] loc2] EmptyBinds exp_ty')
 
 tcGRHSs ctxt (GRHSs grhss binds _) exp_ty
-  = tcBindsAndThen glue_on binds       $
-    zapExpectedType exp_ty             `thenM` \ exp_ty' ->
+  = tcBindsAndThen glueBindsOnGRHSs binds      $
+    zapExpectedType exp_ty                     `thenM` \ exp_ty' ->
        -- Even if there is only one guard, we zap the RHS type to
        -- a monotype.  Reason: it makes tcStmts much easier,
        -- and even a one-armed guard has a notional second arm
     let
+      stmt_ctxt = SC { sc_what = PatGuard ctxt, 
+                      sc_rhs  = tcCheckRho, 
+                      sc_body = \ body -> tcCheckRho body exp_ty',
+                      sc_ty   = exp_ty' }
+
       tc_grhs (GRHS guarded locn)
-       = addSrcLoc locn                        $
-         tcStmts (PatGuard ctxt) m_ty guarded  `thenM` \ guarded' ->
+       = addSrcLoc locn                $
+         tcStmts stmt_ctxt  guarded    `thenM` \ guarded' ->
          returnM (GRHS guarded' locn)
-
-      m_ty =  (\ty -> ty, exp_ty') 
     in
     mappM tc_grhs grhss                        `thenM` \ grhss' ->
     returnM (GRHSs grhss' EmptyBinds exp_ty')
@@ -263,21 +266,22 @@ tcThingWithSig sig_ty thing_inside res_ty
 
 \begin{code}     
 tcMatchPats
-       :: [RenamedPat] -> Expected TcRhoType
-       -> (Expected TcRhoType -> TcM a)
+       :: [(RenamedPat, Expected TcRhoType)]
+       -> Expected TcRhoType
+       -> TcM a
        -> TcM ([TcPat], a, TcHsBinds)
 -- Typecheck the patterns, extend the environment to bind the variables,
 -- do the thing inside, use any existentially-bound dictionaries to 
 -- discharge parts of the returning LIE, and deal with pattern type
 -- signatures
 
-tcMatchPats pats expected_ty thing_inside
+tcMatchPats pats_w_tys body_ty thing_inside
   =    -- STEP 1: Bring pattern-signature type variables into scope
-    tcAddScopedTyVars (collectSigTysFromPats pats)     (
+    tcAddScopedTyVars (collectSigTysFromPats (map fst pats_w_tys))     (
 
        -- STEP 2: Typecheck the patterns themselves, gathering all the stuff
        --         then do the thing inside
-        getLIE (tc_match_pats pats expected_ty thing_inside)
+        getLIE (tc_match_pats pats_w_tys thing_inside)
 
     ) `thenM` \ ((pats', ex_tvs, ex_ids, ex_lie, result), lie_req) -> 
 
@@ -288,26 +292,22 @@ tcMatchPats pats expected_ty thing_inside
        -- I'm a bit concerned that lie_req1 from an 'inner' pattern in the list
        -- might need (via lie_req2) something made available from an 'outer' 
        -- pattern.  But it's inconvenient to deal with, and I can't find an example
-    readExpectedType expected_ty                               `thenM` \ exp_ty ->
-    tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req exp_ty  `thenM` \ ex_binds ->
-       -- NB: we *must* pass "exp_ty" not "result_ty" to tcCheckExistentialPat
+    tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req 
+                         pats_w_tys body_ty            `thenM` \ ex_binds ->
+       -- NB: we *must* pass "pats_w_tys" not just "body_ty" to tcCheckExistentialPat
        -- For example, we must reject this program:
        --      data C = forall a. C (a -> Int) 
        --      f (C g) x = g x
-       -- Here, result_ty will be simply Int, but expected_ty is (a -> Int).
+       -- Here, result_ty will be simply Int, but expected_ty is (C -> a -> Int).
 
     returnM (pats', result, mkMonoBind Recursive ex_binds)
 
-tc_match_pats [] expected_ty thing_inside
-  = thing_inside expected_ty   `thenM` \ answer ->
+tc_match_pats [] thing_inside
+  = thing_inside       `thenM` \ answer ->
     returnM ([], emptyBag, [], [], answer)
 
-tc_match_pats (pat:pats) expected_ty thing_inside
-  = subFunTy expected_ty               $ \ arg_ty rest_ty ->
-       -- This is the unique place we call subFunTy
-       -- The point is that if expected_y is a "hole", we want 
-       -- to make arg_ty and rest_ty as "holes" too.
-    tcPat tcMonoPatBndr pat arg_ty     `thenM` \ (pat', ex_tvs, pat_bndrs, ex_lie) ->
+tc_match_pats ((pat,pat_ty):pats) thing_inside
+  = tcPat tcMonoPatBndr pat pat_ty     `thenM` \ (pat', ex_tvs, pat_bndrs, ex_lie) ->
     let
        xve    = bagToList pat_bndrs
        ex_ids = [id | (_, id) <- xve]
@@ -315,7 +315,7 @@ tc_match_pats (pat:pats) expected_ty thing_inside
                -- of the existential Ids used in checkExistentialPat
     in
     tcExtendLocalValEnv2 xve                   $
-    tc_match_pats pats rest_ty thing_inside    `thenM` \ (pats', exs_tvs, exs_ids, exs_lie, answer) ->
+    tc_match_pats pats thing_inside    `thenM` \ (pats', exs_tvs, exs_ids, exs_lie, answer) ->
     returnM (  pat':pats',
                ex_tvs `unionBags` exs_tvs,
                ex_ids ++ exs_ids,
@@ -330,9 +330,11 @@ tcCheckExistentialPat :: Bag TcTyVar       -- Existentially quantified tyvars bound by
                                        --   (b) to generate helpful error messages
                      -> [Inst]         --   and context
                      -> [Inst]         -- Required context
-                     -> TcType         --   and type of the Match; vars in here must not escape
+                     -> [(pat,Expected TcRhoType)]     -- Types of the patterns
+                     -> Expected TcRhoType             -- Type of the body of the match
+                                                       -- Tyvars in either of these must not escape
                      -> TcM TcDictBinds        -- LIE to float out and dict bindings
-tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req match_ty
+tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req pats_w_tys body_ty
   | isEmptyBag ex_tvs && all not_overloaded ex_ids
        -- Short cut for case when there are no existentials
        -- and no polymorphic overloaded variables
@@ -344,7 +346,9 @@ tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req match_ty
     returnM EmptyMonoBinds
 
   | otherwise
-  = addErrCtxtM (sigPatCtxt tv_list ex_ids match_ty)           $
+  =    -- Read the by-now-filled-in expected types
+    mapM readExpectedType (body_ty : map snd pats_w_tys)       `thenM` \ tys ->
+    addErrCtxtM (sigPatCtxt tv_list ex_ids tys)                        $
 
        -- In case there are any polymorpic, overloaded binders in the pattern
        -- (which can happen in the case of rank-2 type signatures, or data constructors
@@ -353,7 +357,9 @@ tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req match_ty
 
        -- Deal with overloaded functions bound by the pattern
     tcSimplifyCheck doc tv_list ex_lie lie             `thenM` \ dict_binds ->
-    checkSigTyVarsWrt (tyVarsOfType match_ty) tv_list  `thenM_` 
+
+       -- Check for type variable escape
+    checkSigTyVarsWrt (tyVarsOfTypes tys) tv_list              `thenM_` 
 
     returnM (dict_binds `AndMonoBinds` inst_binds)
   where
@@ -370,25 +376,31 @@ tcCheckExistentialPat ex_tvs ex_ids ex_lie lie_req match_ty
 %************************************************************************
 
 \begin{code}
-tcDoStmts :: HsStmtContext Name -> [RenamedStmt] -> [Name] 
+tcDoStmts :: HsStmtContext Name 
+         -> [RenamedStmt] -> ReboundNames Name
          -> TcRhoType          -- To keep it simple, we don't have an "expected" type here
-         -> TcM (TcMonoBinds, [TcStmt], [Id])
+         -> TcM ([TcStmt], ReboundNames TcId)
 tcDoStmts PArrComp stmts method_names res_ty
-  = unifyPArrTy res_ty                           `thenM` \elt_ty ->
-    tcStmts PArrComp (mkPArrTy, elt_ty) stmts      `thenM` \ stmts' ->
-    returnM (EmptyMonoBinds, stmts', [{- unused -}])
+  = unifyPArrTy res_ty                                 `thenM` \elt_ty ->
+    tcComprehension PArrComp mkPArrTy elt_ty stmts     `thenM` \ stmts' ->
+    returnM (stmts', [{- unused -}])
 
 tcDoStmts ListComp stmts method_names res_ty
-  = unifyListTy res_ty                         `thenM` \ elt_ty ->
-    tcStmts ListComp (mkListTy, elt_ty) stmts  `thenM` \ stmts' ->
-    returnM (EmptyMonoBinds, stmts', [{- unused -}])
+  = unifyListTy res_ty                         `       thenM` \ elt_ty ->
+    tcComprehension ListComp mkListTy elt_ty stmts     `thenM` \ stmts' ->
+    returnM (stmts', [{- unused -}])
 
-tcDoStmts do_or_mdo_expr stmts method_names res_ty
+tcDoStmts do_or_mdo stmts method_names res_ty
   = newTyVarTy (mkArrowKind liftedTypeKind liftedTypeKind)     `thenM` \ m_ty ->
     newTyVarTy liftedTypeKind                                  `thenM` \ elt_ty ->
     unifyTauTy res_ty (mkAppTy m_ty elt_ty)                    `thenM_`
-
-    tcStmts do_or_mdo_expr (mkAppTy m_ty, elt_ty) stmts                `thenM` \ stmts' ->
+    let
+       ctxt = SC { sc_what = do_or_mdo,
+                   sc_rhs  = \ rhs rhs_elt_ty -> tcCheckRho rhs (mkAppTy m_ty rhs_elt_ty),
+                   sc_body = \ body -> tcCheckRho body res_ty,
+                   sc_ty   = res_ty }
+    in 
+    tcStmts ctxt stmts                                         `thenM` \ stmts' ->
 
        -- Build the then and zero methods in case we need them
        -- It's important that "then" and "return" appear just once in the final LIE,
@@ -397,24 +409,17 @@ tcDoStmts do_or_mdo_expr stmts method_names res_ty
        --      then = case d of (t,r) -> t
        --      then = then
        -- where the second "then" sees that it already exists in the "available" stuff.
-       --
-    mapAndUnzipM (tc_syn_name m_ty) 
-                (zipEqual "tcDoStmts" currentMonadNames method_names)  `thenM` \ (binds, ids) ->
-    returnM (andMonoBindList binds, stmts', ids)
+    mapM (tcSyntaxName DoOrigin m_ty) method_names               `thenM` \ methods ->
+
+    returnM (stmts', methods)
+
+tcComprehension do_or_lc mk_mty elt_ty stmts
+  = tcStmts ctxt stmts
   where
-    currentMonadNames = case do_or_mdo_expr of
-                         DoExpr  -> monadNames
-                         MDoExpr -> monadNames ++ [mfixName]
-    tc_syn_name :: TcType -> (Name,Name) -> TcM (TcMonoBinds, Id)
-    tc_syn_name m_ty (std_nm, usr_nm)
-       = tcSyntaxName DoOrigin m_ty std_nm usr_nm      `thenM` \ (expr, expr_ty) ->
-         case expr of
-           HsVar v -> returnM (EmptyMonoBinds, v)
-           other   -> newUnique                `thenM` \ uniq ->
-                      let
-                         id = mkSysLocal FSLIT("syn") uniq expr_ty
-                      in
-                      returnM (VarMonoBind id expr, id)
+    ctxt = SC { sc_what = do_or_lc,
+               sc_rhs  = \ rhs rhs_elt_ty -> tcCheckRho rhs (mk_mty rhs_elt_ty),
+               sc_body = \ body -> tcCheckRho body elt_ty,     -- Note: no mk_mty!
+               sc_ty   = mk_mty elt_ty }
 \end{code}
 
 
@@ -447,85 +452,106 @@ 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.
 
 \begin{code}
-tcStmts do_or_lc m_ty stmts
+tcStmts ctxt stmts
   = ASSERT( notNull stmts )
-    tcStmtsAndThen (:) do_or_lc m_ty stmts (returnM [])
-
+    tcStmtsAndThen (:) ctxt stmts (returnM [])
+
+data TcStmtCtxt 
+  = SC { sc_what :: HsStmtContext Name,                -- What kind of thing this is
+        sc_rhs  :: RenamedHsExpr -> TcType -> TcM TcExpr,      -- Type checker for RHS computations
+        sc_body :: RenamedHsExpr -> TcM TcExpr,                -- Type checker for return computation
+        sc_ty   :: TcType }                                    -- Return type; used *only* to check
+                                                               -- for escape in existential patterns
 tcStmtsAndThen
        :: (TcStmt -> thing -> thing)   -- Combiner
-       -> HsStmtContext Name
-        -> (TcType -> TcType, TcType)  -- m, the relationship type of pat and rhs in pat <- rhs
-                                       -- res_ty, the type of the entire comprehension
-                                       --         used at the end for the type of (return x)
-                                       --         or the final expression in do-notation
+       -> TcStmtCtxt
         -> [RenamedStmt]
        -> TcM thing
         -> TcM thing
 
        -- Base case
-tcStmtsAndThen combine do_or_lc m_ty [] do_next
-  = do_next
+tcStmtsAndThen combine ctxt [] thing_inside
+  = thing_inside
 
-tcStmtsAndThen combine do_or_lc m_ty (stmt:stmts) do_next
-  = tcStmtAndThen combine do_or_lc m_ty stmt
-       (tcStmtsAndThen combine do_or_lc m_ty stmts do_next)
+tcStmtsAndThen combine ctxt (stmt:stmts) thing_inside
+  = tcStmtAndThen  combine ctxt stmt  $
+    tcStmtsAndThen combine ctxt stmts $
+    thing_inside
 
        -- LetStmt
-tcStmtAndThen combine do_or_lc m_ty (LetStmt binds) thing_inside
+tcStmtAndThen combine ctxt (LetStmt binds) thing_inside
   = tcBindsAndThen             -- No error context, but a binding group is
        (glue_binds combine)    -- rather a large thing for an error context anyway
        binds
        thing_inside
 
-tcStmtAndThen combine do_or_lc m_ty@(m,elt_ty) stmt@(BindStmt pat exp src_loc) thing_inside
-  = addSrcLoc src_loc                                          $
-    addErrCtxt (stmtCtxt do_or_lc stmt)                                $
-    newTyVarTy liftedTypeKind                                  `thenM` \ pat_ty ->
-    tcCheckRho exp (m pat_ty)                                  `thenM` \ exp' ->
-    tcMatchPats [pat] (Check (mkFunTy pat_ty (m elt_ty)))      (\ _ ->
+       -- BindStmt
+tcStmtAndThen combine ctxt stmt@(BindStmt pat exp src_loc) thing_inside
+  = addSrcLoc src_loc                                  $
+    addErrCtxt (stmtCtxt ctxt stmt)                    $
+    newTyVarTy liftedTypeKind                          `thenM` \ pat_ty ->
+    sc_rhs ctxt exp pat_ty                             `thenM` \ exp' ->
+    tcMatchPats [(pat, Check pat_ty)] (Check (sc_ty ctxt)) (
        popErrCtxt thing_inside
     )                                                  `thenM` \ ([pat'], thing, dict_binds) ->
     returnM (combine (BindStmt pat' exp' src_loc)
                     (glue_binds combine dict_binds thing))
 
+       -- ExprStmt
+tcStmtAndThen combine ctxt stmt@(ExprStmt exp _ src_loc) thing_inside
+  = addSrcLoc src_loc          (
+       addErrCtxt (stmtCtxt ctxt stmt) $
+       if isDoExpr (sc_what ctxt)
+       then    -- do or mdo; the expression is a computation
+               newTyVarTy openTypeKind         `thenM` \ any_ty ->
+               sc_rhs ctxt exp any_ty          `thenM` \ exp' ->
+               returnM (ExprStmt exp' any_ty src_loc)
+       else    -- List comprehensions, pattern guards; expression is a boolean
+               tcCheckRho exp boolTy           `thenM` \ exp' ->
+               returnM (ExprStmt exp' boolTy src_loc)
+    )                                          `thenM` \ stmt' ->
+
+    thing_inside                               `thenM` \ thing ->
+    returnM (combine stmt' thing)
+
+
        -- ParStmt
-tcStmtAndThen combine do_or_lc m_ty (ParStmtOut bndr_stmts_s) thing_inside
+tcStmtAndThen combine ctxt (ParStmt bndr_stmts_s) thing_inside
   = loop bndr_stmts_s          `thenM` \ (pairs', thing) ->
-    returnM (combine (ParStmtOut pairs') thing)
+    returnM (combine (ParStmt pairs') thing)
   where
-    loop []
-      = thing_inside                   `thenM` \ thing ->
-       returnM ([], thing)
-
-    loop ((bndrs,stmts) : pairs)
-      = tcStmtsAndThen 
-               combine_par ListComp m_ty stmts
-                       -- Notice we pass on m_ty; the result type is used only
-                       -- to get escaping type variables for checkExistentialPat
-               (tcLookupLocalIds bndrs `thenM` \ bndrs' ->
-                loop pairs             `thenM` \ (pairs', thing) ->
-                returnM ([], (bndrs', pairs', thing))) `thenM` \ (stmts', (bndrs', pairs', thing)) ->
+    loop [] = thing_inside             `thenM` \ thing ->
+             returnM ([], thing)
 
-       returnM ((bndrs',stmts') : pairs', thing)
+    loop ((stmts, bndrs) : pairs)
+      = tcStmtsAndThen combine_par ctxt stmts $
+                       -- Notice we pass on ctxt; the result type is used only
+                       -- to get escaping type variables for checkExistentialPat
+       tcLookupLocalIds bndrs          `thenM` \ bndrs' ->
+       loop pairs                      `thenM` \ (pairs', thing) ->
+       returnM (([], bndrs') : pairs', thing)
 
-    combine_par stmt (stmts, thing) = (stmt:stmts, thing)
+    combine_par stmt ((stmts, bndrs) : pairs , thing) = ((stmt:stmts, bndrs) : pairs, thing)
 
        -- RecStmt
-tcStmtAndThen combine do_or_lc m_ty (RecStmt recNames stmts _) thing_inside
+tcStmtAndThen combine ctxt (RecStmt stmts laterNames recNames _) thing_inside
   = newTyVarTys (length recNames) liftedTypeKind               `thenM` \ recTys ->
     let
-       mono_ids = zipWith mkLocalId recNames recTys
+       rec_ids = zipWith mkLocalId recNames recTys
     in
-    tcExtendLocalValEnv mono_ids                       $
-    tcStmtsAndThen combine_rec do_or_lc m_ty stmts (
-       mappM tc_ret (recNames `zip` recTys)    `thenM` \ rets ->
-       returnM ([], rets)
-    )                                          `thenM` \ (stmts', rets) ->
-
-       -- NB: it's the mono_ids that scope over this part
+    tcExtendLocalValEnv rec_ids                        $
+    tcStmtsAndThen combine_rec ctxt stmts (
+       mappM tc_ret (recNames `zip` recTys)    `thenM` \ rec_rets ->
+       tcLookupLocalIds laterNames             `thenM` \ later_ids ->
+       returnM ([], (later_ids, rec_rets))
+    )                                          `thenM` \ (stmts', (later_ids, rec_rets)) ->
+
+    tcExtendLocalValEnv later_ids              $
+       -- NB:  The rec_ids for the recursive things 
+       --      already scope over this part
     thing_inside                               `thenM` \ thing ->
   
-    returnM (combine (RecStmt mono_ids stmts' rets) thing)
+    returnM (combine (RecStmt stmts' later_ids rec_ids rec_rets) thing)
   where 
     combine_rec stmt (stmts, thing) = (stmt:stmts, thing)
 
@@ -537,33 +563,10 @@ tcStmtAndThen combine do_or_lc m_ty (RecStmt recNames stmts _) thing_inside
          tcSubExp (Check mono_ty) (idType poly_id)     `thenM` \ co_fn ->
          returnM (co_fn <$> HsVar poly_id) 
 
-       -- ExprStmt
-tcStmtAndThen combine do_or_lc m_ty@(m, _) stmt@(ExprStmt exp _ locn) thing_inside
-  = addErrCtxt (stmtCtxt do_or_lc stmt) (
-       if isDoExpr do_or_lc then
-               newTyVarTy openTypeKind         `thenM` \ any_ty ->
-               tcCheckRho exp (m any_ty)       `thenM` \ exp' ->
-               returnM (ExprStmt exp' any_ty locn)
-       else
-               tcCheckRho exp boolTy           `thenM` \ exp' ->
-               returnM (ExprStmt exp' boolTy locn)
-    )                                          `thenM` \ stmt' ->
-
-    thing_inside                               `thenM` \ thing ->
-    returnM (combine stmt' thing)
-
-
        -- Result statements
-tcStmtAndThen combine do_or_lc m_ty@(m, res_elt_ty) stmt@(ResultStmt exp locn) thing_inside
-  = addErrCtxt (resCtxt do_or_lc stmt) (
-       if isDoExpr do_or_lc then
-               tcCheckRho exp (m res_elt_ty)
-       else
-               tcCheckRho exp res_elt_ty
-    )                                          `thenM` \ exp' ->
-
-    thing_inside                               `thenM` \ thing ->
-
+tcStmtAndThen combine ctxt stmt@(ResultStmt exp locn) thing_inside
+  = addErrCtxt (stmtCtxt ctxt stmt) (sc_body ctxt exp) `thenM` \ exp' ->
+    thing_inside                                       `thenM` \ thing ->
     returnM (combine (ResultStmt exp' locn) thing)
 
 
@@ -594,24 +597,32 @@ sameNoOfArgs matches = isSingleton (nub (map args_in_match matches))
 varyingArgsErr name matches
   = sep [ptext SLIT("Varying number of arguments for function"), quotes (ppr name)]
 
-matchCtxt ctxt  match  = hang (ptext SLIT("In") <+> pprMatchContext ctxt <> colon) 4 (pprMatch ctxt match)
-stmtCtxt do_or_lc stmt = hang (ptext SLIT("In") <+> pprStmtContext do_or_lc <> colon) 4 (ppr stmt)
-resCtxt  do_or_lc stmt = hang (ptext SLIT("In") <+> pprStmtResultContext do_or_lc <> colon) 4 (ppr stmt)
-
-sigPatCtxt bound_tvs bound_ids match_ty tidy_env 
-  = zonkTcType match_ty                `thenM` \ match_ty' ->
+matchCtxt ctxt  match  = hang (ptext SLIT("In") <+> pprMatchContext ctxt <> colon) 
+                             4 (pprMatch ctxt match)
+
+stmtCtxt ctxt stmt = hang (ptext SLIT("In") <+> pp_ctxt (sc_what ctxt) <> colon) 4 (ppr stmt)
+       where
+         pp_ctxt  = case stmt of
+                       ResultStmt _ _ -> pprStmtResultContext
+                       other          -> pprStmtContext
+                       
+sigPatCtxt bound_tvs bound_ids tys tidy_env 
+  =    -- tys is (body_ty : pat_tys)  
+    mapM zonkTcType tys                `thenM` \ tys' ->
     let
        (env1, tidy_tys) = tidyOpenTypes tidy_env (map idType show_ids)
-       (env2, tidy_mty) = tidyOpenType  env1     match_ty'
+       (env2, tidy_body_ty : tidy_pat_tys) = tidyOpenTypes env1 tys'
     in
     returnM (env1,
                 sep [ptext SLIT("When checking an existential match that binds"),
                      nest 4 (vcat (zipWith ppr_id show_ids tidy_tys)),
-                     ptext SLIT("and whose type is") <+> ppr tidy_mty])
+                     ptext SLIT("The pattern(s) have type(s):") <+> vcat (map ppr tidy_pat_tys),
+                     ptext SLIT("The body has type:") <+> ppr tidy_body_ty
+               ])
   where
     show_ids = filter is_interesting bound_ids
     is_interesting id = any (`elemVarSet` idFreeTyVars id) bound_tvs
 
-    ppr_id id ty     = ppr id <+> dcolon <+> ppr ty
+    ppr_id id ty = ppr id <+> dcolon <+> ppr ty
        -- Don't zonk the types so we get the separate, un-unified versions
 \end{code}
index b7743ae..c257251 100644 (file)
@@ -767,6 +767,6 @@ wrongThingErr expected thing name
     pp_thing (AGlobal (AnId   _))   = ptext SLIT("Identifier")
     pp_thing (AGlobal (ADataCon _)) = ptext SLIT("Data constructor")
     pp_thing (ATyVar _)          = ptext SLIT("Type variable")
-    pp_thing (ATcId _ _)         = ptext SLIT("Local identifier")
+    pp_thing (ATcId _ _ _)       = ptext SLIT("Local identifier")
     pp_thing (AThing _)          = ptext SLIT("Utterly bogus")
 \end{code}
index 63b7ac9..133db82 100644 (file)
@@ -271,8 +271,8 @@ tcPat tc_bndr pat@(NPatIn over_lit mb_neg) pat_ty
        Nothing  -> returnM pos_lit_expr        -- Positive literal
        Just neg ->     -- Negative literal
                        -- The 'negate' is re-mappable syntax
-                   tcSyntaxName origin pat_ty' negateName neg  `thenM` \ (neg_expr, _) ->
-                   returnM (HsApp neg_expr pos_lit_expr)
+           tcSyntaxName origin pat_ty' (negateName, HsVar neg) `thenM` \ (_, neg_expr) ->
+           returnM (HsApp neg_expr pos_lit_expr)
     )                                                          `thenM` \ lit_expr ->
 
     let
@@ -307,7 +307,7 @@ tcPat tc_bndr pat@(NPlusKPatIn name lit@(HsIntegral i _) minus_name) pat_ty
     newMethodFromName origin pat_ty' geName     `thenM` \ ge ->
 
        -- The '-' part is re-mappable syntax
-    tcSyntaxName origin pat_ty' minusName minus_name   `thenM` \ (minus_expr, _) ->
+    tcSyntaxName origin pat_ty' (minusName, HsVar minus_name)  `thenM` \ (_, minus_expr) ->
 
        -- The Report says that n+k patterns must be in Integral
        -- We may not want this when using re-mappable syntax, though (ToDo?)
index b6e94aa..bd65fc4 100644 (file)
@@ -6,11 +6,11 @@
 \begin{code}
 module TcRnDriver (
 #ifdef GHCI
-       mkGlobalContext, getModuleContents,
+       mkGlobalContext, getModuleContents, tcRnStmt, tcRnThing, tcRnExpr,
 #endif
        tcRnModule, checkOldIface, 
        importSupportingDecls, tcTopSrcDecls,
-       tcRnIface, tcRnExtCore, tcRnStmt, tcRnExpr, tcRnThing
+       tcRnIface, tcRnExtCore
     ) where
 
 #include "HsVersions.h"
@@ -34,7 +34,7 @@ import RdrHsSyn               ( RdrNameHsModule, RdrNameHsDecl, RdrNameStmt, RdrNameHsExpr,
 
 import PrelNames       ( iNTERACTIVE, ioTyConName, printName,
                          returnIOName, bindIOName, failIOName, thenIOName, runIOName, 
-                         dollarMainName, itName, mAIN_Name
+                         dollarMainName, itName, mAIN_Name, unsafeCoerceName
                        )
 import MkId            ( unsafeCoerceId )
 import RdrName         ( RdrName, getRdrName, mkRdrUnqual, 
@@ -47,14 +47,14 @@ import TcHsSyn              ( TypecheckedHsExpr, TypecheckedRuleDecl,
                          zonkTopExpr, zonkTopBndrs
                        )
 
-import TcExpr          ( tcInferRho )
+import TcExpr          ( tcInferRho, tcCheckRho )
 import TcRnMonad
 import TcMType         ( newTyVarTy, zonkTcType )
 import TcType          ( Type, liftedTypeKind, 
                          tyVarsOfType, tcFunResultTy, tidyTopType,
                          mkForAllTys, mkFunTys, mkTyConApp, tcSplitForAllTys
                        )
-import TcMatches       ( tcStmtsAndThen )
+import TcMatches       ( tcStmtsAndThen, TcStmtCtxt(..) )
 import Inst            ( showLIE )
 import TcBinds         ( tcTopBinds )
 import TcClassDcl      ( tcClassDecls2 )
@@ -260,6 +260,7 @@ hsCoreRules rules = [(id,rule) | IfaceRuleOut id rule <- rules]
 %************************************************************************
 
 \begin{code}
+#ifdef GHCI
 tcRnStmt :: HscEnv -> PersistentCompilerState
         -> InteractiveContext
         -> RdrNameStmt
@@ -381,33 +382,39 @@ tcUserStmt stmt = tc_stmts [stmt]
 
 ---------------------------
 tc_stmts stmts
- = do { io_ids <- mappM tcLookupId 
-                       [returnIOName, failIOName, bindIOName, thenIOName] ;
-       ioTyCon <- tcLookupTyCon ioTyConName ;
-       res_ty  <- newTyVarTy liftedTypeKind ;
+ = do { ioTyCon <- tcLookupTyCon ioTyConName ;
        let {
-           names      = collectStmtsBinders stmts ;
-           return_id  = head io_ids ;  -- Rather gruesome
+           ret_ty = mkListTy unitTy ;
+           names  = collectStmtsBinders stmts ;
+
+           stmt_ctxt = SC { sc_what = DoExpr, 
+                            sc_rhs  = check_rhs,
+                            sc_body = check_body,
+                            sc_ty   = ret_ty } ;
 
-           io_ty = (\ ty -> mkTyConApp ioTyCon [ty], res_ty) ;
+           check_rhs rhs rhs_ty = tcCheckRho rhs  (mkTyConApp ioTyCon [rhs_ty]) ;
+           check_body body      = tcCheckRho body (mkTyConApp ioTyCon [ret_ty]) ;
 
-               -- mk_return builds the expression
-               --      returnIO @ [()] [coerce () x, ..,  coerce () z]
-           mk_return ids = HsApp (TyApp (HsVar return_id) [mkListTy unitTy]) 
-                                 (ExplicitList unitTy (map mk_item ids)) ;
+               -- ret_expr is the expression
+               --      returnIO [coerce () x, ..,  coerce () z]
+           ret_stmt = ResultStmt ret_expr noSrcLoc ;
+           ret_expr = HsApp (HsVar returnIOName) 
+                            (ExplicitList placeHolderType (map mk_item names)) ;
+           mk_item name = HsApp (HsVar unsafeCoerceName) (HsVar name) ;
 
-           mk_item id = HsApp (TyApp (HsVar unsafeCoerceId) [idType id, unitTy])
-                              (HsVar id) } ;
+           all_stmts = stmts ++ [ret_stmt]
+        } ;
 
        -- OK, we're ready to typecheck the stmts
        traceTc (text "tcs 2") ;
        ((ids, tc_stmts), lie) <- 
-               getLIE $ tcStmtsAndThen combine DoExpr io_ty stmts $ 
+               getLIE                                  $ 
+               tcStmtsAndThen combine stmt_ctxt stmts  $ 
                do {
                    -- Look up the names right in the middle,
                    -- where they will all be in scope
                    ids <- mappM tcLookupId names ;
-                   return (ids, [ResultStmt (mk_return ids) noSrcLoc])
+                   return (ids, [])
                } ;
 
        -- Simplify the context right here, so that we fail
@@ -420,9 +427,11 @@ tc_stmts stmts
        const_binds <- tcSimplifyTop lie ;
 
        -- Build result expression and zonk it
+       io_ids <- mappM mk_rebound
+                       [returnIOName, failIOName, bindIOName, thenIOName] ;
        let { expr = mkHsLet const_binds $
                     HsDo DoExpr tc_stmts io_ids
-                         (mkTyConApp ioTyCon [mkListTy unitTy]) noSrcLoc } ;
+                         (mkTyConApp ioTyCon [ret_ty]) noSrcLoc } ;
        zonked_expr <- zonkTopExpr expr ;
        zonked_ids  <- zonkTopBndrs ids ;
 
@@ -430,6 +439,8 @@ tc_stmts stmts
        }
   where
     combine stmt (ids, stmts) = (ids, stmt:stmts)
+    mk_rebound n = do { id <- tcLookupId n; return (n, HsVar id) }
+       -- A bit hackoid
 \end{code}
 
 
@@ -523,6 +534,7 @@ initRnInteractive ictxt rn_thing
   = initRn CmdLineMode $
     setLocalRdrEnv (ic_rn_local_env ictxt) $
     rn_thing
+#endif
 \end{code}
 
 %************************************************************************
index 927f7e2..1177d67 100644 (file)
@@ -150,11 +150,12 @@ initTc  (HscEnv { hsc_mode   = ghci_mode,
                tcg_fords    = [] } ;
 
             lcl_env = TcLclEnv {
-               tcl_ctxt   = [],
-               tcl_level  = topStage,
-               tcl_env    = emptyNameEnv,
-               tcl_tyvars = tvs_var,
-               tcl_lie    = panic "initTc:LIE" } ;
+               tcl_ctxt       = [],
+               tcl_th_ctxt    = topStage,
+               tcl_arrow_ctxt = topArrowCtxt,
+               tcl_env        = emptyNameEnv,
+               tcl_tyvars     = tvs_var,
+               tcl_lie        = panic "initTc:LIE" } ;
                        -- LIE only valid inside a getLIE
             } ;
    
@@ -254,6 +255,7 @@ setEnvs :: (TcGblEnv, m) -> TcRn m a -> TcRn m a
 setEnvs (gbl_env, lcl_env) = updEnv (\ env -> env { env_gbl = gbl_env, env_lcl = lcl_env })
 \end{code}
 
+
 Command-line flags
 
 \begin{code}
@@ -683,7 +685,7 @@ ctxt_to_use ctxt | opt_PprStyle_Debug = ctxt
 
 %************************************************************************
 %*                                                                     *
-            Other stuff specific to type checker
+            Type constraints (the so-called LIE)
 %*                                                                     *
 %************************************************************************
 
@@ -718,14 +720,7 @@ extendLIEs insts
         writeMutVar lie_var (mkLIE insts `plusLIE` lie) }
 \end{code}
 
-
 \begin{code}
-getStage :: TcM Stage
-getStage = do { env <- getLclEnv; return (tcl_level env) }
-
-setStage :: Stage -> TcM a -> TcM a 
-setStage s = updLclEnv (\ env -> env { tcl_level = s })
-
 setLclTypeEnv :: TcLclEnv -> TcM a -> TcM a
 -- Set the local type envt, but do *not* disturb other fields,
 -- notably the lie_var
@@ -739,6 +734,47 @@ setLclTypeEnv lcl_env thing_inside
 
 %************************************************************************
 %*                                                                     *
+            Template Haskell context
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+getStage :: TcM ThStage
+getStage = do { env <- getLclEnv; return (tcl_th_ctxt env) }
+
+setStage :: ThStage -> TcM a -> TcM a 
+setStage s = updLclEnv (\ env -> env { tcl_th_ctxt = s })
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+            Arrow context
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+popArrowBinders :: TcM a -> TcM a      -- Move to the left of a (-<); see comments in TcRnTypes
+popArrowBinders 
+  = updLclEnv (\ env -> env { tcl_arrow_ctxt = pop (tcl_arrow_ctxt env)  })
+  where
+    pop (ArrCtxt {proc_level = curr_lvl, proc_banned = banned})
+       = ASSERT( not (curr_lvl `elem` banned) )
+         ArrCtxt {proc_level = curr_lvl, proc_banned = curr_lvl : banned}
+
+getBannedProcLevels :: TcM [ProcLevel]
+  = do { env <- getLclEnv; return (proc_banned (tcl_arrow_ctxt env)) }
+
+incProcLevel :: TcM a -> TcM a
+incProcLevel 
+  = updLclEnv (\ env -> env { tcl_arrow_ctxt = inc (tcl_arrow_ctxt env) })
+  where
+    inc ctxt = ctxt { proc_level = proc_level ctxt + 1 }
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
             Stuff for the renamer's local env
 %*                                                                     *
 %************************************************************************
index 50a5c55..c5620e7 100644 (file)
@@ -30,8 +30,11 @@ module TcRnTypes(
        TcTyThing(..),
 
        -- Template Haskell
-       Stage(..), topStage, topSpliceStage,
-       Level, impLevel, topLevel,
+       ThStage(..), topStage, topSpliceStage,
+       ThLevel, impLevel, topLevel,
+
+       -- Arrows
+       ArrowCtxt(..), topArrowCtxt, ProcLevel, topProcLevel, 
 
        -- Insts
        Inst(..), InstOrigin(..), InstLoc(..), pprInstLoc, instLocSrcLoc,
@@ -389,7 +392,8 @@ data TcLclEnv
   = TcLclEnv {
        tcl_ctxt :: ErrCtxt,    -- Error context
 
-       tcl_level  :: Stage,            -- Template Haskell context
+       tcl_th_ctxt    :: ThStage,      -- Template Haskell context
+       tcl_arrow_ctxt :: ArrowCtxt,    -- Arrow-notation context
 
        tcl_env    :: NameEnv TcTyThing,  -- The local type environment: Ids and TyVars
                                          -- defined in this module
@@ -403,20 +407,24 @@ data TcLclEnv
        tcl_lie :: TcRef LIE            -- Place to accumulate type constraints
     }
 
-type Level = Int
+---------------------------
+-- Template Haskell levels 
+---------------------------
+
+type ThLevel = Int     -- Always >= 0
 
-data Stage
+data ThStage
   = Comp                               -- Ordinary compiling, at level topLevel
-  | Splice Level                       -- Inside a splice
-  | Brack  Level                       -- Inside brackets; 
+  | Splice ThLevel                     -- Inside a splice
+  | Brack  ThLevel                     -- Inside brackets; 
           (TcRef [PendingSplice])      --   accumulate pending splices here
           (TcRef LIE)                  --   and type constraints here
-topStage, topSpliceStage :: Stage
+topStage, topSpliceStage :: ThStage
 topStage       = Comp
 topSpliceStage = Splice (topLevel - 1) -- Stage for the body of a top-level splice
 
 
-impLevel, topLevel :: Level
+impLevel, topLevel :: ThLevel
 topLevel = 1   -- Things defined at top level of this module
 impLevel = 0   -- Imported things; they can be used inside a top level splice
 --
@@ -425,11 +433,50 @@ impLevel = 0      -- Imported things; they can be used inside a top level splice
 --     g1 = $(map ...)         is OK
 --     g2 = $(f ...)           is not OK; because we havn't compiled f yet
 
+
+---------------------------
+-- Arrow-notation stages
+---------------------------
+
+-- In arrow notation, a variable bound by a proc (or enclosed let/kappa)
+-- is not in scope to the left of an arrow tail (-<).  For example
+--
+--     proc x -> (e1 -< e2)
+--
+-- Here, x is not in scope in e1, but it is in scope in e2.  This can get 
+-- a bit complicated:
+--
+--     let x = 3 in
+--     prox y -> (proc z -> e1) -< e2
+--
+-- Here, x and z are in scope in e1, but y is not.  Here's how we track this:
+--     a) Assign an "proc level" to each proc, being the number of
+--        lexically-enclosing procs + 1.  
+--     b) Assign to each local variable the proc-level of its lexically
+--        enclosing proc.
+--     c) Keep a list of out-of-scope procs.  When moving to the left of
+--        an arrow-tail, add the proc-level of the immediately enclosing
+--        proc to the list.
+--     d) When looking up a variable, complain if its proc-level is in
+--        the banned list
+
+type ProcLevel = Int   -- Always >= 0
+topProcLevel = 0       -- Not inside any proc
+
+data ArrowCtxt = ArrCtxt { proc_level :: ProcLevel,    -- Current level
+                          proc_banned :: [ProcLevel] } -- Out of scope proc-levels
+
+topArrowCtxt = ArrCtxt { proc_level = topProcLevel, proc_banned = [] }
+
+---------------------------
+-- TcTyThing
+---------------------------
+
 data TcTyThing
-  = AGlobal TyThing            -- Used only in the return type of a lookup
-  | ATcId   TcId Level                 -- Ids defined in this module; may not be fully zonked
-  | ATyVar  TyVar              -- Type variables
-  | AThing  TcKind             -- Used temporarily, during kind checking
+  = AGlobal TyThing                    -- Used only in the return type of a lookup
+  | ATcId   TcId ThLevel ProcLevel     -- Ids defined in this module; may not be fully zonked
+  | ATyVar  TyVar                      -- Type variables
+  | AThing  TcKind                     -- Used temporarily, during kind checking
 -- Here's an example of how the AThing guy is used
 -- Suppose we are checking (forall a. T a Int):
 --     1. We first bind (a -> AThink kv), where kv is a kind variable. 
@@ -438,10 +485,10 @@ data TcTyThing
 --     4. Now we know the kind for 'a', and we add (a -> ATyVar a::K) to the environment
 
 instance Outputable TcTyThing where    -- Debugging only
-   ppr (AGlobal g) = text "AGlobal" <+> ppr g
-   ppr (ATcId g l) = text "ATcId" <+> ppr g <+> ppr l
-   ppr (ATyVar t)  = text "ATyVar" <+> ppr t
-   ppr (AThing k)  = text "AThing" <+> ppr k
+   ppr (AGlobal g)     = text "AGlobal" <+> ppr g
+   ppr (ATcId g tl pl) = text "ATcId" <+> ppr g <+> ppr tl <+> ppr pl
+   ppr (ATyVar t)      = text "ATyVar" <+> ppr t
+   ppr (AThing k)      = text "AThing" <+> ppr k
 \end{code}
 
 \begin{code}
@@ -849,6 +896,7 @@ data InstOrigin
                                -- of a rank-2 typed function
 
   | DoOrigin                   -- The monad for a do expression
+  | ProcOrigin                 -- A proc expression
 
   | ClassDeclOrigin            -- Manufactured during a class decl
 
@@ -907,6 +955,8 @@ pprInstLoc (InstLoc orig locn ctxt)
        =  ptext SLIT("a function with an overloaded argument type")
     pp_orig (DoOrigin)
        =  ptext SLIT("a do statement")
+    pp_orig (ProcOrigin)
+       =  ptext SLIT("a proc expression")
     pp_orig (ClassDeclOrigin)
        =  ptext SLIT("a class declaration")
     pp_orig (InstanceSpecOrigin clas ty)
index dcf4863..d5323d8 100644 (file)
@@ -17,7 +17,7 @@ module TcUnify (
   -- Holes
   Expected(..), newHole, readExpectedType, 
   zapExpectedType, zapExpectedTo, zapExpectedBranches,
-  subFunTy,            unifyFunTy, 
+  subFunTys,           unifyFunTy, 
   zapToListTy,         unifyListTy, 
   zapToPArrTy,         unifyPArrTy, 
   zapToTupleTy, unifyTupleTy
@@ -35,7 +35,7 @@ import TypeRep                ( Type(..), SourceType(..), TyNote(..), openKindCon )
 import TcRnMonad         -- TcType, amongst others
 import TcType          ( TcKind, TcType, TcSigmaType, TcRhoType, TcTyVar, TcTauType,
                          TcTyVarSet, TcThetaType, TyVarDetails(SigTv),
-                         isTauTy, isSigmaTy, 
+                         isTauTy, isSigmaTy, mkFunTys,
                          tcSplitAppTy_maybe, tcSplitTyConApp_maybe, 
                          tcGetTyVar_maybe, tcGetTyVar, 
                          mkFunTy, tyVarsOfType, mkPhiTy,
@@ -128,33 +128,40 @@ creation of type variables.
   type variables, so we should create new ordinary type variables
 
 \begin{code}
-subFunTy :: Expected TcRhoType -- Fail if ty isn't a function type
-                               -- If it's a hole, make two holes, feed them to...
-        -> (Expected TcRhoType -> Expected TcRhoType -> TcM a) -- the thing inside
-        -> TcM a       -- and bind the function type to the hole
+subFunTys :: [pat]
+        -> Expected TcRhoType  -- Fail if ty isn't a function type
+        -> ([(pat, Expected TcRhoType)] -> Expected TcRhoType -> TcM a)
+        -> TcM a
 
-subFunTy (Infer hole) thing_inside
+subFunTys pats (Infer hole) thing_inside
   =    -- This is the interesting case
-    newHole                    `thenM` \ arg_hole ->
+    mapM new_pat_hole pats     `thenM` \ pats_w_holes ->
     newHole                    `thenM` \ res_hole ->
 
        -- Do the business
-    thing_inside (Infer arg_hole) (Infer res_hole)     `thenM` \ answer ->
+    thing_inside pats_w_holes (Infer res_hole) `thenM` \ answer ->
 
        -- Extract the answers
-    readMutVar arg_hole                `thenM` \ arg_ty ->
-    readMutVar res_hole                `thenM` \ res_ty ->
+    mapM read_pat_hole pats_w_holes    `thenM` \ arg_tys ->
+    readMutVar res_hole                        `thenM` \ res_ty ->
 
        -- Write the answer into the incoming hole
-    writeMutVar hole (mkFunTy arg_ty res_ty)   `thenM_` 
+    writeMutVar hole (mkFunTys arg_tys res_ty) `thenM_` 
 
        -- And return the answer
     returnM answer
+  where
+    new_pat_hole pat = newHole `thenM` \ hole -> return (pat, Infer hole)
+    read_pat_hole (pat, Infer hole) = readMutVar hole
 
-subFunTy (Check ty) thing_inside
-  = unifyFunTy ty      `thenM` \ (arg,res) ->
-    thing_inside (Check arg) (Check res)
-
+subFunTys pats (Check ty) thing_inside
+  = go pats ty         `thenM` \ (pats_w_tys, res_ty) ->
+    thing_inside pats_w_tys res_ty
+  where
+    go []         ty = return ([], Check ty)
+    go (pat:pats) ty = unifyFunTy ty   `thenM` \ (arg,res) ->
+                      go pats res      `thenM` \ (pats_w_tys, final_res) ->
+                      return ((pat, Check arg) : pats_w_tys, final_res)
                 
 unifyFunTy :: TcRhoType                        -- Fail if ty isn't a function type
           -> TcM (TcType, TcType)      -- otherwise return arg and result types