1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
|
{-# LANGUAGE ViewPatterns #-}
module ExpPatFrame (
-- * The expression/pattern frame
ExpPatFrame(..),
LExpPatFrame,
-- * Tuple elements
TupArgFrame(..),
LTupArgFrame,
-- * Record elements
FrameRecordBinds,
FrameRecUpdField,
LFrameRecUpdField,
-- * Match elements
FrameMatch(..),
LFrameMatch,
FrameGRHSs(..),
FrameGRHS(..),
LFrameGRHS,
-- * Statements
FrameStmt(..),
LFrameStmt,
-- * Conversion
fromTupArgPresent,
checkExpr,
checkExprStmt,
checkExprMatch,
checkExprGRHSs,
checkExprGRHS,
-- * Construction
unguardedFrameRHS
) where
import GhcPrelude
import FastString
import Outputable
import SrcLoc
import Name
import RdrName
import BasicTypes
import HsSyn
type LExpPatFrame = Located ExpPatFrame
{-
There are places in the grammar where we do not know whether we are parsing an
expression or a pattern without infinite lookahead (which we do not have in
'happy'):
1. View patterns:
f (Con a b ) = ... -- 'Con a b' is a pattern
f (Con a b -> x) = ... -- 'Con a b' is an expression
2. do-notation:
do { Con a b <- x } -- 'Con a b' is a pattern
do { Con a b } -- 'Con a b' is an expression
3. Guards:
x | True <- p && q = ... -- 'True' is a pattern
x | True = ... -- 'True' is an expression
4. Top-level value/function declarations (FunBind/PatBind):
f !a -- TH splice
f !a = ... -- function declaration
Until we encounter the = sign, we don't know if it's a top-level
TemplateHaskell splice where ! is an infix operator, or if it's a function
declaration where ! is a strictness annotation.
An ExpPatFrame (expression/pattern frame) is an intermediate data structure for
parsing expressions and patterns. We convert to HsExpr or HsPat when we can
resolve the ambiguity.
See https://ghc.haskell.org/trac/ghc/wiki/Design/ExpPatFrame for details.
-}
data ExpPatFrame
= FrameVar RdrName
-- ^ Identifier: Just, map, BS.length
| FrameIPVar HsIPName
-- ^ Implicit parameter: ?x
| FrameOverLabel FastString
-- ^ Overloaded label: #label
| FrameLit (HsLit GhcPs)
-- ^ Non-overloaded literal: 'c', "str"
| FrameOverLit (HsOverLit GhcPs)
-- ^ Overloaded literal: 15, 2.4
| FramePar LExpPatFrame
-- ^ Parentheses
| FrameSum ConTag Arity LExpPatFrame
-- ^ Sum: (a||), (|a|), (||a)
| FrameTuple [LTupArgFrame] Boxity
-- ^ Tuple (section): (a,b) (a,b,c) (a,,) (,a,)
| FrameList [LExpPatFrame]
-- ^ List: [1, 2, 3]
| FrameComp (HsStmtContext Name) [LFrameStmt] LExpPatFrame
-- ^ List/monad comprehension: [ a | x <- f n, p, q ]
| FrameArithSeq (ArithSeqInfo GhcPs)
-- ^ Arithmetic sequence: [1..], [1,2..], [1..5]
| FrameWild
-- ^ Wildcard: _
| FrameSplice (HsSplice GhcPs)
-- ^ TH splice: $a, $(expr), $$(expr), [quasi| ... |]
| FrameBracket (HsBracket GhcPs)
-- ^ TH bracket: [|expr|], [p|pat|], 'x, ''T
| FrameArrForm LExpPatFrame [LHsCmdTop GhcPs]
-- ^ Command formation (arrows): (| e cmd1 cmd2 cmd3 |)
| FrameRecordUpd LExpPatFrame [LFrameRecUpdField]
-- ^ Record update: (f x) { a = z }
| FrameRecordCon (Located RdrName) FrameRecordBinds
-- ^ Record constructor: D { x, y = f t, .. }
| FrameAsPat (Located RdrName) LExpPatFrame
-- ^ As-pattern: x@(D a b)
| FrameLam [LPat GhcPs] LExpPatFrame
-- ^ Lambda-expression: \x -> e
| FrameLet (LHsLocalBinds GhcPs) LExpPatFrame
-- ^ Let-expression: let p = t in e
| FrameLamCase [LFrameMatch]
-- ^ Lambda-expression: \x -> e
| FrameIf LExpPatFrame LExpPatFrame LExpPatFrame
-- ^ If-expression: if p then x else y
| FrameMultiIf [LFrameGRHS]
-- ^ Multi-way if-expression: if | p = x \n | q = x
| FrameCase LExpPatFrame [LFrameMatch]
-- ^ Case-expression: case x of { p1 -> e1; p2 -> e2 }
| FrameDo (HsStmtContext Name) [LFrameStmt]
-- ^ Do-expression: do { s1; a <- s2; s3 }
| FrameProc (LPat GhcPs) (LHsCmdTop GhcPs)
-- ^ Proc-expression: proc p -> cmd
| FrameViewPat LExpPatFrame LExpPatFrame
-- ^ View pattern: e -> p
| FrameTySig LExpPatFrame (LHsSigWcType GhcPs)
-- ^ Type signature: x :: ty
| FrameArrApp LExpPatFrame LExpPatFrame HsArrAppType Bool
-- ^ Arrow application: f -< arg, f -<< arg, arg >- f, arg >>- f
| FrameSCC SourceText StringLiteral LExpPatFrame
-- ^ SCC annotation: {-# SCC .. #-} e
| FrameTickPragma
SourceText
(StringLiteral,(Int,Int),(Int,Int))
((SourceText,SourceText),(SourceText,SourceText))
LExpPatFrame
-- ^ Tick pragma: {-# GENERATED .. #-} e
| FrameCoreAnn SourceText StringLiteral LExpPatFrame
-- ^ Core annotation: {-# CORE .. #-} e
| FrameApp LExpPatFrame LExpPatFrame
-- ^ Function application: f a
| FrameAppType LExpPatFrame (LHsWcType GhcPs)
-- ^ Visible type application: f @t
| FrameOpApp LExpPatFrame LExpPatFrame LExpPatFrame
-- ^ Operator application: x # y
| FrameSectionL LExpPatFrame LExpPatFrame
-- ^ Left section: (x #)
| FrameSectionR LExpPatFrame LExpPatFrame
-- ^ Right section: (# y)
| FrameNegApp LExpPatFrame
-- ^ Prefix negation: -a
| FrameLazyPat LExpPatFrame
-- ^ Lazy pattern: ~a
| FrameStatic LExpPatFrame
-- ^ Static expression: static e
instance Outputable ExpPatFrame where
ppr = ppr . unLoc . checkExpr . noLoc
type FrameRecordBinds = HsRecFields GhcPs LExpPatFrame
type FrameRecUpdField = HsRecField' (AmbiguousFieldOcc GhcPs) LExpPatFrame
type LFrameRecUpdField = Located FrameRecUpdField
type LTupArgFrame = Located TupArgFrame
data TupArgFrame
= TupArgFramePresent LExpPatFrame
| TupArgFrameMissing
fromTupArgPresent :: TupArgFrame -> Maybe LExpPatFrame
fromTupArgPresent (TupArgFramePresent e) = Just e
fromTupArgPresent TupArgFrameMissing = Nothing
type LFrameMatch = Located FrameMatch
data FrameMatch =
FrameMatch (HsMatchContext RdrName) [LPat GhcPs] FrameGRHSs
type LFrameStmt = Located FrameStmt
data FrameGRHSs =
FrameGRHSs [LFrameGRHS] (LHsLocalBinds GhcPs)
type LFrameGRHS = Located FrameGRHS
data FrameGRHS = FrameGRHS [GuardLStmt GhcPs] LExpPatFrame
data FrameStmt
= FrameTransformStmt [LFrameStmt] LExpPatFrame
-- ^ TransformListComp statement: then f
| FrameTransformByStmt [LFrameStmt] LExpPatFrame LExpPatFrame
-- ^ TransformListComp statement: then f by e
| FrameGroupUsingStmt [LFrameStmt] LExpPatFrame
-- ^ TransformListComp statement: then group using f
| FrameGroupByUsingStmt [LFrameStmt] LExpPatFrame LExpPatFrame
-- ^ TransformListComp statement: then group by e using f
| FrameBindStmt (LPat GhcPs) LExpPatFrame
-- ^ Binding statement: p <- e
| FrameBodyStmt LExpPatFrame
-- ^ Body statement: e
| FrameLetStmt (LHsLocalBinds GhcPs)
-- ^ Let statement: let p = t
| FrameRecStmt [LFrameStmt]
-- ^ Rec statement: rec { s1; s2; ... }
| FrameParStmt [[LFrameStmt]]
-- ^ Parallel statement: s1 | s2
instance Outputable FrameStmt where
ppr = ppr . unLoc . checkExprStmt . noLoc
{-
Convert an expression/pattern frame to an expression. In the future, this
function will perform validation and reject FrameAsPat, FrameViewPat,
FrameLazyPat, and so on:
checkExpr :: LExpPatFrame -> P (LHsExpr GhcPs)
-}
checkExpr :: LExpPatFrame -> LHsExpr GhcPs
checkExpr (dL->L l epf) = cL l $ case epf of
FrameVar name -> HsVar noExt (cL l name)
FrameIPVar ipname -> HsIPVar noExt ipname
FrameOverLabel str -> HsOverLabel noExt Nothing str
FrameLit lit -> HsLit noExt lit
FrameOverLit lit -> HsOverLit noExt lit
FramePar e -> HsPar noExt (checkExpr e)
FrameSum alt arity e -> ExplicitSum noExt alt arity (checkExpr e)
FrameTuple args boxity ->
ExplicitTuple noExt (map checkExprTupArg args) boxity
FrameList xs -> ExplicitList noExt Nothing (map checkExpr xs)
FrameComp ctxt quals e ->
mkHsComp ctxt (map checkExprStmt quals) (checkExpr e)
FrameArithSeq a -> ArithSeq noExt Nothing a
FrameWild -> EWildPat noExt
FrameSplice splice -> HsSpliceE noExt splice
FrameBracket br -> HsBracket noExt br
FrameArrForm op cmds -> HsArrForm noExt (checkExpr op) Nothing cmds
FrameRecordUpd exp flds ->
RecordUpd noExt (checkExpr exp) ((fmap.fmap.fmap) checkExpr flds)
FrameRecordCon con flds -> RecordCon noExt con (fmap checkExpr flds)
FrameAsPat v e -> EAsPat noExt v (checkExpr e)
FrameLam ps e ->
HsLam noExt $
mkMatchGroup FromSource
[cL l $ Match { m_ext = noExt
, m_ctxt = LambdaExpr
, m_pats = ps
, m_grhss = unguardedGRHSs (checkExpr e) }]
FrameLet binds expr -> HsLet noExt binds (checkExpr expr)
FrameLamCase matches ->
HsLamCase noExt $
mkMatchGroup FromSource (map checkExprMatch matches)
FrameIf c a b -> mkHsIf (checkExpr c) (checkExpr a) (checkExpr b)
FrameMultiIf alts -> HsMultiIf noExt (map checkExprGRHS alts)
FrameCase scrut matches ->
HsCase noExt (checkExpr scrut) $
mkMatchGroup FromSource (map checkExprMatch matches)
FrameDo ctxt stmts -> mkHsDo ctxt (map checkExprStmt stmts)
FrameProc pat cmd -> HsProc noExt pat cmd
FrameViewPat p e -> EViewPat noExt (checkExpr p) (checkExpr e)
FrameTySig e sig -> ExprWithTySig noExt (checkExpr e) sig
FrameArrApp f a haat b ->
HsArrApp noExt (checkExpr f) (checkExpr a) haat b
FrameSCC src lbl e -> HsSCC noExt src lbl (checkExpr e)
FrameTickPragma src info srcInfo e ->
HsTickPragma noExt src info srcInfo (checkExpr e)
FrameCoreAnn src lbl e -> HsCoreAnn noExt src lbl (checkExpr e)
FrameApp f a -> HsApp noExt (checkExpr f) (checkExpr a)
FrameAppType f t -> HsAppType noExt (checkExpr f) t
FrameOpApp e1 op e2 ->
OpApp noExt (checkExpr e1) (checkExpr op) (checkExpr e2)
FrameSectionL e1 op -> SectionL noExt (checkExpr e1) (checkExpr op)
FrameSectionR op e2 -> SectionR noExt (checkExpr op) (checkExpr e2)
FrameNegApp e -> NegApp noExt (checkExpr e) noSyntaxExpr
FrameLazyPat p -> ELazyPat noExt (checkExpr p)
FrameStatic e -> HsStatic noExt (checkExpr e)
checkExprTupArg :: LTupArgFrame -> LHsTupArg GhcPs
checkExprTupArg = mapLoc go
where
go (TupArgFramePresent e) = Present noExt (checkExpr e)
go TupArgFrameMissing = Missing noExt
checkExprStmt :: LFrameStmt -> LStmt GhcPs (LHsExpr GhcPs)
checkExprStmt (dL->L l stmt) = cL l $ case stmt of
FrameTransformStmt ss f ->
mkTransformStmt (map checkExprStmt ss) (checkExpr f)
FrameTransformByStmt ss f e ->
mkTransformByStmt (map checkExprStmt ss) (checkExpr f) (checkExpr e)
FrameGroupUsingStmt ss f ->
mkGroupUsingStmt (map checkExprStmt ss) (checkExpr f)
FrameGroupByUsingStmt ss e f ->
mkGroupByUsingStmt (map checkExprStmt ss) (checkExpr e) (checkExpr f)
FrameBindStmt p e -> mkBindStmt p (checkExpr e)
FrameBodyStmt e -> mkBodyStmt (checkExpr e)
FrameLetStmt binds -> LetStmt noExt binds
FrameRecStmt ss -> mkRecStmt (map checkExprStmt ss)
FrameParStmt qss ->
ParStmt noExt
[ParStmtBlock noExt (map checkExprStmt qs) [] noSyntaxExpr
| qs <- qss]
noExpr
noSyntaxExpr
checkExprMatch :: LFrameMatch -> LMatch GhcPs (LHsExpr GhcPs)
checkExprMatch (dL->L l match) = cL l $
let FrameMatch ctxt pats grhss = match in
Match { m_ext = NoExt,
m_ctxt = ctxt,
m_pats = pats,
m_grhss = checkExprGRHSs grhss }
checkExprGRHSs :: FrameGRHSs -> GRHSs GhcPs (LHsExpr GhcPs)
checkExprGRHSs (FrameGRHSs grhss binds) =
GRHSs { grhssExt = noExt
, grhssGRHSs = map checkExprGRHS grhss
, grhssLocalBinds = binds }
checkExprGRHS :: LFrameGRHS -> LGRHS GhcPs (LHsExpr GhcPs)
checkExprGRHS (dL->L l grhs) = cL l $
let FrameGRHS guards rhs = grhs in
GRHS noExt guards (checkExpr rhs)
unguardedFrameRHS :: SrcSpan -> LExpPatFrame -> [LFrameGRHS]
unguardedFrameRHS loc rhs = [cL loc (FrameGRHS [] rhs)]
|