DsArrows.hs 47.1 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 #-}
Ian Lynagh's avatar
Ian Lynagh committed
10

11 12 13 14
module DsArrows ( dsProcExpr ) where

#include "HsVersions.h"

Simon Marlow's avatar
Simon Marlow committed
15 16
import Match
import DsUtils
17 18
import DsMonad

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

-- 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
28
import {-# SOURCE #-} DsExpr ( dsExpr, dsLExpr, dsLExprNoLP, dsLocalBinds, dsSyntaxExpr )
29

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

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

data DsCmdEnv = DsCmdEnv {
57
        arr_id, compose_id, first_id, app_id, choice_id, loop_id :: CoreExpr
58 59
    }

60 61 62 63
mkCmdEnv :: CmdSyntaxTable Id -> DsM ([CoreBind], DsCmdEnv)
-- See Note [CmdSyntaxTable] in HsExpr
mkCmdEnv tc_meths
  = do { (meth_binds, prs) <- mapAndUnzipM mk_bind tc_meths
Richard Eisenberg's avatar
Richard Eisenberg committed
64 65 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

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

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

Richard Eisenberg's avatar
Richard Eisenberg committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
    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))

125 126 127 128 129 130 131

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

158 159 160
-- 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 ->
161
                CoreExpr -> CoreExpr -> CoreExpr
162 163
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
164

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

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

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

Austin Seipp's avatar
Austin Seipp committed
187
{-
188 189
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
190
-}
191 192

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

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

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

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

mkCorePairExpr :: CoreExpr -> CoreExpr -> CoreExpr
mkCorePairExpr e1 e2 = mkCoreTup [e1, e2]
210 211 212

mkCoreUnitExpr :: CoreExpr
mkCoreUnitExpr = mkCoreTup []
213

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

219
        ((x1,...,xn), (s1,...(sk,())...))
220 221 222

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
223
-}
224

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

----------------------------------------------
237
--              buildEnvStack
238
--
239
--      ((x1,...,xn),stk)
240

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

----------------------------------------------
246
--              matchEnvStack
247
--
248 249 250 251 252 253 254 255 256 257 258
--      \ ((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
259
matchEnvStack env_ids stack_id body = do
260 261
    uniqs <- newUniqueSupply
    tup_var <- newSysLocalDs (mkBigCoreVarTupTy env_ids)
262 263 264
    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))
265

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

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

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

298 299 300
mkHsEnvStackExpr :: [Id] -> Id -> LHsExpr Id
mkHsEnvStackExpr env_ids stack_id
  = mkLHsTupleExpr [mkLHsVarTuple env_ids, nlHsVar stack_id]
301

Austin Seipp's avatar
Austin Seipp committed
302
-- Translation of arrow abstraction
303

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

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

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

333
        D; xs |-a c : stk --> t
334 335

to an expression e such that
336

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

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

345 346 347 348 349 350 351 352 353
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
        -> HsCmd Id             -- command to desugar
        -> [Id]                 -- list of vars in the input to this command
                                -- This is typically fed back,
                                -- so don't pull on it too early
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
354
                DIdSet)         -- subset of local vars that occur free
355

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

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

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

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

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

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

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

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

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

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

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

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

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

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

480 481
dsCmd ids local_vars stack_ty res_ty (HsCmdPar cmd) env_ids
  = dsLCmd ids local_vars stack_ty res_ty cmd env_ids
482

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

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

503 504
    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]
505

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

512 513
        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)
514

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

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

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

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

is translated to

534 535 536 537 538
        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
539 540 541 542

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.
543
To build all this, we use triples describing segments of the list of
ross's avatar
ross committed
544
case bodies, containing the following fields:
545
 * a list of expressions of the form (Left|Right)* ((xs)*ts), to be put
ross's avatar
ross committed
546
   into the case replacing the commands
547
 * a sum type that is the common type of these expressions, and also the
ross's avatar
ross committed
548
   input type of the arrow
549
 * a CoreExpr for an arrow built by combining the translated command
ross's avatar
ross committed
550
   bodies with |||.
Austin Seipp's avatar
Austin Seipp committed
551
-}
ross's avatar
ross committed
552

553
dsCmd ids local_vars stack_ty res_ty
554 555
      (HsCmdCase exp (MG { mg_alts = L l matches, mg_arg_tys = arg_tys
                         , mg_origin = origin }))
556
      env_ids = do
557
    stack_id <- newSysLocalDs stack_ty
558 559 560 561 562 563

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

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

571 572 573 574
    branches <- mapM make_branch leaves
    either_con <- dsLookupTyCon eitherTyConName
    left_con <- dsLookupDataCon leftDataConName
    right_con <- dsLookupDataCon rightDataConName
575
    let
Richard Eisenberg's avatar
Richard Eisenberg committed
576 577
        left_id  = HsConLikeOut (RealDataCon left_con)
        right_id = HsConLikeOut (RealDataCon right_con)
578 579
        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
580

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

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

        -- 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
596
        in_ty = envStackType env_ids stack_ty
597

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

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

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

Richard Eisenberg's avatar
Richard Eisenberg committed
614
dsCmd ids local_vars stack_ty res_ty (HsCmdLet lbinds@(L _ binds) body) env_ids = do
615
    let
616
        defined_vars = mkVarSet (collectLocalBinders binds)
617
        local_vars' = defined_vars `unionVarSet` local_vars
618

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

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

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

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

Alan Zimmerman's avatar
Alan Zimmerman committed
659
dsCmd _ids local_vars _stack_ty _res_ty (HsCmdArrForm op _ _ args) env_ids = do
660 661 662 663
    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
664
            unionDVarSets fv_sets)
665

eir@cis.upenn.edu's avatar
eir@cis.upenn.edu committed
666
dsCmd ids local_vars stack_ty res_ty (HsCmdWrap wrap cmd) env_ids = do
667
    (core_cmd, env_ids') <- dsCmd ids local_vars stack_ty res_ty cmd env_ids
Simon Peyton Jones's avatar
Simon Peyton Jones committed
668 669
    core_wrap <- dsHsWrapper wrap
    return (core_wrap core_cmd, env_ids')
670

Ian Lynagh's avatar
Ian Lynagh committed
671 672
dsCmd _ _ _ _ _ c = pprPanic "dsCmd" (ppr c)

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

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

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

dsfixCmd
699 700 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
        -> LHsCmd Id            -- command to desugar
        -> DsM (CoreExpr,       -- desugared expression
niteria's avatar
niteria committed
705
                DIdSet,         -- subset of local vars that occur free
706
                [Id])           -- the same local vars as a list, fed back
707
dsfixCmd ids local_vars stk_ty cmd_ty cmd
Richard Eisenberg's avatar
Richard Eisenberg committed
708 709 710
  = do { putSrcSpanDs (getLoc cmd) $ dsNoLevPoly cmd_ty
           (text "When desugaring the command:" <+> ppr cmd)
       ; trimInput (dsLCmd ids local_vars stk_ty cmd_ty cmd) }
711 712 713 714 715

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

Austin Seipp's avatar
Austin Seipp committed
727
{-
728 729
Translation of command judgements of the form

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

733 734 735 736 737 738 739 740
dsCmdDo :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this statement
        -> Type                 -- return type of the statement
        -> [CmdLStmt Id]        -- statements to desugar
        -> [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
741
                DIdSet)         -- subset of local vars that occur free
742

743
dsCmdDo _ _ _ [] _ = panic "dsCmdDo"
744

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

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

766
dsCmdDo ids local_vars res_ty (stmt:stmts) env_ids = do
767 768
    let bound_vars  = mkVarSet (collectLStmtBinders stmt)
    let local_vars' = bound_vars `unionVarSet` local_vars
769 770
    (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
771 772 773 774 775 776 777
    return (do_compose ids
                (mkBigCoreVarTupTy env_ids)
                (mkBigCoreVarTupTy env_ids')
                res_ty
                core_stmt
                core_stmts,
              fv_stmt)
778

Austin Seipp's avatar
Austin Seipp committed
779
{-
ross's avatar
ross committed
780 781 782
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
783 784
-}

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

790
dsCmdStmt
791 792 793 794 795 796 797 798
        :: DsCmdEnv             -- arrow combinators
        -> IdSet                -- set of local vars available to this statement
        -> [Id]                 -- list of vars in the output of this statement
        -> CmdStmt Id           -- statement to desugar
        -> [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
799
                DIdSet)         -- subset of local vars that occur free
800

801 802 803 804
-- D; xs1 |-a c : () --> t
-- D; xs' |-a do { ss } : t'
-- ------------------------------
-- D; xs  |-a do { c; ss } : t'
805
--
806 807
--              ---> premap (\ ((xs)) -> (((xs1),()),(xs')))
--                      (first c >>> arr snd) >>> ss
808

809
dsCmdStmt ids local_vars out_ids (BodyStmt cmd _ _ c_ty) env_ids = do
810 811 812
    (core_cmd, fv_cmd, env_ids1) <- dsfixCmd ids local_vars unitTy c_ty cmd
    core_mux <- matchEnv env_ids
        (mkCorePairExpr