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 (mainType, occurs, wireTypes) 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.Expression.Canonical as Canonical
20import qualified AST.PrettyPrint as PP
21import qualified AST.Type as ST
22import qualified AST.Variable as Var
23import qualified Transform.Expression as Expr
24import qualified Type.Hint as Hint
25import qualified Type.Type as TT
26import qualified Type.State as TS
29throw :: [Doc] -> Either [Doc] a
36mainType :: TS.Env -> ErrorT [P.Doc] IO (Map.Map String ST.CanonicalType)
38 do environment' <- liftIO $ Traverse.traverse TT.toSrcType environment
39 mainCheck environment'
44 => Map.Map String ST.CanonicalType
45 -> ErrorT [P.Doc] m (Map.Map String ST.CanonicalType)
47 case Map.lookup "main" env of
52 let tipe = ST.dealias typeOfMain
54 if tipe `elem` validMainTypes
56 else throwError [ badMainMessage typeOfMain ]
59validMainTypes :: [ST.CanonicalType]
67 fromModule :: [String] -> String -> ST.CanonicalType
68 fromModule home name =
69 ST.Type (Var.fromModule home name)
72 fromModule ["VirtualDom"] "Node"
75 ST.App (fromModule ["Signal"] "Varying") [ tipe ]
79 ST.Type (Var.builtin name)
82 ST.App (fromModule ["Maybe"] "Maybe") [ tipe ]
85 [ ("element", fromModule ["Graphics","Element"] "ElementPrim")
88 [ ("click" , builtin "_Tuple0")
89 , ("color" , maybe (fromModule ["Color"] "Color"))
90 , ("height" , builtin "Int")
91 , ("hover" , builtin "_Tuple0")
92 , ("href" , builtin "String")
93 , ("id" , builtin "Int")
94 , ("opacity", builtin "Float")
95 , ("tag" , builtin "String")
96 , ("width" , builtin "Int")
104badMainMessage :: ST.CanonicalType -> P.Doc
105badMainMessage typeOfMain =
107 [ P.text "Type Error: 'main' must have one of the following types:"
109 , P.text " Element, Html, Varying Element, Varying Html"
111 , P.text "Instead 'main' has type:\n"
112 , P.nest 4 (PP.pretty typeOfMain)
119data Direction = In | Out
122wireTypes :: (Monad m) => Canonical.Expr -> ErrorT [P.Doc] m ()
124 case Expr.checkWires (checkWires In) (checkWires Out) expr of
125 Left err -> throwError err
129checkWires :: Direction -> String -> ST.CanonicalType -> Either [P.Doc] ()
130checkWires direction name tipe =
131 checkWiresHelp direction name tipe tipe
140checkWiresHelp direction name rootType tipe =
143 checkWiresHelp direction name rootType t
145 ST.App (ST.Type signal) [t]
146 | Var.isStream signal ->
147 validWireType False (Just Stream) direction name rootType t
149 | Var.isVarying signal ->
150 validWireType False (Just Varying) direction name rootType t
153 validWireType False Nothing direction name rootType tipe
156data Signal = Stream | Varying
167validWireType seenFunc seenSignal direction name rootType tipe =
168 let valid localType =
169 validWireType seenFunc seenSignal direction name rootType localType
172 throw (wireError name direction rootType tipe kind)
179 case any ($ v) [ Var.isJson, Var.isPrimitive, Var.isTuple ] of
181 False -> err "It contains an unsupported type"
186 ST.App (ST.Type v) [t]
187 | Var.isMaybe v -> valid t
188 | Var.isArray v -> valid t
189 | Var.isList v -> valid t
191 ST.App (ST.Type v) ts
192 | Var.isTuple v -> mapM_ valid ts
195 err "It contains an unsupported type"
198 err "It contains a free type variable"
202 In -> err "It contains functions"
205 then err "It contains higher-order functions"
209 err "It is a streams that contains a function"
212 err "It is a varying value that contains a function"
215 forM_ (ST.collectLambdas tipe)
216 (validWireType True seenSignal direction name rootType)
218 ST.Record _ (Just _) ->
219 err "It contains extended records with free type variables"
221 ST.Record fields Nothing ->
222 mapM_ (\(k,v) -> (,) k <$> valid v) fields
232wireError name direction rootType localType problemMessage =
233 [ P.text (dir "Input" "Output" ++ " Error:")
236 [ txt [ "The ", wire, " named '", name, "' was has an invalid type.\n" ]
237 , P.nest 2 (PP.pretty rootType) <> P.text "\n"
238 , txt [ problemMessage, ":\n" ]
239 , P.nest 2 (PP.pretty localType) <> P.text "\n"
240 , txt [ "Acceptable values for ", wire, "s include:" ]
241 , txt [ " Ints, Floats, Bools, Strings, Maybes, Lists, Arrays, Tuples, unit values," ]
242 , txt [ " Json.Values, ", dir "" "first-order functions, promises, ", "and concrete records." ]
251 txt = P.text . concat
259occurs :: (String, TT.Variable) -> StateT TS.SolverState IO ()
260occurs (name, variable) =
261 do vars <- liftIO $ infiniteVars [] variable
267 do desc <- liftIO $ UF.descriptor var
268 case TT.structure desc of
270 TS.addHint (P.text msg)
273 do liftIO $ UF.setDescriptor var (desc { TT.structure = Nothing })
274 var' <- liftIO $ UF.fresh desc
275 hint <- liftIO $ Hint.create (A.None (P.text name)) (Just msg) var var'
278 msg = "Infinite types are not allowed"
280 infiniteVars :: [TT.Variable] -> TT.Variable -> IO [TT.Variable]
281 infiniteVars seen var =
282 let go = infiniteVars (var:seen) in
286 desc <- UF.descriptor var
287 case TT.structure desc of
291 TT.App1 a b -> (++) <$> go a <*> go b
292 TT.Fun1 a b -> (++) <$> go a <*> go b
294 TT.EmptyRecord1 -> return []
295 TT.Record1 fields ext -> 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