1{-# OPTIONS_GHC -Wall #-}
3{-| This module contains checks to be run *after* type inference has completed
4successfully. At that point we still need to do occurs checks and ensure that
5`main` has an acceptable type.
7module Type.ExtraChecks (effectTypes, occurs) where
9import Prelude hiding (maybe)
10import Control.Applicative ((<$>),(<*>))
11import Control.Monad.Error
12import Control.Monad.State
13import qualified Data.Map as Map
14import qualified Data.Traversable as Traverse
15import qualified Data.UnionFind.IO as UF
16import Text.PrettyPrint as P
18import qualified AST.Annotation as A
19import qualified AST.PrettyPrint as PP
20import qualified AST.Type as ST
21import qualified AST.Variable as Var
22import qualified Type.Hint as Hint
23import qualified Type.Type as TT
24import qualified Type.State as TS
29effectTypes :: TS.Env -> ErrorT [P.Doc] IO (Map.Map String ST.CanonicalType)
30effectTypes environment =
31 do environment' <- liftIO $ Traverse.traverse TT.toSrcType environment
32 mainCheck environment'
33 performCheck environment'
41 => Map.Map String ST.CanonicalType
42 -> ErrorT [P.Doc] m ()
44 case Map.lookup "main" env of
49 let tipe = ST.deepDealias typeOfMain
51 if tipe `elem` validMainTypes
53 else throwError [ badMainMessage typeOfMain ]
56validMainTypes :: [ST.CanonicalType]
64 fromModule :: [String] -> String -> ST.CanonicalType
65 fromModule home name =
66 ST.Type (Var.fromModule home name)
69 fromModule ["VirtualDom"] "Node"
72 ST.App (fromModule ["Signal"] "Varying") [ tipe ]
76 ST.Type (Var.builtin name)
79 ST.App (fromModule ["Maybe"] "Maybe") [ tipe ]
82 [ ("element", fromModule ["Graphics","Element"] "ElementPrim")
85 [ ("click" , builtin "_Tuple0")
86 , ("color" , maybe (fromModule ["Color"] "Color"))
87 , ("height" , builtin "Int")
88 , ("hover" , builtin "_Tuple0")
89 , ("href" , builtin "String")
90 , ("id" , builtin "Int")
91 , ("opacity", builtin "Float")
92 , ("tag" , builtin "String")
93 , ("width" , builtin "Int")
101badMainMessage :: ST.CanonicalType -> P.Doc
102badMainMessage typeOfMain =
104 [ P.text "Type Error: 'main' must have one of the following types:"
106 , P.text " Element, Html, Varying Element, Varying Html"
108 , P.text "Instead 'main' has type:\n"
109 , P.nest 4 (PP.pretty typeOfMain)
118 => Map.Map String ST.CanonicalType
119 -> ErrorT [P.Doc] m ()
121 let check (name, tipe) =
122 case Var.fromEffectName name of
127 case ST.deepDealias tipe of
128 ST.App (ST.Type task) [_, _]
132 throwError [ badPerformMessage lineNumber tipe ]
134 mapM_ check (Map.toList env)
137badPerformMessage :: String -> ST.CanonicalType -> P.Doc
138badPerformMessage lineNumber tipe =
140 [ P.text $ "Type Error: the 'perform' declaration on line " ++ lineNumber
141 , P.text "It must have type Task, but instead it has type:\n"
142 , P.nest 4 (PP.pretty tipe)
149occurs :: (String, TT.Variable) -> StateT TS.SolverState IO ()
150occurs (name, variable) =
151 do vars <- liftIO $ infiniteVars [] variable
157 do desc <- liftIO $ UF.descriptor var
158 case TT.structure desc of
160 TS.addHint (P.text msg)
163 do liftIO $ UF.setDescriptor var (desc { TT.structure = Nothing })
164 var' <- liftIO $ UF.fresh desc
165 hint <- liftIO $ Hint.create (A.None (P.text name)) (Just msg) var var'
168 msg = "Infinite types are not allowed"
170 infiniteVars :: [TT.Variable] -> TT.Variable -> IO [TT.Variable]
171 infiniteVars seen var =
172 let go = infiniteVars (var:seen) in
176 desc <- UF.descriptor var
177 case TT.structure desc of
182 (++) <$> go a <*> go b
185 (++) <$> go a <*> go b
193 TT.Record1 fields ext ->
194 concat <$> mapM go (ext : concat (Map.elems fields))
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