summaryrefslogtreecommitdiff
path: root/compiler/Language
diff options
context:
space:
mode:
authorShayne Fletcher <shayne@shaynefletcher.org>2021-02-21 11:48:17 -0500
committerBen Gamari <ben@smart-cactus.org>2021-03-06 19:27:04 -0500
commitcf65cf16c89414273c4f6b2d090d4b2fffb90759 (patch)
tree57d893535444c2face265c12ade95f0ef3f0ceba /compiler/Language
parent9e0c0c3a7b6cad8c08e5de7e2a27cf2cb2d2368f (diff)
downloadhaskell-cf65cf16c89414273c4f6b2d090d4b2fffb90759.tar.gz
Implement record dot syntaxwip/joachim/bump-haddock
Diffstat (limited to 'compiler/Language')
-rw-r--r--compiler/Language/Haskell/Syntax/Expr.hs135
-rw-r--r--compiler/Language/Haskell/Syntax/Extension.hs2
2 files changed, 136 insertions, 1 deletions
diff --git a/compiler/Language/Haskell/Syntax/Expr.hs b/compiler/Language/Haskell/Syntax/Expr.hs
index 3d6500d342..9967a78314 100644
--- a/compiler/Language/Haskell/Syntax/Expr.hs
+++ b/compiler/Language/Haskell/Syntax/Expr.hs
@@ -40,6 +40,7 @@ import Language.Haskell.Syntax.Binds
-- others:
import GHC.Tc.Types.Evidence
import GHC.Core
+import GHC.Core.DataCon (FieldLabelString)
import GHC.Types.Name
import GHC.Types.Basic
import GHC.Types.Fixity
@@ -59,6 +60,110 @@ import qualified Data.Data as Data (Fixity(..))
import GHCi.RemoteTypes ( ForeignRef )
import qualified Language.Haskell.TH as TH (Q)
+{- Note [RecordDotSyntax field updates]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The extensions @OverloadedRecordDot@ @OverloadedRecordUpdate@ together
+enable record updates like @a{foo.bar.baz = 1}@. Introducing this
+syntax slightly complicates parsing. This note explains how it's done.
+
+In the event a record is being constructed or updated, it's this
+production that's in play:
+@
+aexp1 -> aexp1 '{' fbinds '}' {
+ ...
+ mkHsRecordPV ... $1 (snd $3)
+}
+@
+@fbinds@ is a list of field bindings. @mkHsRecordPV@ is a function of
+the @DisambECP b@ typeclass, see Note [Ambiguous syntactic
+categories].
+
+The "normal" rules for an @fbind@ are:
+@
+fbind
+ : qvar '=' texp
+ | qvar
+@
+These rules compute values of @LHsRecField GhcPs (Located b)@. They
+apply in the context of record construction, record updates, record
+patterns and record expressions. That is, @b@ ranges over @HsExpr
+GhcPs@, @HsPat GhcPs@ and @HsCmd GhcPs@.
+
+When @OverloadedRecordDot@ and @OverloadedRecordUpdate@ are both
+enabled, two additional @fbind@ rules are admitted:
+@
+ | field TIGHT_INFIX_PROJ fieldToUpdate '=' texp
+ | field TIGHT_INFIX_PROJ fieldToUpdate
+@
+
+These rules only make sense when parsing record update expressions
+(that is, patterns and commands cannot be parsed by these rules and
+neither record constructions).
+
+The results of these new rules cannot be represented by @LHsRecField
+GhcPs (LHsExpr GhcPs)@ values as the type is defined today. We
+minimize modifying existing code by having these new rules calculate
+@LHsRecProj GhcPs (Located b)@ ("record projection") values instead:
+@
+newtype FieldLabelStrings = FieldLabelStrings [Located FieldLabelString]
+type RecProj arg = HsRecField' FieldLabelStrings arg
+type LHsRecProj p arg = Located (RecProj arg)
+@
+
+The @fbind@ rule is then given the type @fbind :: { forall b.
+DisambECP b => PV (Fbind b) }@ accomodating both alternatives:
+@
+type Fbind b = Either
+ (LHsRecField GhcPs (Located b))
+ ( LHsRecProj GhcPs (Located b))
+@
+
+In @data HsExpr p@, the @RecordUpd@ constuctor indicates regular
+updates vs. projection updates by means of the @rupd_flds@ member
+type, an @Either@ instance:
+@
+ | RecordUpd
+ { rupd_ext :: XRecordUpd p
+ , rupd_expr :: LHsExpr p
+ , rupd_flds :: Either [LHsRecUpdField p] [LHsRecUpdProj p]
+ }
+@
+Here,
+@
+type RecUpdProj p = RecProj (LHsExpr p)
+type LHsRecUpdProj p = Located (RecUpdProj p)
+@
+and @Left@ values indicating regular record update, @Right@ values
+updates desugared to @setField@s.
+
+If @OverloadedRecordUpdate@ is enabled, any updates parsed as
+@LHsRecField GhcPs@ values are converted to @LHsRecUpdProj GhcPs@
+values (see function @mkRdrRecordUpd@ in 'GHC.Parser.PostProcess').
+-}
+
+-- | RecordDotSyntax field updates
+
+newtype FieldLabelStrings =
+ FieldLabelStrings [Located FieldLabelString]
+ deriving (Data)
+
+instance Outputable FieldLabelStrings where
+ ppr (FieldLabelStrings flds) =
+ hcat (punctuate dot (map (ppr . unLoc) flds))
+
+-- Field projection updates (e.g. @foo.bar.baz = 1@). See Note
+-- [RecordDotSyntax field updates].
+type RecProj arg = HsRecField' FieldLabelStrings arg
+
+-- The phantom type parameter @p@ is for symmetry with @LHsRecField p
+-- arg@ in the definition of @data Fbind@ (see GHC.Parser.Process).
+type LHsRecProj p arg = Located (RecProj arg)
+
+-- These two synonyms are used in the definition of syntax @RecordUpd@
+-- below.
+type RecUpdProj p = RecProj (LHsExpr p)
+type LHsRecUpdProj p = Located (RecUpdProj p)
+
{-
************************************************************************
* *
@@ -356,16 +461,44 @@ data HsExpr p
--
-- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnOpen' @'{'@,
-- 'GHC.Parser.Annotation.AnnDotdot','GHC.Parser.Annotation.AnnClose' @'}'@
+ -- 'GHC.Parser.Annotation.AnnComma, 'GHC.Parser.Annotation.AnnDot',
+ -- 'GHC.Parser.Annotation.AnnClose' @'}'@
-- For details on above see note [Api annotations] in GHC.Parser.Annotation
| RecordUpd
{ rupd_ext :: XRecordUpd p
, rupd_expr :: LHsExpr p
- , rupd_flds :: [LHsRecUpdField p]
+ , rupd_flds :: Either [LHsRecUpdField p] [LHsRecUpdProj p]
}
-- For a type family, the arg types are of the *instance* tycon,
-- not the family tycon
+ -- | Record field selection e.g @z.x@.
+ --
+ -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnDot'
+ --
+ -- This case only arises when the OverloadedRecordDot langauge
+ -- extension is enabled.
+
+ | HsGetField {
+ gf_ext :: XGetField p
+ , gf_expr :: LHsExpr p
+ , gf_field :: Located FieldLabelString
+ }
+
+ -- | Record field selector. e.g. @(.x)@ or @(.x.y)@
+ --
+ -- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnOpenP'
+ -- 'GHC.Parser.Annotation.AnnDot', 'GHC.Parser.Annotation.AnnCloseP'
+ --
+ -- This case only arises when the OverloadedRecordDot langauge
+ -- extensions is enabled.
+
+ | HsProjection {
+ proj_ext :: XProjection p
+ , proj_flds :: [Located FieldLabelString]
+ }
+
-- | Expression with an explicit type signature. @e :: type@
--
-- - 'GHC.Parser.Annotation.AnnKeywordId' : 'GHC.Parser.Annotation.AnnDcolon'
diff --git a/compiler/Language/Haskell/Syntax/Extension.hs b/compiler/Language/Haskell/Syntax/Extension.hs
index 16b11b3e30..f843bee1a2 100644
--- a/compiler/Language/Haskell/Syntax/Extension.hs
+++ b/compiler/Language/Haskell/Syntax/Extension.hs
@@ -387,6 +387,8 @@ type family XDo x
type family XExplicitList x
type family XRecordCon x
type family XRecordUpd x
+type family XGetField x
+type family XProjection x
type family XExprWithTySig x
type family XArithSeq x
type family XBracket x