on master help sign in
Properly report region on bad exports
e0e0b2eEvan Czaplicki
src/AST/Module.hs+8−3
@@ -38,14 +38,19 @@ type CanonicalAdt = (Var.Canonical, AdtInfo Var.Canonical)
38-- MODULES
38-- MODULES
39
39
40type SourceModule =
40type SourceModule =
41+ Module
42+ [UserImport]
41− Module [UserImport] (Var.Listing Var.Value) [Decl.SourceDecl]
43+ (Var.Listing (A.Located Var.Value))
44+ [Decl.SourceDecl]
45+
42
46
43type ValidModule =
47type ValidModule =
44 Module
48 Module
45 ([DefaultImport], [UserImport])
49 ([DefaultImport], [UserImport])
46− (Var.Listing Var.Value)
50+ (Var.Listing (A.Located Var.Value))
47 [Decl.ValidDecl]
51 [Decl.ValidDecl]
48
52
53+
49type CanonicalModule =
54type CanonicalModule =
50 Module [Name] [Var.Value] CanonicalBody
55 Module [Name] [Var.Value] CanonicalBody
51
56
@@ -73,7 +78,7 @@ data CanonicalBody = CanonicalBody
73{-| Basic info needed to identify modules and determine dependencies. -}
78{-| Basic info needed to identify modules and determine dependencies. -}
74data Header imports = Header
79data Header imports = Header
75 { _names :: Name
80 { _names :: Name
76− , _exports :: Var.Listing Var.Value
81+ , _exports :: Var.Listing (A.Located Var.Value)
77 , _imports :: imports
82 , _imports :: imports
78 }
83 }
79
84
src/Canonicalize.hs+73−47
@@ -120,80 +120,106 @@ warnUnusedImport uses (A.A region (name, _method)) =
120
120
121resolveExports
121resolveExports
122 :: [Var.Value]
122 :: [Var.Value]
123− -> Var.Listing Var.Value
123+ -> Var.Listing (A.Located Var.Value)
124 -> Result.ResultErr [Var.Value]
124 -> Result.ResultErr [Var.Value]
125resolveExports fullList (Var.Listing partialList open) =
125resolveExports fullList (Var.Listing partialList open) =
126 if open
126 if open
127 then Result.ok fullList
127 then Result.ok fullList
128 else
128 else
129 (\xs ys zs -> xs ++ ys ++ zs)
129 (\xs ys zs -> xs ++ ys ++ zs)
130− <$> getValueExports
130+ <$> T.traverse getValueExport values
131 <*> (concat <$> T.traverse getAliasExport aliases)
131 <*> (concat <$> T.traverse getAliasExport aliases)
132 <*> T.traverse getAdtExport adts
132 <*> T.traverse getAdtExport adts
133 where
133 where
134 (allValues, allAliases, allAdts) =
134 (allValues, allAliases, allAdts) =
135− splitValues fullList
135+ maybeUnzip3 (map splitValue fullList)
136
136
137 (values, aliases, adts) =
137 (values, aliases, adts) =
138− splitValues partialList
138+ maybeUnzip3 (map splitLocatedValue partialList)
139
139
140− getValueExports =
140+ allValuesSet = Set.fromList allValues
141− case Set.toList (Set.difference values' allValues') of
141+ adtTypes = map fst allAdts
142− [] -> Result.ok (map Var.Value values)
143− xs -> manyNotFound xs allValues
144− where
145− allValues' = Set.fromList allValues
146− values' = Set.fromList values
147
142
143+ getValueExport (A.A region name) =
144+ if Set.member name allValuesSet
145+ then Result.ok (Var.Value name)
146+ else manyNotFound region [name] allValues
147+
148− getAliasExport alias
148+ getAliasExport (A.A region alias)
149 | alias `elem` allAliases =
149 | alias `elem` allAliases =
150− let recordConstructor =
150+ Result.ok $ (:) (Var.Alias alias) $
151− if alias `elem` allValues then [Var.Value alias] else []
151+ if alias `elem` allValues then [Var.Value alias] else []
152− in
152+
153+ | List.elem alias adtTypes =
153− Result.ok (Var.Alias alias : recordConstructor)
154+ Result.ok [Var.Union alias (Var.Listing [] False)]
154
155
155 | otherwise =
156 | otherwise =
156− case List.find (\(name, _ctors) -> name == alias) allAdts of
157− Nothing -> manyNotFound [alias] allAliases
157+ manyNotFound region [alias] (allAliases ++ adtTypes)
158− Just (name, _ctor) ->
158+
159− Result.ok [Var.Union name (Var.Listing [] False)]
160−
161− getAdtExport (name, Var.Listing ctors open) =
159+ getAdtExport (A.A region (name, Var.Listing ctors open)) =
162− case lookup name allAdts of
160+ case List.lookup name allAdts of
161+ Nothing ->
163− Nothing -> manyNotFound [name] (map fst allAdts)
162+ manyNotFound region [name] adtTypes
163+
164 Just (Var.Listing allCtors _)
164 Just (Var.Listing allCtors _)
165 | open ->
165 | open ->
166 Result.ok (Var.Union name (Var.Listing allCtors False))
166 Result.ok (Var.Union name (Var.Listing allCtors False))
167 | otherwise ->
167 | otherwise ->
168 case filter (`notElem` allCtors) ctors of
168 case filter (`notElem` allCtors) ctors of
169+ [] ->
169− [] -> Result.ok (Var.Union name (Var.Listing ctors False))
170+ Result.ok (Var.Union name (Var.Listing ctors False))
171+ unfoundCtors ->
170− unfoundCtors -> manyNotFound unfoundCtors allCtors
172+ manyNotFound region unfoundCtors allCtors
171
173
172− manyNotFound nameList possibilities =
174+ manyNotFound region nameList possibilities =
173− Result.errors (map (notFound possibilities) nameList)
175+ Result.errors (map (notFound region possibilities) nameList)
174
176
175− notFound possibilities name =
177+ notFound region possibilities name =
176− A.A undefined $ CError.Export name $
178+ A.A region $ CError.Export name $
177 CError.nearbyNames id name possibilities
179 CError.nearbyNames id name possibilities
178
180
179
181
180−splitValues
182+-- GROUPING VALUES
181− :: [Var.Value]
183+
182− -> ([String], [String], [(String, Var.Listing String)])
184+maybeUnzip3 :: [(Maybe a, Maybe b, Maybe c)] -> ([a],[b],[c])
183−splitValues mixedValues =
185+maybeUnzip3 tuples =
184− case mixedValues of
186+ let (as, bs, cs) = unzip3 tuples
185− [] -> ([], [], [])
187+ in
186− x:xs ->
188+ (Maybe.catMaybes as, Maybe.catMaybes bs, Maybe.catMaybes cs)
187− let (values, aliases, adts) = splitValues xs in
189+
190+
191+splitValue
192+ :: Var.Value
193+ -> ( Maybe String, Maybe String, Maybe (String, Var.Listing String) )
194+splitValue value =
188− case x of
195+ case value of
189− Var.Value name ->
196+ Var.Value name ->
190− (name : values, aliases, adts)
197+ (Just name, Nothing, Nothing)
191−
198+
199+ Var.Alias name ->
200+ (Nothing, Just name, Nothing)
201+
192− Var.Alias name ->
202+ Var.Union name listing ->
193− (values, name : aliases, adts)
203+ (Nothing, Nothing, Just (name, listing))
194−
204+
205+
206+splitLocatedValue
207+ :: A.Located Var.Value
208+ ->
209+ ( Maybe (A.Located String)
210+ , Maybe (A.Located String)
211+ , Maybe (A.Located (String, Var.Listing String))
212+ )
213+splitLocatedValue (A.A region value) =
214+ case value of
215+ Var.Value name ->
216+ (Just (A.A region name), Nothing, Nothing)
217+
218+ Var.Alias name ->
219+ (Nothing, Just (A.A region name), Nothing)
220+
195− Var.Union name listing ->
221+ Var.Union name listing ->
196− (values, aliases, (name, listing) : adts)
222+ (Nothing, Nothing, Just (A.A region (name, listing)))
197
223
198
224
199-- DECLARATIONS
225-- DECLARATIONS
src/Parse/Module.hs+3−2
@@ -6,6 +6,7 @@ import Text.Parsec hiding (newline, spaces)
6import Parse.Helpers
6import Parse.Helpers
7import qualified AST.Module as Module
7import qualified AST.Module as Module
8import qualified AST.Variable as Var
8import qualified AST.Variable as Var
9+import Reporting.Annotation as A
9
10
10
11
11getModuleName :: String -> Maybe String
12getModuleName :: String -> Maybe String
@@ -29,13 +30,13 @@ header =
29 return (Module.Header names exports imports')
30 return (Module.Header names exports imports')
30
31
31
32
32−moduleDecl :: IParser ([String], Var.Listing Var.Value)
33+moduleDecl :: IParser ([String], Var.Listing (A.Located Var.Value))
33moduleDecl =
34moduleDecl =
34 do try (reserved "module")
35 do try (reserved "module")
35 whitespace
36 whitespace
36 names <- dotSep1 capVar <?> "name of module"
37 names <- dotSep1 capVar <?> "name of module"
37 whitespace
38 whitespace
38− exports <- option Var.openListing (listing value)
39+ exports <- option Var.openListing (listing (addLocation value))
39 whitespace <?> "reserved word 'where'"
40 whitespace <?> "reserved word 'where'"
40 reserved "where"
41 reserved "where"
41 return (names, exports)
42 return (names, exports)