summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/deSugar/Coverage.lhs3
-rw-r--r--compiler/deSugar/DsArrows.lhs486
-rw-r--r--compiler/hsSyn/HsExpr.lhs13
-rw-r--r--compiler/hsSyn/HsUtils.lhs7
-rw-r--r--compiler/parser/Parser.y.pp4
-rw-r--r--compiler/parser/RdrHsSyn.lhs4
-rw-r--r--compiler/rename/RnExpr.lhs4
-rw-r--r--compiler/rename/RnTypes.lhs2
-rw-r--r--compiler/typecheck/TcArrows.lhs272
-rw-r--r--compiler/typecheck/TcHsSyn.lhs6
-rw-r--r--docs/users_guide/glasgow_exts.xml48
11 files changed, 461 insertions, 388 deletions
diff --git a/compiler/deSugar/Coverage.lhs b/compiler/deSugar/Coverage.lhs
index 45183ba3db..bdcf9c9f78 100644
--- a/compiler/deSugar/Coverage.lhs
+++ b/compiler/deSugar/Coverage.lhs
@@ -803,6 +803,9 @@ addTickHsCmd (HsCmdArrForm e fix cmdtop) =
(return fix)
(mapM (liftL (addTickHsCmdTop)) cmdtop)
+addTickHsCmd (HsCmdCast co cmd)
+ = liftM2 HsCmdCast (return co) (addTickHsCmd cmd)
+
-- Others should never happen in a command context.
--addTickHsCmd e = pprPanic "addTickHsCmd" (ppr e)
diff --git a/compiler/deSugar/DsArrows.lhs b/compiler/deSugar/DsArrows.lhs
index 76b279655d..b825acb836 100644
--- a/compiler/deSugar/DsArrows.lhs
+++ b/compiler/deSugar/DsArrows.lhs
@@ -37,6 +37,7 @@ import CoreSyn
import CoreFVs
import CoreUtils
import MkCore
+import DsBinds (dsHsWrapper)
import Name
import Var
@@ -124,6 +125,15 @@ mkFailExpr :: HsMatchContext Id -> Type -> DsM CoreExpr
mkFailExpr ctxt ty
= mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt)
+-- construct CoreExpr for \ (a :: a_ty, b :: b_ty) -> a
+mkFstExpr :: Type -> Type -> DsM CoreExpr
+mkFstExpr a_ty b_ty = do
+ a_var <- newSysLocalDs a_ty
+ b_var <- newSysLocalDs b_ty
+ pair_var <- newSysLocalDs (mkCorePairTy a_ty b_ty)
+ return (Lam pair_var
+ (coreCasePair pair_var a_var b_var (Var a_var)))
+
-- construct CoreExpr for \ (a :: a_ty, b :: b_ty) -> b
mkSndExpr :: Type -> Type -> DsM CoreExpr
mkSndExpr a_ty b_ty = do
@@ -158,91 +168,108 @@ mkCorePairTy t1 t2 = mkBoxedTupleTy [t1, t2]
mkCorePairExpr :: CoreExpr -> CoreExpr -> CoreExpr
mkCorePairExpr e1 e2 = mkCoreTup [e1, e2]
+
+mkCoreUnitExpr :: CoreExpr
+mkCoreUnitExpr = mkCoreTup []
\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 environment in turn. In general, the input has the form
+(unless it's too big), and a stack, which is a right-nested pair.
+In general, the input has the form
- (...((x1,...,xn),s1),...sk)
+ ((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 (mkBigCoreVarTupTy ids) stack_tys
+envStackType :: [Id] -> Type -> Type
+envStackType ids stack_ty = mkCorePairTy (mkBigCoreVarTupTy ids) stack_ty
+
+-- splitTypeAt n (t1,... (tn,t)...) = ([t1, ..., tn], t)
+splitTypeAt :: Int -> Type -> ([Type], Type)
+splitTypeAt n ty
+ | n == 0 = ([], ty)
+ | otherwise = case tcTyConAppArgs ty of
+ [t, ty'] -> let (ts, ty_r) = splitTypeAt (n-1) ty' in (t:ts, ty_r)
+ _ -> pprPanic "splitTypeAt" (ppr ty)
----------------------------------------------
-- buildEnvStack
--
--- (...((x1,...,xn),s1),...sk)
+-- ((x1,...,xn),stk)
-buildEnvStack :: [Id] -> [Id] -> CoreExpr
-buildEnvStack env_ids stack_ids
- = foldl mkCorePairExpr (mkBigCoreVarTup env_ids) (map Var stack_ids)
+buildEnvStack :: [Id] -> Id -> CoreExpr
+buildEnvStack env_ids stack_id
+ = mkCorePairExpr (mkBigCoreVarTup env_ids) (Var stack_id)
----------------------------------------------
-- matchEnvStack
--
--- \ (...((x1,...,xn),s1),...sk) -> e
+-- \ ((x1,...,xn),stk) -> body
-- =>
--- \ zk ->
--- case zk of (zk-1,sk) ->
--- ...
--- case z1 of (z0,s1) ->
--- case z0 of (x1,...,xn) ->
--- e
+-- \ pair ->
+-- case pair of (tup,stk) ->
+-- case tup of (x1,...,xn) ->
+-- body
matchEnvStack :: [Id] -- x1..xn
- -> [Id] -- s1..sk
+ -> Id -- stk
-> CoreExpr -- e
-> DsM CoreExpr
-matchEnvStack env_ids stack_ids body = do
+matchEnvStack env_ids stack_id body = do
uniqs <- newUniqueSupply
tup_var <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
- matchVarStack tup_var stack_ids
- (coreCaseTuple uniqs tup_var env_ids body)
+ let match_env = coreCaseTuple uniqs tup_var env_ids body
+ pair_id <- newSysLocalDs (mkCorePairTy (idType tup_var) (idType stack_id))
+ return (Lam pair_id (coreCasePair pair_id tup_var stack_id match_env))
+----------------------------------------------
+-- matchEnv
+--
+-- \ (x1,...,xn) -> body
+-- =>
+-- \ tup ->
+-- case tup of (x1,...,xn) ->
+-- body
+
+matchEnv :: [Id] -- x1..xn
+ -> CoreExpr -- e
+ -> DsM CoreExpr
+matchEnv env_ids body = do
+ uniqs <- newUniqueSupply
+ tup_id <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
+ return (Lam tup_id (coreCaseTuple uniqs tup_id env_ids body))
----------------------------------------------
--- matchVarStack
+-- matchVarStack
--
--- \ (...(z0,s1),...sk) -> e
+-- case (x1, ...(xn, s)...) -> e
-- =>
--- \ zk ->
--- case zk of (zk-1,sk) ->
--- ...
--- case z1 of (z0,s1) ->
+-- case z0 of (x1,z1) ->
+-- case zn-1 of (xn,s) ->
-- e
-
-matchVarStack :: Id -- z0
- -> [Id] -- s1..sk
- -> CoreExpr -- e
- -> DsM CoreExpr
-matchVarStack env_id [] body
- = return (Lam env_id body)
-matchVarStack env_id (stack_id:stack_ids) body = do
- pair_id <- newSysLocalDs (mkCorePairTy (idType env_id) (idType stack_id))
- matchVarStack pair_id stack_ids
- (coreCasePair pair_id env_id stack_id body)
+matchVarStack :: [Id] -> Id -> CoreExpr -> DsM (Id, CoreExpr)
+matchVarStack [] stack_id body = return (stack_id, body)
+matchVarStack (param_id:param_ids) stack_id body = do
+ (tail_id, tail_code) <- matchVarStack param_ids stack_id body
+ pair_id <- newSysLocalDs (mkCorePairTy (idType param_id) (idType tail_id))
+ return (pair_id, coreCasePair pair_id param_id tail_id tail_code)
\end{code}
\begin{code}
-mkHsEnvStackExpr :: [Id] -> [Id] -> LHsExpr Id
-mkHsEnvStackExpr env_ids stack_ids
- = foldl (\a b -> mkLHsTupleExpr [a,b])
- (mkLHsVarTuple env_ids)
- (map nlHsVar stack_ids)
+mkHsEnvStackExpr :: [Id] -> Id -> LHsExpr Id
+mkHsEnvStackExpr env_ids stack_id
+ = mkLHsTupleExpr [mkLHsVarTuple env_ids, nlHsVar stack_id]
\end{code}
Translation of arrow abstraction
\begin{code}
--- A | xs |- c :: [] t' ---> c'
--- --------------------------
--- A |- proc p -> c :: a t t' ---> premap (\ p -> (xs)) c'
+-- D; xs |-a c : () --> t' ---> c'
+-- --------------------------
+-- D |- proc p -> c :: a t t' ---> premap (\ p -> ((xs),())) c'
--
-- where (xs) is the tuple of variables bound by p
@@ -250,35 +277,40 @@ dsProcExpr
:: LPat Id
-> LHsCmdTop Id
-> DsM CoreExpr
-dsProcExpr pat (L _ (HsCmdTop cmd [] cmd_ty ids)) = do
+dsProcExpr pat (L _ (HsCmdTop cmd _unitTy cmd_ty ids)) = do
(meth_binds, meth_ids) <- mkCmdEnv ids
let locals = mkVarSet (collectPatBinders pat)
- (core_cmd, _free_vars, env_ids) <- dsfixCmd meth_ids locals [] cmd_ty cmd
+ (core_cmd, _free_vars, env_ids) <- dsfixCmd meth_ids locals unitTy cmd_ty cmd
let env_ty = mkBigCoreVarTupTy env_ids
- fail_expr <- mkFailExpr ProcExpr env_ty
+ let env_stk_ty = mkCorePairTy env_ty unitTy
+ let env_stk_expr = mkCorePairExpr (mkBigCoreVarTup env_ids) mkCoreUnitExpr
+ fail_expr <- mkFailExpr ProcExpr env_stk_ty
var <- selectSimpleMatchVarL pat
- match_code <- matchSimply (Var var) ProcExpr pat (mkBigCoreVarTup env_ids) fail_expr
+ match_code <- matchSimply (Var var) ProcExpr pat env_stk_expr fail_expr
let pat_ty = hsLPatType pat
- proc_code = do_premap meth_ids pat_ty env_ty cmd_ty
+ proc_code = do_premap meth_ids pat_ty env_stk_ty cmd_ty
(Lam var match_code)
core_cmd
return (mkLets meth_binds proc_code)
-dsProcExpr _ c = pprPanic "dsProcExpr" (ppr c)
\end{code}
-Translation of command judgements of the form
+Translation of a command judgement of the form
+
+ D; xs |-a c : stk --> t
+
+to an expression e such that
- A | xs |- c :: [ts] t
+ D |- e :: a (xs, stk) t
\begin{code}
-dsLCmd :: DsCmdEnv -> IdSet -> [Type] -> Type -> LHsCmd Id -> [Id]
+dsLCmd :: DsCmdEnv -> IdSet -> Type -> Type -> LHsCmd Id -> [Id]
-> DsM (CoreExpr, IdSet)
-dsLCmd ids local_vars stack res_ty cmd env_ids
- = dsCmd ids local_vars stack res_ty (unLoc cmd) env_ids
+dsLCmd ids local_vars stk_ty res_ty cmd env_ids
+ = dsCmd ids local_vars stk_ty res_ty (unLoc cmd) env_ids
dsCmd :: DsCmdEnv -- arrow combinators
-> IdSet -- set of local vars available to this command
- -> [Type] -- type of the stack
+ -> Type -- type of the stack (right-nested tuple)
-> Type -- return type of the command
-> HsCmd Id -- command to desugar
-> [Id] -- list of vars in the input to this command
@@ -287,14 +319,14 @@ dsCmd :: DsCmdEnv -- arrow combinators
-> DsM (CoreExpr, -- desugared expression
IdSet) -- subset of local vars that occur free
--- A |- f :: a (t*ts) t'
--- A, xs |- arg :: t
--- -----------------------------
--- A | xs |- f -< arg :: [ts] t'
+-- D |- fun :: a t1 t2
+-- D, xs |- arg :: t1
+-- -----------------------------
+-- D; xs |-a fun -< arg : stk --> t2
--
--- ---> premap (\ ((xs)*ts) -> (arg*ts)) f
+-- ---> premap (\ ((xs), _stk) -> arg) fun
-dsCmd ids local_vars stack res_ty
+dsCmd ids local_vars stack_ty res_ty
(HsCmdArrApp arrow arg arrow_ty HsFirstOrderApp _)
env_ids = do
let
@@ -302,25 +334,24 @@ dsCmd ids local_vars stack res_ty
(_a_ty, arg_ty) = tcSplitAppTy a_arg_ty
core_arrow <- dsLExpr arrow
core_arg <- dsLExpr arg
- stack_ids <- mapM newSysLocalDs stack
- core_make_arg <- matchEnvStack env_ids stack_ids
- (foldl mkCorePairExpr core_arg (map Var stack_ids))
+ stack_id <- newSysLocalDs stack_ty
+ core_make_arg <- matchEnvStack env_ids stack_id core_arg
return (do_premap ids
- (envStackType env_ids stack)
+ (envStackType env_ids stack_ty)
arg_ty
res_ty
core_make_arg
core_arrow,
exprFreeIds core_arg `intersectVarSet` local_vars)
--- A, xs |- f :: a (t*ts) t'
--- A, xs |- arg :: t
--- ------------------------------
--- A | xs |- f -<< arg :: [ts] t'
+-- D, xs |- fun :: a t1 t2
+-- D, xs |- arg :: t1
+-- ------------------------------
+-- D; xs |-a fun -<< arg : stk --> t2
--
--- ---> premap (\ ((xs)*ts) -> (f,(arg*ts))) app
+-- ---> premap (\ ((xs), _stk) -> (fun, arg)) app
-dsCmd ids local_vars stack res_ty
+dsCmd ids local_vars stack_ty res_ty
(HsCmdArrApp arrow arg arrow_ty HsHigherOrderApp _)
env_ids = do
let
@@ -329,13 +360,12 @@ dsCmd ids local_vars stack res_ty
core_arrow <- dsLExpr arrow
core_arg <- dsLExpr arg
- stack_ids <- mapM newSysLocalDs stack
- core_make_pair <- matchEnvStack env_ids stack_ids
- (mkCorePairExpr core_arrow
- (foldl mkCorePairExpr core_arg (map Var stack_ids)))
-
+ stack_id <- newSysLocalDs stack_ty
+ core_make_pair <- matchEnvStack env_ids stack_id
+ (mkCorePairExpr core_arrow core_arg)
+
return (do_premap ids
- (envStackType env_ids stack)
+ (envStackType env_ids stack_ty)
(mkCorePairTy arrow_ty arg_ty)
res_ty
core_make_pair
@@ -343,90 +373,94 @@ dsCmd ids local_vars stack res_ty
(exprFreeIds core_arrow `unionVarSet` exprFreeIds core_arg)
`intersectVarSet` local_vars)
--- A | ys |- c :: [t:ts] t'
--- A, xs |- e :: t
--- ------------------------
--- A | xs |- c e :: [ts] t'
+-- D; ys |-a cmd : (t,stk) --> t'
+-- D, xs |- exp :: t
+-- ------------------------
+-- D; xs |-a cmd exp : stk --> t'
--
--- ---> premap (\ ((xs)*ts) -> let z = e in (((ys),z)*ts)) c
+-- ---> premap (\ ((xs),stk) -> ((ys),(e,stk))) cmd
-dsCmd ids local_vars stack res_ty (HsCmdApp cmd arg) env_ids = do
+dsCmd ids local_vars stack_ty res_ty (HsCmdApp cmd arg) env_ids = do
core_arg <- dsLExpr arg
let
arg_ty = exprType core_arg
- stack' = arg_ty:stack
+ stack_ty' = mkCorePairTy arg_ty stack_ty
(core_cmd, free_vars, env_ids')
- <- dsfixCmd ids local_vars stack' res_ty cmd
- stack_ids <- mapM newSysLocalDs stack
+ <- dsfixCmd ids local_vars stack_ty' res_ty cmd
+ stack_id <- newSysLocalDs stack_ty
arg_id <- newSysLocalDs arg_ty
-- push the argument expression onto the stack
let
+ stack' = mkCorePairExpr (Var arg_id) (Var stack_id)
core_body = bindNonRec arg_id core_arg
- (buildEnvStack env_ids' (arg_id:stack_ids))
+ (mkCorePairExpr (mkBigCoreVarTup env_ids') stack')
+
-- match the environment and stack against the input
- core_map <- matchEnvStack env_ids stack_ids core_body
+ core_map <- matchEnvStack env_ids stack_id core_body
return (do_premap ids
- (envStackType env_ids stack)
- (envStackType env_ids' stack')
+ (envStackType env_ids stack_ty)
+ (envStackType env_ids' stack_ty')
res_ty
core_map
core_cmd,
free_vars `unionVarSet`
(exprFreeIds core_arg `intersectVarSet` local_vars))
--- A | ys |- c :: [ts] t'
--- -----------------------------------------------
--- A | xs |- \ p1 ... pk -> c :: [t1:...:tk:ts] t'
+-- D; ys |-a cmd : stk t'
+-- -----------------------------------------------
+-- D; xs |-a \ p1 ... pk -> cmd : (t1,...(tk,stk)...) t'
--
--- ---> premap (\ ((((xs), p1), ... pk)*ts) -> ((ys)*ts)) c
+-- ---> premap (\ ((xs), (p1, ... (pk,stk)...)) -> ((ys),stk)) cmd
-dsCmd ids local_vars stack res_ty
+dsCmd ids local_vars stack_ty res_ty
(HsCmdLam (MG { mg_alts = [L _ (Match pats _ (GRHSs [L _ (GRHS [] body)] _ ))] }))
env_ids = do
let
pat_vars = mkVarSet (collectPatsBinders pats)
local_vars' = pat_vars `unionVarSet` local_vars
- stack' = drop (length pats) stack
- (core_body, free_vars, env_ids') <- dsfixCmd ids local_vars' stack' res_ty body
- stack_ids <- mapM newSysLocalDs stack
+ (pat_tys, stack_ty') = splitTypeAt (length pats) stack_ty
+ (core_body, free_vars, env_ids') <- dsfixCmd ids local_vars' stack_ty' res_ty body
+ param_ids <- mapM newSysLocalDs pat_tys
+ stack_id' <- newSysLocalDs stack_ty'
-- 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'
+ core_expr = buildEnvStack env_ids' stack_id'
+ in_ty = envStackType env_ids stack_ty
+ in_ty' = envStackType env_ids' stack_ty'
fail_expr <- mkFailExpr LambdaExpr in_ty'
- -- match the patterns against the top of the old stack
- match_code <- matchSimplys (map Var actual_ids) LambdaExpr pats core_expr fail_expr
+ -- match the patterns against the parameters
+ match_code <- matchSimplys (map Var param_ids) LambdaExpr pats core_expr fail_expr
+ -- match the parameters against the top of the old stack
+ (stack_id, param_code) <- matchVarStack param_ids stack_id' match_code
-- match the old environment and stack against the input
- select_code <- matchEnvStack env_ids stack_ids match_code
+ select_code <- matchEnvStack env_ids stack_id param_code
return (do_premap ids in_ty in_ty' res_ty select_code core_body,
free_vars `minusVarSet` pat_vars)
-dsCmd ids local_vars stack res_ty (HsCmdPar cmd) env_ids
- = dsLCmd ids local_vars stack res_ty cmd env_ids
+dsCmd ids local_vars stack_ty res_ty (HsCmdPar cmd) env_ids
+ = dsLCmd ids local_vars stack_ty res_ty cmd env_ids
--- A, xs |- e :: Bool
--- A | xs1 |- c1 :: [ts] t
--- A | xs2 |- c2 :: [ts] t
--- ----------------------------------------
--- A | xs |- if e then c1 else c2 :: [ts] t
+-- D, xs |- e :: Bool
+-- D; xs1 |-a c1 : stk --> t
+-- D; xs2 |-a c2 : stk --> t
+-- ----------------------------------------
+-- D; xs |-a if e then c1 else c2 : stk --> t
--
--- ---> premap (\ ((xs)*ts) ->
--- if e then Left ((xs1)*ts) else Right ((xs2)*ts))
+-- ---> premap (\ ((xs),stk) ->
+-- if e then Left ((xs1),stk) else Right ((xs2),stk))
-- (c1 ||| c2)
-dsCmd ids local_vars stack res_ty (HsCmdIf mb_fun cond then_cmd else_cmd)
+dsCmd ids local_vars stack_ty res_ty (HsCmdIf mb_fun cond then_cmd else_cmd)
env_ids = do
core_cond <- dsLExpr cond
- (core_then, fvs_then, then_ids) <- dsfixCmd ids local_vars stack res_ty then_cmd
- (core_else, fvs_else, else_ids) <- dsfixCmd ids local_vars stack res_ty else_cmd
- stack_ids <- mapM newSysLocalDs stack
+ (core_then, fvs_then, then_ids) <- dsfixCmd ids local_vars stack_ty res_ty then_cmd
+ (core_else, fvs_else, else_ids) <- dsfixCmd ids local_vars stack_ty res_ty else_cmd
+ stack_id <- newSysLocalDs stack_ty
either_con <- dsLookupTyCon eitherTyConName
left_con <- dsLookupDataCon leftDataConName
right_con <- dsLookupDataCon rightDataConName
@@ -434,20 +468,20 @@ dsCmd ids local_vars stack res_ty (HsCmdIf mb_fun cond then_cmd else_cmd)
let mk_left_expr ty1 ty2 e = mkConApp left_con [Type ty1, Type ty2, e]
mk_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
+ in_ty = envStackType env_ids stack_ty
+ then_ty = envStackType then_ids stack_ty
+ else_ty = envStackType else_ids stack_ty
sum_ty = mkTyConApp either_con [then_ty, else_ty]
fvs_cond = exprFreeIds core_cond `intersectVarSet` local_vars
- core_left = mk_left_expr then_ty else_ty (buildEnvStack then_ids stack_ids)
- core_right = mk_right_expr then_ty else_ty (buildEnvStack else_ids stack_ids)
+ core_left = mk_left_expr then_ty else_ty (buildEnvStack then_ids stack_id)
+ core_right = mk_right_expr then_ty else_ty (buildEnvStack else_ids stack_id)
core_if <- case mb_fun of
Just fun -> do { core_fun <- dsExpr fun
- ; matchEnvStack env_ids stack_ids $
+ ; matchEnvStack env_ids stack_id $
mkCoreApps core_fun [core_cond, core_left, core_right] }
- Nothing -> matchEnvStack env_ids stack_ids $
+ Nothing -> matchEnvStack env_ids stack_id $
mkIfThenElse core_cond core_left core_right
return (do_premap ids in_ty sum_ty res_ty
@@ -482,10 +516,10 @@ case bodies, containing the following fields:
bodies with |||.
\begin{code}
-dsCmd ids local_vars stack res_ty
+dsCmd ids local_vars stack_ty res_ty
(HsCmdCase exp (MG { mg_alts = matches, mg_arg_tys = arg_tys }))
env_ids = do
- stack_ids <- mapM newSysLocalDs stack
+ stack_id <- newSysLocalDs stack_ty
-- Extract and desugar the leaf commands in the case, building tuple
-- expressions that will (after tagging) replace these leaves
@@ -494,9 +528,9 @@ dsCmd ids local_vars stack res_ty
leaves = concatMap leavesMatch matches
make_branch (leaf, bound_vars) = do
(core_leaf, _fvs, leaf_ids) <-
- dsfixCmd ids (bound_vars `unionVarSet` local_vars) stack res_ty leaf
- return ([mkHsEnvStackExpr leaf_ids stack_ids],
- envStackType leaf_ids stack,
+ dsfixCmd ids (bound_vars `unionVarSet` local_vars) stack_ty res_ty leaf
+ return ([mkHsEnvStackExpr leaf_ids stack_id],
+ envStackType leaf_ids stack_ty,
core_leaf)
branches <- mapM make_branch leaves
@@ -524,66 +558,82 @@ dsCmd ids local_vars stack res_ty
-- yielding a HsExpr Id we can feed to dsExpr.
(_, matches') = mapAccumL (replaceLeavesMatch res_ty) leaves' matches
- in_ty = envStackType env_ids stack
+ in_ty = envStackType env_ids stack_ty
core_body <- dsExpr (HsCase exp (MG { mg_alts = matches', mg_arg_tys = arg_tys
, mg_res_ty = sum_ty }))
-- Note that we replace the HsCase result type by sum_ty,
-- which is the type of matches'
- core_matches <- matchEnvStack env_ids stack_ids core_body
+ core_matches <- matchEnvStack env_ids stack_id core_body
return (do_premap ids in_ty sum_ty res_ty core_matches core_choices,
exprFreeIds core_body `intersectVarSet` local_vars)
--- A | ys |- c :: [ts] t
--- ----------------------------------
--- A | xs |- let binds in c :: [ts] t
+-- D; ys |-a cmd : stk --> t
+-- ----------------------------------
+-- D; xs |-a let binds in cmd : stk --> t
--
--- ---> premap (\ ((xs)*ts) -> let binds in ((ys)*ts)) c
+-- ---> premap (\ ((xs),stk) -> let binds in ((ys),stk)) c
-dsCmd ids local_vars stack res_ty (HsCmdLet binds body) env_ids = do
+dsCmd ids local_vars stack_ty res_ty (HsCmdLet binds body) env_ids = do
let
defined_vars = mkVarSet (collectLocalBinders binds)
local_vars' = defined_vars `unionVarSet` local_vars
- (core_body, _free_vars, env_ids') <- dsfixCmd ids local_vars' stack res_ty body
- stack_ids <- mapM newSysLocalDs stack
+ (core_body, _free_vars, env_ids') <- dsfixCmd ids local_vars' stack_ty res_ty body
+ stack_id <- newSysLocalDs stack_ty
-- build a new environment, plus the stack, using the let bindings
- core_binds <- dsLocalBinds binds (buildEnvStack env_ids' stack_ids)
+ core_binds <- dsLocalBinds binds (buildEnvStack env_ids' stack_id)
-- match the old environment and stack against the input
- core_map <- matchEnvStack env_ids stack_ids core_binds
+ core_map <- matchEnvStack env_ids stack_id core_binds
return (do_premap ids
- (envStackType env_ids stack)
- (envStackType env_ids' stack)
+ (envStackType env_ids stack_ty)
+ (envStackType env_ids' stack_ty)
res_ty
core_map
core_body,
exprFreeIds core_binds `intersectVarSet` local_vars)
-dsCmd ids local_vars [] res_ty (HsCmdDo stmts _) env_ids
- = dsCmdDo ids local_vars res_ty stmts env_ids
-
--- 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
+-- D; xs |-a ss : t
+-- ----------------------------------
+-- D; xs |-a do { ss } : () --> t
+--
+-- ---> premap (\ (env,stk) -> env) c
-dsCmd _ids local_vars _stack _res_ty (HsCmdArrForm op _ args) env_ids = do
+dsCmd ids local_vars stack_ty res_ty (HsCmdDo stmts _) env_ids = do
+ (core_stmts, env_ids') <- dsCmdDo ids local_vars res_ty stmts env_ids
+ let env_ty = mkBigCoreVarTupTy env_ids
+ core_fst <- mkFstExpr env_ty stack_ty
+ return (do_premap ids
+ (mkCorePairTy env_ty stack_ty)
+ env_ty
+ res_ty
+ core_fst
+ core_stmts,
+ env_ids')
+
+-- D |- e :: forall e. a1 (e,stk1) t1 -> ... an (e,stkn) tn -> a (e,stk) t
+-- D; xs |-a ci :: stki --> ti
+-- -----------------------------------
+-- D; xs |-a (|e c1 ... cn|) :: stk --> t ---> e [t_xs] c1 ... cn
+
+dsCmd _ids local_vars _stack_ty _res_ty (HsCmdArrForm op _ args) env_ids = do
let env_ty = mkBigCoreVarTupTy env_ids
core_op <- dsLExpr op
(core_args, fv_sets) <- mapAndUnzipM (dsTrimCmdArg local_vars env_ids) args
return (mkApps (App core_op (Type env_ty)) core_args,
unionVarSets fv_sets)
---dsCmd ids local_vars stack res_ty (HsTick tickish expr) env_ids = do
--- (expr1,id_set) <- dsLCmd ids local_vars stack res_ty expr env_ids
--- return (Tick tickish expr1, id_set)
+dsCmd ids local_vars stack_ty res_ty (HsCmdCast coercion cmd) env_ids = do
+ (core_cmd, env_ids') <- dsCmd ids local_vars stack_ty res_ty cmd env_ids
+ wrapped_cmd <- dsHsWrapper (WpCast coercion) core_cmd
+ return (wrapped_cmd, env_ids')
dsCmd _ _ _ _ _ c = pprPanic "dsCmd" (ppr c)
--- A | ys |- c :: [ts] t (ys <= xs)
--- ---------------------
--- A | xs |- c :: [ts] t ---> premap_ts (\ (xs) -> (ys)) c
+-- D; ys |-a c : stk --> t (ys <= xs)
+-- ---------------------
+-- D; xs |-a c : stk --> t ---> premap (\ ((xs),stk) -> ((ys),stk)) c
dsTrimCmdArg
:: IdSet -- set of local vars available to this command
@@ -591,32 +641,32 @@ dsTrimCmdArg
-> LHsCmdTop Id -- command argument to desugar
-> DsM (CoreExpr, -- desugared expression
IdSet) -- subset of local vars that occur free
-dsTrimCmdArg local_vars env_ids (L _ (HsCmdTop cmd stack cmd_ty ids)) = do
+dsTrimCmdArg local_vars env_ids (L _ (HsCmdTop cmd stack_ty cmd_ty ids)) = do
(meth_binds, meth_ids) <- mkCmdEnv ids
- (core_cmd, free_vars, env_ids') <- dsfixCmd meth_ids local_vars stack cmd_ty cmd
- stack_ids <- mapM newSysLocalDs stack
- trim_code <- matchEnvStack env_ids stack_ids (buildEnvStack env_ids' stack_ids)
+ (core_cmd, free_vars, env_ids') <- dsfixCmd meth_ids local_vars stack_ty cmd_ty cmd
+ stack_id <- newSysLocalDs stack_ty
+ trim_code <- matchEnvStack env_ids stack_id (buildEnvStack env_ids' stack_id)
let
- in_ty = envStackType env_ids stack
- in_ty' = envStackType env_ids' stack
+ in_ty = envStackType env_ids stack_ty
+ in_ty' = envStackType env_ids' stack_ty
arg_code = if env_ids' == env_ids then core_cmd else
do_premap meth_ids in_ty in_ty' cmd_ty trim_code core_cmd
return (mkLets meth_binds 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))
+-- Given D; xs |-a c : stk --> t, builds c with xs fed back.
+-- Typically needs to be prefixed with arr (\(p, stk) -> ((xs),stk))
dsfixCmd
:: DsCmdEnv -- arrow combinators
-> IdSet -- set of local vars available to this command
- -> [Type] -- type of the stack
+ -> Type -- type of the stack (right-nested tuple)
-> Type -- return type of the command
-> LHsCmd Id -- command to desugar
-> DsM (CoreExpr, -- desugared expression
IdSet, -- subset of local vars that occur free
[Id]) -- the same local vars as a list, fed back
-dsfixCmd ids local_vars stack cmd_ty cmd
- = trimInput (dsLCmd ids local_vars stack cmd_ty cmd)
+dsfixCmd ids local_vars stk_ty cmd_ty cmd
+ = trimInput (dsLCmd ids local_vars stk_ty cmd_ty cmd)
-- Feed back the list of local variables actually used a command,
-- for use as the input tuple of the generated arrow.
@@ -637,7 +687,7 @@ trimInput build_arrow
Translation of command judgements of the form
- A | xs |- do { ss } :: [] t
+ D |-a do { ss } : t
\begin{code}
@@ -651,14 +701,26 @@ dsCmdDo :: DsCmdEnv -- arrow combinators
-> DsM (CoreExpr, -- desugared expression
IdSet) -- subset of local vars that occur free
--- A | xs |- c :: [] t
--- --------------------------
--- A | xs |- do { c } :: [] t
-
dsCmdDo _ _ _ [] _ = panic "dsCmdDo"
-dsCmdDo ids local_vars res_ty [L _ (LastStmt body _)] env_ids
- = dsLCmd ids local_vars [] res_ty body env_ids
+-- D; xs |-a c : () --> t
+-- --------------------------
+-- D; xs |-a do { c } : t
+--
+-- ---> premap (\ (xs) -> ((xs), ())) c
+
+dsCmdDo ids local_vars res_ty [L _ (LastStmt body _)] env_ids = do
+ (core_body, env_ids') <- dsLCmd ids local_vars unitTy res_ty body env_ids
+ let env_ty = mkBigCoreVarTupTy env_ids
+ env_var <- newSysLocalDs env_ty
+ let core_map = Lam env_var (mkCorePairExpr (Var env_var) mkCoreUnitExpr)
+ return (do_premap ids
+ env_ty
+ (mkCorePairTy env_ty unitTy)
+ res_ty
+ core_map
+ core_body,
+ env_ids')
dsCmdDo ids local_vars res_ty (stmt:stmts) env_ids = do
let
@@ -695,21 +757,23 @@ dsCmdStmt
-> DsM (CoreExpr, -- desugared expression
IdSet) -- subset of local vars that occur free
--- A | xs1 |- c :: [] t
--- A | xs' |- do { ss } :: [] t'
--- ------------------------------
--- A | xs |- do { c; ss } :: [] t'
+-- D; xs1 |-a c : () --> t
+-- D; xs' |-a do { ss } : t'
+-- ------------------------------
+-- D; xs |-a do { c; ss } : t'
--
--- ---> premap (\ (xs) -> ((xs1),(xs')))
+-- ---> premap (\ ((xs)) -> (((xs1),()),(xs')))
-- (first c >>> arr snd) >>> ss
dsCmdStmt ids local_vars out_ids (BodyStmt cmd _ _ c_ty) env_ids = do
- (core_cmd, fv_cmd, env_ids1) <- dsfixCmd ids local_vars [] c_ty cmd
- core_mux <- matchEnvStack env_ids []
- (mkCorePairExpr (mkBigCoreVarTup env_ids1) (mkBigCoreVarTup out_ids))
+ (core_cmd, fv_cmd, env_ids1) <- dsfixCmd ids local_vars unitTy c_ty cmd
+ core_mux <- matchEnv env_ids
+ (mkCorePairExpr
+ (mkCorePairExpr (mkBigCoreVarTup env_ids1) mkCoreUnitExpr)
+ (mkBigCoreVarTup out_ids))
let
in_ty = mkBigCoreVarTupTy env_ids
- in_ty1 = mkBigCoreVarTupTy env_ids1
+ in_ty1 = mkCorePairTy (mkBigCoreVarTupTy env_ids1) unitTy
out_ty = mkBigCoreVarTupTy out_ids
before_c_ty = mkCorePairTy in_ty1 out_ty
after_c_ty = mkCorePairTy c_ty out_ty
@@ -719,21 +783,20 @@ dsCmdStmt ids local_vars out_ids (BodyStmt cmd _ _ c_ty) env_ids = do
(do_first ids in_ty1 c_ty out_ty core_cmd) $
do_arr ids after_c_ty out_ty snd_fn,
extendVarSetList fv_cmd out_ids)
- where
--- A | xs1 |- c :: [] t
--- A | xs' |- do { ss } :: [] t' xs2 = xs' - defs(p)
--- -----------------------------------
--- A | xs |- do { p <- c; ss } :: [] t'
+-- D; xs1 |-a c : () --> t
+-- D; xs' |-a do { ss } : t' xs2 = xs' - defs(p)
+-- -----------------------------------
+-- D; xs |-a do { p <- c; ss } : t'
--
--- ---> premap (\ (xs) -> ((xs1),(xs2)))
+-- ---> premap (\ (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 out_ids (BindStmt pat cmd _ _) env_ids = do
- (core_cmd, fv_cmd, env_ids1) <- dsfixCmd ids local_vars [] (hsLPatType pat) cmd
+ (core_cmd, fv_cmd, env_ids1) <- dsfixCmd ids local_vars unitTy (hsLPatType pat) cmd
let
pat_ty = hsLPatType pat
pat_vars = mkVarSet (collectPatBinders pat)
@@ -741,10 +804,12 @@ dsCmdStmt ids local_vars out_ids (BindStmt pat cmd _ _) env_ids = do
env_ty2 = mkBigCoreVarTupTy env_ids2
-- multiplexing function
- -- \ (xs) -> ((xs1),(xs2))
+ -- \ (xs) -> (((xs1),()),(xs2))
- core_mux <- matchEnvStack env_ids []
- (mkCorePairExpr (mkBigCoreVarTup env_ids1) (mkBigCoreVarTup env_ids2))
+ core_mux <- matchEnv env_ids
+ (mkCorePairExpr
+ (mkCorePairExpr (mkBigCoreVarTup env_ids1) mkCoreUnitExpr)
+ (mkBigCoreVarTup env_ids2))
-- projection function
-- \ (p, (xs2)) -> (zs)
@@ -766,7 +831,7 @@ dsCmdStmt ids local_vars out_ids (BindStmt pat cmd _ _) env_ids = do
-- put it all together
let
in_ty = mkBigCoreVarTupTy env_ids
- in_ty1 = mkBigCoreVarTupTy env_ids1
+ in_ty1 = mkCorePairTy (mkBigCoreVarTupTy env_ids1) unitTy
in_ty2 = mkBigCoreVarTupTy env_ids2
before_c_ty = mkCorePairTy in_ty1 in_ty2
return (do_premap ids in_ty before_c_ty out_ty core_mux $
@@ -775,9 +840,9 @@ dsCmdStmt ids local_vars out_ids (BindStmt pat cmd _ _) env_ids = do
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
+-- D; xs' |-a do { ss } : t
+-- --------------------------------------
+-- D; xs |-a do { let binds; ss } : t
--
-- ---> arr (\ (xs) -> let binds in (xs')) >>> ss
@@ -785,17 +850,17 @@ dsCmdStmt ids local_vars out_ids (LetStmt binds) env_ids = do
-- build a new environment using the let bindings
core_binds <- dsLocalBinds binds (mkBigCoreVarTup out_ids)
-- match the old environment against the input
- core_map <- matchEnvStack env_ids [] core_binds
+ core_map <- matchEnv env_ids core_binds
return (do_arr ids
(mkBigCoreVarTupTy env_ids)
(mkBigCoreVarTupTy out_ids)
core_map,
exprFreeIds core_binds `intersectVarSet` local_vars)
--- A | ys |- do { ss; returnA -< ((xs1), (ys2)) } :: [] ...
--- A | xs' |- do { ss' } :: [] t
--- ------------------------------------
--- A | xs |- do { rec ss; ss' } :: [] t
+-- D; ys |-a do { ss; returnA -< ((xs1), (ys2)) } : ...
+-- D; xs' |-a do { ss' } : t
+-- ------------------------------------
+-- D; xs |-a do { rec ss; ss' } : t
--
-- xs1 = xs' /\ defs(ss)
-- xs2 = xs' - defs(ss)
@@ -825,7 +890,7 @@ dsCmdStmt ids local_vars out_ids
post_pair_ty = mkCorePairTy later_ty env2_ty
post_loop_body = coreCaseTuple uniqs env2_id env2_ids (mkBigCoreVarTup out_ids)
- post_loop_fn <- matchEnvStack later_ids [env2_id] post_loop_body
+ post_loop_fn <- matchEnvStack later_ids env2_id post_loop_body
--- loop (...)
@@ -840,7 +905,7 @@ dsCmdStmt ids local_vars out_ids
pre_loop_body = mkCorePairExpr (mkBigCoreVarTup env1_ids)
(mkBigCoreVarTup env2_ids)
- pre_loop_fn <- matchEnvStack env_ids [] pre_loop_body
+ pre_loop_fn <- matchEnv env_ids pre_loop_body
-- arr pre_loop_fn >>> first (loop (...)) >>> arr post_loop_fn
@@ -898,7 +963,7 @@ dsRecCmd ids local_vars stmts later_ids later_rets rec_ids rec_rets = do
out_pair = mkCorePairExpr later_tuple rec_tuple
out_pair_ty = mkCorePairTy later_ty rec_ty
- mk_pair_fn <- matchEnvStack out_ids [] out_pair
+ mk_pair_fn <- matchEnv out_ids out_pair
-- ss
@@ -919,7 +984,7 @@ dsRecCmd ids local_vars stmts later_ids later_rets rec_ids rec_rets = do
= mkTupleSelector rec_ids v rec_id (Var rec_id)
| otherwise = Var v
- squash_pair_fn <- matchEnvStack env1_ids [rec_id] core_body
+ squash_pair_fn <- matchEnvStack env1_ids rec_id core_body
-- loop (premap squash_pair_fn (ss >>> arr mk_pair_fn))
@@ -936,7 +1001,7 @@ dsRecCmd ids local_vars stmts later_ids later_rets rec_ids rec_rets = do
\end{code}
A sequence of statements (as in a rec) is desugared to an arrow between
-two environments
+two environments (no stack)
\begin{code}
dsfixCmdStmts
@@ -978,7 +1043,6 @@ dsCmdStmts ids local_vars out_ids (stmt:stmts) env_ids = do
fv_stmt)
dsCmdStmts _ _ _ [] _ = panic "dsCmdStmts []"
-
\end{code}
Match a list of expressions against a list of patterns, left-to-right.
diff --git a/compiler/hsSyn/HsExpr.lhs b/compiler/hsSyn/HsExpr.lhs
index b4de840e47..d59c193ae8 100644
--- a/compiler/hsSyn/HsExpr.lhs
+++ b/compiler/hsSyn/HsExpr.lhs
@@ -689,6 +689,12 @@ data HsCmd id
| HsCmdDo [CmdLStmt id]
PostTcType -- Type of the whole expression
+
+ | HsCmdCast TcCoercion -- A simpler version of HsWrap in HsExpr
+ (HsCmd id) -- If cmd :: arg1 --> res
+ -- co :: arg1 ~ arg2
+ -- Then (HsCmdCast co cmd) :: arg2 --> res
+
deriving (Data, Typeable)
data HsArrAppType = HsHigherOrderApp | HsFirstOrderApp
@@ -705,7 +711,7 @@ type LHsCmdTop id = Located (HsCmdTop id)
data HsCmdTop id
= HsCmdTop (LHsCmd id)
- [PostTcType] -- types of inputs on the command's stack
+ PostTcType -- Nested tuple of inputs on the command's stack
PostTcType -- return type of the command
(CmdSyntaxTable id) -- See Note [CmdSyntaxTable]
deriving (Data, Typeable)
@@ -772,8 +778,9 @@ ppr_cmd (HsCmdLet binds cmd)
= sep [hang (ptext (sLit "let")) 2 (pprBinds binds),
hang (ptext (sLit "in")) 2 (ppr cmd)]
-ppr_cmd (HsCmdDo stmts _) = pprDo ArrowExpr stmts
-
+ppr_cmd (HsCmdDo stmts _) = pprDo ArrowExpr stmts
+ppr_cmd (HsCmdCast co cmd) = sep [ ppr_cmd cmd
+ , ptext (sLit "|>") <+> ppr co ]
ppr_cmd (HsCmdArrApp arrow arg _ HsFirstOrderApp True)
= hsep [ppr_lexpr arrow, ptext (sLit "-<"), ppr_lexpr arg]
diff --git a/compiler/hsSyn/HsUtils.lhs b/compiler/hsSyn/HsUtils.lhs
index 325bd2e37c..1fa949653e 100644
--- a/compiler/hsSyn/HsUtils.lhs
+++ b/compiler/hsSyn/HsUtils.lhs
@@ -1,4 +1,3 @@
-
%
% (c) The University of Glasgow, 1992-2006
%
@@ -29,7 +28,7 @@ module HsUtils(
mkHsWrap, mkLHsWrap, mkHsWrapCo, mkLHsWrapCo,
coToHsWrapper, mkHsDictLet, mkHsLams,
mkHsOpApp, mkHsDo, mkHsComp, mkHsWrapPat, mkHsWrapPatCo,
- mkLHsPar,
+ mkLHsPar, mkHsCmdCast,
nlHsTyApp, nlHsVar, nlHsLit, nlHsApp, nlHsApps, nlHsIntLit, nlHsVarApps,
nlHsDo, nlHsOpApp, nlHsLam, nlHsPar, nlHsIf, nlHsCase, nlList,
@@ -394,6 +393,10 @@ mkLHsWrapCo :: TcCoercion -> LHsExpr id -> LHsExpr id
mkLHsWrapCo co (L loc e) | isTcReflCo co = L loc e
| otherwise = L loc (mkHsWrap (WpCast co) e)
+mkHsCmdCast :: TcCoercion -> HsCmd id -> HsCmd id
+mkHsCmdCast co cmd | isTcReflCo co = cmd
+ | otherwise = HsCmdCast co cmd
+
coToHsWrapper :: TcCoercion -> HsWrapper
coToHsWrapper co | isTcReflCo co = idHsWrapper
| otherwise = WpCast co
diff --git a/compiler/parser/Parser.y.pp b/compiler/parser/Parser.y.pp
index 6d60f38dea..18651b97c2 100644
--- a/compiler/parser/Parser.y.pp
+++ b/compiler/parser/Parser.y.pp
@@ -1464,7 +1464,7 @@ exp10 :: { LHsExpr RdrName }
| 'proc' aexp '->' exp
{% checkPattern empty $2 >>= \ p ->
checkCommand $4 >>= \ cmd ->
- return (LL $ HsProc p (LL $ HsCmdTop cmd []
+ return (LL $ HsProc p (LL $ HsCmdTop cmd placeHolderType
placeHolderType undefined)) }
-- TODO: is LL right here?
@@ -1559,7 +1559,7 @@ cmdargs :: { [LHsCmdTop RdrName] }
acmd :: { LHsCmdTop RdrName }
: aexp2 {% checkCommand $1 >>= \ cmd ->
- return (L1 $ HsCmdTop cmd [] placeHolderType undefined) }
+ return (L1 $ HsCmdTop cmd placeHolderType placeHolderType undefined) }
cvtopbody :: { [LHsDecl RdrName] }
: '{' cvtopdecls0 '}' { $2 }
diff --git a/compiler/parser/RdrHsSyn.lhs b/compiler/parser/RdrHsSyn.lhs
index b077032809..3695daef58 100644
--- a/compiler/parser/RdrHsSyn.lhs
+++ b/compiler/parser/RdrHsSyn.lhs
@@ -872,8 +872,8 @@ checkCmd _ (OpApp eLeft op fixity eRight) = do
-- OpApp becomes a HsCmdArrForm with a (Just fixity) in it
c1 <- checkCommand eLeft
c2 <- checkCommand eRight
- let arg1 = L (getLoc c1) $ HsCmdTop c1 [] placeHolderType []
- arg2 = L (getLoc c2) $ HsCmdTop c2 [] placeHolderType []
+ let arg1 = L (getLoc c1) $ HsCmdTop c1 placeHolderType placeHolderType []
+ arg2 = L (getLoc c2) $ HsCmdTop c2 placeHolderType placeHolderType []
return $ HsCmdArrForm op (Just fixity) [arg1, arg2]
checkCmd l e = cmdFail l e
diff --git a/compiler/rename/RnExpr.lhs b/compiler/rename/RnExpr.lhs
index 7e1df1c840..29674ca34c 100644
--- a/compiler/rename/RnExpr.lhs
+++ b/compiler/rename/RnExpr.lhs
@@ -433,7 +433,7 @@ rnCmdTop = wrapLocFstM rnCmdTop'
-- Generate the rebindable syntax for the monad
; (cmd_names', cmd_fvs) <- lookupSyntaxNames cmd_names
- ; return (HsCmdTop cmd' [] placeHolderType (cmd_names `zip` cmd_names'),
+ ; return (HsCmdTop cmd' placeHolderType placeHolderType (cmd_names `zip` cmd_names'),
fvCmd `plusFV` cmd_fvs) }
rnLCmd :: LHsCmd RdrName -> RnM (LHsCmd Name, FreeVars)
@@ -511,6 +511,7 @@ rnCmd (HsCmdDo stmts _)
= do { ((stmts', _), fvs) <- rnStmts ArrowExpr rnLCmd stmts (\ _ -> return ((), emptyFVs))
; return ( HsCmdDo stmts' placeHolderType, fvs ) }
+rnCmd cmd@(HsCmdCast {}) = pprPanic "rnCmd" (ppr cmd)
---------------------------------------------------
type CmdNeeds = FreeVars -- Only inhabitants are
@@ -527,6 +528,7 @@ methodNamesCmd (HsCmdArrApp _arrow _arg _ HsFirstOrderApp _rtl)
methodNamesCmd (HsCmdArrApp _arrow _arg _ HsHigherOrderApp _rtl)
= unitFV appAName
methodNamesCmd (HsCmdArrForm {}) = emptyFVs
+methodNamesCmd (HsCmdCast _ cmd) = methodNamesCmd cmd
methodNamesCmd (HsCmdPar c) = methodNamesLCmd c
diff --git a/compiler/rename/RnTypes.lhs b/compiler/rename/RnTypes.lhs
index bc66eea923..95bdcb413f 100644
--- a/compiler/rename/RnTypes.lhs
+++ b/compiler/rename/RnTypes.lhs
@@ -679,7 +679,7 @@ mkOpFormRn a1@(L loc (HsCmdTop (L _ (HsCmdArrForm op1 (Just fix1) [a11,a12])) _
| associate_right
= do new_c <- mkOpFormRn a12 op2 fix2 a2
return (HsCmdArrForm op1 (Just fix1)
- [a11, L loc (HsCmdTop (L loc new_c) [] placeHolderType [])])
+ [a11, L loc (HsCmdTop (L loc new_c) placeHolderType placeHolderType [])])
-- TODO: locs are wrong
where
(nofix_error, associate_right) = compareFixity fix1 fix2
diff --git a/compiler/typecheck/TcArrows.lhs b/compiler/typecheck/TcArrows.lhs
index 9248fd6af6..6dca32abcc 100644
--- a/compiler/typecheck/TcArrows.lhs
+++ b/compiler/typecheck/TcArrows.lhs
@@ -14,7 +14,7 @@ Typecheck arrow notation
module TcArrows ( tcProc ) where
-import {-# SOURCE #-} TcExpr( tcMonoExpr, tcInferRho, tcSyntaxOp, tcCheckId )
+import {-# SOURCE #-} TcExpr( tcMonoExpr, tcInferRho, tcSyntaxOp, tcCheckId, tcPolyExpr )
import HsSyn
import TcMatches
@@ -33,7 +33,7 @@ import Name
import TysWiredIn
import VarSet
import TysPrim
-
+import BasicTypes( Arity )
import SrcLoc
import Outputable
import FastString
@@ -42,6 +42,39 @@ import Util
import Control.Monad
\end{code}
+Note [Arrow overivew]
+~~~~~~~~~~~~~~~~~~~~~
+Here's a summary of arrows and how they typecheck. First, here's
+a cut-down syntax:
+
+ expr ::= ....
+ | proc pat cmd
+
+ cmd ::= cmd exp -- Arrow application
+ | \pat -> cmd -- Arrow abstraction
+ | (| exp cmd1 ... cmdn |) -- Arrow form, n>=0
+ | ... -- If, case in the usual way
+
+ cmd_type ::= carg_type --> type
+
+ carg_type ::= ()
+ | (type, carg_type)
+
+Note that
+ * The 'exp' in an arrow form can mention only
+ "arrow-local" variables
+
+ * An "arrow-local" variable is bound by an enclosing
+ cmd binding form (eg arrow abstraction)
+
+ * A cmd_type is here written with a funny arrow "-->",
+ The bit on the left is a carg_type (command argument type)
+ which itself is a nested tuple, finishing with ()
+
+ * The arrow-tail operator (e1 -< e2) means
+ (| e1 <<< arr snd |) e2
+
+
%************************************************************************
%* *
Proc
@@ -59,7 +92,7 @@ tcProc pat cmd exp_ty
; (co1, (arr_ty, arg_ty)) <- matchExpectedAppTy exp_ty1
; let cmd_env = CmdEnv { cmd_arr = arr_ty }
; (pat', cmd') <- tcPat ProcExpr pat arg_ty $
- tcCmdTop cmd_env cmd [] res_ty
+ tcCmdTop cmd_env cmd (unitTy, res_ty)
; let res_co = mkTcTransCo co (mkTcAppCo co1 (mkTcReflCo res_ty))
; return (pat', cmd', res_co) }
\end{code}
@@ -72,10 +105,13 @@ tcProc pat cmd exp_ty
%************************************************************************
\begin{code}
-type CmdStack = [TcTauType]
+-- See Note [Arrow overview]
+type CmdType = (CmdArgType, TcTauType) -- cmd_type
+type CmdArgType = TcTauType -- carg_type, a nested tuple
+
data CmdEnv
= CmdEnv {
- cmd_arr :: TcType -- arrow type constructor, of kind *->*->*
+ cmd_arr :: TcType -- arrow type constructor, of kind *->*->*
}
mkCmdArrTy :: CmdEnv -> TcTauType -> TcTauType -> TcTauType
@@ -84,29 +120,23 @@ mkCmdArrTy env t1 t2 = mkAppTys (cmd_arr env) [t1, t2]
---------------------------------------
tcCmdTop :: CmdEnv
-> LHsCmdTop Name
- -> 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 (LHsCmdTop TcId)
-
-tcCmdTop env (L loc (HsCmdTop cmd _ _ names)) cmd_stk res_ty
+ -> CmdType
+ -> TcM (LHsCmdTop TcId)
+
+tcCmdTop env (L loc (HsCmdTop cmd _ _ names)) cmd_ty@(cmd_stk, res_ty)
= setSrcSpan loc $
- do { cmd' <- tcCmd env cmd (cmd_stk, res_ty)
+ do { cmd' <- tcCmd env cmd cmd_ty
; names' <- mapM (tcSyntaxName ProcOrigin (cmd_arr env)) names
; return (L loc $ HsCmdTop cmd' cmd_stk res_ty names') }
-
-
----------------------------------------
-tcCmd :: CmdEnv -> LHsCmd Name -> (CmdStack, TcTauType) -> TcM (LHsCmd TcId)
+tcCmd :: CmdEnv -> LHsCmd Name -> CmdType -> TcM (LHsCmd TcId)
-- The main recursive function
tcCmd env (L loc cmd) res_ty
= setSrcSpan loc $ do
{ cmd' <- tc_cmd env cmd res_ty
; return (L loc cmd') }
-tc_cmd :: CmdEnv -> HsCmd Name -> (CmdStack, TcTauType) -> TcM (HsCmd TcId)
+tc_cmd :: CmdEnv -> HsCmd Name -> CmdType -> TcM (HsCmd TcId)
tc_cmd env (HsCmdPar cmd) res_ty
= do { cmd' <- tcCmd env cmd res_ty
; return (HsCmdPar cmd') }
@@ -154,12 +184,23 @@ tc_cmd env (HsCmdIf (Just fun) pred b1 b2) res_ty -- Rebindable syntax for if
-------------------------------------------
-- Arrow application
-- (f -< a) or (f -<< a)
+--
+-- D |- fun :: a t1 t2
+-- D,G |- arg :: t1
+-- ------------------------
+-- D;G |-a fun -< arg :: stk --> t2
+--
+-- D,G |- fun :: a t1 t2
+-- D,G |- arg :: t1
+-- ------------------------
+-- D;G |-a fun -<< arg :: stk --> t2
+--
+-- (plus -<< requires ArrowApply)
-tc_cmd env cmd@(HsCmdArrApp fun arg _ ho_app lr) (cmd_stk, res_ty)
+tc_cmd env cmd@(HsCmdArrApp fun arg _ ho_app lr) (_, res_ty)
= addErrCtxt (cmdCtxt cmd) $
do { arg_ty <- newFlexiTyVarTy openTypeKind
- ; let fun_ty = mkCmdArrTy env (foldl mkPairTy arg_ty cmd_stk) res_ty
-
+ ; let fun_ty = mkCmdArrTy env arg_ty res_ty
; fun' <- select_arrow_scope (tcMonoExpr fun fun_ty)
-- ToDo: There should be no need for the escapeArrowScope stuff
-- See Note [Escaping the arrow scope] in TcRnTypes
@@ -178,159 +219,98 @@ tc_cmd env cmd@(HsCmdArrApp fun arg _ ho_app lr) (cmd_stk, res_ty)
-------------------------------------------
-- Command application
+--
+-- D,G |- exp : t
+-- D;G |-a cmd : (t,stk) --> res
+-- -----------------------------
+-- D;G |-a cmd exp : stk --> res
tc_cmd env cmd@(HsCmdApp fun arg) (cmd_stk, res_ty)
= addErrCtxt (cmdCtxt cmd) $
do { arg_ty <- newFlexiTyVarTy openTypeKind
-
- ; fun' <- tcCmd env fun (arg_ty:cmd_stk, res_ty)
-
- ; arg' <- tcMonoExpr arg arg_ty
-
+ ; fun' <- tcCmd env fun (mkPairTy arg_ty cmd_stk, res_ty)
+ ; arg' <- tcMonoExpr arg arg_ty
; return (HsCmdApp fun' arg') }
-------------------------------------------
-- Lambda
+--
+-- D;G,x:t |-a cmd : stk --> res
+-- ------------------------------
+-- D;G |-a (\x.cmd) : (t,stk) --> res
-tc_cmd env cmd@(HsCmdLam (MG { mg_alts = [L mtch_loc (match@(Match pats _maybe_rhs_sig grhss))] }))
+tc_cmd env
+ (HsCmdLam (MG { mg_alts = [L mtch_loc (match@(Match pats _maybe_rhs_sig grhss))] }))
(cmd_stk, res_ty)
= addErrCtxt (pprMatchInCtxt match_ctxt match) $
-
- do { -- Check the cmd stack is big enough
- ; checkTc (lengthAtLeast cmd_stk n_pats)
- (kappaUnderflow cmd)
+ do { (co, arg_tys, cmd_stk') <- matchExpectedCmdArgs n_pats cmd_stk
-- Check the patterns, and the GRHSs inside
; (pats', grhss') <- setSrcSpan mtch_loc $
- tcPats LambdaExpr pats cmd_stk $
- tc_grhss grhss res_ty
+ tcPats LambdaExpr pats arg_tys $
+ tc_grhss grhss cmd_stk' res_ty
; let match' = L mtch_loc (Match pats' Nothing grhss')
arg_tys = map hsLPatType pats'
- ; return (HsCmdLam (MG { mg_alts = [match'], mg_arg_tys = arg_tys
- , mg_res_ty = res_ty }))
- -- Or should we decompose res_ty?
- }
-
+ cmd' = HsCmdLam (MG { mg_alts = [match'], mg_arg_tys = arg_tys
+ , mg_res_ty = res_ty })
+ ; return (mkHsCmdCast co cmd') }
where
n_pats = length pats
- stk' = drop n_pats cmd_stk
match_ctxt = (LambdaExpr :: HsMatchContext Name) -- Maybe KappaExpr?
pg_ctxt = PatGuard match_ctxt
- tc_grhss (GRHSs grhss binds) res_ty
+ tc_grhss (GRHSs grhss binds) stk_ty res_ty
= do { (binds', grhss') <- tcLocalBinds binds $
- mapM (wrapLocM (tc_grhs res_ty)) grhss
+ mapM (wrapLocM (tc_grhs stk_ty res_ty)) grhss
; return (GRHSs grhss' binds') }
- tc_grhs res_ty (GRHS guards body)
+ tc_grhs stk_ty res_ty (GRHS guards body)
= do { (guards', rhs') <- tcStmtsAndThen pg_ctxt tcGuardStmt guards res_ty $
- \ res_ty -> tcCmd env body (stk', res_ty)
+ \ res_ty -> tcCmd env body (stk_ty, res_ty)
; return (GRHS guards' rhs') }
-------------------------------------------
-- Do notation
-tc_cmd env cmd@(HsCmdDo stmts _) (cmd_stk, res_ty)
- = do { checkTc (null cmd_stk) (nonEmptyCmdStkErr cmd)
+tc_cmd env (HsCmdDo stmts _) (cmd_stk, res_ty)
+ = do { co <- unifyType unitTy cmd_stk -- Expecting empty argument stack
; stmts' <- tcStmts ArrowExpr (tcArrDoStmt env) stmts res_ty
- ; return (HsCmdDo stmts' res_ty) }
- where
+ ; return (mkHsCmdCast co (HsCmdDo stmts' 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)
+-- D; G |-a1 c1 : stk1 --> r1
+-- ...
+-- D; G |-an cn : stkn --> rn
+-- D |- e :: forall e. a1 (e, stk1) t1
+-- ...
+-- -> an (e, stkn) tn
+-- -> a (e, stk) t
+-- e \not\in (stk, stk1, ..., stkm, t, t1, ..., tn)
-- ----------------------------------------------
--- G |-a (| e c |) : [t1 .. tn] t
+-- D; G |-a (| e c1 ... cn |) : stk --> t
tc_cmd env cmd@(HsCmdArrForm expr fixity cmd_args) (cmd_stk, res_ty)
= addErrCtxt (cmdCtxt cmd) $
- do { cmds_w_tys <- zipWithM new_cmd_ty cmd_args [1..]
- ; (_, [w_tv]) <- tcInstSkolTyVars [alphaTyVar]
- ; let w_ty = mkTyVarTy w_tv -- Just a convenient starting point
-
- -- 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
-
- -- ToDo: SLPJ: something is badly wrong here.
- -- The escapeArrowScope pops the Untouchables.. but that
- -- risks screwing up the skolem-escape check
- -- Moreover, arrowfail001 fails with an ASSERT failure
- -- because a variable gets the wrong level
- -- Check expr
- ; (inner_binds, expr')
- <- checkConstraints ArrowSkol [w_tv] [] $
- escapeArrowScope (tcMonoExpr expr e_ty)
-
-{-
- ; ((inner_binds, expr'), lie)
- <- captureConstraints $
- checkConstraints ArrowSkol [w_tv] [] $
- tcMonoExpr expr e_ty
- -- No need for escapeArrowScope in the
- -- type checker.
- -- Note [Escaping the arrow scope] in TcRnTypes
- ; (lie, outer_binds) <- solveWantedsTcM lie
- ; emitConstraints lie
--}
-
- -- 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
-
- ; let wrap = WpTyLam w_tv <.> mkWpLet inner_binds
- ; return (HsCmdArrForm (mkLHsWrap wrap expr') fixity cmds') }
+ do { (cmd_args', cmd_tys) <- mapAndUnzipM tc_cmd_arg cmd_args
+ ; let e_ty = mkForAllTy alphaTyVar $ -- We use alphaTyVar for 'w'
+ mkFunTys cmd_tys $
+ mkCmdArrTy env (mkPairTy alphaTy cmd_stk) res_ty
+ ; expr' <- tcPolyExpr expr e_ty
+ ; return (HsCmdArrForm expr' fixity cmd_args') }
+
where
- -- Make the types
- -- b, ((e,s1) .. sm), s
- new_cmd_ty :: LHsCmdTop Name -> Int
- -> TcM (LHsCmdTop Name, Int, TcType, TcType, TcType)
- new_cmd_ty cmd i
- = do { b_ty <- newFlexiTyVarTy arrowTyConKind
- ; tup_ty <- newFlexiTyVarTy liftedTypeKind
- -- We actually make a type variable for the tuple
- -- because we don't know how deeply nested it is yet
- ; s_ty <- newFlexiTyVarTy 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
- ; _bogus <- unifyType corner_ty (mkTyVarTy w_tv)
- ; checkTc (not (w_tv `elemVarSet` tyVarsOfTypes arg_tys))
- (badFormFun i tup_ty')
- -- JPM: WARNING: this test is utterly bogus; see #5609
- -- We are not using the coercion returned by the unify;
- -- and (even more seriously) the w not in arg_tys test is totally
- -- bogus if there are suspended equality constraints. This code
- -- needs to be re-architected.
-
- ; tcCmdTop (env { cmd_arr = b }) cmd arg_tys s }
-
- unscramble :: TcType -> (TcType, [TcType])
- -- unscramble ((w,s1) .. sn) = (w, [s1..sn])
- unscramble ty = unscramble' ty []
-
- unscramble' ty ss
- = case tcSplitTyConApp_maybe ty of
- Just (tc, [t,s]) | tc == pairTyCon
- -> unscramble' t (s:ss)
- _ -> (ty, ss)
+ tc_cmd_arg :: LHsCmdTop Name -> TcM (LHsCmdTop TcId, TcType)
+ tc_cmd_arg cmd
+ = do { arr_ty <- newFlexiTyVarTy arrowTyConKind
+ ; stk_ty <- newFlexiTyVarTy liftedTypeKind
+ ; res_ty <- newFlexiTyVarTy liftedTypeKind
+ ; let env' = env { cmd_arr = arr_ty }
+ ; cmd' <- tcCmdTop env' cmd (stk_ty, res_ty)
+ ; return (cmd', mkCmdArrTy env' (mkPairTy alphaTy stk_ty) res_ty) }
-----------------------------------------------------------------
-- Base case for illegal commands
@@ -339,6 +319,15 @@ tc_cmd env cmd@(HsCmdArrForm expr fixity cmd_args) (cmd_stk, res_ty)
tc_cmd _ cmd _
= failWithTc (vcat [ptext (sLit "The expression"), nest 2 (ppr cmd),
ptext (sLit "was found where an arrow command was expected")])
+
+
+matchExpectedCmdArgs :: Arity -> TcType -> TcM (TcCoercion, [TcType], TcType)
+matchExpectedCmdArgs 0 ty
+ = return (mkTcReflCo ty, [], ty)
+matchExpectedCmdArgs n ty
+ = do { (co1, [ty1, ty2]) <- matchExpectedTyConApp pairTyCon ty
+ ; (co2, tys, res_ty) <- matchExpectedCmdArgs (n-1) ty2
+ ; return (mkTcTyConAppCo pairTyCon [co1, co2], ty1:tys, res_ty) }
\end{code}
@@ -357,7 +346,7 @@ tc_cmd _ cmd _
tcArrDoStmt :: CmdEnv -> TcCmdStmtChecker
tcArrDoStmt env _ (LastStmt rhs _) res_ty thing_inside
- = do { rhs' <- tcCmd env rhs ([], res_ty)
+ = do { rhs' <- tcCmd env rhs (unitTy, res_ty)
; thing <- thing_inside (panic "tcArrDoStmt")
; return (LastStmt rhs' noSyntaxExpr, thing) }
@@ -407,7 +396,7 @@ tcArrDoStmt _ _ stmt _ _
tc_arr_rhs :: CmdEnv -> LHsCmd Name -> TcM (LHsCmd TcId, TcType)
tc_arr_rhs env rhs = do { ty <- newFlexiTyVarTy liftedTypeKind
- ; rhs' <- tcCmd env rhs ([], ty)
+ ; rhs' <- tcCmd env rhs (unitTy, ty)
; return (rhs', ty) }
\end{code}
@@ -437,19 +426,4 @@ arrowTyConKind = mkArrowKinds [liftedTypeKind, liftedTypeKind] liftedTypeKind
\begin{code}
cmdCtxt :: HsCmd Name -> SDoc
cmdCtxt cmd = ptext (sLit "In the command:") <+> ppr cmd
-
-nonEmptyCmdStkErr :: HsCmd Name -> SDoc
-nonEmptyCmdStkErr cmd
- = hang (ptext (sLit "Non-empty command stack at command:"))
- 2 (ppr cmd)
-
-kappaUnderflow :: HsCmd Name -> SDoc
-kappaUnderflow cmd
- = hang (ptext (sLit "Command stack underflow at command:"))
- 2 (ppr cmd)
-
-badFormFun :: Int -> TcType -> SDoc
-badFormFun i tup_ty'
- = hang (ptext (sLit "The type of the") <+> speakNth i <+> ptext (sLit "argument of a command form has the wrong shape"))
- 2 (ptext (sLit "Argument type:") <+> ppr tup_ty')
\end{code}
diff --git a/compiler/typecheck/TcHsSyn.lhs b/compiler/typecheck/TcHsSyn.lhs
index 22ce21a184..1e2961258d 100644
--- a/compiler/typecheck/TcHsSyn.lhs
+++ b/compiler/typecheck/TcHsSyn.lhs
@@ -730,6 +730,10 @@ zonkCmd :: ZonkEnv -> HsCmd TcId -> TcM (HsCmd Id)
zonkLCmd env cmd = wrapLocM (zonkCmd env) cmd
+zonkCmd env (HsCmdCast co cmd)
+ = do { co' <- zonkTcLCoToLCo env co
+ ; cmd' <- zonkCmd env cmd
+ ; return (HsCmdCast co' cmd') }
zonkCmd env (HsCmdArrApp e1 e2 ty ho rl)
= zonkLExpr env e1 `thenM` \ new_e1 ->
zonkLExpr env e2 `thenM` \ new_e2 ->
@@ -786,7 +790,7 @@ zonkCmdTop env cmd = wrapLocM (zonk_cmd_top env) cmd
zonk_cmd_top :: ZonkEnv -> HsCmdTop TcId -> TcM (HsCmdTop Id)
zonk_cmd_top env (HsCmdTop cmd stack_tys ty ids)
= zonkLCmd env cmd `thenM` \ new_cmd ->
- zonkTcTypeToTypes env stack_tys `thenM` \ new_stack_tys ->
+ zonkTcTypeToType env stack_tys `thenM` \ new_stack_tys ->
zonkTcTypeToType env ty `thenM` \ new_ty ->
mapSndM (zonkExpr env) ids `thenM` \ new_ids ->
returnM (HsCmdTop new_cmd new_stack_tys new_ty new_ids)
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 1357395eff..03682bf848 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -8226,7 +8226,7 @@ Thus combinators that produce arrows from arrows
may also be used to build commands from commands.
For example, the <literal>ArrowPlus</literal> class includes a combinator
<programlisting>
-ArrowPlus a => (&lt;+>) :: a e c -> a e c -> a e c
+ArrowPlus a => (&lt;+>) :: a b c -> a b c -> a b c
</programlisting>
so we can use it to build commands:
<programlisting>
@@ -8256,18 +8256,24 @@ expr' = (proc x -> returnA -&lt; x)
y &lt;- term -&lt; ()
expr' -&lt; x - y)
</programlisting>
+We are actually using <literal>&lt;+></literal> here with the more specific type
+<programlisting>
+ArrowPlus a => (&lt;+>) :: a (e,()) c -> a (e,()) c -> a (e,()) c
+</programlisting>
It is essential that this operator be polymorphic in <literal>e</literal>
(representing the environment input to the command
and thence to its subcommands)
and satisfy the corresponding naturality property
<screen>
-arr k >>> (f &lt;+> g) = (arr k >>> f) &lt;+> (arr k >>> g)
+arr (first k) >>> (f &lt;+> g) = (arr (first k) >>> f) &lt;+> (arr (first k) >>> g)
</screen>
at least for strict <literal>k</literal>.
(This should be automatic if you're not using <function>seq</function>.)
This ensures that environments seen by the subcommands are environments
of the whole command,
and also allows the translation to safely trim these environments.
+(The second component of the input pairs can contain unnamed input values,
+as described in the next section.)
The operator must also not use any variable defined within the current
arrow abstraction.
</para>
@@ -8275,7 +8281,7 @@ arrow abstraction.
<para>
We could define our own operator
<programlisting>
-untilA :: ArrowChoice a => a e () -> a e Bool -> a e ()
+untilA :: ArrowChoice a => a (e,s) () -> a (e,s) Bool -> a (e,s) ()
untilA body cond = proc x ->
b &lt;- cond -&lt; x
if b then returnA -&lt; ()
@@ -8305,7 +8311,7 @@ the operator that attaches an exception handler will wish to pass the
exception that occurred to the handler.
Such an operator might have a type
<screen>
-handleA :: ... => a e c -> a (e,Ex) c -> a e c
+handleA :: ... => a (e,s) c -> a (e,(Ex,s)) c -> a (e,s) c
</screen>
where <literal>Ex</literal> is the type of exceptions handled.
You could then use this with arrow notation by writing a command
@@ -8320,22 +8326,24 @@ Though the syntax here looks like a functional lambda,
we are talking about commands, and something different is going on.
The input to the arrow represented by a command consists of values for
the free local variables in the command, plus a stack of anonymous values.
-In all the prior examples, this stack was empty.
+In all the prior examples, we made no assumptions about this stack.
In the second argument to <function>handleA</function>,
-this stack consists of one value, the value of the exception.
+the value of the exception has been added to the stack input to the handler.
The command form of lambda merely gives this value a name.
</para>
<para>
More concretely,
-the values on the stack are paired to the right of the environment.
+the input to a command consists of a pair of an environment and a stack.
+Each value on the stack is paired with the remainder of the stack,
+with an empty stack being <literal>()</literal>.
So operators like <function>handleA</function> that pass
extra inputs to their subcommands can be designed for use with the notation
-by pairing the values with the environment in this way.
+by placing the values on the stack paired with the environment in this way.
More precisely, the type of each argument of the operator (and its result)
should have the form
<screen>
-a (...(e,t1), ... tn) t
+a (e, (t1, ... (tn, ())...)) t
</screen>
where <replaceable>e</replaceable> is a polymorphic variable
(representing the environment)
@@ -8347,9 +8355,9 @@ The polymorphic variable <replaceable>e</replaceable> must not occur in
However the arrows involved need not be the same.
Here are some more examples of suitable operators:
<screen>
-bracketA :: ... => a e b -> a (e,b) c -> a (e,c) d -> a e d
-runReader :: ... => a e c -> a' (e,State) c
-runState :: ... => a e c -> a' (e,State) (c,State)
+bracketA :: ... => a (e,s) b -> a (e,(b,s)) c -> a (e,(c,s)) d -> a (e,s) d
+runReader :: ... => a (e,s) c -> a' (e,(State,s)) c
+runState :: ... => a (e,s) c -> a' (e,(State,s)) (c,State)
</screen>
We can supply the extra input required by commands built with the last two
by applying them to ordinary expressions, as in
@@ -8371,16 +8379,16 @@ are the core of the notation; everything else can be built using them,
though the results would be somewhat clumsy.
For example, we could simulate <literal>do</literal>-notation by defining
<programlisting>
-bind :: Arrow a => a e b -> a (e,b) c -> a e c
+bind :: Arrow a => a (e,s) b -> a (e,(b,s)) c -> a (e,s) c
u `bind` f = returnA &amp;&amp;&amp; u >>> f
-bind_ :: Arrow a => a e b -> a e c -> a e c
+bind_ :: Arrow a => a (e,s) b -> a (e,s) c -> a (e,s) c
u `bind_` f = u `bind` (arr fst >>> f)
</programlisting>
We could simulate <literal>if</literal> by defining
<programlisting>
-cond :: ArrowChoice a => a e b -> a e b -> a (e,Bool) b
-cond f g = arr (\ (e,b) -> if b then Left e else Right e) >>> f ||| g
+cond :: ArrowChoice a => a (e,s) b -> a (e,s) b -> a (e,(Bool,s)) b
+cond f g = arr (\ (e,(b,s)) -> if b then Left (e,s) else Right (e,s)) >>> f ||| g
</programlisting>
</para>
@@ -8405,6 +8413,14 @@ a new <literal>form</literal> keyword.
</para>
</listitem>
+<listitem>
+<para>In the paper and the previous implementation,
+values on the stack were paired to the right of the environment
+in a single argument,
+but now the environment and stack are separate arguments.
+</para>
+</listitem>
+
</itemizedlist>
</sect2>