@@ -39,31 +39,22 @@ etc.) exported by every module. For example, here are a couple of entries from
39
39
``` json
40
40
[
41
41
{
42
- "fixity" : null ,
43
- "origin" : {
44
- "name" : " map" ,
45
- "module" : " GHC.Base" ,
46
- "package" : " base-4.7.0.0"
47
- },
48
- "entity" : " value"
42
+ "name" : " map" ,
43
+ "entity" : " value" ,
44
+ "module" : " GHC.Base"
49
45
},
50
46
{
51
- "fixity" : null ,
52
- "origin" : {
53
- "name" : " IO" ,
54
- "module" : " GHC.Types" ,
55
- "package" : " ghc-prim-0.3.1.0"
56
- },
57
- "entity" : " data"
47
+ "name" : " IO" ,
48
+ "entity" : " newtype" ,
49
+ "module" : " GHC.Types"
58
50
},
59
51
...
60
52
]
61
53
```
62
54
63
- As you see, each entity is annotated with the module and package where it was
64
- originally defined, and also with its fixity. Additionally, class methods, field
65
- selectors, and data constructors are annotated with the class or type they
66
- belong to.
55
+ As you see, each entity is annotated with the module where it was
56
+ originally defined. Additionally, class methods, field selectors, and data
57
+ constructors are annotated with the class or type they belong to.
67
58
68
59
### Generating interfaces
69
60
@@ -82,9 +73,10 @@ haskell-names comes with the global package database populated with some core
82
73
packages:
83
74
84
75
% hs-gen-iface pkg list --global
76
+ array-0.4.0.2
85
77
base-4.7.0.0
86
- ghc-prim-0.3.1.0
87
78
integer-simple-0.1.1.0
79
+ ghc-prim-0.3.1.0
88
80
89
81
#### Compiling core packages by hand
90
82
@@ -122,14 +114,9 @@ the package database `NamesDB` defined in `Language.Haskell.Modules.Interfaces`.
122
114
Name resolution
123
115
---------------
124
116
125
- There are two approaches to name resolution .
117
+ The ` annotateModule ` function annotates the module with scoping information .
126
118
127
- A simpler one is provided by the ` annotateModule ` function which annotates the
128
- module with scoping information.
129
-
130
- A more advanced interface is given by the ` Language.Haskell.Names.Open ` module.
131
119
Its essence is described in the article [ Open your name resolution] [ openrec ] .
132
- It is, however, very experimental.
133
120
134
121
[ openrec ] : http://ro-che.info/articles/2013-03-04-open-name-resolution.html
135
122
@@ -139,7 +126,10 @@ Let's say you have a module and you want to find out whether it uses
139
126
` Prelude.head ` .
140
127
141
128
``` haskell
129
+ module Main where
130
+
142
131
import Language.Haskell.Exts.Annotated
132
+ import qualified Language.Haskell.Exts as UnAnn (Name (Ident ))
143
133
import Language.Haskell.Names
144
134
import Language.Haskell.Names.Interfaces
145
135
import Distribution.HaskellSuite
@@ -148,12 +138,12 @@ import Distribution.Simple.Compiler
148
138
import Data.Maybe
149
139
import Data.List
150
140
import Data.Proxy
151
- import qualified Data.Set as Set
152
141
import qualified Data.Foldable as Foldable
153
142
import Text.Printf
154
143
import Control.Applicative
155
144
import Control.Monad
156
145
146
+ main :: IO ()
157
147
main = do
158
148
159
149
-- read the program's source from stdin
@@ -178,44 +168,46 @@ main = do
178
168
when (null headUsages) $
179
169
printf " Congratulations! Your code doesn't use Prelude.head\n "
180
170
181
- -- this is a computation in a ModuleT monad, because we need access to
182
- -- modules' interfaces
183
- findHeads :: Module SrcSpanInfo -> ModuleT Symbols IO [SrcSpanInfo ]
184
- findHeads ast = do
185
- -- first of all, figure out the canonical name of "Prelude.head"
186
- -- (hint: it's "GHC.List.head")
187
- Symbols values _types <- fromMaybe (error " Prelude not found" ) <$> getModuleInfo " Prelude"
188
- let
189
- headOrigName =
190
- fromMaybe (error " Prelude.head not found" ) $
191
- listToMaybe
192
- -- this looks a bit scary, but we're just walking through all
193
- -- values defined in Prelude and looking for one with unqualified
194
- -- name "head"
195
- [ origName
196
- | SymValue { sv_origName = origName@ (OrigName _pkg (GName _mod " head" )) } <- Set. toList values
197
- ]
198
-
199
- -- annotate our ast with name binding information
200
- annotatedAst <-
201
- annotateModule
202
- Haskell2010 -- base language
203
- [] -- set of extensions
204
- ast
205
-
206
-
207
- let
208
- -- get list of all annotations
209
- annotations = Foldable. toList annotatedAst
210
-
211
- -- look for headOrigName
212
- headUsages = nub
213
- [ location
214
- | Scoped (GlobalValue valueInfo) location <- annotations
215
- , sv_origName valueInfo == headOrigName
216
- ]
171
+ -- | The `findHeads` function finds all occurrences of the `head` symbol in
172
+ -- a given AST of a Haskell module. It needs access to stored name information
173
+ -- and therefore runs in `ModuleT`.
174
+ findHeads :: Module SrcSpanInfo -> ModuleT [Symbol ] IO [SrcSpanInfo ]
175
+ findHeads ast = do
176
+
177
+ -- First we get all symbols exported from `Prelude` with `getModuleInfo`.
178
+ symbols <- fromMaybe (error " Prelude not found" ) <$>
179
+ getModuleInfo " Prelude"
180
+
181
+ -- Then we filter those for the one with name `"head"`.
182
+ let
183
+ headSymbol =
184
+ fromMaybe (error " Prelude.head not found" ) (listToMaybe (do
185
+ symbol <- symbols
186
+ guard (symbolName symbol == UnAnn. Ident " head" )
187
+ return symbol))
188
+
189
+ -- We annotate the given ast.
190
+ annotatedAst <-
191
+ annotateModule
192
+ Haskell2010 -- base language
193
+ [] -- set of extensions
194
+ ast
195
+
196
+ -- We get a list of all annotations from the annotated module.
197
+ let
198
+ annotations = Foldable. toList annotatedAst
199
+
200
+ -- A `GlobalSymbol` annotation means that the annotated name refers to a
201
+ -- global symbol. It also contains the qualified name that corresponds
202
+ -- to how it is referenced but that is not needed here.
203
+ headUsages = nub (do
204
+ Scoped (GlobalSymbol globalSymbol _) location <- annotations
205
+ guard (globalSymbol == headSymbol)
206
+ return location)
207
+
208
+ -- And finally we return all found usages.
209
+ return headUsages
217
210
218
- return headUsages
219
211
```
220
212
221
213
#### Example invocation
@@ -263,20 +255,18 @@ See the [list of all issues][issues].
263
255
* Symbol fixities are not recorded ([ #1 ] [ ] )
264
256
* Type variables are not resolved ([ #2 ] [ ] )
265
257
* Arrows are not fully supported ([ #8 ] [ ] )
266
- * Type/data families and associated types are not fully supported ([ #25 ] [ ] )
267
258
268
259
[ issues ] : https://github.com/haskell-suite/haskell-names/issues/
269
260
[ #1 ] : https://github.com/haskell-suite/haskell-names/issues/1
270
261
[ #2 ] : https://github.com/haskell-suite/haskell-names/issues/2
271
262
[ #8 ] : https://github.com/haskell-suite/haskell-names/issues/8
272
- [ #25 ] : https://github.com/haskell-suite/haskell-names/issues/25
273
263
[ #32 ] : https://github.com/haskell-suite/haskell-names/issues/32
274
264
[ validation ] : https://github.com/haskell-suite/haskell-names/issues?labels=validation&page=1&state=open
275
265
276
266
Maintainers
277
267
-----------
278
268
279
- [ Roman Cheplyaka ] ( https://github.com/feuerbach ) is the primary maintainer.
269
+ [ Philipp Schuster ] ( https://github.com/phischu ) is the primary maintainer.
280
270
281
271
[ Adam Bergmark] ( https://github.com/bergmark ) is the backup maintainer. Please
282
272
get in touch with him if the primary maintainer cannot be reached.
0 commit comments