1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Canonicalize.Setup (environment) where
5import Control.Arrow (second)
6import Control.Monad (foldM)
7import qualified Data.Graph as Graph
8import qualified Data.Map as Map
9import qualified Data.Maybe as Maybe
10import Data.Monoid ((<>))
11import Data.Text (Text)
13import qualified AST.Declaration as D
14import qualified AST.Effects as Effects
15import qualified AST.Exposing as Exposing
16import qualified AST.Expression.Source as Src
17import qualified AST.Module as Module
18import qualified AST.Module.Name as ModuleName
19import qualified AST.Pattern as P
20import qualified AST.Type as Type
21import qualified AST.Variable as Var
22import Elm.Utils ((|>))
23import qualified Reporting.Annotation as A
24import qualified Reporting.Error.Canonicalize as Error
25import qualified Reporting.Helpers as Help (nearbyNames)
26import qualified Reporting.Region as R
27import qualified Reporting.Result as Result
28import qualified Canonicalize.Environment as Env
29import qualified Canonicalize.Type as Canonicalize
30import Canonicalize.Variable (Result)
35 :: Map.Map ModuleName.Raw ModuleName.Canonical
39environment importDict interfaces (Module.Module name info) =
41 (Module.Valid _ _ (defaults, imports) decls effects) =
45 imports ++ map (A.A (error "default import not found")) defaults
48 traverse (importToPatches importDict interfaces) allImports
50 (typeAliasNodes, declPatches) =
51 declsToPatches name decls
54 effectsToPatches name effects
56 createEnv importPatches =
59 (concat (Env.builtinPatches : declPatches : effectPatches : importPatches))
61 do env <- createEnv <$> getImportPatches
62 addTypeAliases name typeAliasNodes env
70 :: Map.Map ModuleName.Raw ModuleName.Canonical
72 -> A.Located (ModuleName.Raw, Module.ImportMethod)
74importToPatches importDict allInterfaces (A.A region (rawImportName, method)) =
77 do canonicalName <- Map.lookup rawImportName importDict
78 interface <- Map.lookup canonicalName allInterfaces
79 return (canonicalName, restrictToPublicApi interface)
81 case maybeInterface of
83 if ModuleName.isKernel rawImportName then
89 |> map ModuleName._module
90 |> Help.nearbyNames ModuleName.toText rawImportName
91 |> Error.moduleNotFound rawImportName
92 |> Result.throw region
94 Just (importName, interface) ->
96 (Module.ImportMethod maybeAlias listing) =
100 maybe (ModuleName.toText rawImportName) id maybeAlias
103 map (infixToPatch (Var.fromModule importName)) (Module.iFixities interface)
106 interfaceToPatches importName (qualifier <> ".") interface
111 Result.ok (interfaceToPatches importName "" interface)
113 Exposing.Explicit xs ->
114 concat <$> traverse (entryToPatches importName interface) xs
116 (++) (infixPatches ++ qualifiedPatches) <$> unqualifiedPatches
119interfaceToPatches :: ModuleName.Canonical -> Text -> Module.Interface -> [Env.Patch]
120interfaceToPatches moduleName prefix interface =
122 genericPatch mkPatch name value =
123 mkPatch (prefix <> name) value
126 genericPatch mkPatch name (Var.fromModule moduleName name)
128 aliasPatch (name, (tvars, tipe)) =
132 (Var.fromModule moduleName name, tvars, tipe)
134 patternPatch (name, args) =
138 (Var.fromModule moduleName name, length args)
141 concatMap snd (Map.elems (Module.iUnions interface))
147 [ map (patch Env.Value) (Map.keys (Module.iTypes interface))
148 , map (patch Env.Value) ctorNames
149 , map (patch Env.Union) (Map.keys (Module.iUnions interface))
150 , map aliasPatch (Map.toList (Module.iAliases interface))
151 , map patternPatch ctors
156-- PATCHES FOR INDIVIDUAL ENTRIES
160 :: ModuleName.Canonical
162 -> A.Located Exposing.Entry
163 -> Result [Env.Patch]
164entryToPatches moduleName interface (A.A region entry) =
167 mkPatch name (Var.fromModule moduleName name)
169 patternPatch (name, numArgs) =
170 Env.Pattern name (Var.fromModule moduleName name, numArgs)
172 notFound subRegion getNames name =
173 Module.iExports interface
175 |> Help.nearbyNames id name
176 |> Error.valueNotFound (ModuleName._module moduleName) name
177 |> Result.throw subRegion
180 Exposing.Lower name ->
181 if Map.notMember name (Module.iTypes interface) then
182 notFound region Exposing._values name
185 Result.ok [patch Env.Value name]
187 Exposing.Upper x Nothing ->
188 case Map.lookup x (Module.iAliases interface) of
192 Env.Alias x (Var.fromModule moduleName x, tvars, t)
195 if Map.member x (Module.iTypes interface) then
196 [alias, patch Env.Value x]
202 case Map.lookup x (Module.iUnions interface) of
204 Result.ok [patch Env.Union x]
207 let getNames values =
208 Exposing._aliases values
209 ++ map fst (Exposing._unions values)
211 notFound region getNames x
213 Exposing.Upper givenName (Just exposing) ->
214 case Map.lookup givenName (Module.iUnions interface) of
216 notFound region (map fst . Exposing._unions) givenName
218 Just (_tvars, realCtors) ->
222 Result.ok realCtorList
224 Exposing.Explicit xs ->
225 traverse ctorExists xs
228 map (second length) realCtors
231 Map.fromList realCtorList
233 ctorExists (A.A ctorRegion givenCtorName) =
234 case Map.lookup givenCtorName realCtorDict of
236 Result.ok (givenCtorName, numArgs)
239 notFound ctorRegion (const (map fst realCtors)) givenCtorName
242 patch Env.Union givenName
243 : map (patch Env.Value . fst) ctors
244 ++ map patternPatch ctors
248-- PATCHES FOR TYPE ALIASES
252 ( (R.Region, Text, [Text], Type.Raw), Text, [Text] )
255node :: R.Region -> Text -> [Text] -> Type.Raw -> Node
256node region name tvars alias =
257 ((region, name, tvars, alias), name, edges alias)
261 Type.RLambda t1 t2 ->
267 Type.RType (Var.Raw x) ->
271 edges t ++ concatMap edges ts
273 Type.RRecord fs ext ->
274 maybe [] edges ext ++ concatMap (edges . snd) fs
277addTypeAliases :: ModuleName.Canonical -> [Node] -> Env.Env -> Result Env.Env
278addTypeAliases moduleName typeAliasNodes initialEnv =
279 foldM (addTypeAlias moduleName) initialEnv (Graph.stronglyConnComp typeAliasNodes)
283 :: ModuleName.Canonical
285 -> Graph.SCC (R.Region, Text, [Text], Type.Raw)
287addTypeAlias moduleName env scc =
289 Graph.AcyclicSCC (_, name, tvars, alias) ->
290 addToEnv <$> Canonicalize.tipe env alias
294 (Var.fromModule moduleName name, tvars, alias')
296 env { Env._aliases = Env.insert name value (Env._aliases env) }
298 Graph.CyclicSCC [] ->
301 Graph.CyclicSCC [(region, name, tvars, alias)] ->
302 Result.throw region (Error.Alias (Error.SelfRecursive name tvars alias))
304 Graph.CyclicSCC aliases@((region, _, _, _) : _) ->
305 Result.throw region (Error.Alias (Error.MutuallyRecursive aliases))
309-- DECLARATIONS TO PATCHES
312{- When canonicalizing, it is important that:
314 _adts are fully namespaced (Var.Module ...)
315 _patterns are fully namespaced (Var.Module ...)
316 _values that are defined as top-level declarations are (Var.TopLevel ...)
317 all other _values are local (Var.Local)
320declsToPatches :: ModuleName.Canonical -> D.Valid -> ([Node], [Env.Patch])
321declsToPatches moduleName (D.Decls defs unions aliases infixes) =
327 Env.Value x (Var.topLevel moduleName x)
329 patternPatch (name, args) =
330 Env.Pattern name (Var.fromModule moduleName name, length args)
334 defToPatches (A.A _ (Src.Def _ pattern _ _)) =
335 map topLevelValue (P.boundVarList pattern)
337 unionToPatches (A.A _ (D.Type name _ ctors)) =
338 Env.Union name (Var.fromModule moduleName name)
339 : map topLevelValue (map fst ctors)
340 ++ map patternPatch ctors
342 aliasToPatches (A.A _ (D.Type name _ alias)) =
344 Type.RRecord _ Nothing ->
345 Just (topLevelValue name)
352 aliasToNode (A.A (region, _) (D.Type name tvars alias)) =
353 node region name tvars alias
356 map aliasToNode aliases
359 [ map (infixToPatch (Var.topLevel moduleName)) infixes
360 , Maybe.mapMaybe aliasToPatches aliases
361 , concatMap unionToPatches unions
362 , concatMap defToPatches defs
367infixToPatch :: (Text -> Var.Canonical) -> D.Infix -> Env.Patch
368infixToPatch toVar (D.Infix name assoc prec) =
369 Env.Infix (toVar name) assoc prec
376effectsToPatches :: ModuleName.Canonical -> Effects.Raw -> [Env.Patch]
377effectsToPatches moduleName effects =
382 Effects.Port ports ->
384 toPatch (A.A _ (Effects.PortRaw name _)) =
385 Env.Value name (Var.topLevel moduleName name)
389 Effects.Manager _ info ->
390 map (\name -> Env.Value name (Var.topLevel moduleName name)) $
391 case Effects._managerType info of
392 Effects.CmdManager _ ->
395 Effects.SubManager _ ->
398 Effects.FxManager _ _ ->
399 [ "command", "subscription" ]
403-- RESTRICT VISIBLE API OF INTERFACES
406restrictToPublicApi :: Module.Interface -> Module.Interface
407restrictToPublicApi interface =
409 (Exposing.Canonical values aliases unions) =
410 Module.iExports interface
413 { Module.iTypes = Map.fromList $
414 Maybe.mapMaybe (get (Module.iTypes interface)) (values ++ concatMap snd unions)
416 , Module.iAliases = Map.fromList $
417 Maybe.mapMaybe (get (Module.iAliases interface)) aliases
419 , Module.iUnions = Map.fromList $
420 Maybe.mapMaybe (trimUnions interface) unions
425get :: Map.Map Text a -> Text -> Maybe (Text, a)
427 case Map.lookup key dict of
435trimUnions :: Module.Interface -> (Text, [Text]) -> Maybe (Text, Module.UnionInfo Text)
436trimUnions interface (name, exposedCtors) =
437 case Map.lookup name (Module.iUnions interface) of
441 Just (tvars, ctors) ->
443 isExposed (ctor, _) =
444 ctor `elem` exposedCtors
446 Just (name, (tvars, filter isExposed 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