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.Expression.Canonical as Can
13import qualified AST.Expression.Source as Src
14import qualified AST.Expression.Valid as Valid
15import qualified AST.Module.Name as ModuleName
16import qualified AST.Type as Type
17import qualified Canonicalize.Effects as Effects
18import qualified Canonicalize.Environment as Env
19import qualified Canonicalize.Environment.Dups as Dups
20import qualified Canonicalize.Expression as Expr
21import qualified Canonicalize.Pattern as Pattern
22import qualified Canonicalize.Type as Type
23import qualified Elm.Interface as I
24import qualified Elm.Name as N
25import qualified Elm.Package as Pkg
26import qualified Reporting.Annotation as A
27import qualified Reporting.Error.Canonicalize as Error
28import qualified Reporting.Region as R
29import qualified Reporting.Result as Result
30import qualified Reporting.Warning as Warning
38 Result.Result () Warning.Warning Error.Error a
47 -> Map.Map N.Name ModuleName.Canonical
51canonicalize pkg importDict interfaces module_ =
52 do env <- Env.create pkg importDict interfaces module_
53 let (Valid.Module name _ _ exports _ decls unions aliases binops effects) = module_
54 (cdecls, cunions, caliases) <-
56 <$> canonicalizeDecls env decls
57 <*> (Map.fromList <$> traverse (canonicalizeUnion env) unions)
58 <*> (Map.fromList <$> traverse (canonicalizeAlias env) aliases)
60 let cbinops = Map.fromList (map canonicalizeBinop binops)
61 ceffects <- Effects.canonicalize env cunions effects
62 cexports <- canonicalizeExports decls cunions caliases cbinops ceffects exports
64 let home = ModuleName.Canonical pkg name
65 let docs = toDocs module_
66 return $ Can.Module home docs cexports cdecls cunions caliases cbinops ceffects
73toDocs :: Valid.Module -> A.Located (Maybe Can.Docs)
74toDocs (Valid.Module _ (A.A region maybeOverview) comments _ _ _ _ _ _ _) =
80 A.A region (Just (Can.Docs overview comments))
87canonicalizeAlias :: Env.Env -> Valid.Alias -> Result ( N.Name, Can.Alias )
88canonicalizeAlias env (Valid.Alias (A.A _ name) args tipe) =
89 do ctipe <- Type.canonicalize env tipe
90 return (name, Can.Alias (map A.drop args) ctipe (toRecordCtorInfo tipe))
93toRecordCtorInfo :: Type.Raw -> Maybe [N.Name]
94toRecordCtorInfo (A.A _ tipe) =
96 Type.RRecord fields Nothing ->
97 Just (map (A.drop . fst) fields)
107canonicalizeUnion :: Env.Env -> Valid.Union -> Result ( N.Name, Can.Union )
108canonicalizeUnion env (Valid.Union (A.A _ name) args ctors) =
110 canonicalizeCtor (A.A _ ctor, tipes) =
111 do ctipes <- traverse (Type.canonicalize env) tipes
112 return (ctor, ctipes)
114 do cctors <- traverse canonicalizeCtor ctors
115 return ( name, Can.Union (map A.drop args) cctors )
122canonicalizeBinop :: Valid.Binop -> ( N.Name, Can.Binop )
123canonicalizeBinop (Valid.Binop (A.A _ op) associativity precedence func) =
124 ( op, Can.Binop_ associativity precedence func )
128-- CANONICALIZE DECLARATIONS
131canonicalizeDecls :: Env.Env -> [A.Located Valid.Decl] -> Result Can.Decls
132canonicalizeDecls env decls =
133 do nodes <- traverse (toNode env) decls
134 detectCycles (Graph.stronglyConnComp nodes)
137detectCycles :: [Graph.SCC Decl] -> Result Can.Decls
141 Result.ok Can.SaveTheEnvironment
145 Graph.AcyclicSCC decl ->
146 Can.Declare (toCanDecl decl)
147 <$> detectCycles otherSccs
149 Graph.CyclicSCC [] ->
150 detectCycles otherSccs
152 Graph.CyclicSCC (decl:decls) ->
153 do detectBadCycles decl decls
154 Can.DeclareRec (toCanDecl decl) (map toCanDecl decls)
155 <$> detectCycles otherSccs
158toNode :: Env.Env -> A.Located Valid.Decl -> Result (Decl, N.Name, [N.Name])
159toNode env (A.A region (Valid.Decl name@(A.A _ key) args body tipe)) =
162 do ctipe <- traverse (Type.canonicalize env) tipe
163 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern Map.empty $
164 Expr.canonicalize env body
165 return (Value region name cbody ctipe, key, Set.toList freeLocals)
168 do ctipe <- traverse (Type.canonicalize env) tipe
169 cargs@(Can.Args _ destructors) <- Pattern.canonicalizeArgs env args
170 newEnv <- Env.addLocals destructors env
171 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern destructors $
172 Expr.canonicalize newEnv body
173 return (Function key cargs cbody ctipe, key, Set.toList freeLocals)
177 = Value R.Region (A.Located N.Name) Can.Expr (Maybe Type.Canonical)
178 | Function N.Name Can.Args Can.Expr (Maybe Type.Canonical)
181toCanDecl :: Decl -> Can.Decl
184 Value _ (A.A _ name) body tipe ->
185 Can.Value name body tipe
187 Function name args body tipe ->
188 Can.Function name args body tipe
191detectBadCycles :: Decl -> [Decl] -> Result ()
192detectBadCycles decl decls =
193 case traverse detectBadCyclesHelp (decl:decls) of
202 (declRegion, A.A region name) : otherInfo ->
203 let otherNames = map (A.drop . snd) otherInfo in
204 Result.throw declRegion (Error.RecursiveDecl region name otherNames)
207detectBadCyclesHelp :: Decl -> Maybe (R.Region, A.Located N.Name)
208detectBadCyclesHelp decl =
210 Value region name _ _ ->
218-- CANONICALIZE EXPORTS
222 :: [A.Located Valid.Decl]
223 -> Map.Map N.Name union
224 -> Map.Map N.Name alias
225 -> Map.Map N.Name binop
228 -> Result Can.Exports
229canonicalizeExports decls unions aliases binops effects exposing =
232 Result.ok Can.ExportEverything
234 Src.Explicit exposeds ->
235 do let names = Map.fromList (map declToName decls)
236 infos <- traverse (checkExposed names unions aliases binops effects) exposeds
237 let toError name () () = Error.ExportDuplicate name
238 Can.Export <$> Dups.detect toError infos
241declToName :: A.Located Valid.Decl -> (N.Name, Can.Export)
242declToName (A.A _ (Valid.Decl (A.A _ name) _ _ _)) =
243 (name, Can.ExportValue)
247 :: Map.Map N.Name decl
248 -> Map.Map N.Name union
249 -> Map.Map N.Name alias
250 -> Map.Map N.Name binop
252 -> A.Located Src.Exposed
253 -> Result (N.Name, [Dups.Info () Can.Export])
254checkExposed decls unions aliases binops effects (A.A region exposed) =
257 if Map.member name decls then
258 Result.ok (Dups.info name region () Can.ExportValue)
260 case checkPorts effects name of
262 Result.ok (Dups.info name region () Can.ExportPort)
265 Result.throw region $ Error.ExportNotFound Error.BadVar name $
266 ports ++ Map.keys decls
269 if Map.member name binops then
270 Result.ok (Dups.info name region () Can.ExportBinop)
272 Result.throw region $ Error.ExportNotFound Error.BadOp name $
275 Src.Upper name Src.Public ->
276 if Map.member name unions then
277 Result.ok (Dups.info name region () Can.ExportUnionOpen)
278 else if Map.member name aliases then
279 Result.throw region $ Error.ExportOpenAlias name
281 Result.throw region $ Error.ExportNotFound Error.BadType name $
282 Map.keys unions ++ Map.keys aliases
284 Src.Upper name Src.Private ->
285 if Map.member name unions then
286 Result.ok (Dups.info name region () Can.ExportUnionClosed)
287 else if Map.member name aliases then
288 Result.ok (Dups.info name region () Can.ExportAlias)
290 Result.throw region $ Error.ExportNotFound Error.BadType name $
291 Map.keys unions ++ Map.keys aliases
294checkPorts :: Can.Effects -> N.Name -> Maybe [N.Name]
295checkPorts effects name =
301 if Map.member name ports then Nothing else Just (Map.keys ports)
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