-
Notifications
You must be signed in to change notification settings - Fork 18
/
Copy pathExports.hs
116 lines (104 loc) · 4.72 KB
/
Exports.hs
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
{-# LANGUAGE TypeFamilies, NoMonoLocalBinds #-}
module Language.Haskell.Names.Exports
( exportedSymbols
, annotateExportSpecList
) where
import Control.Monad
import Data.Data
import Language.Haskell.Exts
import Language.Haskell.Names.GlobalSymbolTable as Global
import Language.Haskell.Names.ModuleSymbols
import Language.Haskell.Names.ScopeUtils
import Language.Haskell.Names.SyntaxUtils
import Language.Haskell.Names.Types
import qualified Data.Map as Map
import qualified Data.Set as Set
-- | Compute the list of symbols the given module exports using the given
-- table of symbols that are in scope in that module.
exportedSymbols :: (Data l, Eq l) => Global.Table -> Module l -> [Symbol]
exportedSymbols globalTable modul = nubSymbols (case getExportSpecList modul of
Nothing -> moduleSymbols globalTable modul
Just (ExportSpecList _ exportSpecs) ->
concatMap (exportSpecSymbols globalTable) exportSpecs)
exportSpecSymbols :: Global.Table -> ExportSpec l -> [Symbol]
exportSpecSymbols globalTable exportSpec =
case annotateExportSpec globalTable exportSpec of
EVar (Scoped (Export symbols) _) _ -> symbols
EAbs (Scoped (Export symbols) _) _ _ -> symbols
EThingWith (Scoped (Export symbols) _) _ _ _ -> symbols
EModuleContents (Scoped (Export symbols) _) _ -> symbols
_ -> []
-- | Annotate the given export list with scoping information using the given
-- table of symbols that are in scope in that module.
annotateExportSpecList :: Global.Table -> ExportSpecList l -> ExportSpecList (Scoped l)
annotateExportSpecList globalTable (ExportSpecList l exportSpecs) =
ExportSpecList (none l) (map (annotateExportSpec globalTable) exportSpecs)
annotateExportSpec :: Global.Table -> ExportSpec l -> ExportSpec (Scoped l)
annotateExportSpec globalTable exportSpec =
case exportSpec of
EVar l qn ->
case Global.lookupValue qn globalTable of
[] -> scopeError (ENotInScope qn) exportSpec
[symbol] -> EVar (Scoped (Export [symbol]) l)
(Scoped (GlobalSymbol symbol (dropAnn qn)) <$> qn)
symbols -> scopeError (EAmbiguous qn symbols) exportSpec
EAbs l ns@(PatternNamespace _) qn ->
case Global.lookupValue qn globalTable of
[] -> scopeError (ENotInScope qn) exportSpec
[symbol] -> EAbs (Scoped (Export [symbol]) l)
(noScope ns)
(Scoped (GlobalSymbol symbol (dropAnn qn)) <$> qn)
symbols -> scopeError (EAmbiguous qn symbols) exportSpec
EAbs l ns qn ->
case Global.lookupType qn globalTable of
[] -> scopeError (ENotInScope qn) exportSpec
[symbol] -> EAbs (Scoped (Export [symbol]) l)
(noScope ns)
(Scoped (GlobalSymbol symbol (dropAnn qn)) <$> qn)
symbols -> scopeError (EAmbiguous qn symbols) exportSpec
EThingWith l w@(EWildcard _ _) qn _ ->
case Global.lookupType qn globalTable of
[] -> scopeError (ENotInScope qn) exportSpec
[symbol] ->
let
subSymbols = nubSymbols (do
subSymbol <- concat (Map.elems globalTable)
Just subSymbolParentName <- return $ symbolParent subSymbol
guard (subSymbolParentName == symbolName symbol)
guard (symbolModule subSymbol == symbolModule symbol)
return subSymbol)
s = [symbol] <> subSymbols
in
EThingWith (Scoped (Export s) l) (fmap (Scoped None) w) (Scoped (GlobalSymbol symbol (dropAnn qn)) <$> qn) []
symbols -> scopeError (EAmbiguous qn symbols) exportSpec
EThingWith l w@(NoWildcard {}) qn cns ->
case Global.lookupType qn globalTable of
[] -> scopeError (ENotInScope qn) exportSpec
[symbol] ->
let
(cns', subSymbols) =
resolveCNames
(concat (Map.elems globalTable))
(symbolName symbol)
(\cn -> ENotInScope (UnQual (ann cn) (unCName cn))) -- FIXME better error
cns
s = [symbol] <> subSymbols
in
EThingWith (Scoped (Export s) l) (fmap (Scoped None) w) (Scoped (GlobalSymbol symbol (dropAnn qn)) <$> qn) cns'
symbols -> scopeError (EAmbiguous qn symbols) exportSpec
-- FIXME ambiguity check
EModuleContents _ modulename -> Scoped (Export exportedSymbols) <$> exportSpec where
exportedSymbols = Set.toList (Set.intersection inScopeQualified inScopeUnqualified)
inScopeQualified = Set.fromList (do
(Qual _ prefix _, symbols) <- Map.toList globalTable
guard (prefix == dropAnn modulename)
symbols)
inScopeUnqualified = Set.fromList (do
(UnQual _ _, symbols) <- Map.toList globalTable
symbols)
nubSymbols :: [Symbol] -> [Symbol]
nubSymbols = loop Set.empty where
loop _ [] = []
loop a (b : c) = if Set.member b a
then loop a c
else b : loop (Set.insert b a) c