on master help sign in
cosmetic: make "infer" more clear with ErrorT
commit6c3be9b380f28bc31a45e85d70c5e31e337cbcf4 authorEvan Czaplicki <info@elm-lang.org> dateTue 10 Jun 2014, 14:41 (12 years ago) parent0f3f409
2 files changed+52−42
compiler/Type/ExtraChecks.hs+13−8 compiler/Type/Inference.hs+39−34
compiler/Type/ExtraChecks.hs+13−8
@@ -7,6 +7,7 @@ successfully. At that point we still need to do occurs checks and ensure that
77module Type.ExtraChecks (mainType, occurs, portTypes) where
88
99import Control.Applicative ((<$>),(<*>))
10+import Control.Monad.Error
1011import Control.Monad.State
1112import qualified Data.Map as Map
1213import qualified Data.Traversable as Traverse
@@ -25,17 +26,19 @@ import qualified Type.State as TS
2526throw :: [Doc] -> Either [Doc] a
2627throw err = Left [ P.vcat err ]
2728
28−mainType :: TS.Env -> IO (Either [P.Doc] (Map.Map String ST.CanonicalType))
29+mainType :: TS.Env -> ErrorT [P.Doc] IO (Map.Map String ST.CanonicalType)
2930mainType environment =
30− mainCheck <$> Traverse.traverse TT.toSrcType environment
31+ do environment' <- liftIO $ Traverse.traverse TT.toSrcType environment
32+ mainCheck environment'
3133 where
32− mainCheck :: Map.Map String ST.CanonicalType -> Either [P.Doc] (Map.Map String ST.CanonicalType)
34+ mainCheck :: (Monad m) => Map.Map String ST.CanonicalType
35+ -> ErrorT [P.Doc] m (Map.Map String ST.CanonicalType)
3336 mainCheck env =
3437 case Map.lookup "main" env of
35− Nothing -> Right env
38+ Nothing -> return env
3639 Just typeOfMain
37− | tipe `elem` acceptable -> Right env
38− | otherwise -> throw err
40+ | tipe `elem` acceptable -> return env
41+ | otherwise -> throwError err
3942 where
4043 acceptable = [ "Graphics.Element.Element"
4144 , "Signal.Signal Graphics.Element.Element" ]
@@ -48,9 +51,11 @@ mainType environment =
4851
4952data Direction = In | Out
5053
51−portTypes :: Canonical.Expr -> Either [P.Doc] ()
54+portTypes :: (Monad m) => Canonical.Expr -> ErrorT [P.Doc] m ()
5255portTypes expr =
53− const () <$> Expr.checkPorts (check In) (check Out) expr
56+ case Expr.checkPorts (check In) (check Out) expr of
57+ Left err -> throwError err
58+ Right _ -> return ()
5459 where
5560 check = isValid True False False
5661 isValid isTopLevel seenFunc seenSignal direction name tipe =
compiler/Type/Inference.hs+39−34
@@ -8,8 +8,8 @@ import qualified Type.Environment as Env
88import qualified Type.Constrain.Expression as TcExpr
99import qualified Type.Solve as Solve
1010
11+import qualified AST.Annotation as A
1112import AST.Module as Module
12−import AST.Annotation (noneNoDocs)
1313import AST.Type (CanonicalType)
1414import qualified AST.Variable as Var
1515import Text.PrettyPrint
@@ -17,45 +17,50 @@ import qualified Type.State as TS
1717import qualified Type.ExtraChecks as Check
1818import Control.Arrow (first, second)
1919import Control.Monad.State (execStateT, forM)
20−import Control.Monad.Error (ErrorT, runErrorT, liftIO)
20+import Control.Monad.Error (ErrorT, runErrorT, liftIO, throwError)
2121
2222import System.IO.Unsafe -- Possible to switch over to the ST monad instead of
2323 -- the IO monad. I don't think that'd be worthwhile.
2424
2525
2626infer :: Interfaces -> CanonicalModule -> Either [Doc] (Map.Map String CanonicalType)
27−infer interfaces modul = unsafePerformIO $ do
28− let moduleBody = body modul
29−
30− env <- Env.initialEnvironment (canonicalizeAdts interfaces modul)
31− ctors <- forM (Map.keys (Env.constructor env)) $ \name ->
32− do (_, vars, args, result) <- Env.freshDataScheme env name
33− return (name, (vars, foldr (T.==>) result args))
34−
35− attemptConstraint <- runErrorT $ do
36− importedVars <- mapM (canonicalizeValues env) (Map.toList interfaces)
37−
38− let allTypes = concat (ctors : importedVars)
39− vars = concatMap (fst . snd) allTypes
40− header = Map.map snd (Map.fromList allTypes)
41− environ = noneNoDocs . T.CLet [ T.Scheme vars [] (noneNoDocs T.CTrue) header ]
42−
43− fvar <- liftIO $ T.variable T.Flexible
44− c <- TcExpr.constrain env (program moduleBody) (T.varN fvar)
45− return (header, environ c)
46−
47− case attemptConstraint of
48− Left err -> return $ Left err
49− Right (header, constraint) -> do
50− state <- execStateT (Solve.solve constraint) TS.initialState
51− case TS.sErrors state of
52− errors@(_:_) -> return (Left errors)
53− [] -> case Check.portTypes (program moduleBody) of
54− Left err -> return (Left err)
55− Right () -> Check.mainType types
56− where
57− header' = Map.delete "::" header
58− types = Map.difference (TS.sSavedEnv state) header'
27+infer interfaces modul = unsafePerformIO $ runErrorT $ do
28+ (header, constraint) <- genConstraints interfaces modul
29+
30+ state <- liftIO $ execStateT (Solve.solve constraint) TS.initialState
31+
32+ () <- case TS.sErrors state of
33+ errors@(_:_) -> throwError errors
34+ [] -> return ()
35+
36+ () <- Check.portTypes (program (body modul))
37+
38+ let header' = Map.delete "::" header
39+ types = Map.difference (TS.sSavedEnv state) header'
40+
41+ Check.mainType types
42+
43+
44+genConstraints :: Interfaces -> CanonicalModule
45+ -> ErrorT [Doc] IO (Env.TypeDict, T.TypeConstraint)
46+genConstraints interfaces modul = do
47+ env <- liftIO $ Env.initialEnvironment (canonicalizeAdts interfaces modul)
48+
49+ ctors <- forM (Map.keys (Env.constructor env)) $ \name -> do
50+ (_, vars, args, result) <- liftIO $ Env.freshDataScheme env name
51+ return (name, (vars, foldr (T.==>) result args))
52+
53+ importedVars <- mapM (canonicalizeValues env) (Map.toList interfaces)
54+
55+ let allTypes = concat (ctors : importedVars)
56+ vars = concatMap (fst . snd) allTypes
57+ header = Map.map snd (Map.fromList allTypes)
58+ environ = A.noneNoDocs . T.CLet [ T.Scheme vars [] (A.noneNoDocs T.CTrue) header ]
59+
60+ fvar <- liftIO $ T.variable T.Flexible
61+ c <- TcExpr.constrain env (program (body modul)) (T.varN fvar)
62+ return (header, environ c)
63+
5964
6065canonicalizeValues :: Env.Environment -> (String, Interface)
6166 -> ErrorT [Doc] IO [(String, ([T.Variable], T.Type))]