forked from RefactoringTools/HaRe
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathTODO
347 lines (221 loc) · 8.16 KB
/
TODO
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
341
342
343
344
345
346
Intention: Make use of existing tools to parse/pretty print, round
trip haskell code.
Resources
Tool support for refactoring haskell programs, Chris Brown
http://www.cs.kent.ac.uk/projects/refactor-fp/publications/ChrisThesis.pdf
http://www.haskell.org/onlinereport/
Generating token stream from a buffer
http://www.haskell.org/pipermail/cvs-ghc/2008-September/045023.html
Overview of Syntax Elements used in the original
http://hackage.haskell.org/packages/archive/haskell-src/1.0.1.4/doc/html/Language-Haskell-Syntax.html
Possible tools
GHC API
Buildwrapper
hint
haskell-src-exts
template haskell
Probably in combination
Other things to look at
haskell-mode
ghc-mod - uses ghc API directly
zippers, multirec
- to keep parse tree and token stream in sync when making changes
Buildwrapper is already IDE-aware
Can a lense be used to present the pfe parse tree as if it were the
GHC one?
From "Technical Report - Porting HaRe to the GHC API":
The porting process was centered on four modules,
RefacLocUtils.hs,
RefacUtils.hs,
RefacTypeSyn.hs and
RefacUtils.hs
RefacTypeUtils?
Looks like ifToCase is a really simple start point: but no tests
refacDataNewType
-------------------
Dependencies
------------
ghc-mod
ghc api
haskell-src-exts
buildwrapper (also ghc-api)
buildwrapper
haskell-src-exts (also ghc-api)
hint
haskell-src (and ghc-api)
haskell-mode
- elisp only
-----------------------------
Tasks
1. Understand round-tripping of source using GHC
getRichTokenStream :: GhcMonad m => Module -> m [(Located Token, String)]
Give even more information on the source than getTokenStream
This function allows reconstructing the source completely with
showRichTokenStream.
showRichTokenStream :: [(Located Token, String)] -> StringSource
Take a rich token stream such as produced from
getRichTokenStream and return source code almost identical to the
original code (except for insignificant whitespace.)
Seems to work.
2. Get a handle on Data.Generics / SYB / Stafunski
3. Identify how to modify the GHC output, and push it out again
4. First use GHC types, then see about using SYB et al instead of
Strafunski
-------------------
Template haskell packages to investigate
loch-th
newtype-th
test-framework-th
th-build
th-expand-syns
th-extras
th-fold
th-instances
th-kinds
th-lift
th-orphans
th-sccs
type-sub-th
zeroth
--------------------------------------------
The type for these kind of identifiers is called PNT (Programatica
Name Type) and is defined as follows:
data PNT = PNT (PN HsName Orig) (IdTy Pid) OptSrcLoc
the PNT is a uniquely identified name, and is equivalent to the GHC
Name in the RenamedSource
the PN is the equivalent of the GHC RdrName
----------------------------------------------
Seems the holes in the GHC Staged result will require
a) Update Strafunski to deal with it; OR
b) Use Data.Generics, from ghc-syb-utils, to avoid the holes
Equivalences
TP = Type Preserving - used for transformations
TU = Type Unifying - used to query
applyTU - applies a type-unifying strategy
full_tdTU - full traversal, top down
adhocTU allows the function worker to be applied to all nodes in a
layered data type: it updates a strategy to add type-specific
behavior so that the function on the left can be applied unless the
function on the right succeeds.
once_tdTU
Top-down traversal that performs its argument strategy at most once.
SO
full_tdTU (corresponds to)
everything :: (r -> r -> r) -> GenericQ r -> GenericQ r
Summarise all nodes in top-down, left-to-right order
From GHC.SYB.Utils (ghc-syb-utils-0.2.1.0)
everythingStaged :: Stage -> (r -> r -> r) -> r -> GenericQ r -> GenericQ rSource
Like everything, but avoid known potholes, based on the Stage that
generated the Ast.
------------------------------------------------------------------------
StrategyLib 5.0.3 2013-04-25
Chasing example
hsFreeAndDeclared'= applyTU (stop_tdTU (failTU `adhocTU` expr) t
--- StrategyLib extracts used above
applyTU :: (Monad m, Data x) => TU a m -> x -> m a
applyTU = unTU
-- Derive version:
unTU (MkTU f) = f
-- Starting point down the rabbit hole of checkItemStage
-- | Top-down type-unifying traversal that is cut of below nodes
-- where the argument strategy succeeds.
stop_tdTU :: (MonadPlus m, Monoid a) => TU a m -> TU a m
stop_tdTU s = s `choiceTU` (allTU' (stop_tdTU s))
choiceTU :: MonadPlus m => TU a m -> TU a m -> TU a m
choiceTU f g = MkTU ((unTU f) `mchoice` (unTU g))
-- This is the one that needs checkItemStage
allTU :: Monad m => (a -> a -> a) -> a -> TU a m -> TU a m
allTU op2 u s = MkTU (\x -> fold (gmapQ (applyTU s) x))
where
fold l = foldM op2' u l
op2' x c = c >>= \y -> return (x `op2` y)
-- Hence this one too
allTU' :: (Monad m, Monoid a) => TU a m -> TU a m
allTU' = allTU mappend mempty
-- | Type-unifying failure. Always fails, independent of the incoming
-- term. Uses 'MonadPlus' to model partiality.
failTU :: MonadPlus m => TU a m
failTU = paraTU (const mzero)
paraTU :: Monad m => (forall t. t -> m a) -> TU a m
paraTU f = MkTU f
adhocTU :: (Monad m, Data t) => TU a m -> (t -> m a) -> TU a m
adhocTU s f = MkTU (unTU s `extQ` f)
------------------------------------------------------------------------
-------
Tokens
GHC has no token for whitespace. All spacing information is in the
srcloc. Need to check the implications.
----------
Thought: do refactoring on RenamedSource, not ParsedSource. Need to
rework token stream anyway, and at least the names are resolved.
-------------------------------------
GHC structures
data ParsedModule Source
The result of successful parsing.
Constructors
ParsedModule
pm_mod_summary :: ModSummary
pm_parsed_source :: ParsedSource
pm_extra_src_files :: [FilePath]
---
The ModSummary holds compiler housekeeping information
We will work with the ParsedSource, so it is always Located.
NOTE: GHC stages
1. Parser : end up with ValDecl of (HsBind RdrName) which becomes
(HsBindLR RdrName)
2. Renamer : end up with (HsValBinds Name) which becomes
(HsBindLR Name)
3. TypeChecker : end up with
(HsBindLR Id)
RdrName : straight from the parser, no resolution
Name: have had their scoping and binding resolved, have a unique identifier
Id : Name but also has Type, and some additional info
Var: synonym for Id, but has Kind info not Type info
Bring in no-code flage to GHC when type checking
----------
type ParsedSource = Located (HsModule RdrName)
HsModule RdrName has
hsmodDecls :: [LHsDecl RdrName]
LHsDecl RdrName = Located (HsDecl RdrName)
HsDecl RdrName has
ValD (HsBind RdrName)
HsBind RdrName = HsBindLR RdrName RdrName
-- Same as bottom of RenamedSource
----------
RenamedSource
(HsGroup Name, [LImportDecl Name], Maybe [LIE Name], Maybe LHsDocString)
HsGroup has
hs_valds :: HsValBinds Name
HsValBinds has
ValBindsIn (LHsBindsLR Name Name) [LSig Name]
ValBindsOut [(RecFlag, LHsBinds Name)] [LSig Name]
LHsBindsLR Name Name = Bag (LHsBindLR Name Name)
(LHsBindLR Name Name) = Located (HsBindLR Name Name)
HsBindLR Name Name has
FunBind
PatBind
VarBind
AbsBinds
--
Look at using
modInfoLookupName :: GhcMonad m => ModuleInfo -> Name -> m (Maybe TyThing)
------
NOTE: GHC SrcSpan columns
1. Are 0 based. So what an editor calls col 1, is col 0 for GHC
2. Extend one beyond the last char. So the end col of a tok is the
same as the start col of the next one
3. HaRe internally will work with GHC cols, the translation must
happen in the API wrapper to it. Buildwrapper does something
similar.
------------------------------------------
Look at implementing hlint suggestions as refactorings
http://community.haskell.org/~ndm/hlint/hlint-report.htm
[as suggested by robstewartuk]
------------------------------------------
Decision: will use renamed source and tokens for refactoring. No
parsedsource. at all
Mechanics
- Need Renamed Source for exact Name resolution
- Need Parsed Source for decent pretty print
- Need Token Stream for good output of changed file
Must sort out pretty printer, to not have to use ParsedSource