1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize.Module
8import qualified Data.Graph as Graph
9import qualified Data.Map as Map
10import qualified Data.Set as Set
12import qualified AST.Canonical as Can
13import qualified AST.Source as Src
14import qualified AST.Valid as Valid
15import qualified AST.Module.Name as ModuleName
16import qualified Canonicalize.Effects as Effects
17import qualified Canonicalize.Environment as Env
18import qualified Canonicalize.Environment.Dups as Dups
19import qualified Canonicalize.Environment.Foreign as Foreign
20import qualified Canonicalize.Environment.Local as Local
21import qualified Canonicalize.Expression as Expr
22import qualified Canonicalize.Pattern as Pattern
23import qualified Canonicalize.Type as Type
24import qualified Elm.Interface as I
25import qualified Elm.Name as N
26import qualified Elm.Package as Pkg
27import qualified Reporting.Annotation as A
28import qualified Reporting.Error.Canonicalize as Error
29import qualified Reporting.Region as R
30import qualified Reporting.Result as Result
31import qualified Reporting.Warning as Warning
39 Result.Result () Warning.Warning Error.Error a
48 -> Map.Map N.Name ModuleName.Canonical
52canonicalize pkg importDict interfaces module_@(Valid.Module name _ _ exports imports decls unions aliases binops effects) =
53 do let home = ModuleName.Canonical pkg name
55 startEnv <- Local.addVarsAndTypes module_ =<<
56 Foreign.createInitialEnv home importDict interfaces imports
58 (cunions, caliases) <-
60 <$> (Map.fromList <$> traverse (canonicalizeUnion startEnv) unions)
61 <*> (Map.fromList <$> traverse (canonicalizeAlias startEnv) aliases)
63 let finalEnv = Local.addPatterns cunions startEnv
64 let cbinops = Map.fromList (map canonicalizeBinop binops)
68 <$> canonicalizeDecls finalEnv decls
69 <*> Effects.canonicalize finalEnv decls cunions effects
71 cexports <- canonicalizeExports decls cunions caliases cbinops ceffects exports
73 let docs = toDocs module_
74 return $ Can.Module home docs cexports cdecls cunions caliases cbinops ceffects
81toDocs :: Valid.Module -> A.Located (Maybe Can.Docs)
82toDocs (Valid.Module _ (A.A region maybeOverview) comments _ _ _ _ _ _ _) =
88 A.A region (Just (Can.Docs overview comments))
95canonicalizeAlias :: Env.Env -> Valid.Alias -> Result ( N.Name, Can.Alias )
96canonicalizeAlias env (Valid.Alias (A.A _ name) args tipe) =
97 do ctipe <- Type.canonicalize env tipe
98 return (name, Can.Alias (map A.drop args) ctipe (toRecordCtorInfo tipe))
101toRecordCtorInfo :: Src.Type -> Maybe [N.Name]
102toRecordCtorInfo (A.A _ tipe) =
104 Src.TRecord fields Nothing ->
105 Just (map (A.drop . fst) fields)
115canonicalizeUnion :: Env.Env -> Valid.Union -> Result ( N.Name, Can.Union )
116canonicalizeUnion env (Valid.Union (A.A _ name) args ctors) =
118 canonicalizeCtor (A.A _ ctor, tipes) =
119 do ctipes <- traverse (Type.canonicalize env) tipes
120 return (ctor, ctipes)
122 do cctors <- traverse canonicalizeCtor ctors
123 return ( name, Can.Union (map A.drop args) cctors )
130canonicalizeBinop :: Valid.Binop -> ( N.Name, Can.Binop )
131canonicalizeBinop (Valid.Binop (A.A _ op) associativity precedence func) =
132 ( op, Can.Binop_ associativity precedence func )
136-- CANONICALIZE DECLARATIONS
139canonicalizeDecls :: Env.Env -> [A.Located Valid.Decl] -> Result Can.Decls
140canonicalizeDecls env decls =
141 do nodes <- traverse (toNode env) decls
142 detectCycles (Graph.stronglyConnComp nodes)
145detectCycles :: [Graph.SCC Decl] -> Result Can.Decls
149 Result.ok Can.SaveTheEnvironment
153 Graph.AcyclicSCC decl ->
154 Can.Declare (toCanDecl decl)
155 <$> detectCycles otherSccs
157 Graph.CyclicSCC [] ->
158 detectCycles otherSccs
160 Graph.CyclicSCC (decl:decls) ->
161 do detectBadCycles decl decls
162 Can.DeclareRec (toCanDecl decl) (map toCanDecl decls)
163 <$> detectCycles otherSccs
166toNode :: Env.Env -> A.Located Valid.Decl -> Result (Decl, N.Name, [N.Name])
167toNode env (A.A region (Valid.Decl name@(A.A _ key) args body tipe)) =
170 do ctipe <- traverse (Type.canonicalize env) tipe
171 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern Map.empty $
172 Expr.canonicalize env body
173 return (Value region name cbody ctipe, key, Set.toList freeLocals)
176 do ctipe <- traverse (Type.canonicalize env) tipe
177 cargs@(Can.Args _ destructors) <- Pattern.canonicalizeArgs env args
178 newEnv <- Env.addLocals destructors env
179 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern destructors $
180 Expr.canonicalize newEnv body
181 return (Function key cargs cbody ctipe, key, Set.toList freeLocals)
185 = Value R.Region (A.Located N.Name) Can.Expr (Maybe Can.Type)
186 | Function N.Name Can.Args Can.Expr (Maybe Can.Type)
189toCanDecl :: Decl -> Can.Decl
192 Value _ (A.A _ name) body tipe ->
193 Can.Value name body tipe
195 Function name args body tipe ->
196 Can.Function name args body tipe
199detectBadCycles :: Decl -> [Decl] -> Result ()
200detectBadCycles decl decls =
201 case traverse detectBadCyclesHelp (decl:decls) of
210 (declRegion, A.A region name) : otherInfo ->
211 let otherNames = map (A.drop . snd) otherInfo in
212 Result.throw declRegion (Error.RecursiveDecl region name otherNames)
215detectBadCyclesHelp :: Decl -> Maybe (R.Region, A.Located N.Name)
216detectBadCyclesHelp decl =
218 Value region name _ _ ->
226-- CANONICALIZE EXPORTS
230 :: [A.Located Valid.Decl]
231 -> Map.Map N.Name union
232 -> Map.Map N.Name alias
233 -> Map.Map N.Name binop
236 -> Result Can.Exports
237canonicalizeExports decls unions aliases binops effects exposing =
240 Result.ok Can.ExportEverything
242 Src.Explicit exposeds ->
243 do let names = Map.fromList (map declToName decls)
244 infos <- traverse (checkExposed names unions aliases binops effects) exposeds
245 let toError name () () = Error.ExportDuplicate name
246 Can.Export <$> Dups.detect toError infos
249declToName :: A.Located Valid.Decl -> ( N.Name, () )
250declToName (A.A _ (Valid.Decl (A.A _ name) _ _ _)) =
255 :: Map.Map N.Name decl
256 -> Map.Map N.Name union
257 -> Map.Map N.Name alias
258 -> Map.Map N.Name binop
260 -> A.Located Src.Exposed
261 -> Result (N.Name, [Dups.Info () Can.Export])
262checkExposed decls unions aliases binops effects (A.A region exposed) =
265 if Map.member name decls then
266 Result.ok (Dups.info name region () Can.ExportValue)
268 case checkPorts effects name of
270 Result.ok (Dups.info name region () Can.ExportPort)
273 Result.throw region $ Error.ExportNotFound Error.BadVar name $
274 ports ++ Map.keys decls
277 if Map.member name binops then
278 Result.ok (Dups.info name region () Can.ExportBinop)
280 Result.throw region $ Error.ExportNotFound Error.BadOp name $
283 Src.Upper name Src.Public ->
284 if Map.member name unions then
285 Result.ok (Dups.info name region () Can.ExportUnionOpen)
286 else if Map.member name aliases then
287 Result.throw region $ Error.ExportOpenAlias name
289 Result.throw region $ Error.ExportNotFound Error.BadType name $
290 Map.keys unions ++ Map.keys aliases
292 Src.Upper name Src.Private ->
293 if Map.member name unions then
294 Result.ok (Dups.info name region () Can.ExportUnionClosed)
295 else if Map.member name aliases then
296 Result.ok (Dups.info name region () Can.ExportAlias)
298 Result.throw region $ Error.ExportNotFound Error.BadType name $
299 Map.keys unions ++ Map.keys aliases
302checkPorts :: Can.Effects -> N.Name -> Maybe [N.Name]
303checkPorts effects name =
309 if Map.member name ports then Nothing else Just (Map.keys ports)
311 Can.Manager _ _ _ _ ->
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