DsArrows.hs 47.2 KB
Newer Older
Austin Seipp's avatar
Austin Seipp committed
1 2 3 4
{-
(c) The University of Glasgow 2006
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998

Simon Marlow's avatar
Simon Marlow committed
5 6

Desugaring arrow commands
Austin Seipp's avatar
Austin Seipp committed
7
-}
8

9
{-# LANGUAGE CPP #-}
10
{-# LANGUAGE TypeFamilies #-}
Ian Lynagh's avatar
Ian Lynagh committed
11

12 13 14 15
module DsArrows ( dsProcExpr ) where

#include "HsVersions.h"

16 17
import GhcPrelude

Simon Marlow's avatar
Simon Marlow committed
18 19
import Match
import DsUtils
20 21
import DsMonad

22
import HsSyn    hiding (collectPatBinders, collectPatsBinders, collectLStmtsBinders, collectLStmtBinders, collectStmtBinders )
Simon Marlow's avatar
Simon Marlow committed
23
import TcHsSyn
Simon Marlow's avatar
Simon Marlow committed
24
import qualified HsUtils
25 26 27 28 29 30

-- 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.

Richard Eisenberg's avatar
Richard Eisenberg committed
31
import {-# SOURCE #-} DsExpr ( dsExpr, dsLExpr, dsLExprNoLP, dsLocalBinds, dsSyntaxExpr )
32

Simon Marlow's avatar
Simon Marlow committed
33
import TcType
Richard Eisenberg's avatar
Richard Eisenberg committed
34
import Type ( splitPiTy )
35
import TcEvidence
36
import CoreSyn
Simon Marlow's avatar
Simon Marlow committed
37 38
import CoreFVs
import CoreUtils
39
import MkCore
40
import DsBinds (dsHsWrapper)
41

Simon Marlow's avatar
Simon Marlow committed
42
import Name
43
import Id
Richard Eisenberg's avatar
Richard Eisenberg committed
44
import ConLike
Simon Marlow's avatar
Simon Marlow committed
45 46 47
import TysWiredIn
import BasicTypes
import PrelNames
Ian Lynagh's avatar
Ian Lynagh committed
48
import Outputable
49
import Bag
Simon Marlow's avatar
Simon Marlow committed
50 51
import VarSet
import SrcLoc
Richard Eisenberg's avatar
Richard Eisenberg committed
52
import ListSetOps( assocMaybe )
53
import Data.List
niteria's avatar
niteria committed
54
import Util
niteria's avatar
niteria committed
55
import UniqDFM
David Feuer's avatar
David Feuer committed
56
import UniqSet
57 58

data DsCmdEnv = DsCmdEnv {
59
        arr_id, compose_id, first_id, app_id, choice_id, loop_id :: CoreExpr
60 61
    }

62
mkCmdEnv :: CmdSyntaxTable GhcTc -> DsM ([CoreBind], DsCmdEnv)
63 64 65
-- See Note [CmdSyntaxTable] in HsExpr
mkCmdEnv tc_meths
  = do { (meth_binds, prs) <- mapAndUnzipM mk_bind tc_meths
Richard Eisenberg's avatar
Richard Eisenberg committed
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95

       -- NB: Some of these lookups might fail, but that's OK if the
       -- symbol is never used. That's why we use Maybe first and then
       -- panic. An eager panic caused trouble in typecheck/should_compile/tc192
       ; let the_arr_id     = assocMaybe prs arrAName
             the_compose_id = assocMaybe prs composeAName
             the_first_id   = assocMaybe prs firstAName
             the_app_id     = assocMaybe prs appAName
             the_choice_id  = assocMaybe prs choiceAName
             the_loop_id    = assocMaybe prs loopAName

           -- used as an argument in, e.g., do_premap
       ; check_lev_poly 3 the_arr_id

           -- used as an argument in, e.g., dsCmdStmt/BodyStmt
       ; check_lev_poly 5 the_compose_id

           -- used as an argument in, e.g., dsCmdStmt/BodyStmt
       ; check_lev_poly 4 the_first_id

           -- the result of the_app_id is used as an argument in, e.g.,
           -- dsCmd/HsCmdArrApp/HsHigherOrderApp
       ; check_lev_poly 2 the_app_id

           -- used as an argument in, e.g., HsCmdIf
       ; check_lev_poly 5 the_choice_id

           -- used as an argument in, e.g., RecStmt
       ; check_lev_poly 4 the_loop_id

96
       ; return (meth_binds, DsCmdEnv {
Richard Eisenberg's avatar
Richard Eisenberg committed
97 98 99 100 101 102
               arr_id     = Var (unmaybe the_arr_id arrAName),
               compose_id = Var (unmaybe the_compose_id composeAName),
               first_id   = Var (unmaybe the_first_id firstAName),
               app_id     = Var (unmaybe the_app_id appAName),
               choice_id  = Var (unmaybe the_choice_id choiceAName),
               loop_id    = Var (unmaybe the_loop_id loopAName)
103 104 105 106
             }) }
  where
    mk_bind (std_name, expr)
      = do { rhs <- dsExpr expr
Richard Eisenberg's avatar
Richard Eisenberg committed
107
           ; id <- newSysLocalDs (exprType rhs)  -- no check needed; these are functions
108
           ; return (NonRec id rhs, (std_name, id)) }
109

Richard Eisenberg's avatar
Richard Eisenberg committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    unmaybe Nothing name = pprPanic "mkCmdEnv" (text "Not found:" <+> ppr name)
    unmaybe (Just id) _  = id

      -- returns the result type of a pi-type (that is, a forall or a function)
      -- Note that this result type may be ill-scoped.
    res_type :: Type -> Type
    res_type ty = res_ty
      where
        (_, res_ty) = splitPiTy ty

    check_lev_poly :: Int -- arity
                   -> Maybe Id -> DsM ()
    check_lev_poly _     Nothing = return ()
    check_lev_poly arity (Just id)
      = dsNoLevPoly (nTimes arity res_type (idType id))
          (text "In the result of the function" <+> quotes (ppr id))

127 128 129 130 131 132 133

-- 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 ->
134
                CoreExpr -> CoreExpr -> CoreExpr
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
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 ->
150
                CoreExpr -> CoreExpr -> CoreExpr
151 152 153 154 155 156 157 158 159
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]

160 161 162
-- premap :: forall b c d. (b -> c) -> a c d -> a b d
-- premap f g = arr f >>> g
do_premap :: DsCmdEnv -> Type -> Type -> Type ->
163
                CoreExpr -> CoreExpr -> CoreExpr
164 165
do_premap ids b_ty c_ty d_ty f g
   = do_compose ids b_ty c_ty d_ty (do_arr ids b_ty c_ty f) g
166

167
mkFailExpr :: HsMatchContext Id -> Type -> DsM CoreExpr
168 169 170
mkFailExpr ctxt ty
  = mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt)

171 172 173 174 175 176 177 178 179
-- 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)))

180 181
-- construct CoreExpr for \ (a :: a_ty, b :: b_ty) -> b
mkSndExpr :: Type -> Type -> DsM CoreExpr
182 183 184 185 186 187
mkSndExpr 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 b_var)))
188

Austin Seipp's avatar
Austin Seipp committed
189
{-
190 191
Build case analysis of a tuple.  This cannot be done in the DsM monad,
because the list of variables is typically not yet defined.
Austin Seipp's avatar
Austin Seipp committed
192
-}
193 194

-- coreCaseTuple [u1..] v [x1..xn] body
195
--      = case v of v { (x1, .., xn) -> body }
196 197 198
-- But the matching may be nested if the tuple is very big

coreCaseTuple :: UniqSupply -> Id -> [Id] -> CoreExpr -> CoreExpr
ross's avatar
ross committed
199 200
coreCaseTuple uniqs scrut_var vars body
  = mkTupleCase uniqs vars body scrut_var (Var scrut_var)
201

ross's avatar
ross committed
202 203
coreCasePair :: Id -> Id -> Id -> CoreExpr -> CoreExpr
coreCasePair scrut_var var1 var2 body
204
  = Case (Var scrut_var) scrut_var (exprType body)
205
         [(DataAlt (tupleDataCon Boxed 2), [var1, var2], body)]
206 207

mkCorePairTy :: Type -> Type -> Type
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
208
mkCorePairTy t1 t2 = mkBoxedTupleTy [t1, t2]
209 210 211

mkCorePairExpr :: CoreExpr -> CoreExpr -> CoreExpr
mkCorePairExpr e1 e2 = mkCoreTup [e1, e2]
212 213 214

mkCoreUnitExpr :: CoreExpr
mkCoreUnitExpr = mkCoreTup []
215

Austin Seipp's avatar
Austin Seipp committed
216
{-
217
The input is divided into a local environment, which is a flat tuple
218 219
(unless it's too big), and a stack, which is a right-nested pair.
In general, the input has the form
220

221
        ((x1,...,xn), (s1,...(sk,())...))
222 223 224

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.
Austin Seipp's avatar
Austin Seipp committed
225
-}
226

227 228 229 230 231 232 233 234 235 236
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)
237 238

----------------------------------------------
239
--              buildEnvStack
240
--
241
--      ((x1,...,xn),stk)
242

243 244 245
buildEnvStack :: [Id] -> Id -> CoreExpr
buildEnvStack env_ids stack_id
  = mkCorePairExpr (mkBigCoreVarTup env_ids) (Var stack_id)
246 247

----------------------------------------------
248
--              matchEnvStack
249
--
250 251 252 253 254 255 256 257 258 259 260
--      \ ((x1,...,xn),stk) -> body
--      =>
--      \ pair ->
--      case pair of (tup,stk) ->
--      case tup of (x1,...,xn) ->
--      body

matchEnvStack   :: [Id]         -- x1..xn
                -> Id           -- stk
                -> CoreExpr     -- e
                -> DsM CoreExpr
261
matchEnvStack env_ids stack_id body = do
262 263
    uniqs <- newUniqueSupply
    tup_var <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
264 265 266
    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))
267

268
----------------------------------------------
269
--              matchEnv
270
--
271 272 273 274 275 276 277 278 279
--      \ (x1,...,xn) -> body
--      =>
--      \ tup ->
--      case tup of (x1,...,xn) ->
--      body

matchEnv :: [Id]        -- x1..xn
         -> CoreExpr    -- e
         -> DsM CoreExpr
280 281 282 283
matchEnv env_ids body = do
    uniqs <- newUniqueSupply
    tup_id <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
    return (Lam tup_id (coreCaseTuple uniqs tup_id env_ids body))
284 285

----------------------------------------------
286
--              matchVarStack
287
--
288 289 290 291 292
--      case (x1, ...(xn, s)...) -> e
--      =>
--      case z0 of (x1,z1) ->
--      case zn-1 of (xn,s) ->
--      e
293 294 295 296 297 298
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)
299

300
mkHsEnvStackExpr :: [Id] -> Id -> LHsExpr GhcTc
301 302
mkHsEnvStackExpr env_ids stack_id
  = mkLHsTupleExpr [mkLHsVarTuple env_ids, nlHsVar stack_id]
303

Austin Seipp's avatar
Austin Seipp committed
304
-- Translation of arrow abstraction
305

306
-- D; xs |-a c : () --> t'      ---> c'
307
-- --------------------------
308
-- D |- proc p -> c :: a t t'   ---> premap (\ p -> ((xs),())) c'
309
--
310
--              where (xs) is the tuple of variables bound by p
311 312

dsProcExpr
313 314
        :: LPat GhcTc
        -> LHsCmdTop GhcTc
315
        -> DsM CoreExpr
Ben Gamari's avatar
Ben Gamari committed
316
dsProcExpr pat (L _ (HsCmdTop cmd _unitTy cmd_ty ids)) = do
317
    (meth_binds, meth_ids) <- mkCmdEnv ids
318
    let locals = mkVarSet (collectPatBinders pat)
319
    (core_cmd, _free_vars, env_ids) <- dsfixCmd meth_ids locals unitTy cmd_ty cmd
320
    let env_ty = mkBigCoreVarTupTy env_ids
321 322 323
    let env_stk_ty = mkCorePairTy env_ty unitTy
    let env_stk_expr = mkCorePairExpr (mkBigCoreVarTup env_ids) mkCoreUnitExpr
    fail_expr <- mkFailExpr ProcExpr env_stk_ty
324
    var <- selectSimpleMatchVarL pat
325
    match_code <- matchSimply (Var var) ProcExpr pat env_stk_expr fail_expr
326
    let pat_ty = hsLPatType pat
327
    let proc_code = do_premap meth_ids pat_ty env_stk_ty cmd_ty
328 329
                    (Lam var match_code)
                    core_cmd
330
    return (mkLets meth_binds proc_code)
331

Austin Seipp's avatar
Austin Seipp committed
332
{-
333 334
Translation of a command judgement of the form

335
        D; xs |-a c : stk --> t
336 337

to an expression e such that
338

339
        D |- e :: a (xs, stk) t
Austin Seipp's avatar
Austin Seipp committed
340
-}
341

342
dsLCmd :: DsCmdEnv -> IdSet -> Type -> Type -> LHsCmd GhcTc -> [Id]
niteria's avatar
niteria committed
343
       -> DsM (CoreExpr, DIdSet)
344 345
dsLCmd ids local_vars stk_ty res_ty cmd env_ids
  = dsCmd ids local_vars stk_ty res_ty (unLoc cmd) env_ids
346

347 348 349 350
dsCmd   :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this command
        -> Type                 -- type of the stack (right-nested tuple)
        -> Type                 -- return type of the command
351 352
        -> HsCmd GhcTc           -- command to desugar
        -> [Id]           -- list of vars in the input to this command
353 354 355
                                -- This is typically fed back,
                                -- so don't pull on it too early
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
356
                DIdSet)         -- subset of local vars that occur free
357

358 359 360 361
-- D |- fun :: a t1 t2
-- D, xs |- arg :: t1
-- -----------------------------
-- D; xs |-a fun -< arg : stk --> t2
ross's avatar
ross committed
362
--
363
--              ---> premap (\ ((xs), _stk) -> arg) fun
364

365
dsCmd ids local_vars stack_ty res_ty
Ben Gamari's avatar
Ben Gamari committed
366
        (HsCmdArrApp arrow arg arrow_ty HsFirstOrderApp _)
367
        env_ids = do
368 369
    let
        (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
ross's avatar
ross committed
370
        (_a_ty, arg_ty) = tcSplitAppTy a_arg_ty
Richard Eisenberg's avatar
Richard Eisenberg committed
371
    core_arrow <- dsLExprNoLP arrow
372
    core_arg   <- dsLExpr arg
373 374
    stack_id   <- newSysLocalDs stack_ty
    core_make_arg <- matchEnvStack env_ids stack_id core_arg
375
    return (do_premap ids
376
              (envStackType env_ids stack_ty)
377 378 379 380
              arg_ty
              res_ty
              core_make_arg
              core_arrow,
David Feuer's avatar
David Feuer committed
381
            exprFreeIdsDSet core_arg `udfmIntersectUFM` (getUniqSet local_vars))
382

383 384 385 386
-- D, xs |- fun :: a t1 t2
-- D, xs |- arg :: t1
-- ------------------------------
-- D; xs |-a fun -<< arg : stk --> t2
ross's avatar
ross committed
387
--
388
--              ---> premap (\ ((xs), _stk) -> (fun, arg)) app
389

390
dsCmd ids local_vars stack_ty res_ty
Ben Gamari's avatar
Ben Gamari committed
391
        (HsCmdArrApp arrow arg arrow_ty HsHigherOrderApp _)
392
        env_ids = do
393 394
    let
        (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
ross's avatar
ross committed
395
        (_a_ty, arg_ty) = tcSplitAppTy a_arg_ty
396

397 398
    core_arrow <- dsLExpr arrow
    core_arg   <- dsLExpr arg
399 400 401 402
    stack_id   <- newSysLocalDs stack_ty
    core_make_pair <- matchEnvStack env_ids stack_id
          (mkCorePairExpr core_arrow core_arg)

403
    return (do_premap ids
404
              (envStackType env_ids stack_ty)
405 406 407 408
              (mkCorePairTy arrow_ty arg_ty)
              res_ty
              core_make_pair
              (do_app ids arg_ty res_ty),
niteria's avatar
niteria committed
409
            (exprsFreeIdsDSet [core_arrow, core_arg])
David Feuer's avatar
David Feuer committed
410
              `udfmIntersectUFM` getUniqSet local_vars)
411

412 413 414 415
-- D; ys |-a cmd : (t,stk) --> t'
-- D, xs |-  exp :: t
-- ------------------------
-- D; xs |-a cmd exp : stk --> t'
ross's avatar
ross committed
416
--
417
--              ---> premap (\ ((xs),stk) -> ((ys),(e,stk))) cmd
ross's avatar
ross committed
418

Ben Gamari's avatar
Ben Gamari committed
419
dsCmd ids local_vars stack_ty res_ty (HsCmdApp cmd arg) env_ids = do
420
    core_arg <- dsLExpr arg
ross's avatar
ross committed
421
    let
422
        arg_ty = exprType core_arg
423
        stack_ty' = mkCorePairTy arg_ty stack_ty
424
    (core_cmd, free_vars, env_ids')
425 426
             <- dsfixCmd ids local_vars stack_ty' res_ty cmd
    stack_id <- newSysLocalDs stack_ty
Richard Eisenberg's avatar
Richard Eisenberg committed
427
    arg_id <- newSysLocalDsNoLP arg_ty
ross's avatar
ross committed
428 429
    -- push the argument expression onto the stack
    let
430
        stack' = mkCorePairExpr (Var arg_id) (Var stack_id)
431
        core_body = bindNonRec arg_id core_arg
432
                        (mkCorePairExpr (mkBigCoreVarTup env_ids') stack')
433

ross's avatar
ross committed
434
    -- match the environment and stack against the input
435
    core_map <- matchEnvStack env_ids stack_id core_body
436
    return (do_premap ids
437 438
                      (envStackType env_ids stack_ty)
                      (envStackType env_ids' stack_ty')
439 440 441
                      res_ty
                      core_map
                      core_cmd,
niteria's avatar
niteria committed
442
            free_vars `unionDVarSet`
David Feuer's avatar
David Feuer committed
443
              (exprFreeIdsDSet core_arg `udfmIntersectUFM` getUniqSet local_vars))
ross's avatar
ross committed
444

445 446 447
-- D; ys |-a cmd : stk t'
-- -----------------------------------------------
-- D; xs |-a \ p1 ... pk -> cmd : (t1,...(tk,stk)...) t'
448
--
449
--              ---> premap (\ ((xs), (p1, ... (pk,stk)...)) -> ((ys),stk)) cmd
450

451
dsCmd ids local_vars stack_ty res_ty
Ben Gamari's avatar
Ben Gamari committed
452
        (HsCmdLam (MG { mg_alts = L _ [L _ (Match { m_pats  = pats
453
                                                  , m_grhss = GRHSs [L _ (GRHS [] body)] _ })] }))
454
        env_ids = do
455
    let pat_vars = mkVarSet (collectPatsBinders pats)
456
    let
457
        local_vars' = pat_vars `unionVarSet` local_vars
458
        (pat_tys, stack_ty') = splitTypeAt (length pats) stack_ty
459
    (core_body, free_vars, env_ids') <- dsfixCmd ids local_vars' stack_ty' res_ty body
Richard Eisenberg's avatar
Richard Eisenberg committed
460
    param_ids <- mapM newSysLocalDsNoLP pat_tys
461
    stack_id' <- newSysLocalDs stack_ty'
462 463 464 465 466

    -- the expression is built from the inside out, so the actions
    -- are presented in reverse order

    let
467
        -- build a new environment, plus what's left of the stack
468 469 470
        core_expr = buildEnvStack env_ids' stack_id'
        in_ty = envStackType env_ids stack_ty
        in_ty' = envStackType env_ids' stack_ty'
471

472
    fail_expr <- mkFailExpr LambdaExpr in_ty'
473 474 475 476
    -- 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
477
    -- match the old environment and stack against the input
478
    select_code <- matchEnvStack env_ids stack_id param_code
479
    return (do_premap ids in_ty in_ty' res_ty select_code core_body,
David Feuer's avatar
David Feuer committed
480
            free_vars `udfmMinusUFM` getUniqSet pat_vars)
481

Ben Gamari's avatar
Ben Gamari committed
482
dsCmd ids local_vars stack_ty res_ty (HsCmdPar cmd) env_ids
483
  = dsLCmd ids local_vars stack_ty res_ty cmd env_ids
484

485 486 487 488 489
-- 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
ross's avatar
ross committed
490
--
491 492 493
--              ---> premap (\ ((xs),stk) ->
--                       if e then Left ((xs1),stk) else Right ((xs2),stk))
--                     (c1 ||| c2)
ross's avatar
ross committed
494

Ben Gamari's avatar
Ben Gamari committed
495
dsCmd ids local_vars stack_ty res_ty (HsCmdIf mb_fun cond then_cmd else_cmd)
496
        env_ids = do
497
    core_cond <- dsLExpr cond
498 499 500
    (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
501 502 503
    either_con <- dsLookupTyCon eitherTyConName
    left_con   <- dsLookupDataCon leftDataConName
    right_con  <- dsLookupDataCon rightDataConName
504

505 506
    let mk_left_expr ty1 ty2 e = mkCoreConApps left_con   [Type ty1, Type ty2, e]
        mk_right_expr ty1 ty2 e = mkCoreConApps right_con [Type ty1, Type ty2, e]
507

508 509 510
        in_ty = envStackType env_ids stack_ty
        then_ty = envStackType then_ids stack_ty
        else_ty = envStackType else_ids stack_ty
511
        sum_ty = mkTyConApp either_con [then_ty, else_ty]
David Feuer's avatar
David Feuer committed
512
        fvs_cond = exprFreeIdsDSet core_cond `udfmIntersectUFM` getUniqSet local_vars
513

514 515
        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)
516

517
    core_if <- case mb_fun of
518 519
       Just fun -> do { fun_apps <- dsSyntaxExpr fun [core_cond, core_left, core_right]
                      ; matchEnvStack env_ids stack_id fun_apps }
520
       Nothing  -> matchEnvStack env_ids stack_id $
521 522
                   mkIfThenElse core_cond core_left core_right

523
    return (do_premap ids in_ty sum_ty res_ty
524 525
                core_if
                (do_choice ids then_ty else_ty res_ty core_then core_else),
niteria's avatar
niteria committed
526
        fvs_cond `unionDVarSet` fvs_then `unionDVarSet` fvs_else)
ross's avatar
ross committed
527

Austin Seipp's avatar
Austin Seipp committed
528
{-
ross's avatar
ross committed
529 530 531
Case commands are treated in much the same way as if commands
(see above) except that there are more alternatives.  For example

532
        case e of { p1 -> c1; p2 -> c2; p3 -> c3 }
ross's avatar
ross committed
533 534 535

is translated to

536 537 538 539 540
        premap (\ ((xs)*ts) -> case e of
                p1 -> (Left (Left (xs1)*ts))
                p2 -> Left ((Right (xs2)*ts))
                p3 -> Right ((xs3)*ts))
        ((c1 ||| c2) ||| c3)
ross's avatar
ross committed
541 542 543 544

The idea is to extract the commands from the case, build a balanced tree
of choices, and replace the commands with expressions that build tagged
tuples, obtaining a case expression that can be desugared normally.
545
To build all this, we use triples describing segments of the list of
ross's avatar
ross committed
546
case bodies, containing the following fields:
547
 * a list of expressions of the form (Left|Right)* ((xs)*ts), to be put
ross's avatar
ross committed
548
   into the case replacing the commands
549
 * a sum type that is the common type of these expressions, and also the
ross's avatar
ross committed
550
   input type of the arrow
551
 * a CoreExpr for an arrow built by combining the translated command
ross's avatar
ross committed
552
   bodies with |||.
Austin Seipp's avatar
Austin Seipp committed
553
-}
ross's avatar
ross committed
554

555
dsCmd ids local_vars stack_ty res_ty
Ben Gamari's avatar
Ben Gamari committed
556 557
      (HsCmdCase exp (MG { mg_alts = L l matches, mg_arg_tys = arg_tys
                         , mg_origin = origin }))
558
      env_ids = do
559
    stack_id <- newSysLocalDs stack_ty
560 561 562 563 564 565

    -- Extract and desugar the leaf commands in the case, building tuple
    -- expressions that will (after tagging) replace these leaves

    let
        leaves = concatMap leavesMatch matches
566
        make_branch (leaf, bound_vars) = do
567
            (core_leaf, _fvs, leaf_ids) <-
568 569 570
                  dsfixCmd ids (bound_vars `unionVarSet` local_vars) stack_ty res_ty leaf
            return ([mkHsEnvStackExpr leaf_ids stack_id],
                    envStackType leaf_ids stack_ty,
571
                    core_leaf)
572

573 574 575 576
    branches <- mapM make_branch leaves
    either_con <- dsLookupTyCon eitherTyConName
    left_con <- dsLookupDataCon leftDataConName
    right_con <- dsLookupDataCon rightDataConName
577
    let
Ben Gamari's avatar
Ben Gamari committed
578 579 580 581
        left_id  = HsConLikeOut (RealDataCon left_con)
        right_id = HsConLikeOut (RealDataCon right_con)
        left_expr  ty1 ty2 e = noLoc $ HsApp (noLoc $ mkHsWrap (mkWpTyApps [ty1, ty2]) left_id ) e
        right_expr ty1 ty2 e = noLoc $ HsApp (noLoc $ mkHsWrap (mkWpTyApps [ty1, ty2]) right_id) e
582

583 584
        -- Prefix each tuple with a distinct series of Left's and Right's,
        -- in a balanced way, keeping track of the types.
585

586 587 588
        merge_branches (builds1, in_ty1, core_exp1)
                       (builds2, in_ty2, core_exp2)
          = (map (left_expr in_ty1 in_ty2) builds1 ++
589 590 591
                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)
592
        (leaves', sum_ty, core_choices) = foldb merge_branches branches
593 594 595 596 597

        -- Replace the commands in the case with these tagged tuples,
        -- yielding a HsExpr Id we can feed to dsExpr.

        (_, matches') = mapAccumL (replaceLeavesMatch res_ty) leaves' matches
598
        in_ty = envStackType env_ids stack_ty
599

Ben Gamari's avatar
Ben Gamari committed
600 601 602
    core_body <- dsExpr (HsCase exp (MG { mg_alts = L l matches'
                                        , mg_arg_tys = arg_tys
                                        , mg_res_ty = sum_ty, mg_origin = origin }))
603 604
        -- Note that we replace the HsCase result type by sum_ty,
        -- which is the type of matches'
605

606
    core_matches <- matchEnvStack env_ids stack_id core_body
607
    return (do_premap ids in_ty sum_ty res_ty core_matches core_choices,
David Feuer's avatar
David Feuer committed
608
            exprFreeIdsDSet core_body `udfmIntersectUFM` getUniqSet local_vars)
609

610 611 612
-- D; ys |-a cmd : stk --> t
-- ----------------------------------
-- D; xs |-a let binds in cmd : stk --> t
613
--
614
--              ---> premap (\ ((xs),stk) -> let binds in ((ys),stk)) c
615

Ben Gamari's avatar
Ben Gamari committed
616
dsCmd ids local_vars stack_ty res_ty (HsCmdLet lbinds@(L _ binds) body) env_ids = do
617
    let
618
        defined_vars = mkVarSet (collectLocalBinders binds)
619
        local_vars' = defined_vars `unionVarSet` local_vars
620

621 622
    (core_body, _free_vars, env_ids') <- dsfixCmd ids local_vars' stack_ty res_ty body
    stack_id <- newSysLocalDs stack_ty
623
    -- build a new environment, plus the stack, using the let bindings
Richard Eisenberg's avatar
Richard Eisenberg committed
624
    core_binds <- dsLocalBinds lbinds (buildEnvStack env_ids' stack_id)
625
    -- match the old environment and stack against the input
626
    core_map <- matchEnvStack env_ids stack_id core_binds
627
    return (do_premap ids
628 629
                        (envStackType env_ids stack_ty)
                        (envStackType env_ids' stack_ty)
630 631 632
                        res_ty
                        core_map
                        core_body,
David Feuer's avatar
David Feuer committed
633
        exprFreeIdsDSet core_binds `udfmIntersectUFM` getUniqSet local_vars)
634

635 636 637 638
-- D; xs |-a ss : t
-- ----------------------------------
-- D; xs |-a do { ss } : () --> t
--
639
--              ---> premap (\ (env,stk) -> env) c
640

Ben Gamari's avatar
Ben Gamari committed
641
dsCmd ids local_vars stack_ty res_ty do_block@(HsCmdDo (L loc stmts) stmts_ty) env_ids = do
Richard Eisenberg's avatar
Richard Eisenberg committed
642 643 644
    putSrcSpanDs loc $
      dsNoLevPoly stmts_ty
        (text "In the do-command:" <+> ppr do_block)
645 646 647 648
    (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
649 650 651 652 653 654
                (mkCorePairTy env_ty stack_ty)
                env_ty
                res_ty
                core_fst
                core_stmts,
        env_ids')
655 656 657 658

-- D |- e :: forall e. a1 (e,stk1) t1 -> ... an (e,stkn) tn -> a (e,stk) t
-- D; xs |-a ci :: stki --> ti
-- -----------------------------------
659
-- D; xs |-a (|e c1 ... cn|) :: stk --> t       ---> e [t_xs] c1 ... cn
660

Ben Gamari's avatar
Ben Gamari committed
661
dsCmd _ids local_vars _stack_ty _res_ty (HsCmdArrForm op _ _ args) env_ids = do
662 663 664 665
    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,
niteria's avatar
niteria committed
666
            unionDVarSets fv_sets)
667

Ben Gamari's avatar
Ben Gamari committed
668
dsCmd ids local_vars stack_ty res_ty (HsCmdWrap wrap cmd) env_ids = do
669
    (core_cmd, env_ids') <- dsCmd ids local_vars stack_ty res_ty cmd env_ids
Simon Peyton Jones's avatar
Simon Peyton Jones committed
670 671
    core_wrap <- dsHsWrapper wrap
    return (core_wrap core_cmd, env_ids')
672

Ian Lynagh's avatar
Ian Lynagh committed
673 674
dsCmd _ _ _ _ _ c = pprPanic "dsCmd" (ppr c)

675
-- D; ys |-a c : stk --> t      (ys <= xs)
676
-- ---------------------
677
-- D; xs |-a c : stk --> t      ---> premap (\ ((xs),stk) -> ((ys),stk)) c
678 679

dsTrimCmdArg
680
        :: IdSet                -- set of local vars available to this command
681 682
        -> [Id]           -- list of vars in the input to this command
        -> LHsCmdTop GhcTc       -- command argument to desugar
683
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
684
                DIdSet)         -- subset of local vars that occur free
Ben Gamari's avatar
Ben Gamari committed
685
dsTrimCmdArg local_vars env_ids (L _ (HsCmdTop cmd stack_ty cmd_ty ids)) = do
686
    (meth_binds, meth_ids) <- mkCmdEnv ids
687 688 689
    (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)
690
    let
691 692
        in_ty = envStackType env_ids stack_ty
        in_ty' = envStackType env_ids' stack_ty
693
        arg_code = if env_ids' == env_ids then core_cmd else
694
                do_premap meth_ids in_ty in_ty' cmd_ty trim_code core_cmd
695
    return (mkLets meth_binds arg_code, free_vars)
696

697 698
-- Given D; xs |-a c : stk --> t, builds c with xs fed back.
-- Typically needs to be prefixed with arr (\(p, stk) -> ((xs),stk))
699 700

dsfixCmd
701 702 703 704
        :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this command
        -> Type                 -- type of the stack (right-nested tuple)
        -> Type                 -- return type of the command
705
        -> LHsCmd GhcTc         -- command to desugar
706
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
707
                DIdSet,         -- subset of local vars that occur free
708
                [Id])           -- the same local vars as a list, fed back
709
dsfixCmd ids local_vars stk_ty cmd_ty cmd
Richard Eisenberg's avatar
Richard Eisenberg committed
710 711 712
  = do { putSrcSpanDs (getLoc cmd) $ dsNoLevPoly cmd_ty
           (text "When desugaring the command:" <+> ppr cmd)
       ; trimInput (dsLCmd ids local_vars stk_ty cmd_ty cmd) }
713 714 715 716 717

-- Feed back the list of local variables actually used a command,
-- for use as the input tuple of the generated arrow.

trimInput
niteria's avatar
niteria committed
718
        :: ([Id] -> DsM (CoreExpr, DIdSet))
719
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
720
                DIdSet,         -- subset of local vars that occur free
721 722 723
                [Id])           -- same local vars as a list, fed back to
                                -- the inner function to form the tuple of
                                -- inputs to the arrow.
724 725 726
trimInput build_arrow
  = fixDs (\ ~(_,_,env_ids) -> do
        (core_cmd, free_vars) <- build_arrow env_ids
niteria's avatar
niteria committed
727
        return (core_cmd, free_vars, dVarSetElems free_vars))
728

Austin Seipp's avatar
Austin Seipp committed
729
{-
730 731
Translation of command judgements of the form

732
        D |-a do { ss } : t
Austin Seipp's avatar
Austin Seipp committed
733
-}
734

735 736 737
dsCmdDo :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this statement
        -> Type                 -- return type of the statement
738
        -> [CmdLStmt GhcTc]     -- statements to desugar
739 740 741 742
        -> [Id]                 -- list of vars in the input to this statement
                                -- This is typically fed back,
                                -- so don't pull on it too early
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
743
                DIdSet)         -- subset of local vars that occur free
744

745
dsCmdDo _ _ _ [] _ = panic "dsCmdDo"
746

747 748 749 750
-- D; xs |-a c : () --> t
-- --------------------------
-- D; xs |-a do { c } : t
--
751
--              ---> premap (\ (xs) -> ((xs), ())) c
752

Richard Eisenberg's avatar
Richard Eisenberg committed
753 754 755
dsCmdDo ids local_vars res_ty [L loc (LastStmt body _ _)] env_ids = do
    putSrcSpanDs loc $ dsNoLevPoly res_ty
                         (text "In the command:" <+> ppr body)
756 757 758 759 760 761
    (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
762
                        (mkCorePairTy env_ty unitTy)
763 764 765
                        res_ty
                        core_map
                        core_body,
766
        env_ids')
767

768
dsCmdDo ids local_vars res_ty (stmt:stmts) env_ids = do
769 770
    let bound_vars  = mkVarSet (collectLStmtBinders stmt)
    let local_vars' = bound_vars `unionVarSet` local_vars
771 772
    (core_stmts, _, env_ids') <- trimInput (dsCmdDo ids local_vars' res_ty stmts)
    (core_stmt, fv_stmt) <- dsCmdLStmt ids local_vars env_ids' stmt env_ids
773 774 775 776 777 778 779
    return (do_compose ids
                (mkBigCoreVarTupTy env_ids)
                (mkBigCoreVarTupTy env_ids')
                res_ty
                core_stmt
                core_stmts,
              fv_stmt)
780

Austin Seipp's avatar
Austin Seipp committed
781
{-
ross's avatar
ross committed
782 783 784
A statement maps one local environment to another, and is represented
as an arrow from one tuple type to another.  A statement sequence is
translated to a composition of such arrows.
Austin Seipp's avatar
Austin Seipp committed
785 786
-}

787
dsCmdLStmt :: DsCmdEnv -> IdSet -> [Id] -> CmdLStmt GhcTc -> [Id]
niteria's avatar
niteria committed
788
           -> DsM (CoreExpr, DIdSet)
789 790
dsCmdLStmt ids local_vars out_ids cmd env_ids
  = dsCmdStmt ids local_vars out_ids (unLoc cmd) env_ids
ross's avatar
ross committed
791

792
dsCmdStmt
793 794 795
        :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this statement
        -> [Id]                 -- list of vars in the output of this statement
796
        -> CmdStmt GhcTc        -- statement to desugar