@@ -1,21 +1,20 @@
11{-# OPTIONS_GHC -Wall #-}
22module Nitpick.TopLevelTypes (topLevelTypes) where
33
4−import Control.Monad (foldM, when)
4+import qualified Data.Foldable as F
55import Data.Map ((!))
66import qualified Data.Map as Map
7−import qualified Data.Maybe as Maybe
87
9−import qualified AST.Expression.Valid as Valid
10−import qualified AST.Declaration as Decl
8+import qualified AST.Expression.Canonical as Can
9+import qualified AST.Expression.General as Expr
1110import qualified AST.Module.Name as ModuleName
1211import qualified AST.Pattern as P
1312import qualified AST.Type as Type
1413import qualified AST.Variable as Var
14+import qualified Canonicalize.Effects as Effects
1515import qualified Elm.Package as Pkg
1616import qualified Reporting.Annotation as A
1717import qualified Reporting.Error.Type as Error
18−import qualified Reporting.Region as R
1918import qualified Reporting.Result as Result
2019import qualified Reporting.Warning as Warning
2120
@@ -25,52 +24,85 @@ type Result =
2524 Result.Result () Warning.Warning Error.Error
2625
2726
27+type TypeDict =
28+ Map.Map String Type.Canonical
29+
30+
31+
2832-- CHECK TOP LEVEL TYPES
2933
3034
31−topLevelTypes :: Map.Map String Type.Canonical -> Decl.Valid -> Result ()
32−topLevelTypes typeEnv (Decl.Decls defs _ _ _) =
33− do maybeMainRegion <- foldM (warnMissingAnnotation typeEnv) Nothing defs
34− maybe (return ()) (checkMainType typeEnv) maybeMainRegion
35+topLevelTypes :: TypeDict -> Can.SortedDefs -> Result [Can.Def]
36+topLevelTypes typeEnv sortedDefs =
37+ let
38+ check =
39+ checkAnnotation typeEnv
40+ in
41+ case sortedDefs of
42+ Can.NoMain defs ->
43+ pure defs
44+ <* F.traverse_ check defs
3545
46+ Can.YesMain before main after ->
47+ do check main
48+ <* F.traverse_ check before
49+ <* F.traverse_ check after
3650
51+ mainDef <- checkMain typeEnv main
52+
53+ return (before ++ mainDef : after)
3754
38−-- MISSING ANNOTATIONS
3955
4056
41−warnMissingAnnotation
42− :: Map.Map String Type.Canonical
43− -> Maybe R.Region
44− -> A.Commented Valid.Def
45− -> Result (Maybe R.Region)
46−warnMissingAnnotation typeEnv maybeMainRegion (A.A (region,_) def) =
47− case def of
48− Valid.Def (A.A _ (P.Var name)) _ maybeType ->
49− do when (Maybe.isNothing maybeType) $
50− Result.warn region (Warning.MissingTypeAnnotation name (typeEnv ! name)) ()
57+-- MISSING ANNOTATIONS
58+
5159
52− return (if name == "main" then Just region else maybeMainRegion)
60+checkAnnotation :: TypeDict -> Can.Def -> Result ()
61+checkAnnotation typeEnv (Can.Def _ (A.A region pattern) _ maybeType) =
62+ case (pattern, maybeType) of
63+ (P.Var name, Nothing) ->
64+ let
65+ warning =
66+ Warning.MissingTypeAnnotation name (typeEnv ! name)
67+ in
68+ Result.warn region warning ()
5369
5470 _ ->
55− return maybeMainRegion
71+ return ()
5672
5773
5874
5975-- CHECK MAIN TYPE
6076
6177
62−checkMainType :: Map.Map String Type.Canonical -> R.Region -> Result ()
63−checkMainType typeEnv region =
78+checkMain :: TypeDict -> Can.Def -> Result Can.Def
79+checkMain typeEnv (Can.Def facts pattern@(A.A region _) body maybeType) =
6480 let
65− tipe =
81+ mainType =
6682 typeEnv ! "main"
67− in
68− case Type.deepDealias tipe of
69− Type.App name [_] | name `elem` [program, vdomNode] ->
70− return ()
7183
72− _ ->
73− Result.throw region (Error.BadMain tipe)
84+ makeError tipe maybeMsg =
85+ A.A region (Error.BadFlags tipe maybeMsg)
86+
87+ getMainKind =
88+ case Type.deepDealias mainType of
89+ Type.App name [arg]
90+ | name == vdomNode ->
91+ return Expr.VDom
92+
93+ | name == program && arg == never ->
94+ return Expr.NoFlags
95+
96+ | name == program ->
97+ return (Expr.Flags arg)
98+ <* Effects.checkForeignType makeError arg
99+
100+ _ ->
101+ Result.throw region (Error.BadMain mainType)
102+ in
103+ do kind <- getMainKind
104+ let newBody = A.A undefined (Expr.Program kind body)
105+ return (Can.Def facts pattern newBody maybeType)
74106
75107
76108program :: Type.Canonical
@@ -78,6 +110,11 @@ program =
78110 Type.Type (Var.inCore ["Platform"] "Program")
79111
80112
113+never :: Type.Canonical
114+never =
115+ Type.Type (Var.inCore ["Basics"] "Never")
116+
117+
81118vdomNode :: Type.Canonical
82119vdomNode =
83120 let