1
1
module Language.PureScript.Backend.IR
2
2
( module Language.PureScript.Backend.IR
3
3
, module Language.PureScript.Backend.IR.Types
4
+ , module Language.PureScript.Backend.IR.Names
4
5
) where
5
6
6
7
import Control.Monad.Error.Class (MonadError (throwError ))
@@ -14,11 +15,11 @@ import Data.Text qualified as Text
14
15
import Data.Traversable (for )
15
16
import Language.PureScript.Backend.IR.Inliner (Annotation )
16
17
import Language.PureScript.Backend.IR.Inliner qualified as Inliner
18
+ import Language.PureScript.Backend.IR.Names
17
19
import Language.PureScript.Backend.IR.Types
18
20
import Language.PureScript.Comments (Comment (.. ))
19
21
import Language.PureScript.CoreFn qualified as Cfn
20
22
import Language.PureScript.CoreFn.Laziness (applyLazinessTransform )
21
- import Language.PureScript.Names (ModuleName (.. ), runModuleName )
22
23
import Language.PureScript.Names qualified as Names
23
24
import Language.PureScript.Names qualified as PS
24
25
import Language.PureScript.PSString
@@ -35,7 +36,7 @@ import Prelude hiding (identity, show)
35
36
36
37
data Context = Context
37
38
{ annotations
38
- ∷ [ Annotation]
39
+ ∷ Map Name Annotation
39
40
, contextModule
40
41
∷ Cfn.Module Cfn.Ann
41
42
, contextDataTypes
@@ -87,7 +88,7 @@ mkModule cfnModule contextDataTypes = do
87
88
, needsRuntimeLazy = Any False
88
89
}
89
90
do
90
- moduleBindings ← mkDecls
91
+ moduleBindings ← mkBindings
91
92
moduleImports ← mkImports
92
93
moduleExports ← mkExports
93
94
moduleReExports ← mkReExports
@@ -103,20 +104,20 @@ mkModule cfnModule contextDataTypes = do
103
104
, moduleForeigns
104
105
}
105
106
106
- parseAnnotations ∷ Cfn. Module Cfn. Ann → Either CoreFnError [ Annotation ]
107
+ parseAnnotations ∷ Cfn. Module Cfn. Ann → Either CoreFnError ( Map Name Annotation )
107
108
parseAnnotations currentModule =
108
109
Cfn. moduleComments currentModule
109
110
& foldMapM \ case
110
- LineComment line → pure <$> parseAnnotationLine line
111
- BlockComment block → traverse parseAnnotationLine (lines block)
112
- & fmap catMaybes
111
+ LineComment line → pure <$> parsePragmaLine line
112
+ BlockComment block → traverse parsePragmaLine (lines block)
113
+ & fmap ( Map. fromList . catMaybes)
113
114
where
114
- parseAnnotationLine ∷ Text → Either CoreFnError (Maybe Annotation )
115
- parseAnnotationLine ( Text. strip → ln) = do
116
- let parser = optional (Inliner. annotationParser <* Megaparsec. eof)
117
- first
118
- ( CoreFnError ( Cfn. moduleName currentModule) . AnnotationParsingError )
119
- ( Megaparsec. parse parser ( Cfn. modulePath currentModule) ln )
115
+ parsePragmaLine ∷ Text → Either CoreFnError (Maybe Inliner. Pragma )
116
+ parsePragmaLine ln = do
117
+ let parser = optional (Inliner. pragmaParser <* Megaparsec. eof)
118
+ Megaparsec. parse parser ( Cfn. modulePath currentModule) ( Text. strip ln)
119
+ & first
120
+ ( CoreFnError ( Cfn. moduleName currentModule) . AnnotationParsingError )
120
121
121
122
mkImports ∷ RepM [ModuleName ]
122
123
mkImports = do
@@ -169,80 +170,88 @@ mkQualified f (PS.Qualified by a) =
169
170
identToName ∷ PS. Ident → Name
170
171
identToName = Name . PS. runIdent
171
172
172
- mkDecls ∷ RepM [Grouping (Ann , Name , Exp )]
173
- mkDecls = do
174
- psDecls ← gets $ contextModule >>> Cfn. moduleBindings
175
- traverse mkGrouping psDecls
176
-
177
- mkGrouping ∷ Cfn. Bind Cfn. Ann → RepM (Grouping (Ann , Name , Exp ))
178
- mkGrouping = \ case
179
- Cfn. NonRec _ann ident cfnExpr →
180
- Standalone . (noAnn,identToName ident,) <$> makeExp cfnExpr
173
+ mkBindings ∷ RepM [Binding ]
174
+ mkBindings = do
175
+ psBindings ← gets $ contextModule >>> Cfn. moduleBindings
176
+ traverse mkBinding psBindings
177
+
178
+ mkBinding ∷ Cfn. Bind Cfn. Ann → RepM Binding
179
+ mkBinding = \ case
180
+ Cfn. NonRec _ann ident cfnExpr → do
181
+ let name = identToName ident
182
+ ann ← gets $ annotations >>> Map. lookup name
183
+ expr ← makeExprAnnotated ann cfnExpr
184
+ pure $ Standalone (noAnn, name, expr)
181
185
Cfn. Rec bindingGroup → do
182
186
modname ← gets $ contextModule >>> Cfn. moduleName
183
187
bindings ← writer $ applyLazinessTransform modname bindingGroup
184
188
case NE. nonEmpty bindings of
185
189
Nothing → throwContextualError EmptyBindingGroup
186
190
Just bs →
187
191
RecursiveGroup <$> for bs \ ((_ann, ident), expr) →
188
- (noAnn,identToName ident,) <$> makeExp expr
192
+ (noAnn,identToName ident,) <$> makeExpr expr
193
+
194
+ makeExpr ∷ CfnExp → RepM Exp
195
+ makeExpr = makeExprAnnotated Nothing
189
196
190
- makeExp ∷ CfnExp → RepM Exp
191
- makeExp cfnExpr =
197
+ makeExprAnnotated ∷ Ann → CfnExp → RepM Exp
198
+ makeExprAnnotated ann cfnExpr =
192
199
case cfnExpr of
193
200
Cfn. Literal _ann literal →
194
- mkLiteral literal
195
- Cfn. Constructor ann tyName ctorName ids →
196
- mkConstructor ann tyName ctorName ids
201
+ mkLiteral ann literal
202
+ Cfn. Constructor cfnAnn tyName ctorName ids →
203
+ mkConstructor cfnAnn ann tyName ctorName ids
197
204
Cfn. Accessor _ann str expr →
198
- mkAccessor str expr
205
+ mkAccessor ann str expr
199
206
Cfn. ObjectUpdate _ann expr patches →
200
207
mkObjectUpdate expr patches
201
208
Cfn. Abs _ann ident expr →
202
- mkAbstraction ident expr
209
+ mkAbstraction ann ident expr
203
210
Cfn. App _ann abstr arg →
204
211
mkApplication abstr arg
205
212
Cfn. Var _ann qualifiedIdent →
206
213
mkRef qualifiedIdent
207
214
Cfn. Case _ann exprs alternatives →
208
215
case NE. nonEmpty alternatives of
209
- Just as → mkCase exprs as
216
+ Just as → mkCase ann exprs as
210
217
Nothing → throwContextualError $ EmptyCase cfnExpr
211
- Cfn. Let _ann binds exprs → mkLet binds exprs
218
+ Cfn. Let _ann binds exprs →
219
+ mkLet ann binds exprs
212
220
213
- mkLiteral ∷ Cfn. Literal CfnExp → RepM Exp
214
- mkLiteral = \ case
221
+ mkLiteral ∷ Ann → Cfn. Literal CfnExp → RepM Exp
222
+ mkLiteral ann = \ case
215
223
Cfn. NumericLiteral (Left i) →
216
- pure $ literalInt i
224
+ pure $ LiteralInt ann i
217
225
Cfn. NumericLiteral (Right d) →
218
- pure $ literalFloat d
226
+ pure $ LiteralFloat ann d
219
227
Cfn. StringLiteral s →
220
- pure $ literalString $ decodeStringEscaping s
228
+ pure $ LiteralString ann $ decodeStringEscaping s
221
229
Cfn. CharLiteral c →
222
- pure $ literalChar c
230
+ pure $ LiteralChar ann c
223
231
Cfn. BooleanLiteral b →
224
- pure $ literalBool b
232
+ pure $ LiteralBool ann b
225
233
Cfn. ArrayLiteral exprs →
226
- literalArray <$> traverse makeExp exprs
234
+ LiteralArray ann <$> traverse makeExpr exprs
227
235
Cfn. ObjectLiteral kvs →
228
- literalObject <$> traverse (bitraverse mkPropName makeExp ) kvs
236
+ LiteralObject ann <$> traverse (bitraverse mkPropName makeExpr ) kvs
229
237
230
238
mkConstructor
231
239
∷ Cfn. Ann
240
+ → Ann
232
241
→ PS. ProperName 'PS.TypeName
233
242
→ PS. ProperName 'PS.ConstructorName
234
243
→ [PS. Ident ]
235
244
→ RepM Exp
236
- mkConstructor ann properTyName properCtorName fields = do
245
+ mkConstructor cfnAnn ann properTyName properCtorName fields = do
237
246
let tyName = mkTyName properTyName
238
247
contextModuleName ← gets (Cfn. moduleName . contextModule)
239
248
algTy ← algebraicTy contextModuleName tyName
240
249
pure
241
- if isNewtype ann
250
+ if isNewtype cfnAnn
242
251
then identity
243
252
else
244
253
Ctor
245
- noAnn
254
+ ann
246
255
algTy
247
256
contextModuleName
248
257
tyName
@@ -263,21 +272,21 @@ mkPropName str = case decodeString str of
263
272
Left err → throwContextualError $ UnicodeDecodeError err
264
273
Right decodedString → pure $ PropName decodedString
265
274
266
- mkAccessor ∷ PSString → CfnExp → RepM Exp
267
- mkAccessor prop cfnExpr = do
275
+ mkAccessor ∷ Ann → PSString → CfnExp → RepM Exp
276
+ mkAccessor ann prop cfnExpr = do
268
277
propName ← mkPropName prop
269
- makeExp cfnExpr <&> \ expr → ObjectProp noAnn expr propName
278
+ makeExprAnnotated ann cfnExpr <&> \ expr → ObjectProp noAnn expr propName
270
279
271
280
mkObjectUpdate ∷ CfnExp → [(PSString , CfnExp )] → RepM Exp
272
281
mkObjectUpdate cfnExp props = do
273
- expr ← makeExp cfnExp
274
- patch ← traverse (bitraverse mkPropName makeExp ) props
282
+ expr ← makeExpr cfnExp
283
+ patch ← traverse (bitraverse mkPropName makeExpr ) props
275
284
case NE. nonEmpty patch of
276
285
Nothing → throwContextualError EmptyObjectUpdate
277
286
Just ps → pure $ ObjectUpdate noAnn expr ps
278
287
279
- mkAbstraction ∷ PS. Ident → CfnExp → RepM Exp
280
- mkAbstraction i e = abstraction param <$> makeExp e
288
+ mkAbstraction ∷ Ann → PS. Ident → CfnExp → RepM Exp
289
+ mkAbstraction ann i e = Abs ann param <$> makeExpr e
281
290
where
282
291
param ∷ Parameter Ann =
283
292
case PS. runIdent i of
@@ -287,8 +296,8 @@ mkAbstraction i e = abstraction param <$> makeExp e
287
296
mkApplication ∷ CfnExp → CfnExp → RepM Exp
288
297
mkApplication e1 e2 =
289
298
if isNewtype (Cfn. extractAnn e1)
290
- then makeExp e2
291
- else application <$> makeExp e1 <*> makeExp e2
299
+ then makeExpr e2
300
+ else application <$> makeExpr e1 <*> makeExpr e2
292
301
293
302
mkQualifiedIdent ∷ PS. Qualified PS. Ident → RepM (Qualified Name )
294
303
mkQualifiedIdent (PS. Qualified by ident) =
@@ -303,27 +312,27 @@ mkQualifiedIdent (PS.Qualified by ident) =
303
312
mkRef ∷ PS. Qualified PS. Ident → RepM Exp
304
313
mkRef = (\ n → Ref noAnn n 0 ) <<$>> mkQualifiedIdent
305
314
306
- mkLet ∷ [Cfn. Bind Cfn. Ann ] → CfnExp → RepM Exp
307
- mkLet binds expr = do
308
- groupings ∷ NonEmpty ( Grouping ( Ann , Name , Exp )) ←
315
+ mkLet ∷ Ann → [Cfn. Bind Cfn. Ann ] → CfnExp → RepM Exp
316
+ mkLet ann binds expr = do
317
+ groupings ∷ NonEmpty Binding ←
309
318
NE.nonEmpty binds
310
- & maybe (throwContextualError LetWithoutBinds ) (traverse mkGrouping )
311
- lets groupings <$> makeExp expr
319
+ & maybe (throwContextualError LetWithoutBinds ) (traverse mkBinding )
320
+ Let ann groupings <$> makeExpr expr
312
321
313
322
--------------------------------------------------------------------------------
314
323
-- Case statements are compiled to a decision trees (nested if/else's) ---------
315
324
-- The algorithm is based on this document: ------------------------------------
316
325
-- https://julesjacobs.com/notes/patternmatching/patternmatching.pdf -----------
317
326
318
- mkCase ∷ [CfnExp ] → NonEmpty (Cfn. CaseAlternative Cfn. Ann ) → RepM Exp
319
- mkCase cfnExpressions alternatives = do
320
- expressions ← traverse makeExp cfnExpressions
327
+ mkCase ∷ Ann -> [CfnExp ] → NonEmpty (Cfn. CaseAlternative Cfn. Ann ) → RepM Exp
328
+ mkCase ann cfnExpressions alternatives = do
329
+ expressions ← traverse makeExpr cfnExpressions
321
330
-- Before making clauses, we need to prepare bindings
322
331
-- such that instead of repeating the same expression multiple times,
323
332
-- we can bind it to a name once and then repeat references.
324
333
(references, bindings) ← prepareBindings expressions
325
334
clauses ← traverse (alternativeToClauses references) alternatives
326
- let addHeader = maybe id lets (NE. nonEmpty bindings)
335
+ let addHeader = maybe id ( Let ann) (NE. nonEmpty bindings)
327
336
addHeader <$> mkCaseClauses (NE. toList clauses)
328
337
329
338
-- Either an expression to inline, or a named expression reference.
@@ -649,8 +658,8 @@ alternativeToClauses
649
658
650
659
clauseResult ←
651
660
bitraverse
652
- (traverse (bitraverse makeExp makeExp ))
653
- makeExp
661
+ (traverse (bitraverse makeExpr makeExpr ))
662
+ makeExpr
654
663
caseAlternativeResult
655
664
656
665
pure
0 commit comments