1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Setup (environment) where
4import Control.Arrow (second)
5import qualified Data.Graph as Graph
6import qualified Data.Map as Map
7import qualified Data.Maybe as Maybe
8import qualified Data.Traversable as Trav
10import qualified AST.Declaration as D
11import qualified AST.Expression.Valid as Valid
12import qualified AST.Module as Module
13import qualified AST.Module.Name as ModuleName
14import qualified AST.Pattern as P
15import qualified AST.Type as Type
16import qualified AST.Variable as Var
17import Elm.Utils ((|>))
18import qualified Reporting.Annotation as A
19import qualified Reporting.Error.Canonicalize as Error
20import qualified Reporting.Error.Helpers as Error
21import qualified Reporting.Region as R
22import qualified Canonicalize.Environment as Env
23import qualified Canonicalize.Result as Result
24import qualified Canonicalize.Type as Canonicalize
28 :: Map.Map ModuleName.Raw ModuleName.Canonical
31 -> Result.ResultErr Env.Environment
32environment importDict interfaces (Module.Module name _ _ _ (defaults, imports) decls) =
35 imports ++ map (A.A (error "default import not found")) defaults
38 concat <$> Trav.traverse (importPatches importDict interfaces) allImports
40 (typeAliasNodes, declPatches) =
41 declarationsToPatches name decls
44 (++) (Env.builtinPatches ++ declPatches) <$> importPatchesResult
46 (Env.fromPatches name <$> patches)
47 `Result.andThen` addTypeAliases name typeAliasNodes
53 :: Map.Map ModuleName.Raw ModuleName.Canonical
55 -> A.Located (ModuleName.Raw, Module.ImportMethod)
56 -> Result.ResultErr [Env.Patch]
57importPatches importDict allInterfaces (A.A region (rawImportName, method)) =
60 do canonicalName <- Map.lookup rawImportName importDict
61 interface <- Map.lookup canonicalName allInterfaces
62 return (canonicalName, restrictToPublicApi interface)
64 case maybeInterface of
66 if ModuleName.isNative rawImportName then
72 |> map ModuleName._module
73 |> Error.nearbyNames ModuleName.toString rawImportName
74 |> Error.moduleNotFound rawImportName
78 Just (importName, interface) ->
79 let (Module.ImportMethod maybeAlias listing) =
82 (Var.Listing exposedValues open) =
86 maybe (ModuleName.toString rawImportName) id maybeAlias
89 interfacePatches importName (qualifier ++ ".") interface
93 then Result.ok (interfacePatches importName "" interface)
94 else concat <$> Trav.traverse (valueToPatches region importName interface) exposedValues
96 (++) qualifiedPatches <$> unqualifiedPatches
99interfacePatches :: ModuleName.Canonical -> String -> Module.Interface -> [Env.Patch]
100interfacePatches moduleName prefix interface =
101 let genericPatch mkPatch name value =
102 mkPatch (prefix ++ name) value
105 genericPatch mkPatch name (Var.fromModule moduleName name)
107 aliasPatch (name, (tvars, tipe)) =
108 genericPatch Env.Alias name
109 (Var.fromModule moduleName name, tvars, tipe)
111 patternPatch (name, args) =
112 genericPatch Env.Pattern name
113 (Var.fromModule moduleName name, length args)
116 concatMap snd (Map.elems (Module.iAdts interface))
122 [ map (patch Env.Value) (Map.keys (Module.iTypes interface))
123 , map (patch Env.Value) ctorNames
124 , map (patch Env.Union) (Map.keys (Module.iAdts interface))
125 , map aliasPatch (Map.toList (Module.iAliases interface))
126 , map patternPatch ctors
130-- PATCHES FOR INDIVIDUAL VALUES
134 -> ModuleName.Canonical
137 -> Result.ResultErr [Env.Patch]
138valueToPatches region moduleName interface value =
139 let patch mkPatch x =
140 mkPatch x (Var.fromModule moduleName x)
142 patternPatch (x, numArgs) =
143 Env.Pattern x (Var.fromModule moduleName x, numArgs)
145 notFound getNames x =
146 Module.iExports interface
148 |> Error.nearbyNames id x
149 |> Error.valueNotFound (ModuleName._module moduleName) x
155 | Map.notMember x (Module.iTypes interface) ->
156 notFound Var.getValues x
159 Result.ok [patch Env.Value x]
162 case Map.lookup x (Module.iAliases interface) of
165 Env.Alias x (Var.fromModule moduleName x, tvars, t)
168 if Map.member x (Module.iTypes interface)
169 then [alias, patch Env.Value x]
173 case Map.lookup x (Module.iAdts interface) of
175 Result.ok [patch Env.Union x]
178 let getNames values =
179 Var.getAliases values
180 ++ map fst (Var.getUnions values)
184 Var.Union givenName (Var.Listing givenCtorNames open) ->
185 case Map.lookup givenName (Module.iAdts interface) of
187 notFound (map fst . Var.getUnions) givenName
189 Just (_tvars, realCtors) ->
192 then Result.ok realCtorList
193 else Trav.traverse ctorExists givenCtorNames
196 map (second length) realCtors
199 Map.fromList realCtorList
201 ctorExists givenCtorName =
202 case Map.lookup givenCtorName realCtorDict of
204 Result.ok (givenCtorName, numArgs)
206 notFound (const (map fst realCtors)) givenCtorName
209 patch Env.Union givenName
210 : map (patch Env.Value . fst) ctors
211 ++ map patternPatch ctors
214-- PATCHES FOR TYPE ALIASES
216type Node = ((R.Region, String, [String], Type.Raw), String, [String])
219node :: R.Region -> String -> [String] -> Type.Raw -> Node
220node region name tvars alias =
221 ((region, name, tvars, alias), name, edges alias)
225 Type.RLambda t1 t2 ->
231 Type.RType (Var.Raw x) ->
235 edges t ++ concatMap edges ts
237 Type.RRecord fs ext ->
238 maybe [] edges ext ++ concatMap (edges . snd) fs
242 :: ModuleName.Canonical
245 -> Result.ResultErr Env.Environment
246addTypeAliases moduleName typeAliasNodes initialEnv =
248 (addTypeAlias moduleName)
250 (Graph.stronglyConnComp typeAliasNodes)
254 :: ModuleName.Canonical
255 -> Graph.SCC (R.Region, String, [String], Type.Raw)
257 -> Result.ResultErr Env.Environment
258addTypeAlias moduleName scc env =
260 Graph.AcyclicSCC (_, name, tvars, alias) ->
261 addToEnv <$> Canonicalize.tipe env alias
265 (Var.fromModule moduleName name, tvars, alias')
267 env { Env._aliases = Env.insert name value (Env._aliases env) }
269 Graph.CyclicSCC [] ->
272 Graph.CyclicSCC [(region, name, tvars, alias)] ->
273 Result.err (A.A region (Error.Alias (Error.SelfRecursive name tvars alias)))
275 Graph.CyclicSCC aliases@((region, _, _, _) : _) ->
276 Result.err (A.A region (Error.Alias (Error.MutuallyRecursive aliases)))
279-- DECLARATIONS TO PATCHES
282 :: ModuleName.Canonical
284 -> ([Node], [Env.Patch])
285declarationsToPatches moduleName decls =
286 let (maybeNodes, patchLists) =
287 unzip (map (declToPatches moduleName) decls)
289 (Maybe.catMaybes maybeNodes, concat patchLists)
292-- When canonicalizing, it is important that:
293-- _adts are fully namespaced (Var.Module ...)
294-- _patterns are fully namespaced (Var.Module ...)
295-- _values that are defined as top-level declarations are (Var.TopLevel ...)
296-- all other _values are local (Var.Local)
298 :: ModuleName.Canonical
300 -> (Maybe Node, [Env.Patch])
301declToPatches moduleName (A.A (region,_) decl) =
302 let topLevel mkPatch x =
303 mkPatch x (Var.topLevel moduleName x )
305 namespaced mkPatch x =
306 mkPatch x (Var.fromModule moduleName x)
308 patternPatch (name, args) =
309 Env.Pattern name (Var.fromModule moduleName name, length args)
312 D.Definition (Valid.Definition pattern _ _) ->
314 , map (topLevel Env.Value) (P.boundVarList pattern)
317 D.Datatype name _ ctors ->
318 let ctorNames = map fst ctors
321 , namespaced Env.Union name
322 : map (topLevel Env.Value) ctorNames
323 ++ map patternPatch ctors
326 D.TypeAlias name tvars alias ->
327 ( Just (node region name tvars alias)
329 A.A _ (Type.RRecord _ Nothing) ->
330 [topLevel Env.Value name]
337 , [topLevel Env.Value (D.validPortName port)]
346-- RESTRICT VISIBLE API OF INTERFACES
348restrictToPublicApi :: Module.Interface -> Module.Interface
349restrictToPublicApi interface =
354 (get (Module.iTypes interface))
355 (Var.getValues exports ++ ctors)
360 (get (Module.iAliases interface))
361 (Var.getAliases exports)
365 (Maybe.mapMaybe (trimUnions interface) unions)
368 exports :: [Var.Value]
370 Module.iExports interface
372 unions :: [(String, Var.Listing String)]
374 Var.getUnions exports
378 concatMap (\(_, Var.Listing ctorList _) -> ctorList) unions
381get :: Map.Map String a -> String -> Maybe (String, a)
383 case Map.lookup key dict of
385 Just value -> Just (key, value)
390 -> (String, Var.Listing String)
391 -> Maybe (String, Module.AdtInfo String)
392trimUnions interface (name, Var.Listing exportedCtors _) =
393 case Map.lookup name (Module.iAdts interface) of
395 Just (tvars, ctors) ->
396 let isExported (ctor, _) =
397 ctor `elem` exportedCtors
399 Just (name, (tvars, filter isExported ctors))
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list