1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Setup (environment) where
4import Control.Arrow (second)
5import Control.Monad (foldM)
6import qualified Data.Graph as Graph
7import qualified Data.Map as Map
8import qualified Data.Maybe as Maybe
9import qualified Data.Traversable as Trav
11import qualified AST.Declaration as D
12import qualified AST.Effects as Effects
13import qualified AST.Expression.Valid as Valid
14import qualified AST.Module as Module
15import qualified AST.Module.Name as ModuleName
16import qualified AST.Pattern as P
17import qualified AST.Type as Type
18import qualified AST.Variable as Var
19import Elm.Utils ((|>))
20import qualified Reporting.Annotation as A
21import qualified Reporting.Error.Canonicalize as Error
22import qualified Reporting.Error.Helpers as Error
23import qualified Reporting.Region as R
24import qualified Reporting.Result as Result
25import qualified Canonicalize.Environment as Env
26import qualified Canonicalize.Type as Canonicalize
27import Canonicalize.Variable (Result)
32 :: Map.Map ModuleName.Raw ModuleName.Canonical
35 -> Result Env.Environment
36environment importDict interfaces (Module.Module name _ info) =
38 (Module.Valid _ _ (defaults, imports) decls effects) =
42 imports ++ map (A.A (error "default import not found")) defaults
45 Trav.traverse (importToPatches importDict interfaces) allImports
47 (typeAliasNodes, declPatches) =
48 declsToPatches name decls
51 effectsToPatches name effects
53 createEnv importPatches =
56 (concat (Env.builtinPatches : declPatches : effectPatches : importPatches))
58 do env <- createEnv <$> getImportPatches
59 addTypeAliases name typeAliasNodes env
67 :: Map.Map ModuleName.Raw ModuleName.Canonical
69 -> A.Located (ModuleName.Raw, Module.ImportMethod)
71importToPatches importDict allInterfaces (A.A region (rawImportName, method)) =
74 do canonicalName <- Map.lookup rawImportName importDict
75 interface <- Map.lookup canonicalName allInterfaces
76 return (canonicalName, restrictToPublicApi interface)
78 case maybeInterface of
80 if ModuleName.isNative rawImportName then
86 |> map ModuleName._module
87 |> Error.nearbyNames ModuleName.toString rawImportName
88 |> Error.moduleNotFound rawImportName
89 |> Result.throw region
91 Just (importName, interface) ->
93 (Module.ImportMethod maybeAlias listing) =
96 (Var.Listing exposedValues open) =
100 maybe (ModuleName.toString rawImportName) id maybeAlias
103 interfaceToPatches importName (qualifier ++ ".") interface
107 Result.ok (interfaceToPatches importName "" interface)
110 concat <$> Trav.traverse (valueToPatches region importName interface) exposedValues
112 (++) qualifiedPatches <$> unqualifiedPatches
115interfaceToPatches :: ModuleName.Canonical -> String -> Module.Interface -> [Env.Patch]
116interfaceToPatches moduleName prefix interface =
118 genericPatch mkPatch name value =
119 mkPatch (prefix ++ name) value
122 genericPatch mkPatch name (Var.fromModule moduleName name)
124 aliasPatch (name, (tvars, tipe)) =
128 (Var.fromModule moduleName name, tvars, tipe)
130 patternPatch (name, args) =
134 (Var.fromModule moduleName name, length args)
137 concatMap snd (Map.elems (Module.iUnions interface))
143 [ map (patch Env.Value) (Map.keys (Module.iTypes interface))
144 , map (patch Env.Value) ctorNames
145 , map (patch Env.Union) (Map.keys (Module.iUnions interface))
146 , map aliasPatch (Map.toList (Module.iAliases interface))
147 , map patternPatch ctors
152-- PATCHES FOR INDIVIDUAL VALUES
157 -> ModuleName.Canonical
160 -> Result [Env.Patch]
161valueToPatches region moduleName interface value =
164 mkPatch x (Var.fromModule moduleName x)
166 patternPatch (x, numArgs) =
167 Env.Pattern x (Var.fromModule moduleName x, numArgs)
169 notFound getNames x =
170 Module.iExports interface
172 |> Error.nearbyNames id x
173 |> Error.valueNotFound (ModuleName._module moduleName) x
174 |> Result.throw region
178 if Map.notMember x (Module.iTypes interface) then
179 notFound Var.getValues x
182 Result.ok [patch Env.Value x]
185 case Map.lookup x (Module.iAliases interface) of
189 Env.Alias x (Var.fromModule moduleName x, tvars, t)
192 if Map.member x (Module.iTypes interface) then
193 [alias, patch Env.Value x]
199 case Map.lookup x (Module.iUnions interface) of
201 Result.ok [patch Env.Union x]
204 let getNames values =
205 Var.getAliases values
206 ++ map fst (Var.getUnions values)
210 Var.Union givenName (Var.Listing givenCtorNames open) ->
211 case Map.lookup givenName (Module.iUnions interface) of
213 notFound (map fst . Var.getUnions) givenName
215 Just (_tvars, realCtors) ->
218 Result.ok realCtorList
221 Trav.traverse ctorExists givenCtorNames
224 map (second length) realCtors
227 Map.fromList realCtorList
229 ctorExists givenCtorName =
230 case Map.lookup givenCtorName realCtorDict of
232 Result.ok (givenCtorName, numArgs)
235 notFound (const (map fst realCtors)) givenCtorName
238 patch Env.Union givenName
239 : map (patch Env.Value . fst) ctors
240 ++ map patternPatch ctors
244-- PATCHES FOR TYPE ALIASES
248 ( (R.Region, String, [String], Type.Raw), String, [String] )
251node :: R.Region -> String -> [String] -> Type.Raw -> Node
252node region name tvars alias =
253 ((region, name, tvars, alias), name, edges alias)
257 Type.RLambda t1 t2 ->
263 Type.RType (Var.Raw x) ->
267 edges t ++ concatMap edges ts
269 Type.RRecord fs ext ->
270 maybe [] edges ext ++ concatMap (edges . snd) fs
273addTypeAliases :: ModuleName.Canonical -> [Node] -> Env.Environment -> Result Env.Environment
274addTypeAliases moduleName typeAliasNodes initialEnv =
275 foldM (addTypeAlias moduleName) initialEnv (Graph.stronglyConnComp typeAliasNodes)
279 :: ModuleName.Canonical
281 -> Graph.SCC (R.Region, String, [String], Type.Raw)
282 -> Result Env.Environment
283addTypeAlias moduleName env scc =
285 Graph.AcyclicSCC (_, name, tvars, alias) ->
286 addToEnv <$> Canonicalize.tipe env alias
290 (Var.fromModule moduleName name, tvars, alias')
292 env { Env._aliases = Env.insert name value (Env._aliases env) }
294 Graph.CyclicSCC [] ->
297 Graph.CyclicSCC [(region, name, tvars, alias)] ->
298 Result.throw region (Error.Alias (Error.SelfRecursive name tvars alias))
300 Graph.CyclicSCC aliases@((region, _, _, _) : _) ->
301 Result.throw region (Error.Alias (Error.MutuallyRecursive aliases))
305-- DECLARATIONS TO PATCHES
308{- When canonicalizing, it is important that:
310 _adts are fully namespaced (Var.Module ...)
311 _patterns are fully namespaced (Var.Module ...)
312 _values that are defined as top-level declarations are (Var.TopLevel ...)
313 all other _values are local (Var.Local)
316declsToPatches :: ModuleName.Canonical -> D.Valid -> ([Node], [Env.Patch])
317declsToPatches moduleName (D.Decls defs unions aliases _) =
323 Env.Value x (Var.topLevel moduleName x)
325 patternPatch (name, args) =
326 Env.Pattern name (Var.fromModule moduleName name, length args)
330 defToPatches (A.A _ (Valid.Def pattern _ _)) =
331 map topLevelValue (P.boundVarList pattern)
333 unionToPatches (A.A _ (D.Type name _ ctors)) =
334 Env.Union name (Var.fromModule moduleName name)
335 : map topLevelValue (map fst ctors)
336 ++ map patternPatch ctors
338 aliasToPatches (A.A _ (D.Type name _ alias)) =
340 Type.RRecord _ Nothing ->
341 Just (topLevelValue name)
348 aliasToNode (A.A (region, _) (D.Type name tvars alias)) =
349 node region name tvars alias
352 map aliasToNode aliases
355 [ Maybe.mapMaybe aliasToPatches aliases
356 , concatMap unionToPatches unions
357 , concatMap defToPatches defs
365effectsToPatches :: ModuleName.Canonical -> Effects.Raw -> [Env.Patch]
366effectsToPatches moduleName effects =
371 Effects.Port ports ->
373 toPatch (A.A _ (Effects.PortRaw name _)) =
374 Env.Value name (Var.topLevel moduleName name)
378 Effects.Manager _ info ->
379 map (\name -> Env.Value name (Var.topLevel moduleName name)) $
380 case Effects._managerType info of
381 Effects.CmdManager _ ->
384 Effects.SubManager _ ->
387 Effects.FxManager _ _ ->
388 [ "command", "subscription" ]
392-- RESTRICT VISIBLE API OF INTERFACES
395restrictToPublicApi :: Module.Interface -> Module.Interface
396restrictToPublicApi interface =
401 (get (Module.iTypes interface))
402 (Var.getValues exports ++ ctors)
407 (get (Module.iAliases interface))
408 (Var.getAliases exports)
412 (Maybe.mapMaybe (trimUnions interface) unions)
415 exports :: [Var.Value]
417 Module.iExports interface
419 unions :: [(String, Var.Listing String)]
421 Var.getUnions exports
425 concatMap (\(_, Var.Listing ctorList _) -> ctorList) unions
428get :: Map.Map String a -> String -> Maybe (String, a)
430 case Map.lookup key dict of
440 -> (String, Var.Listing String)
441 -> Maybe (String, Module.UnionInfo String)
442trimUnions interface (name, Var.Listing exportedCtors _) =
443 case Map.lookup name (Module.iUnions interface) of
447 Just (tvars, ctors) ->
449 isExported (ctor, _) =
450 ctor `elem` exportedCtors
452 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