1module Canonicalize (module') where
3import qualified Data.List as List
4import qualified Data.Map as Map
5import qualified Data.Maybe as Maybe
6import qualified Data.Set as Set
7import qualified Data.Traversable as T
8import qualified Data.Foldable as T
10import AST.Expression.General (Expr'(..), dummyLet)
11import AST.Module (Body(..))
12import Elm.Utils ((|>))
14import qualified AST.Declaration as D
15import qualified AST.Expression.General as E
16import qualified AST.Expression.Valid as Valid
17import qualified AST.Expression.Canonical as Canonical
18import qualified AST.Module as Module
19import qualified AST.Module.Name as ModuleName
20import qualified AST.Pattern as P
21import qualified AST.Type as Type
22import qualified AST.Variable as Var
23import qualified Docs.AST as Docs
24import qualified Docs.Centralize as Docs
25import qualified Reporting.Annotation as A
26import qualified Reporting.Error as Error
27import qualified Reporting.Error.Canonicalize as CError
28import qualified Reporting.Error.Helpers as ErrorHelp
29import qualified Reporting.Region as Region
30import qualified Reporting.Result as R
31import qualified Reporting.Warning as Warning
32import qualified Canonicalize.Declaration as Decls
33import qualified Canonicalize.Environment as Env
34import qualified Canonicalize.Port as Port
35import qualified Canonicalize.Result as Result
36import qualified Canonicalize.Setup as Setup
37import qualified Canonicalize.Sort as Sort
38import qualified Canonicalize.Type as Canonicalize
39import qualified Canonicalize.Variable as Canonicalize
45 :: [ModuleName.Canonical]
48 -> R.Result Warning.Warning Error.Error Module.CanonicalModule
49module' canonicalImports interfaces modul =
53 |> map (\cName -> (ModuleName._module cName, cName))
56 (Result.Result uses rawResults) =
57 moduleHelp importDict interfaces modul
60 Result.Ok (env, almostCanonicalModule) ->
61 R.addDealiaser (Env.toDealiaser env) $
62 filterImports uses almostCanonicalModule
65 R.throwMany (map (A.map Error.Canonicalize) msgs)
68type AlmostCanonicalModule =
71 ([Module.DefaultImport], [Module.UserImport])
73 (Module.Body Canonical.Expr)
77 :: Map.Map ModuleName.Raw ModuleName.Canonical
80 -> Result.ResultErr (Env.Environment, AlmostCanonicalModule)
81moduleHelp importDict interfaces modul@(Module.Module _ _ comment exports _ decls) =
83 <$> canonicalDeclsResult
84 <*> resolveExports locals exports
86 canonicalModule (env, canonicalDecls) canonicalExports =
89 { Module.docs = A.map (fmap (Docs.centralize canonicalDecls)) comment
90 , Module.exports = canonicalExports
91 , Module.body = body canonicalDecls
96 concatMap declToValue decls
98 canonicalDeclsResult =
99 Setup.environment importDict interfaces modul
100 `Result.andThen` \env -> (,) env <$> T.traverse (declaration env) decls
102 body :: [D.CanonicalDecl] -> Module.Body Canonical.Expr
104 let nakedDecls = map A.drop decls
108 let expr = Decls.toExpr (Module.name modul) decls
110 Sort.definitions (dummyLet expr)
116 Map.fromList [ (name,(vars,ctors)) | D.Datatype name vars ctors <- nakedDecls ]
119 [ (assoc,level,op) | D.Fixity assoc level op <- nakedDecls ]
122 Map.fromList [ (name,(tvs,alias)) | D.TypeAlias name tvs alias <- nakedDecls ]
125 [ E.portName impl | D.Port (D.CanonicalPort impl) <- nakedDecls ]
132 :: Set.Set ModuleName.Raw
133 -> AlmostCanonicalModule
134 -> R.Result Warning.Warning e Module.CanonicalModule
135filterImports uses modul@(Module.Module _ _ _ _ (defaults, imports) _) =
137 Maybe.catMaybes <$> T.traverse checkImport imports
141 Set.toList (Set.fromList (map fst defaults ++ reducedImports))
144 checkImport (A.A region (name, _method)) =
145 if Set.member name uses then
148 do R.warn region (Warning.UnusedImport name)
156 -> Var.Listing (A.Located Var.Value)
157 -> Result.ResultErr [Var.Value]
158resolveExports fullList (Var.Listing partialList open) =
163 (allValues, allAliases, allAdts) =
164 maybeUnzip3 (map splitValue fullList)
166 (values, aliases, adts) =
167 maybeUnzip3 (map splitLocatedValue partialList)
172 (\xs ys zs _ -> xs ++ ys ++ zs)
173 <$> T.traverse (getValueExport allValues (Set.fromList allValues)) values
174 <*> (concat <$> T.traverse (getAliasExport allValues allAliases adtTypes) aliases)
175 <*> T.traverse (getAdtExport allAdts adtTypes) adts
176 <*> allUnique partialList
183 -> Result.ResultErr Var.Value
184getValueExport allValues allValuesSet (A.A region name) =
185 if Set.member name allValuesSet then
186 Result.ok (Var.Value name)
188 manyNotFound region [name] allValues
196 -> Result.ResultErr [Var.Value]
197getAliasExport allValues allAliases adtTypes (A.A region alias) =
198 if alias `elem` allAliases then
200 Result.ok $ (:) (Var.Alias alias) $
201 if alias `elem` allValues then [Var.Value alias] else []
203 else if List.elem alias adtTypes then
205 Result.ok [Var.Union alias (Var.Listing [] False)]
209 manyNotFound region [alias] (allAliases ++ adtTypes)
213 :: [(String, Var.Listing String)]
215 -> A.Located (String, Var.Listing String)
216 -> Result.ResultErr Var.Value
217getAdtExport allAdts adtTypes (A.A region (name, Var.Listing ctors open)) =
218 case List.lookup name allAdts of
220 manyNotFound region [name] adtTypes
222 Just (Var.Listing allCtors _) ->
224 Result.ok (Var.Union name (Var.Listing allCtors False))
226 case filter (`notElem` allCtors) ctors of
228 Result.ok (Var.Union name (Var.Listing ctors False))
230 manyNotFound region unfoundCtors allCtors
233manyNotFound :: Region.Region -> [String] -> [String] -> Result.ResultErr a
234manyNotFound region nameList possibilities =
235 Result.errors (map (notFound region possibilities) nameList)
238notFound :: Region.Region -> [String] -> String -> A.Located CError.Error
239notFound region possibilities name =
240 A.A region $ CError.Export name $
241 ErrorHelp.nearbyNames id name possibilities
244allUnique :: [A.Located Var.Value] -> Result.ResultErr ()
245allUnique statedExports =
247 valueToString value =
249 Var.Value name -> name
250 Var.Alias name -> name
251 Var.Union name _ -> name
254 Map.fromListWith (++) (map (\(A.A region value) -> (value, [region])) statedExports)
256 isUnique value allRegions =
259 Result.err (A.A region (CError.DuplicateExport (valueToString value)))
264 T.traverse_ id (Map.mapWithKey isUnique locations)
269maybeUnzip3 :: [(Maybe a, Maybe b, Maybe c)] -> ([a],[b],[c])
271 let (as, bs, cs) = unzip3 tuples
273 (Maybe.catMaybes as, Maybe.catMaybes bs, Maybe.catMaybes cs)
278 -> ( Maybe String, Maybe String, Maybe (String, Var.Listing String) )
282 (Just name, Nothing, Nothing)
285 (Nothing, Just name, Nothing)
287 Var.Union name listing ->
288 (Nothing, Nothing, Just (name, listing))
292 :: A.Located Var.Value
294 ( Maybe (A.Located String)
295 , Maybe (A.Located String)
296 , Maybe (A.Located (String, Var.Listing String))
298splitLocatedValue (A.A region value) =
301 (Just (A.A region name), Nothing, Nothing)
304 (Nothing, Just (A.A region name), Nothing)
306 Var.Union name listing ->
307 (Nothing, Nothing, Just (A.A region (name, listing)))
312declToValue :: D.ValidDecl -> [Var.Value]
313declToValue (A.A _ decl) =
315 D.Definition (Valid.Definition pattern _ _) ->
316 map Var.Value (P.boundVarList pattern)
318 D.Datatype name _tvs ctors ->
319 [ Var.Union name (Var.Listing (map fst ctors) False) ]
321 D.TypeAlias name _ tipe ->
323 A.A _ (Type.RRecord _ Nothing) ->
324 [ Var.Alias name, Var.Value name ]
335 -> Result.ResultErr D.CanonicalDecl
336declaration env (A.A ann@(region,_) decl) =
339 D.Definition (Valid.Definition pat expr typ) ->
341 Canonical.Definition Canonical.dummyFacts
343 <*> expression env expr
344 <*> T.traverse (regionType env) typ
347 D.Datatype name tvars ctors ->
348 D.Datatype name tvars <$> T.traverse canonicalize' ctors
350 canonicalize' (ctor,args) =
351 (,) ctor <$> T.traverse (Canonicalize.tipe env) args
353 D.TypeAlias name tvars expanded ->
354 D.TypeAlias name tvars
355 <$> Canonicalize.tipe env expanded
358 Result.addModule ["Native","Port"] $
359 Result.addModule ["Native","Json"] $
362 Canonicalize.tipe env tipe
363 `Result.andThen` \canonicalType ->
364 D.Port <$> Port.check region name Nothing canonicalType
366 D.Out name expr tipe ->
369 <$> expression env expr
370 <*> Canonicalize.tipe env tipe
373 `Result.andThen` \(expr', tipe') ->
374 D.Port <$> Port.check region name (Just expr') tipe'
376 D.Fixity assoc prec op ->
377 Result.ok (D.Fixity assoc prec op)
383 -> Result.ResultErr (A.Located Type.Canonical)
384regionType env typ@(A.A region _) =
385 A.A region <$> Canonicalize.tipe env typ
391 -> Result.ResultErr Canonical.Expr
392expression env (A.A region validExpr) =
393 let go = expression env
398 Result.ok (Literal lit)
400 Range lowExpr highExpr ->
401 Range <$> go lowExpr <*> go highExpr
403 Access record field ->
404 Access <$> go record <*> Result.ok field
406 Update record fields ->
409 <*> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
413 <$> T.traverse (\(field,expr) -> (,) field <$> go expr) fields
415 Binop (Var.Raw op) leftExpr rightExpr ->
417 <$> Canonicalize.variable region env op
422 let env' = Env.addPattern arg env
424 Lambda <$> pattern env' arg <*> expression env' body
427 App <$> go func <*> go arg
429 If branches finally ->
431 <$> T.traverse go' branches
434 go' (condition, branch) =
435 (,) <$> go condition <*> go branch
438 Let <$> T.traverse rename' defs <*> expression env' body
441 foldr Env.addPattern env $ map (\(Valid.Definition p _ _) -> p) defs
443 rename' (Valid.Definition p body mtipe) =
444 Canonical.Definition Canonical.dummyFacts
446 <*> expression env' body
447 <*> T.traverse (regionType env') mtipe
450 Var <$> Canonicalize.variable region env x
453 Data name <$> T.traverse go exprs
455 ExplicitList exprs ->
456 ExplicitList <$> T.traverse go exprs
459 Case <$> go expr <*> T.traverse branch cases
461 branch (ptrn, brnch) =
462 (,) <$> pattern env ptrn
463 <*> expression (Env.addPattern ptrn env) brnch
470 <$> Canonicalize.tipe env t
472 Type.Signal root arg ->
474 <$> Canonicalize.tipe env root
475 <*> Canonicalize.tipe env arg
480 E.In name <$> portType tipe
482 E.Out name expr tipe ->
483 E.Out name <$> go expr <*> portType tipe
485 E.Task name expr tipe ->
486 E.Task name <$> go expr <*> portType tipe
488 GLShader uid src tipe ->
489 Result.ok (GLShader uid src tipe)
495 -> Result.ResultErr P.CanonicalPattern
496pattern env (A.A region ptrn) =
503 Result.ok (P.Literal lit)
506 Result.ok (P.Record fields)
512 P.Alias x <$> pattern env p
514 P.Data (Var.Raw name) patterns ->
516 <$> Canonicalize.pvar region env name (length patterns)
517 <*> T.traverse (pattern 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