summaryrefslogtreecommitdiff
path: root/compiler/hsSyn/HsUtils.hs
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2015-03-13 16:39:58 +0000
committerSimon Marlow <marlowsd@gmail.com>2015-09-17 16:52:03 +0100
commit8ecf6d8f7dfee9e5b1844cd196f83f00f3b6b879 (patch)
tree9bf2b8601fefa7e1eaac11079d27660824b1466f /compiler/hsSyn/HsUtils.hs
parent43eb1dc52a4d3cbba9617f5a26177b8251d84b6a (diff)
downloadhaskell-8ecf6d8f7dfee9e5b1844cd196f83f00f3b6b879.tar.gz
ApplicativeDo transformation
Summary: This is an implementation of the ApplicativeDo proposal. See the Note [ApplicativeDo] in RnExpr for details on the current implementation, and the wiki page https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo for design notes. Test Plan: validate Reviewers: simonpj, goldfire, austin Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D729
Diffstat (limited to 'compiler/hsSyn/HsUtils.hs')
-rw-r--r--compiler/hsSyn/HsUtils.hs76
1 files changed, 74 insertions, 2 deletions
diff --git a/compiler/hsSyn/HsUtils.hs b/compiler/hsSyn/HsUtils.hs
index 2242d10f76..b45156288f 100644
--- a/compiler/hsSyn/HsUtils.hs
+++ b/compiler/hsSyn/HsUtils.hs
@@ -32,8 +32,13 @@ module HsUtils(
mkLHsTupleExpr, mkLHsVarTuple, missingTupArg,
toHsType, toHsKind,
+ -- * Constructing general big tuples
+ -- $big_tuples
+ mkChunkified, chunkify,
+
-- Bindings
- mkFunBind, mkVarBind, mkHsVarBind, mk_easy_FunBind, mkTopFunBind, mkPatSynBind,
+ mkFunBind, mkVarBind, mkHsVarBind, mk_easy_FunBind, mkTopFunBind,
+ mkPatSynBind,
-- Literals
mkHsIntegral, mkHsFractional, mkHsIsString, mkHsString,
@@ -42,6 +47,7 @@ module HsUtils(
mkNPat, mkNPlusKPat, nlVarPat, nlLitPat, nlConVarPat, nlConPat,
nlConPatName, nlInfixConPat, nlNullaryConPat, nlWildConPat, nlWildPat,
nlWildPatName, nlWildPatId, nlTuplePat, mkParPat,
+ mkBigLHsVarTup, mkBigLHsTup, mkBigLHsVarPatTup, mkBigLHsPatTup,
-- Types
mkHsAppTy, userHsTyVarBndrs,
@@ -99,6 +105,7 @@ import FastString
import Util
import Bag
import Outputable
+import Constants
import Data.Either
import Data.Function
@@ -254,7 +261,7 @@ mkTransformByStmt ss u b = emptyTransStmt { trS_form = ThenForm, trS_stmts = s
mkGroupUsingStmt ss u = emptyTransStmt { trS_form = GroupForm, trS_stmts = ss, trS_using = u }
mkGroupByUsingStmt ss b u = emptyTransStmt { trS_form = GroupForm, trS_stmts = ss, trS_using = u, trS_by = Just b }
-mkLastStmt body = LastStmt body noSyntaxExpr
+mkLastStmt body = LastStmt body False noSyntaxExpr
mkBodyStmt body = BodyStmt body noSyntaxExpr noSyntaxExpr placeHolderType
mkBindStmt pat body = BindStmt pat body noSyntaxExpr noSyntaxExpr
@@ -425,6 +432,66 @@ nlTuplePat pats box = noLoc (TuplePat pats box [])
missingTupArg :: HsTupArg RdrName
missingTupArg = Missing placeHolderType
+mkLHsPatTup :: [LPat id] -> LPat id
+mkLHsPatTup [] = noLoc $ TuplePat [] Boxed []
+mkLHsPatTup [lpat] = lpat
+mkLHsPatTup lpats = L (getLoc (head lpats)) $ TuplePat lpats Boxed []
+
+-- The Big equivalents for the source tuple expressions
+mkBigLHsVarTup :: [id] -> LHsExpr id
+mkBigLHsVarTup ids = mkBigLHsTup (map nlHsVar ids)
+
+mkBigLHsTup :: [LHsExpr id] -> LHsExpr id
+mkBigLHsTup = mkChunkified mkLHsTupleExpr
+
+-- The Big equivalents for the source tuple patterns
+mkBigLHsVarPatTup :: [id] -> LPat id
+mkBigLHsVarPatTup bs = mkBigLHsPatTup (map nlVarPat bs)
+
+mkBigLHsPatTup :: [LPat id] -> LPat id
+mkBigLHsPatTup = mkChunkified mkLHsPatTup
+
+-- $big_tuples
+-- #big_tuples#
+--
+-- GHCs built in tuples can only go up to 'mAX_TUPLE_SIZE' in arity, but
+-- we might concievably want to build such a massive tuple as part of the
+-- output of a desugaring stage (notably that for list comprehensions).
+--
+-- We call tuples above this size \"big tuples\", and emulate them by
+-- creating and pattern matching on >nested< tuples that are expressible
+-- by GHC.
+--
+-- Nesting policy: it's better to have a 2-tuple of 10-tuples (3 objects)
+-- than a 10-tuple of 2-tuples (11 objects), so we want the leaves of any
+-- construction to be big.
+--
+-- If you just use the 'mkBigCoreTup', 'mkBigCoreVarTupTy', 'mkTupleSelector'
+-- and 'mkTupleCase' functions to do all your work with tuples you should be
+-- fine, and not have to worry about the arity limitation at all.
+
+-- | Lifts a \"small\" constructor into a \"big\" constructor by recursive decompositon
+mkChunkified :: ([a] -> a) -- ^ \"Small\" constructor function, of maximum input arity 'mAX_TUPLE_SIZE'
+ -> [a] -- ^ Possible \"big\" list of things to construct from
+ -> a -- ^ Constructed thing made possible by recursive decomposition
+mkChunkified small_tuple as = mk_big_tuple (chunkify as)
+ where
+ -- Each sub-list is short enough to fit in a tuple
+ mk_big_tuple [as] = small_tuple as
+ mk_big_tuple as_s = mk_big_tuple (chunkify (map small_tuple as_s))
+
+chunkify :: [a] -> [[a]]
+-- ^ Split a list into lists that are small enough to have a corresponding
+-- tuple arity. The sub-lists of the result all have length <= 'mAX_TUPLE_SIZE'
+-- But there may be more than 'mAX_TUPLE_SIZE' sub-lists
+chunkify xs
+ | n_xs <= mAX_TUPLE_SIZE = [xs]
+ | otherwise = split xs
+ where
+ n_xs = length xs
+ split [] = []
+ split xs = take mAX_TUPLE_SIZE xs : split (drop mAX_TUPLE_SIZE xs)
+
{-
************************************************************************
* *
@@ -670,6 +737,7 @@ collectStmtBinders (ParStmt xs _ _) = collectLStmtsBinders
$ [s | ParStmtBlock ss _ _ <- xs, s <- ss]
collectStmtBinders (TransStmt { trS_stmts = stmts }) = collectLStmtsBinders stmts
collectStmtBinders (RecStmt { recS_stmts = ss }) = collectLStmtsBinders ss
+collectStmtBinders ApplicativeStmt{} = []
----------------- Patterns --------------------------
@@ -877,7 +945,11 @@ lStmtsImplicits = hs_lstmts
hs_lstmts :: [LStmtLR Name idR (Located (body idR))] -> NameSet
hs_lstmts = foldr (\stmt rest -> unionNameSet (hs_stmt (unLoc stmt)) rest) emptyNameSet
+ hs_stmt :: StmtLR Name idR (Located (body idR)) -> NameSet
hs_stmt (BindStmt pat _ _ _) = lPatImplicits pat
+ hs_stmt (ApplicativeStmt args _ _) = unionNameSets (map do_arg args)
+ where do_arg (_, ApplicativeArgOne pat _) = lPatImplicits pat
+ do_arg (_, ApplicativeArgMany stmts _ _) = hs_lstmts stmts
hs_stmt (LetStmt binds) = hs_local_binds binds
hs_stmt (BodyStmt {}) = emptyNameSet
hs_stmt (LastStmt {}) = emptyNameSet