@@ -3,6 +3,7 @@ module Canonicalize (module') where
33
44import Prelude hiding (last)
55import qualified Data.Foldable as T
6+import Data.List.NonEmpty (NonEmpty((:|)))
67import qualified Data.List as List
78import qualified Data.Map as Map
89import qualified Data.Maybe as Maybe
@@ -10,6 +11,8 @@ import qualified Data.Set as Set
1011import Data.Text (Text)
1112
1213import qualified AST.Declaration as D
14+import qualified AST.Effects as Effects
15+import qualified AST.Exposing as Exposing
1316import qualified AST.Expression.Source as Src
1417import qualified AST.Expression.Canonical as C
1518import qualified AST.Module as Module
@@ -57,7 +60,7 @@ module' importDict interfaces modul =
5760 do env <- Setup.environment importDict interfaces modul
5861
5962 (,,,) env
60− <$> resolveExports (Effects.toValues effects ++ declsToValues decls) exports
63+ <$> resolveExports (getInternalApi effects decls) exports
6164 <*> canonicalizeDecls env decls
6265 <*> Effects.canonicalize env effects
6366 in
@@ -135,77 +138,98 @@ type CResult a =
135138-- EXPORTS
136139
137140
138−resolveExports :: [Var.Value] -> Var.Listing (A.Located Var.Value) -> CResult [Var.Value]
139−resolveExports fullList (Var.Listing partialList open) =
140− if open then
141− Result.ok fullList
142−
143− else
144− let
145− (allValues, allAliases, allAdts) =
146− maybeUnzip3 (map splitValue fullList)
147−
148− (values, aliases, adts) =
149− maybeUnzip3 (map splitLocatedValue partialList)
150−
151− adtTypes =
152− map fst allAdts
153− in
154− (\xs ys zs _ -> xs ++ ys ++ zs)
155− <$> traverse (getValueExport allValues (Set.fromList allValues)) values
156− <*> (concat <$> traverse (getAliasExport allValues allAliases adtTypes) aliases)
157− <*> traverse (getAdtExport allAdts adtTypes) adts
158− <*> allUnique partialList
159−
160−
161−getValueExport :: [Text] -> Set.Set Text -> A.Located Text -> CResult Var.Value
162−getValueExport allValues allValuesSet (A.A region name) =
163− if Set.member name allValuesSet then
164− Result.ok (Var.Value name)
165− else
166− manyNotFound region [name] allValues
167−
168−
169−getAliasExport :: [Text] -> [Text] -> [Text] -> A.Located Text -> CResult [Var.Value]
170−getAliasExport allValues allAliases adtTypes (A.A region alias) =
171− if alias `elem` allAliases then
172−
173− Result.ok $ (:) (Var.Alias alias) $
174− if alias `elem` allValues then [Var.Value alias] else []
175−
176− else if List.elem alias adtTypes then
177−
178− Result.ok [Var.Union alias (Var.Listing [] False)]
179−
180− else
181−
182− manyNotFound region [alias] (allAliases ++ adtTypes)
183−
184−
185−getAdtExport
186− :: [(Text, Var.Listing Text)]
187− -> [Text]
188− -> A.Located (Text, Var.Listing Text)
189− -> CResult Var.Value
190−getAdtExport allAdts adtTypes (A.A region (name, Var.Listing ctors open)) =
191− case List.lookup name allAdts of
192− Nothing ->
193− manyNotFound region [name] adtTypes
194−
195− Just (Var.Listing allCtors _) ->
196− if open then
197− Result.ok (Var.Union name (Var.Listing allCtors False))
198− else
199− case filter (`notElem` allCtors) ctors of
200− [] ->
201− Result.ok (Var.Union name (Var.Listing ctors False))
202− unfoundCtors ->
203− manyNotFound region unfoundCtors allCtors
141+resolveExports :: Exposing.Canonical -> Exposing.Raw -> CResult Exposing.Canonical
142+resolveExports internalApi@(Exposing.Canonical values aliases unions) rawExposing =
143+ case rawExposing of
144+ Exposing.Open ->
145+ Result.ok internalApi
146+
147+ Exposing.Explicit entries ->
148+ let
149+ valueSet = Set.fromList values
150+ aliasSet = Set.fromList aliases
151+ unionMap = Map.fromList unions
152+ in
153+ case List.foldl' (resolveEntry valueSet aliasSet unionMap) (Exposing.nothing, []) entries of
154+ (exposing, []) ->
155+ do checkForDups entries
156+ Result.ok exposing
157+
158+ (_, errors) ->
159+ Result.throwMany errors
160+
161+
162+resolveEntry
163+ :: Set.Set Text
164+ -> Set.Set Text
165+ -> Map.Map Text [Text]
166+ -> (Exposing.Canonical, [A.Located CError.Error])
167+ -> A.Located Exposing.Entry
168+ -> (Exposing.Canonical, [A.Located CError.Error])
169+resolveEntry vSet aSet uSet (exposing@(Exposing.Canonical values aliases unions), errors) (A.A region entry) =
170+ case entry of
171+ Exposing.Lower name ->
172+ if Set.member name vSet then
173+ ( Exposing.Canonical (name:values) aliases unions
174+ , errors
175+ )
204176
177+ else
178+ ( exposing
179+ , notFound region (Set.toList vSet) name : errors
180+ )
181+
182+ Exposing.Upper name Nothing ->
183+ if Set.member name aSet then
184+ ( Exposing.Canonical
185+ (if Set.member name vSet then name:values else values)
186+ (name:aliases)
187+ unions
188+ , errors
189+ )
190+
191+ else if Map.member name uSet then
192+ ( Exposing.Canonical values aliases ((name, []) : unions)
193+ , errors
194+ )
205195
206−manyNotFound :: Region.Region -> [Text] -> [Text] -> CResult a
207−manyNotFound region nameList possibilities =
208− Result.throwMany (map (notFound region possibilities) nameList)
196+ else
197+ ( exposing
198+ , notFound region (Set.toList aSet ++ Map.keys uSet) name : errors
199+ )
200+
201+ Exposing.Upper name (Just exposedCtors) ->
202+ case Map.lookup name uSet of
203+ Nothing ->
204+ ( exposing
205+ , notFound region (Map.keys uSet) name : errors
206+ )
207+
208+ Just allCtors ->
209+ case exposedCtors of
210+ Exposing.Open ->
211+ ( Exposing.Canonical values aliases ((name, allCtors) : unions)
212+ , errors
213+ )
214+
215+ Exposing.Explicit ctors ->
216+ let
217+ isNotKnown (A.A _ ctor) =
218+ ctor `notElem` allCtors
219+
220+ notKnown (A.A ctorRegion ctor) =
221+ notFound ctorRegion allCtors ctor
222+ in
223+ case filter isNotKnown ctors of
224+ [] ->
225+ ( Exposing.Canonical values aliases ((name, map A.drop ctors) : unions)
226+ , errors
227+ )
228+
229+ unfoundCtors ->
230+ ( exposing
231+ , map notKnown unfoundCtors ++ errors
232+ )
209233
210234
211235notFound :: Region.Region -> [Text] -> Text -> A.Located CError.Error
@@ -214,100 +238,61 @@ notFound region possibilities badName =
214238 Help.nearbyNames id badName possibilities
215239
216240
217−allUnique :: [A.Located Var.Value] -> CResult ()
218−allUnique statedExports =
241+checkForDups :: [A.Located Exposing.Entry] -> CResult ()
242+checkForDups entries =
219243 let
220− valueToText value =
221− case value of
222− Var.Value name -> name
223− Var.Alias name -> name
224− Var.Union name _ -> name
225−
226244 locations =
227− Map.fromListWith (++) (map (\(A.A region value) -> (value, [region])) statedExports)
245+ A.listToDict Exposing.getName entries
228246
229− isUnique value allRegions =
230− case allRegions of
231− region : _ : _ ->
232− Result.throw region (CError.DuplicateExport (valueToText value))
247+ isUnique name (region :| duplicates) =
248+ case duplicates of
249+ [] ->
250+ Result.ok ()
233251
234− _ ->
235− Result.ok ()
252+ _ ->
253+ Result.throw region (CError.DuplicateExport name)
236254 in
237255 T.sequenceA_ (Map.mapWithKey isUnique locations)
238256
239257
240258
241−-- CONVERSIONS
259+-- ALL POSSIBLE EXPOSED VALUES
242260
243261
244−declsToValues :: D.Valid -> [Var.Value]
245−declsToValues (D.Decls defs unions aliases _) =
262+getInternalApi :: Effects.Raw -> D.Valid -> Exposing.Canonical
263+getInternalApi effects (D.Decls defs unions aliases _) =
246264 let
247− fromDef (A.A _ def) =
248− map Var.Value (P.boundVarList (Src.getPattern def))
249−
250− fromUnion (A.A _ (D.Type name _ ctors)) =
251− Var.Union name (Var.Listing (map fst ctors) False)
252−
253− fromAlias (A.A _ (D.Type name _ tipe)) =
254− case tipe of
255− A.A _ (Type.RRecord _ Nothing) ->
256− [ Var.Alias name, Var.Value name ]
257−
258− _ ->
259− [ Var.Alias name ]
265+ values =
266+ Effects.toExposedValues effects
267+ ++ concatMap getAliasValues aliases
268+ ++ concatMap getDefValues defs
260269 in
261− concat
262− [ map fromUnion unions
263− , concatMap fromAlias aliases
264− , concatMap fromDef defs
265− ]
266−
267−
270+ Exposing.Canonical values (map getAlias aliases) (map getUnion unions)
268271
269−-- GROUPING VALUES
270−
271−
272−maybeUnzip3 :: [(Maybe a, Maybe b, Maybe c)] -> ([a],[b],[c])
273−maybeUnzip3 tuples =
274− let (as, bs, cs) = unzip3 tuples
275− in
276− (Maybe.catMaybes as, Maybe.catMaybes bs, Maybe.catMaybes cs)
277272
273+getDefValues :: A.Commented Src.ValidDef -> [Text]
274+getDefValues (A.A _ def) =
275+ P.boundVarList (Src.getPattern def)
278276
279−splitValue
280− :: Var.Value
281− -> ( Maybe Text, Maybe Text, Maybe (Text, Var.Listing Text) )
282−splitValue value =
283− case value of
284− Var.Value name ->
285− (Just name, Nothing, Nothing)
286277
287− Var.Alias name ->
288− (Nothing, Just name, Nothing)
278+getAliasValues :: A.Commented (D.Alias Type.Raw) -> [Text]
279+getAliasValues (A.A _ (D.Type name _ tipe)) =
280+ case tipe of
281+ A.A _ (Type.RRecord _ Nothing) ->
282+ [ name ]
289283
290− Var.Union name listing ->
291− (Nothing, Nothing, Just (name, listing))
284+ _ ->
285+ []
292286
293287
294−splitLocatedValue
295− :: A.Located Var.Value
296− ->
297− ( Maybe (A.Located Text)
298− , Maybe (A.Located Text)
299− , Maybe (A.Located (Text, Var.Listing Text))
300− )
301−splitLocatedValue (A.A region value) =
302− case value of
303− Var.Value name ->
304− (Just (A.A region name), Nothing, Nothing)
288+getAlias :: A.Commented (D.Alias Type.Raw) -> Text
289+getAlias (A.A _ (D.Type name _ _)) =
290+ name
305291
306− Var.Alias name ->
307− (Nothing, Just (A.A region name), Nothing)
308292
309− Var.Union name listing ->
310− (Nothing, Nothing, Just (A.A region (name, listing)))
293+getUnion :: A.Commented (D.Union Type.Raw) -> (Text, [Text])
294+getUnion (A.A _ (D.Type name _ ctors)) =
295+ (name, map fst ctors)
311296
312297
313298