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 annotation <- traverse (Type.toAnnotation env) tipe
171 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern Map.empty $
172 Expr.canonicalize env body
174 ( Value region name cbody annotation
176 , Set.toList freeLocals
180 do annotation <- traverse (Type.toAnnotation env) tipe
181 cargs@(Can.Args _ destructors) <- Pattern.canonicalizeArgs env args
182 newEnv <- Env.addLocals destructors env
183 (cbody, freeLocals) <- Expr.removeLocals Warning.Pattern destructors $
184 Expr.canonicalize newEnv body
186 ( Function key cargs cbody annotation
188 , Set.toList freeLocals
193 = Value R.Region (A.Located N.Name) Can.Expr (Maybe Can.Annotation)
194 | Function N.Name Can.Args Can.Expr (Maybe Can.Annotation)
197toCanDecl :: Decl -> Can.Decl
200 Value _ (A.A _ name) body tipe ->
201 Can.Value name body tipe
203 Function name args body tipe ->
204 Can.Function name args body tipe
207detectBadCycles :: Decl -> [Decl] -> Result ()
208detectBadCycles decl decls =
209 case traverse detectBadCyclesHelp (decl:decls) of
218 (declRegion, A.A region name) : otherInfo ->
219 let otherNames = map (A.drop . snd) otherInfo in
220 Result.throw declRegion (Error.RecursiveDecl region name otherNames)
223detectBadCyclesHelp :: Decl -> Maybe (R.Region, A.Located N.Name)
224detectBadCyclesHelp decl =
226 Value region name _ _ ->
234-- CANONICALIZE EXPORTS
238 :: [A.Located Valid.Decl]
239 -> Map.Map N.Name union
240 -> Map.Map N.Name alias
241 -> Map.Map N.Name binop
244 -> Result Can.Exports
245canonicalizeExports decls unions aliases binops effects exposing =
248 Result.ok Can.ExportEverything
250 Src.Explicit exposeds ->
251 do let names = Map.fromList (map declToName decls)
252 infos <- traverse (checkExposed names unions aliases binops effects) exposeds
253 let toError name () () = Error.ExportDuplicate name
254 Can.Export <$> Dups.detect toError infos
257declToName :: A.Located Valid.Decl -> ( N.Name, () )
258declToName (A.A _ (Valid.Decl (A.A _ name) _ _ _)) =
263 :: Map.Map N.Name decl
264 -> Map.Map N.Name union
265 -> Map.Map N.Name alias
266 -> Map.Map N.Name binop
268 -> A.Located Src.Exposed
269 -> Result (N.Name, [Dups.Info () Can.Export])
270checkExposed decls unions aliases binops effects (A.A region exposed) =
273 if Map.member name decls then
274 Result.ok (Dups.info name region () Can.ExportValue)
276 case checkPorts effects name of
278 Result.ok (Dups.info name region () Can.ExportPort)
281 Result.throw region $ Error.ExportNotFound Error.BadVar name $
282 ports ++ Map.keys decls
285 if Map.member name binops then
286 Result.ok (Dups.info name region () Can.ExportBinop)
288 Result.throw region $ Error.ExportNotFound Error.BadOp name $
291 Src.Upper name Src.Public ->
292 if Map.member name unions then
293 Result.ok (Dups.info name region () Can.ExportUnionOpen)
294 else if Map.member name aliases then
295 Result.throw region $ Error.ExportOpenAlias name
297 Result.throw region $ Error.ExportNotFound Error.BadType name $
298 Map.keys unions ++ Map.keys aliases
300 Src.Upper name Src.Private ->
301 if Map.member name unions then
302 Result.ok (Dups.info name region () Can.ExportUnionClosed)
303 else if Map.member name aliases then
304 Result.ok (Dups.info name region () Can.ExportAlias)
306 Result.throw region $ Error.ExportNotFound Error.BadType name $
307 Map.keys unions ++ Map.keys aliases
310checkPorts :: Can.Effects -> N.Name -> Maybe [N.Name]
311checkPorts effects name =
317 if Map.member name ports then Nothing else Just (Map.keys ports)
319 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