DsArrows.hs 48.3 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 #-}
11
{-# LANGUAGE ViewPatterns #-}
Ian Lynagh's avatar
Ian Lynagh committed
12

13 14 15 16
module DsArrows ( dsProcExpr ) where

#include "HsVersions.h"

17 18
import GhcPrelude

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

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

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

34 35
import {-# SOURCE #-} DsExpr ( dsExpr, dsLExpr, dsLExprNoLP, dsLocalBinds,
                               dsSyntaxExpr )
36

Simon Marlow's avatar
Simon Marlow committed
37
import TcType
Richard Eisenberg's avatar
Richard Eisenberg committed
38
import Type ( splitPiTy )
39
import TcEvidence
40
import CoreSyn
Simon Marlow's avatar
Simon Marlow committed
41 42
import CoreFVs
import CoreUtils
43
import MkCore
44
import DsBinds (dsHsWrapper)
45

Simon Marlow's avatar
Simon Marlow committed
46
import Name
47
import Id
Richard Eisenberg's avatar
Richard Eisenberg committed
48
import ConLike
Simon Marlow's avatar
Simon Marlow committed
49 50 51
import TysWiredIn
import BasicTypes
import PrelNames
Ian Lynagh's avatar
Ian Lynagh committed
52
import Outputable
53
import Bag
Simon Marlow's avatar
Simon Marlow committed
54 55
import VarSet
import SrcLoc
Richard Eisenberg's avatar
Richard Eisenberg committed
56
import ListSetOps( assocMaybe )
57
import Data.List
niteria's avatar
niteria committed
58
import Util
Sebastian Graf's avatar
Sebastian Graf committed
59
import UniqDSet
60 61

data DsCmdEnv = DsCmdEnv {
62
        arr_id, compose_id, first_id, app_id, choice_id, loop_id :: CoreExpr
63 64
    }

65
mkCmdEnv :: CmdSyntaxTable GhcTc -> DsM ([CoreBind], DsCmdEnv)
66 67 68
-- See Note [CmdSyntaxTable] in HsExpr
mkCmdEnv tc_meths
  = do { (meth_binds, prs) <- mapAndUnzipM mk_bind tc_meths
Richard Eisenberg's avatar
Richard Eisenberg committed
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 96 97 98

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

99
       ; return (meth_binds, DsCmdEnv {
Richard Eisenberg's avatar
Richard Eisenberg committed
100 101 102 103 104 105
               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)
106 107 108 109
             }) }
  where
    mk_bind (std_name, expr)
      = do { rhs <- dsExpr expr
110 111
           ; id <- newSysLocalDs (exprType rhs)
           -- no check needed; these are functions
112
           ; return (NonRec id rhs, (std_name, id)) }
113

Richard Eisenberg's avatar
Richard Eisenberg committed
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    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))

131 132 133 134 135 136 137

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

164 165 166
-- 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 ->
167
                CoreExpr -> CoreExpr -> CoreExpr
168 169
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
170

171
mkFailExpr :: HsMatchContext Id -> Type -> DsM CoreExpr
172 173 174
mkFailExpr ctxt ty
  = mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt)

175 176 177 178 179 180 181 182 183
-- 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)))

184 185
-- construct CoreExpr for \ (a :: a_ty, b :: b_ty) -> b
mkSndExpr :: Type -> Type -> DsM CoreExpr
186 187 188 189 190 191
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)))
192

Austin Seipp's avatar
Austin Seipp committed
193
{-
194 195
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
196
-}
197 198

-- coreCaseTuple [u1..] v [x1..xn] body
199
--      = case v of v { (x1, .., xn) -> body }
200 201 202
-- But the matching may be nested if the tuple is very big

coreCaseTuple :: UniqSupply -> Id -> [Id] -> CoreExpr -> CoreExpr
ross's avatar
ross committed
203 204
coreCaseTuple uniqs scrut_var vars body
  = mkTupleCase uniqs vars body scrut_var (Var scrut_var)
205

ross's avatar
ross committed
206 207
coreCasePair :: Id -> Id -> Id -> CoreExpr -> CoreExpr
coreCasePair scrut_var var1 var2 body
208
  = Case (Var scrut_var) scrut_var (exprType body)
209
         [(DataAlt (tupleDataCon Boxed 2), [var1, var2], body)]
210 211

mkCorePairTy :: Type -> Type -> Type
simonpj@microsoft.com's avatar
simonpj@microsoft.com committed
212
mkCorePairTy t1 t2 = mkBoxedTupleTy [t1, t2]
213 214 215

mkCorePairExpr :: CoreExpr -> CoreExpr -> CoreExpr
mkCorePairExpr e1 e2 = mkCoreTup [e1, e2]
216 217 218

mkCoreUnitExpr :: CoreExpr
mkCoreUnitExpr = mkCoreTup []
219

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

225
        ((x1,...,xn), (s1,...(sk,())...))
226 227 228

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
229
-}
230

231 232 233 234 235 236 237 238 239 240
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)
241 242

----------------------------------------------
243
--              buildEnvStack
244
--
245
--      ((x1,...,xn),stk)
246

247 248 249
buildEnvStack :: [Id] -> Id -> CoreExpr
buildEnvStack env_ids stack_id
  = mkCorePairExpr (mkBigCoreVarTup env_ids) (Var stack_id)
250 251

----------------------------------------------
252
--              matchEnvStack
253
--
254 255 256 257 258 259 260 261 262 263 264
--      \ ((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
265
matchEnvStack env_ids stack_id body = do
266 267
    uniqs <- newUniqueSupply
    tup_var <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
268 269 270
    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))
271

272
----------------------------------------------
273
--              matchEnv
274
--
275 276 277 278 279 280 281 282 283
--      \ (x1,...,xn) -> body
--      =>
--      \ tup ->
--      case tup of (x1,...,xn) ->
--      body

matchEnv :: [Id]        -- x1..xn
         -> CoreExpr    -- e
         -> DsM CoreExpr
284 285 286 287
matchEnv env_ids body = do
    uniqs <- newUniqueSupply
    tup_id <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
    return (Lam tup_id (coreCaseTuple uniqs tup_id env_ids body))
288 289

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

304
mkHsEnvStackExpr :: [Id] -> Id -> LHsExpr GhcTc
305 306
mkHsEnvStackExpr env_ids stack_id
  = mkLHsTupleExpr [mkLHsVarTuple env_ids, nlHsVar stack_id]
307

Austin Seipp's avatar
Austin Seipp committed
308
-- Translation of arrow abstraction
309

310
-- D; xs |-a c : () --> t'      ---> c'
311
-- --------------------------
312
-- D |- proc p -> c :: a t t'   ---> premap (\ p -> ((xs),())) c'
313
--
314
--              where (xs) is the tuple of variables bound by p
315 316

dsProcExpr
317 318
        :: LPat GhcTc
        -> LHsCmdTop GhcTc
319
        -> DsM CoreExpr
320
dsProcExpr pat (dL->L _ (HsCmdTop (CmdTopTc _unitTy cmd_ty ids) cmd)) = do
321
    (meth_binds, meth_ids) <- mkCmdEnv ids
322
    let locals = mkVarSet (collectPatBinders pat)
323 324
    (core_cmd, _free_vars, env_ids)
       <- dsfixCmd meth_ids locals unitTy cmd_ty cmd
325
    let env_ty = mkBigCoreVarTupTy env_ids
326 327 328
    let env_stk_ty = mkCorePairTy env_ty unitTy
    let env_stk_expr = mkCorePairExpr (mkBigCoreVarTup env_ids) mkCoreUnitExpr
    fail_expr <- mkFailExpr ProcExpr env_stk_ty
329
    var <- selectSimpleMatchVarL pat
330
    match_code <- matchSimply (Var var) ProcExpr pat env_stk_expr fail_expr
331
    let pat_ty = hsLPatType pat
332
    let proc_code = do_premap meth_ids pat_ty env_stk_ty cmd_ty
333 334
                    (Lam var match_code)
                    core_cmd
335
    return (mkLets meth_binds proc_code)
336
dsProcExpr _ _ = panic "dsProcExpr"
337

Austin Seipp's avatar
Austin Seipp committed
338
{-
339 340
Translation of a command judgement of the form

341
        D; xs |-a c : stk --> t
342 343

to an expression e such that
344

345
        D |- e :: a (xs, stk) t
Austin Seipp's avatar
Austin Seipp committed
346
-}
347

348
dsLCmd :: DsCmdEnv -> IdSet -> Type -> Type -> LHsCmd GhcTc -> [Id]
niteria's avatar
niteria committed
349
       -> DsM (CoreExpr, DIdSet)
350 351
dsLCmd ids local_vars stk_ty res_ty cmd env_ids
  = dsCmd ids local_vars stk_ty res_ty (unLoc cmd) env_ids
352

353 354 355 356
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
357 358
        -> HsCmd GhcTc           -- command to desugar
        -> [Id]           -- list of vars in the input to this command
359 360 361
                                -- This is typically fed back,
                                -- so don't pull on it too early
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
362
                DIdSet)         -- subset of local vars that occur free
363

364 365 366 367
-- D |- fun :: a t1 t2
-- D, xs |- arg :: t1
-- -----------------------------
-- D; xs |-a fun -< arg : stk --> t2
ross's avatar
ross committed
368
--
369
--              ---> premap (\ ((xs), _stk) -> arg) fun
370

371
dsCmd ids local_vars stack_ty res_ty
372
        (HsCmdArrApp arrow_ty arrow arg HsFirstOrderApp _)
373
        env_ids = do
374 375
    let
        (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
ross's avatar
ross committed
376
        (_a_ty, arg_ty) = tcSplitAppTy a_arg_ty
Richard Eisenberg's avatar
Richard Eisenberg committed
377
    core_arrow <- dsLExprNoLP arrow
378
    core_arg   <- dsLExpr arg
379 380
    stack_id   <- newSysLocalDs stack_ty
    core_make_arg <- matchEnvStack env_ids stack_id core_arg
381
    return (do_premap ids
382
              (envStackType env_ids stack_ty)
383 384 385 386
              arg_ty
              res_ty
              core_make_arg
              core_arrow,
Sebastian Graf's avatar
Sebastian Graf committed
387
            exprFreeIdsDSet core_arg `uniqDSetIntersectUniqSet` local_vars)
388

389 390 391 392
-- D, xs |- fun :: a t1 t2
-- D, xs |- arg :: t1
-- ------------------------------
-- D; xs |-a fun -<< arg : stk --> t2
ross's avatar
ross committed
393
--
394
--              ---> premap (\ ((xs), _stk) -> (fun, arg)) app
395

396
dsCmd ids local_vars stack_ty res_ty
397
        (HsCmdArrApp arrow_ty arrow arg HsHigherOrderApp _)
398
        env_ids = do
399 400
    let
        (a_arg_ty, _res_ty') = tcSplitAppTy arrow_ty
ross's avatar
ross committed
401
        (_a_ty, arg_ty) = tcSplitAppTy a_arg_ty
402

403 404
    core_arrow <- dsLExpr arrow
    core_arg   <- dsLExpr arg
405 406 407 408
    stack_id   <- newSysLocalDs stack_ty
    core_make_pair <- matchEnvStack env_ids stack_id
          (mkCorePairExpr core_arrow core_arg)

409
    return (do_premap ids
410
              (envStackType env_ids stack_ty)
411 412 413 414
              (mkCorePairTy arrow_ty arg_ty)
              res_ty
              core_make_pair
              (do_app ids arg_ty res_ty),
niteria's avatar
niteria committed
415
            (exprsFreeIdsDSet [core_arrow, core_arg])
Sebastian Graf's avatar
Sebastian Graf committed
416
              `uniqDSetIntersectUniqSet` local_vars)
417

418 419 420 421
-- D; ys |-a cmd : (t,stk) --> t'
-- D, xs |-  exp :: t
-- ------------------------
-- D; xs |-a cmd exp : stk --> t'
ross's avatar
ross committed
422
--
423
--              ---> premap (\ ((xs),stk) -> ((ys),(e,stk))) cmd
ross's avatar
ross committed
424

425
dsCmd ids local_vars stack_ty res_ty (HsCmdApp _ cmd arg) env_ids = do
426
    core_arg <- dsLExpr arg
ross's avatar
ross committed
427
    let
428
        arg_ty = exprType core_arg
429
        stack_ty' = mkCorePairTy arg_ty stack_ty
430
    (core_cmd, free_vars, env_ids')
431 432
             <- dsfixCmd ids local_vars stack_ty' res_ty cmd
    stack_id <- newSysLocalDs stack_ty
Richard Eisenberg's avatar
Richard Eisenberg committed
433
    arg_id <- newSysLocalDsNoLP arg_ty
ross's avatar
ross committed
434 435
    -- push the argument expression onto the stack
    let
436
        stack' = mkCorePairExpr (Var arg_id) (Var stack_id)
437
        core_body = bindNonRec arg_id core_arg
438
                        (mkCorePairExpr (mkBigCoreVarTup env_ids') stack')
439

ross's avatar
ross committed
440
    -- match the environment and stack against the input
441
    core_map <- matchEnvStack env_ids stack_id core_body
442
    return (do_premap ids
443 444
                      (envStackType env_ids stack_ty)
                      (envStackType env_ids' stack_ty')
445 446 447
                      res_ty
                      core_map
                      core_cmd,
niteria's avatar
niteria committed
448
            free_vars `unionDVarSet`
Sebastian Graf's avatar
Sebastian Graf committed
449
              (exprFreeIdsDSet core_arg `uniqDSetIntersectUniqSet` local_vars))
ross's avatar
ross committed
450

451 452 453
-- D; ys |-a cmd : stk t'
-- -----------------------------------------------
-- D; xs |-a \ p1 ... pk -> cmd : (t1,...(tk,stk)...) t'
454
--
455
--              ---> premap (\ ((xs), (p1, ... (pk,stk)...)) -> ((ys),stk)) cmd
456

457
dsCmd ids local_vars stack_ty res_ty
458
        (HsCmdLam _ (MG { mg_alts
459 460
          = (dL->L _ [dL->L _ (Match { m_pats  = pats
                       , m_grhss = GRHSs _ [dL->L _ (GRHS _ [] body)] _ })]) }))
461
        env_ids = do
462
    let pat_vars = mkVarSet (collectPatsBinders pats)
463
    let
464
        local_vars' = pat_vars `unionVarSet` local_vars
465
        (pat_tys, stack_ty') = splitTypeAt (length pats) stack_ty
466 467
    (core_body, free_vars, env_ids')
       <- dsfixCmd ids local_vars' stack_ty' res_ty body
Richard Eisenberg's avatar
Richard Eisenberg committed
468
    param_ids <- mapM newSysLocalDsNoLP pat_tys
469
    stack_id' <- newSysLocalDs stack_ty'
470 471 472 473 474

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

    let
475
        -- build a new environment, plus what's left of the stack
476 477 478
        core_expr = buildEnvStack env_ids' stack_id'
        in_ty = envStackType env_ids stack_ty
        in_ty' = envStackType env_ids' stack_ty'
479

480
    fail_expr <- mkFailExpr LambdaExpr in_ty'
481
    -- match the patterns against the parameters
482 483
    match_code <- matchSimplys (map Var param_ids) LambdaExpr pats core_expr
                    fail_expr
484 485
    -- match the parameters against the top of the old stack
    (stack_id, param_code) <- matchVarStack param_ids stack_id' match_code
486
    -- match the old environment and stack against the input
487
    select_code <- matchEnvStack env_ids stack_id param_code
488
    return (do_premap ids in_ty in_ty' res_ty select_code core_body,
Sebastian Graf's avatar
Sebastian Graf committed
489
            free_vars `uniqDSetMinusUniqSet` pat_vars)
490

491
dsCmd ids local_vars stack_ty res_ty (HsCmdPar _ cmd) env_ids
492
  = dsLCmd ids local_vars stack_ty res_ty cmd env_ids
493

494 495 496 497 498
-- 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
499
--
500 501 502
--              ---> premap (\ ((xs),stk) ->
--                       if e then Left ((xs1),stk) else Right ((xs2),stk))
--                     (c1 ||| c2)
ross's avatar
ross committed
503

504
dsCmd ids local_vars stack_ty res_ty (HsCmdIf _ mb_fun cond then_cmd else_cmd)
505
        env_ids = do
506
    core_cond <- dsLExpr cond
507 508 509 510
    (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
511
    stack_id   <- newSysLocalDs stack_ty
512 513 514
    either_con <- dsLookupTyCon eitherTyConName
    left_con   <- dsLookupDataCon leftDataConName
    right_con  <- dsLookupDataCon rightDataConName
515

516 517
    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]
518

519 520 521
        in_ty = envStackType env_ids stack_ty
        then_ty = envStackType then_ids stack_ty
        else_ty = envStackType else_ids stack_ty
522
        sum_ty = mkTyConApp either_con [then_ty, else_ty]
523 524
        fvs_cond = exprFreeIdsDSet core_cond
                   `uniqDSetIntersectUniqSet` local_vars
525

526 527 528 529
        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)
530

531
    core_if <- case mb_fun of
532 533
       Just fun -> do { fun_apps <- dsSyntaxExpr fun
                                      [core_cond, core_left, core_right]
534
                      ; matchEnvStack env_ids stack_id fun_apps }
535
       Nothing  -> matchEnvStack env_ids stack_id $
536 537
                   mkIfThenElse core_cond core_left core_right

538
    return (do_premap ids in_ty sum_ty res_ty
539 540
                core_if
                (do_choice ids then_ty else_ty res_ty core_then core_else),
niteria's avatar
niteria committed
541
        fvs_cond `unionDVarSet` fvs_then `unionDVarSet` fvs_else)
ross's avatar
ross committed
542

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

547
        case e of { p1 -> c1; p2 -> c2; p3 -> c3 }
ross's avatar
ross committed
548 549 550

is translated to

551 552 553 554 555
        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
556 557 558 559

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.
560
To build all this, we use triples describing segments of the list of
ross's avatar
ross committed
561
case bodies, containing the following fields:
562
 * a list of expressions of the form (Left|Right)* ((xs)*ts), to be put
ross's avatar
ross committed
563
   into the case replacing the commands
564
 * a sum type that is the common type of these expressions, and also the
ross's avatar
ross committed
565
   input type of the arrow
566
 * a CoreExpr for an arrow built by combining the translated command
ross's avatar
ross committed
567
   bodies with |||.
Austin Seipp's avatar
Austin Seipp committed
568
-}
ross's avatar
ross committed
569

570
dsCmd ids local_vars stack_ty res_ty
571
      (HsCmdCase _ exp (MG { mg_alts = (dL->L l matches)
572
                           , mg_ext = MatchGroupTc arg_tys _
573
                           , mg_origin = origin }))
574
      env_ids = do
575
    stack_id <- newSysLocalDs stack_ty
576 577 578 579 580 581

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

    let
        leaves = concatMap leavesMatch matches
582
        make_branch (leaf, bound_vars) = do
583 584 585
            (core_leaf, _fvs, leaf_ids)
               <- dsfixCmd ids (bound_vars `unionVarSet` local_vars) stack_ty
                    res_ty leaf
586 587
            return ([mkHsEnvStackExpr leaf_ids stack_id],
                    envStackType leaf_ids stack_ty,
588
                    core_leaf)
589

590 591 592 593
    branches <- mapM make_branch leaves
    either_con <- dsLookupTyCon eitherTyConName
    left_con <- dsLookupDataCon leftDataConName
    right_con <- dsLookupDataCon rightDataConName
594
    let
595 596 597 598 599 600
        left_id  = HsConLikeOut noExt (RealDataCon left_con)
        right_id = HsConLikeOut noExt (RealDataCon right_con)
        left_expr  ty1 ty2 e = noLoc $ HsApp noExt
                           (noLoc $ mkHsWrap (mkWpTyApps [ty1, ty2]) left_id ) e
        right_expr ty1 ty2 e = noLoc $ HsApp noExt
                           (noLoc $ mkHsWrap (mkWpTyApps [ty1, ty2]) right_id) e
601

602 603
        -- Prefix each tuple with a distinct series of Left's and Right's,
        -- in a balanced way, keeping track of the types.
604

605 606 607
        merge_branches (builds1, in_ty1, core_exp1)
                       (builds2, in_ty2, core_exp2)
          = (map (left_expr in_ty1 in_ty2) builds1 ++
608 609 610
                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)
611
        (leaves', sum_ty, core_choices) = foldb merge_branches branches
612 613 614 615 616

        -- 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
617
        in_ty = envStackType env_ids stack_ty
618

619
    core_body <- dsExpr (HsCase noExt exp
620
                         (MG { mg_alts = cL l matches'
621 622
                             , mg_ext = MatchGroupTc arg_tys sum_ty
                             , mg_origin = origin }))
623 624
        -- Note that we replace the HsCase result type by sum_ty,
        -- which is the type of matches'
625

626
    core_matches <- matchEnvStack env_ids stack_id core_body
627
    return (do_premap ids in_ty sum_ty res_ty core_matches core_choices,
Sebastian Graf's avatar
Sebastian Graf committed
628
            exprFreeIdsDSet core_body `uniqDSetIntersectUniqSet` local_vars)
629

630 631 632
-- D; ys |-a cmd : stk --> t
-- ----------------------------------
-- D; xs |-a let binds in cmd : stk --> t
633
--
634
--              ---> premap (\ ((xs),stk) -> let binds in ((ys),stk)) c
635

636
dsCmd ids local_vars stack_ty res_ty (HsCmdLet _ lbinds@(dL->L _ binds) body)
637
                                                                    env_ids = do
638
    let
639
        defined_vars = mkVarSet (collectLocalBinders binds)
640
        local_vars' = defined_vars `unionVarSet` local_vars
641

642 643
    (core_body, _free_vars, env_ids')
       <- dsfixCmd ids local_vars' stack_ty res_ty body
644
    stack_id <- newSysLocalDs stack_ty
645
    -- build a new environment, plus the stack, using the let bindings
Richard Eisenberg's avatar
Richard Eisenberg committed
646
    core_binds <- dsLocalBinds lbinds (buildEnvStack env_ids' stack_id)
647
    -- match the old environment and stack against the input
648
    core_map <- matchEnvStack env_ids stack_id core_binds
649
    return (do_premap ids
650 651
                        (envStackType env_ids stack_ty)
                        (envStackType env_ids' stack_ty)
652 653 654
                        res_ty
                        core_map
                        core_body,
Sebastian Graf's avatar
Sebastian Graf committed
655
        exprFreeIdsDSet core_binds `uniqDSetIntersectUniqSet` local_vars)
656

657 658 659 660
-- D; xs |-a ss : t
-- ----------------------------------
-- D; xs |-a do { ss } : () --> t
--
661
--              ---> premap (\ (env,stk) -> env) c
662

663 664
dsCmd ids local_vars stack_ty res_ty do_block@(HsCmdDo stmts_ty
                                               (dL->L loc stmts))
665
                                                                   env_ids = do
Richard Eisenberg's avatar
Richard Eisenberg committed
666 667 668
    putSrcSpanDs loc $
      dsNoLevPoly stmts_ty
        (text "In the do-command:" <+> ppr do_block)
669 670 671 672
    (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
673 674 675 676 677 678
                (mkCorePairTy env_ty stack_ty)
                env_ty
                res_ty
                core_fst
                core_stmts,
        env_ids')
679 680 681 682

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

685
dsCmd _ local_vars _stack_ty _res_ty (HsCmdArrForm _ op _ _ args) env_ids = do
686 687 688 689
    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
690
            unionDVarSets fv_sets)
691

692
dsCmd ids local_vars stack_ty res_ty (HsCmdWrap _ wrap cmd) env_ids = do
693
    (core_cmd, env_ids') <- dsCmd ids local_vars stack_ty res_ty cmd env_ids
Simon Peyton Jones's avatar
Simon Peyton Jones committed
694 695
    core_wrap <- dsHsWrapper wrap
    return (core_wrap core_cmd, env_ids')
696

Ian Lynagh's avatar
Ian Lynagh committed
697 698
dsCmd _ _ _ _ _ c = pprPanic "dsCmd" (ppr c)

699
-- D; ys |-a c : stk --> t      (ys <= xs)
700
-- ---------------------
701
-- D; xs |-a c : stk --> t      ---> premap (\ ((xs),stk) -> ((ys),stk)) c
702 703

dsTrimCmdArg
704
        :: IdSet                -- set of local vars available to this command
705 706
        -> [Id]           -- list of vars in the input to this command
        -> LHsCmdTop GhcTc       -- command argument to desugar
707
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
708
                DIdSet)         -- subset of local vars that occur free
709
dsTrimCmdArg local_vars env_ids
710 711
                       (dL->L _ (HsCmdTop
                                 (CmdTopTc stack_ty cmd_ty ids) cmd )) = do
712
    (meth_binds, meth_ids) <- mkCmdEnv ids
713 714
    (core_cmd, free_vars, env_ids')
       <- dsfixCmd meth_ids local_vars stack_ty cmd_ty cmd
715
    stack_id <- newSysLocalDs stack_ty
716 717
    trim_code
      <- matchEnvStack env_ids stack_id (buildEnvStack env_ids' stack_id)
718
    let
719 720
        in_ty = envStackType env_ids stack_ty
        in_ty' = envStackType env_ids' stack_ty
721
        arg_code = if env_ids' == env_ids then core_cmd else
722
                do_premap meth_ids in_ty in_ty' cmd_ty trim_code core_cmd
723
    return (mkLets meth_binds arg_code, free_vars)
724
dsTrimCmdArg _ _ _ = panic "dsTrimCmdArg"
725

726 727
-- Given D; xs |-a c : stk --> t, builds c with xs fed back.
-- Typically needs to be prefixed with arr (\(p, stk) -> ((xs),stk))
728 729

dsfixCmd
730 731 732 733
        :: 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
734
        -> LHsCmd GhcTc         -- command to desugar
735
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
736
                DIdSet,         -- subset of local vars that occur free
737
                [Id])           -- the same local vars as a list, fed back
738
dsfixCmd ids local_vars stk_ty cmd_ty cmd
Richard Eisenberg's avatar
Richard Eisenberg committed
739 740 741
  = do { putSrcSpanDs (getLoc cmd) $ dsNoLevPoly cmd_ty
           (text "When desugaring the command:" <+> ppr cmd)
       ; trimInput (dsLCmd ids local_vars stk_ty cmd_ty cmd) }
742 743 744 745 746

-- 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
747
        :: ([Id] -> DsM (CoreExpr, DIdSet))
748
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
749
                DIdSet,         -- subset of local vars that occur free
750 751 752
                [Id])           -- same local vars as a list, fed back to
                                -- the inner function to form the tuple of
                                -- inputs to the arrow.
753 754 755
trimInput build_arrow
  = fixDs (\ ~(_,_,env_ids) -> do
        (core_cmd, free_vars) <- build_arrow env_ids
niteria's avatar
niteria committed
756
        return (core_cmd, free_vars, dVarSetElems free_vars))
757

Austin Seipp's avatar
Austin Seipp committed
758
{-
759 760
Translation of command judgements of the form

761
        D |-a do { ss } : t
Austin Seipp's avatar
Austin Seipp committed
762
-}
763

764 765 766
dsCmdDo :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this statement
        -> Type                 -- return type of the statement
767
        -> [CmdLStmt GhcTc]     -- statements to desugar
768 769 770 771
        -> [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
772
                DIdSet)         -- subset of local vars that occur free
773

774
dsCmdDo _ _ _ [] _ = panic "dsCmdDo"
775

776 777 778 779
-- D; xs |-a c : () --> t
-- --------------------------
-- D; xs |-a do { c } : t
--
780
--              ---> premap (\ (xs) -> ((xs), ())) c
781

782
dsCmdDo ids local_vars res_ty [dL->L loc (LastStmt _ body _ _)] env_ids = do
Richard Eisenberg's avatar
Richard Eisenberg committed
783 784
    putSrcSpanDs loc $ dsNoLevPoly res_ty
                         (text "In the command:" <+> ppr body)
785 786 787 788 789 790
    (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
791
                        (mkCorePairTy env_ty unitTy)
792 793 794
                        res_ty
                        core_map
                        core_body,
795
        env_ids')