1{-# OPTIONS_GHC -Wall #-}
2module Canonicalize (module') where
4import qualified Data.List as List
5import qualified Data.Map as Map
6import qualified Data.Maybe as Maybe
7import qualified Data.Set as Set
8import qualified Data.Foldable as T
10import AST.Expression.General (Expr'(..))
11import Elm.Utils ((|>))
13import qualified AST.Declaration as D
14import qualified AST.Expression.Valid as Valid
15import qualified AST.Expression.Canonical as Canonical
16import qualified AST.Module as Module
17import qualified AST.Module.Name as ModuleName
18import qualified AST.Pattern as P
19import qualified AST.Type as Type
20import qualified AST.Variable as Var
21import qualified Canonicalize.Body as Body
22import qualified Canonicalize.Effects as Effects
23import qualified Canonicalize.Environment as Env
24import qualified Canonicalize.Setup as Setup
25import qualified Canonicalize.Type as Canon
26import qualified Canonicalize.Variable as Canon
27import qualified Docs.Centralize as Docs
28import qualified Reporting.Annotation as A
29import qualified Reporting.Error as Error
30import qualified Reporting.Error.Canonicalize as CError
31import qualified Reporting.Error.Helpers as ErrorHelp
32import qualified Reporting.Region as Region
33import qualified Reporting.Render.Type as RenderType
34import qualified Reporting.Result as Result
35import qualified Reporting.Warning as Warning
40 Result.Result (Result.One RenderType.Localizer) Warning.Warning Error.Error a
47 :: [ModuleName.Canonical]
50 -> Result Module.Canonical
51module' allCanonicalImports interfaces modul =
53 (Module.Valid docs exports imports decls effects) =
58 |> map (\cName -> (ModuleName._module cName, cName))
61 (Result.Result uses warnings rawResults) =
62 do env <- Setup.environment importDict interfaces modul
65 <$> resolveExports (Effects.toValues effects ++ declsToValues decls) exports
66 <*> canonicalizeDecls env decls
67 <*> Effects.canonicalize env effects
71 Result.mapError Error.Canonicalize $
72 Result.Result Result.None warnings (Result.Err errors)
74 Result.Ok (env, canonicalExports, canonicalDecls, canonicalEffects) ->
76 (D.Decls _ unions aliases infixes) =
80 A.map (fmap (Docs.centralize canonicalDecls)) docs
82 typeToPair (A.A _ (D.Type name args body)) =
83 ( name, (args, body) )
86 Body.flatten (Module.name modul) canonicalDecls canonicalEffects
88 do canonicalImports <- filterImports uses imports
89 Result.accumulate (Result.One (Env.toDealiaser env)) $
93 { Module.docs = centralizedDocs
94 , Module.exports = canonicalExports
95 , Module.imports = canonicalImports
96 , Module.program = program
97 , Module.types = Map.empty
98 , Module.fixities = infixes
99 , Module.aliases = Map.fromList (map typeToPair aliases)
100 , Module.unions = Map.fromList (map typeToPair unions)
101 , Module.effects = canonicalEffects
111 :: Set.Set ModuleName.Raw
112 -> ([Module.DefaultImport], [Module.UserImport])
113 -> Result [ModuleName.Raw]
114filterImports uses (defaults, imports) =
116 checkImport (A.A region (name, _method)) =
117 if Set.member name uses then
121 Result.warn region (Warning.UnusedImport name) Nothing
124 Maybe.catMaybes <$> traverse checkImport imports
127 Set.toList (Set.fromList (map fst defaults ++ reducedImports))
131-------- CANONICALIZATION --------
142resolveExports :: [Var.Value] -> Var.Listing (A.Located Var.Value) -> CResult [Var.Value]
143resolveExports fullList (Var.Listing partialList open) =
149 (allValues, allAliases, allAdts) =
150 maybeUnzip3 (map splitValue fullList)
152 (values, aliases, adts) =
153 maybeUnzip3 (map splitLocatedValue partialList)
158 (\xs ys zs _ -> xs ++ ys ++ zs)
159 <$> traverse (getValueExport allValues (Set.fromList allValues)) values
160 <*> (concat <$> traverse (getAliasExport allValues allAliases adtTypes) aliases)
161 <*> traverse (getAdtExport allAdts adtTypes) adts
162 <*> allUnique partialList
165getValueExport :: [String] -> Set.Set String -> A.Located String -> CResult Var.Value
166getValueExport allValues allValuesSet (A.A region name) =
167 if Set.member name allValuesSet then
168 Result.ok (Var.Value name)
170 manyNotFound region [name] allValues
173getAliasExport :: [String] -> [String] -> [String] -> A.Located String -> CResult [Var.Value]
174getAliasExport allValues allAliases adtTypes (A.A region alias) =
175 if alias `elem` allAliases then
177 Result.ok $ (:) (Var.Alias alias) $
178 if alias `elem` allValues then [Var.Value alias] else []
180 else if List.elem alias adtTypes then
182 Result.ok [Var.Union alias (Var.Listing [] False)]
186 manyNotFound region [alias] (allAliases ++ adtTypes)
190 :: [(String, Var.Listing String)]
192 -> A.Located (String, Var.Listing String)
194getAdtExport allAdts adtTypes (A.A region (name, Var.Listing ctors open)) =
195 case List.lookup name allAdts of
197 manyNotFound region [name] adtTypes
199 Just (Var.Listing allCtors _) ->
201 Result.ok (Var.Union name (Var.Listing allCtors False))
203 case filter (`notElem` allCtors) ctors of
205 Result.ok (Var.Union name (Var.Listing ctors False))
207 manyNotFound region unfoundCtors allCtors
210manyNotFound :: Region.Region -> [String] -> [String] -> CResult a
211manyNotFound region nameList possibilities =
212 Result.throwMany (map (notFound region possibilities) nameList)
215notFound :: Region.Region -> [String] -> String -> A.Located CError.Error
216notFound region possibilities name =
217 A.A region $ CError.Export name $
218 ErrorHelp.nearbyNames id name possibilities
221allUnique :: [A.Located Var.Value] -> CResult ()
222allUnique statedExports =
224 valueToString value =
226 Var.Value name -> name
227 Var.Alias name -> name
228 Var.Union name _ -> name
231 Map.fromListWith (++) (map (\(A.A region value) -> (value, [region])) statedExports)
233 isUnique value allRegions =
236 Result.throw region (CError.DuplicateExport (valueToString value))
241 T.sequenceA_ (Map.mapWithKey isUnique locations)
248declsToValues :: D.Valid -> [Var.Value]
249declsToValues (D.Decls defs unions aliases _) =
251 fromDef (A.A _ def) =
252 map Var.Value (P.boundVarList (Valid.getPattern def))
254 fromUnion (A.A _ (D.Type name _ ctors)) =
255 Var.Union name (Var.Listing (map fst ctors) False)
257 fromAlias (A.A _ (D.Type name _ tipe)) =
259 A.A _ (Type.RRecord _ Nothing) ->
260 [ Var.Alias name, Var.Value name ]
266 [ map fromUnion unions
267 , concatMap fromAlias aliases
268 , concatMap fromDef defs
276maybeUnzip3 :: [(Maybe a, Maybe b, Maybe c)] -> ([a],[b],[c])
278 let (as, bs, cs) = unzip3 tuples
280 (Maybe.catMaybes as, Maybe.catMaybes bs, Maybe.catMaybes cs)
285 -> ( Maybe String, Maybe String, Maybe (String, Var.Listing String) )
289 (Just name, Nothing, Nothing)
292 (Nothing, Just name, Nothing)
294 Var.Union name listing ->
295 (Nothing, Nothing, Just (name, listing))
299 :: A.Located Var.Value
301 ( Maybe (A.Located String)
302 , Maybe (A.Located String)
303 , Maybe (A.Located (String, Var.Listing String))
305splitLocatedValue (A.A region value) =
308 (Just (A.A region name), Nothing, Nothing)
311 (Nothing, Just (A.A region name), Nothing)
313 Var.Union name listing ->
314 (Nothing, Nothing, Just (A.A region (name, listing)))
321canonicalizeDecls :: Env.Environment -> D.Valid -> CResult D.Canonical
322canonicalizeDecls env (D.Decls defs unions aliases infixes) =
324 annTraverse canEntry entries =
325 traverse (\(A.A ann entry) -> A.A ann <$> canEntry entry) entries
327 canonicalizeDef (Valid.Def pat expr typ) =
328 Canonical.Def Canonical.dummyFacts
329 <$> canonicalizePattern env pat
330 <*> canonicalizeExpr env expr
331 <*> traverse (canonicalizeRegionType env) typ
333 canonicalizeArgs (ctor, args) =
334 (,) ctor <$> traverse (Canon.tipe env) args
336 canonicalizeUnion (D.Type name tvars ctors) =
337 D.Type name tvars <$> traverse canonicalizeArgs ctors
339 canonicalizeAlias (D.Type name tvars alias) =
340 D.Type name tvars <$> Canon.tipe env alias
343 <$> annTraverse canonicalizeDef defs
344 <*> annTraverse canonicalizeUnion unions
345 <*> annTraverse canonicalizeAlias aliases
349canonicalizeRegionType
352 -> CResult (A.Located Type.Canonical)
353canonicalizeRegionType env typ@(A.A region _) =
354 A.A region <$> Canon.tipe env typ
360 -> CResult Canonical.Expr
361canonicalizeExpr env (A.A region validExpr) =
362 let go = canonicalizeExpr env
367 Result.ok (Literal lit)
369 Access record field ->
370 Access <$> go record <*> Result.ok field
372 Update record fields ->
375 <*> traverse (\(field,expr) -> (,) field <$> go expr) fields
379 <$> traverse (\(field,expr) -> (,) field <$> go expr) fields
381 Binop (Var.Raw op) leftExpr rightExpr ->
383 <$> Canon.variable region env op
390 Env.addPattern arg env
392 Lambda <$> canonicalizePattern env' arg <*> canonicalizeExpr env' body
395 App <$> go func <*> go arg
397 If branches finally ->
399 <$> traverse go' branches
402 go' (condition, branch) =
403 (,) <$> go condition <*> go branch
406 Let <$> traverse rename' defs <*> canonicalizeExpr env' expr
409 foldr Env.addPattern env (map Valid.getPattern defs)
411 rename' (Valid.Def p body mtipe) =
412 Canonical.Def Canonical.dummyFacts
413 <$> canonicalizePattern env' p
414 <*> canonicalizeExpr env' body
415 <*> traverse (canonicalizeRegionType env') mtipe
418 Var <$> Canon.variable region env x
421 Data name <$> traverse go exprs
423 ExplicitList exprs ->
424 ExplicitList <$> traverse go exprs
427 Case <$> go expr <*> traverse branch cases
429 branch (ptrn, brnch) =
431 <$> canonicalizePattern env ptrn
432 <*> canonicalizeExpr (Env.addPattern ptrn env) brnch
435 Result.ok (Cmd moduleName)
438 Result.ok (Sub moduleName)
440 OutgoingPort name tipe ->
441 OutgoingPort name <$> Canon.tipe env tipe
443 IncomingPort name tipe ->
444 IncomingPort name <$> Canon.tipe env tipe
447 error "DANGER - Program AST nodes should not be in canonicalization."
449 SaveEnv moduleName effects ->
450 Result.ok (SaveEnv moduleName effects)
452 GLShader uid src tipe ->
453 Result.ok (GLShader uid src tipe)
456canonicalizePattern :: Env.Environment -> P.Raw -> CResult P.Canonical
457canonicalizePattern env (A.A region ptrn) =
464 Result.ok (P.Literal lit)
467 Result.ok (P.Record fields)
473 P.Alias x <$> canonicalizePattern env p
475 P.Data (Var.Raw name) patterns ->
477 <$> Canon.pvar region env name (length patterns)
478 <*> traverse (canonicalizePattern env) patterns
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