@@ -15,11 +15,12 @@
15{-# LANGUAGE DeriveDataTypeable, FlexibleContexts #-}
15{-# LANGUAGE DeriveDataTypeable, FlexibleContexts #-}
17module Language.PureScript.TypeChecker.Types (
17module Language.PureScript.TypeChecker.Types (
21import Data.List
21import Data.List
22import Data.Maybe (fromMaybe)
22import Data.Maybe (fromMaybe)
23+import Data.Either (lefts, rights)
23import qualified Data.Data as D
24import qualified Data.Data as D
24import Data.Generics
25import Data.Generics
25 (mkT, something, everywhere, everywhereBut, mkQ, extQ)
26 (mkT, something, everywhere, everywhereBut, mkQ, extQ)
@@ -36,6 +37,7 @@ import Language.PureScript.Unknown
37import Control.Monad.State
38import Control.Monad.State
38import Control.Monad.Error
39import Control.Monad.Error
40+import Control.Monad.Reader
40import Control.Applicative
42import Control.Applicative
41import Control.Arrow (Arrow(..))
43import Control.Arrow (Arrow(..))
@@ -131,41 +133,57 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
131 ret1 `unifyTypes` ret2
133 ret1 `unifyTypes` ret2
132 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
134 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
133 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
135 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
134− modulePath <- checkModulePath `fmap` get
136+ env <- getEnv
137+ moduleName <- substCurrentModule `fmap` ask
135− guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (qualify modulePath c1 == qualify modulePath c2)
138+ guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (typeConstructorsAreEqual env moduleName c1 c2)
136 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
139 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
137 t3 `unifyTypes` t5
140 t3 `unifyTypes` t5
138 t4 `unifyTypes` t6
141 t4 `unifyTypes` t6
139 unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
142 unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
140 unifyTypes' t3 t4 = throwError $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
143 unifyTypes' t3 t4 = throwError $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
142−isFunction :: Value -> Bool
145+typeConstructorsAreEqual :: Environment -> ModuleName -> Qualified ProperName -> Qualified ProperName -> Bool
143−isFunction (Abs _ _) = True
146+typeConstructorsAreEqual env moduleName c1 c2 =
144−isFunction (TypedValue untyped _) = isFunction untyped
147+ let
145−isFunction _ = False
148+ c1' = qualify moduleName c1
146−
149+ c2' = qualify moduleName c2
151+ canonicalize env c1' == canonicalize env c2'
153+ canonicalize :: Environment -> (ModuleName, ProperName) -> (ModuleName, ProperName)
154+ canonicalize _ key = case key `M.lookup` types env of
155+ Just (_, DataAlias mn' pn') -> (mn', pn')
147−typeOf :: Maybe Ident -> Value -> Check Type
158+typesOf :: ModuleName -> [(Ident, Value)] -> Check [Type]
148−typeOf name val = do
159+typesOf moduleName vals = do
149− (ty, sub, checks) <- runSubst $ case name of
160+ (tys, sub, checks) <- runSubst (SubstContext moduleName) $ do
150− Just ident | isFunction val ->
161+ let es = map isTyped vals
164+ typedDict = map (\(ident, ty, _) -> (ident, ty)) typed
165+ untypedNames <- replicateM (length untyped) fresh
166+ let untypedDict = zip (map fst untyped) untypedNames
167+ dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ typedDict ++ untypedDict)
151− case val of
168+ tys <- forM es $ \e -> case e of
152− TypedValue value ty -> do
169+ Left (_, ty, val) -> do
153− kind <- liftCheck $ kindOf ty
170+ kind <- liftCheck $ kindOf moduleName ty
154− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
171+ guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
155− ty' <- replaceAllTypeSynonyms ty
172+ ty' <- replaceAllTypeSynonyms ty
156− modulePath <- checkModulePath <$> get
173+ bindNames dict $ check val ty'
157− bindNames (M.singleton (modulePath, ident) (ty, LocalVariable)) $ check value ty'
158− return ty'
174+ return ty'
159− _ -> do
175+ Right (ident, val) -> do
161− modulePath <- checkModulePath <$> get
162− ty <- bindNames (M.singleton (modulePath, ident) (me, LocalVariable)) $ infer val
176+ ty <- bindNames dict $ infer val
163− ty ~~ me
177+ ty ~~ fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
164− return ty
178+ return ty
165− _ -> infer val
179+ return tys
166− escapeCheck checks ty sub
180+ forM tys $ flip (escapeCheck checks) sub
167− skolemEscapeCheck ty
181+ forM tys $ skolemEscapeCheck
168− return $ varIfUnknown $ desaturateAllTypeSynonyms $ setifyAll ty
182+ return $ map (varIfUnknown . desaturateAllTypeSynonyms . setifyAll) tys
184+isTyped :: (Ident, Value) -> Either (Ident, Type, Value) (Ident, Value)
185+isTyped (name, TypedValue value ty) = Left (name, ty, value)
186+isTyped (name, value) = Right (name, value)
170escapeCheck :: [AnyUnifiable] -> Type -> Substitution -> Check ()
188escapeCheck :: [AnyUnifiable] -> Type -> Substitution -> Check ()
171escapeCheck checks ty sub =
189escapeCheck checks ty sub =
@@ -234,11 +252,12 @@ replaceVarWithUnknown ident ty = do
234 ru <- fresh
252 ru <- fresh
235 return $ replaceRowVars ident ru . replaceTypeVars ident tu $ ty
253 return $ replaceRowVars ident ru . replaceTypeVars ident tu $ ty
237−replaceAllTypeSynonyms :: (Functor m, MonadState CheckState m, MonadError String m) => (D.Data d) => d -> m d
255+replaceAllTypeSynonyms :: (Functor m, MonadState CheckState m, MonadReader SubstContext m, MonadError String m) => (D.Data d) => d -> m d
238replaceAllTypeSynonyms d = do
256replaceAllTypeSynonyms d = do
239 env <- getEnv
257 env <- getEnv
258+ moduleName <- substCurrentModule <$> ask
240− let syns = map (\((path, name), (args, _)) -> (Qualified path name, length args)) . M.toList $ typeSynonyms env
259+ let syns = map (\((path, name), (args, _)) -> (Qualified (Just path) name, length args)) . M.toList $ typeSynonyms env
241− either throwError return $ saturateAllTypeSynonyms syns d
260+ either throwError return $ saturateAllTypeSynonyms moduleName syns d
243desaturateAllTypeSynonyms :: (D.Data d) => d -> d
262desaturateAllTypeSynonyms :: (D.Data d) => d -> d
244desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
263desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
@@ -249,8 +268,8 @@ desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
249expandTypeSynonym :: Qualified ProperName -> [Type] -> Subst Type
268expandTypeSynonym :: Qualified ProperName -> [Type] -> Subst Type
250expandTypeSynonym name args = do
269expandTypeSynonym name args = do
251 env <- getEnv
270 env <- getEnv
252− modulePath <- checkModulePath `fmap` get
271+ moduleName <- substCurrentModule `fmap` ask
253− case M.lookup (qualify modulePath name) (typeSynonyms env) of
272+ case M.lookup (qualify moduleName name) (typeSynonyms env) of
254 Just (synArgs, body) -> return $ replaceAllTypeVars (zip synArgs args) body
273 Just (synArgs, body) -> return $ replaceAllTypeVars (zip synArgs args) body
255 Nothing -> error "Type synonym was not defined"
274 Nothing -> error "Type synonym was not defined"
@@ -308,7 +327,8 @@ infer' (Accessor prop val) = do
308 Just ty -> return ty
327 Just ty -> return ty
309infer' (Abs args ret) = do
328infer' (Abs args ret) = do
310 ts <- replicateM (length args) fresh
329 ts <- replicateM (length args) fresh
330+ moduleName <- substCurrentModule <$> ask
311− bindLocalVariables (zip args ts) $ do
331+ bindLocalVariables moduleName (zip args ts) $ do
312 body <- infer' ret
332 body <- infer' ret
313 return $ Function ts body
333 return $ Function ts body
314infer' app@(App _ _) = do
334infer' app@(App _ _) = do
@@ -318,7 +338,8 @@ infer' app@(App _ _) = do
318 checkFunctionApplications ft argss ret
338 checkFunctionApplications ft argss ret
319 return ret
339 return ret
320infer' (Var var) = do
340infer' (Var var) = do
341+ moduleName <- substCurrentModule <$> ask
321− ty <- lookupVariable var
342+ ty <- lookupVariable moduleName var
322 replaceAllTypeSynonyms ty
343 replaceAllTypeSynonyms ty
323infer' (Block ss) = do
344infer' (Block ss) = do
324 ret <- fresh
345 ret <- fresh
@@ -327,8 +348,8 @@ infer' (Block ss) = do
327 return ret
348 return ret
328infer' (Constructor c) = do
349infer' (Constructor c) = do
329 env <- getEnv
350 env <- getEnv
330− modulePath <- checkModulePath `fmap` get
351+ moduleName <- substCurrentModule `fmap` ask
331− case M.lookup (qualify modulePath c) (dataConstructors env) of
352+ case M.lookup (qualify moduleName c) (dataConstructors env) of
332 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
353 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
333 Just ty -> replaceAllTypeSynonyms ty
354 Just ty -> replaceAllTypeSynonyms ty
334infer' (Case vals binders) = do
355infer' (Case vals binders) = do
@@ -343,7 +364,8 @@ infer' (IfThenElse cond th el) = do
344 return t2
365 return t2
345infer' (TypedValue val ty) = do
366infer' (TypedValue val ty) = do
367+ moduleName <- substCurrentModule <$> ask
346− kind <- liftCheck $ kindOf ty
368+ kind <- liftCheck $ kindOf moduleName ty
347 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
369 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
348 ty' <- replaceAllTypeSynonyms ty
370 ty' <- replaceAllTypeSynonyms ty
349 check val ty'
371 check val ty'
@@ -440,16 +462,16 @@ inferBinder val (BooleanBinder _) = val ~~ Boolean >> return M.empty
440inferBinder val (VarBinder name) = return $ M.singleton name val
462inferBinder val (VarBinder name) = return $ M.singleton name val
441inferBinder val (NullaryBinder ctor) = do
463inferBinder val (NullaryBinder ctor) = do
442 env <- getEnv
464 env <- getEnv
443− modulePath <- checkModulePath <$> get
465+ moduleName <- substCurrentModule <$> ask
444− case M.lookup (qualify modulePath ctor) (dataConstructors env) of
466+ case M.lookup (qualify moduleName ctor) (dataConstructors env) of
445 Just ty -> do
467 Just ty -> do
446 ty `subsumes` val
468 ty `subsumes` val
447 return M.empty
469 return M.empty
448 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
470 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
449inferBinder val (UnaryBinder ctor binder) = do
471inferBinder val (UnaryBinder ctor binder) = do
450 env <- getEnv
472 env <- getEnv
451− modulePath <- checkModulePath <$> get
473+ moduleName <- substCurrentModule <$> ask
452− case M.lookup (qualify modulePath ctor) (dataConstructors env) of
474+ case M.lookup (qualify moduleName ctor) (dataConstructors env) of
453 Just ty -> do
475 Just ty -> do
454 fn <- replaceAllVarsWithUnknowns ty
476 fn <- replaceAllVarsWithUnknowns ty
455 case fn of
477 case fn of
@@ -490,8 +512,9 @@ inferBinder val (NamedBinder name binder) = do
490checkBinders :: [Type] -> Type -> [([Binder], Maybe Guard, Value)] -> Subst ()
512checkBinders :: [Type] -> Type -> [([Binder], Maybe Guard, Value)] -> Subst ()
491checkBinders _ _ [] = return ()
513checkBinders _ _ [] = return ()
492checkBinders nvals ret ((binders, grd, val):bs) = do
514checkBinders nvals ret ((binders, grd, val):bs) = do
515+ moduleName <- substCurrentModule <$> ask
493 m1 <- M.unions <$> zipWithM inferBinder nvals binders
516 m1 <- M.unions <$> zipWithM inferBinder nvals binders
494− bindLocalVariables (M.toList m1) $ do
517+ bindLocalVariables moduleName (M.toList m1) $ do
495 check val ret
518 check val ret
496 case grd of
519 case grd of
497 Nothing -> return ()
520 Nothing -> return ()
@@ -501,8 +524,8 @@ checkBinders nvals ret ((binders, grd, val):bs) = do
501assignVariable :: Ident -> Subst ()
524assignVariable :: Ident -> Subst ()
502assignVariable name = do
525assignVariable name = do
503 env <- checkEnv <$> get
526 env <- checkEnv <$> get
504− modulePath <- checkModulePath <$> get
527+ moduleName <- substCurrentModule <$> ask
505− case M.lookup (modulePath, name) (names env) of
528+ case M.lookup (moduleName, name) (names env) of
506 Just (_, LocalVariable) -> throwError $ "Variable with name " ++ show name ++ " already exists."
529 Just (_, LocalVariable) -> throwError $ "Variable with name " ++ show name ++ " already exists."
507 _ -> return ()
530 _ -> return ()
@@ -525,16 +548,18 @@ checkStatement mass ret (If ifst) = do
525 allCodePathsReturn <- checkIfStatement mass ret ifst
548 allCodePathsReturn <- checkIfStatement mass ret ifst
526 return (allCodePathsReturn, mass)
549 return (allCodePathsReturn, mass)
527checkStatement mass ret (For ident start end inner) = do
550checkStatement mass ret (For ident start end inner) = do
551+ moduleName <- substCurrentModule <$> ask
528 assignVariable ident
552 assignVariable ident
529 check start Number
553 check start Number
530 check end Number
554 check end Number
531− (allCodePathsReturn, _) <- bindLocalVariables [(ident, Number)] $ checkBlock mass ret inner
555+ (allCodePathsReturn, _) <- bindLocalVariables moduleName [(ident, Number)] $ checkBlock mass ret inner
532 return (allCodePathsReturn, mass)
556 return (allCodePathsReturn, mass)
533checkStatement mass ret (ForEach ident vals inner) = do
557checkStatement mass ret (ForEach ident vals inner) = do
558+ moduleName <- substCurrentModule <$> ask
534 assignVariable ident
559 assignVariable ident
535 val <- fresh
560 val <- fresh
536 check vals (Array val)
561 check vals (Array val)
537− (allCodePathsReturn, _) <- bindLocalVariables [(ident, val)] $ checkBlock mass ret inner
562+ (allCodePathsReturn, _) <- bindLocalVariables moduleName [(ident, val)] $ checkBlock mass ret inner
538 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
563 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
539 return (False, mass)
564 return (False, mass)
540checkStatement mass _ (ValueStatement val) = do
565checkStatement mass _ (ValueStatement val) = do
@@ -562,8 +587,9 @@ checkElseStatement mass ret (ElseIf ifst) = checkIfStatement mass ret ifst
562checkBlock :: M.Map Ident Type -> Type -> [Statement] -> Subst (Bool, M.Map Ident Type)
587checkBlock :: M.Map Ident Type -> Type -> [Statement] -> Subst (Bool, M.Map Ident Type)
563checkBlock mass _ [] = return (False, mass)
588checkBlock mass _ [] = return (False, mass)
564checkBlock mass ret (s:ss) = do
589checkBlock mass ret (s:ss) = do
590+ moduleName <- substCurrentModule <$> ask
565 (b1, mass1) <- checkStatement mass ret s
591 (b1, mass1) <- checkStatement mass ret s
566− bindLocalVariables (M.toList mass1) $ case (b1, ss) of
592+ bindLocalVariables moduleName (M.toList mass1) $ case (b1, ss) of
567 (True, []) -> return (True, mass1)
593 (True, []) -> return (True, mass1)
568 (True, _) -> throwError "Unreachable code"
594 (True, _) -> throwError "Unreachable code"
569 (False, ss') -> checkBlock mass1 ret ss'
595 (False, ss') -> checkBlock mass1 ret ss'
@@ -602,18 +628,21 @@ check' (Binary op left right) ty = checkBinary op left right ty
602check' (ArrayLiteral vals) (Array ty) = forM_ vals (\val -> check val ty)
628check' (ArrayLiteral vals) (Array ty) = forM_ vals (\val -> check val ty)
603check' (Indexer index vals) ty = check index Number >> check vals (Array ty)
629check' (Indexer index vals) ty = check index Number >> check vals (Array ty)
604check' (Abs args ret) (Function argTys retTy) = do
630check' (Abs args ret) (Function argTys retTy) = do
631+ moduleName <- substCurrentModule <$> ask
605 guardWith "Incorrect number of function arguments" (length args == length argTys)
632 guardWith "Incorrect number of function arguments" (length args == length argTys)
606− bindLocalVariables (zip args argTys) $ check ret retTy
633+ bindLocalVariables moduleName (zip args argTys) $ check ret retTy
607check' app@(App _ _) ret = do
634check' app@(App _ _) ret = do
608 let (f, argss) = unfoldApplication app
635 let (f, argss) = unfoldApplication app
609 ft <- infer f
636 ft <- infer f
610 checkFunctionApplications ft argss ret
637 checkFunctionApplications ft argss ret
611check' (Var var) ty = do
638check' (Var var) ty = do
639+ moduleName <- substCurrentModule <$> ask
612− ty1 <- lookupVariable var
640+ ty1 <- lookupVariable moduleName var
613 repl <- replaceAllTypeSynonyms ty1
641 repl <- replaceAllTypeSynonyms ty1
614 repl `subsumes` ty
642 repl `subsumes` ty
615check' (TypedValue val ty1) ty2 = do
643check' (TypedValue val ty1) ty2 = do
644+ moduleName <- substCurrentModule <$> ask
616− kind <- liftCheck $ kindOf ty1
645+ kind <- liftCheck $ kindOf moduleName ty1
617 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
646 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
618 ty1 `subsumes` ty2
647 ty1 `subsumes` ty2
619 check val ty1
648 check val ty1
@@ -643,8 +672,8 @@ check' (Block ss) ret = do
643 guardWith "Block is missing a return statement" allCodePathsReturn
672 guardWith "Block is missing a return statement" allCodePathsReturn
644check' (Constructor c) ty = do
673check' (Constructor c) ty = do
645 env <- getEnv
674 env <- getEnv
646− modulePath <- checkModulePath <$> get
675+ moduleName <- substCurrentModule <$> ask
647− case M.lookup (qualify modulePath c) (dataConstructors env) of
676+ case M.lookup (qualify moduleName c) (dataConstructors env) of
648 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
677 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
649 Just ty1 -> do
678 Just ty1 -> do
650 repl <- replaceAllTypeSynonyms ty1
679 repl <- replaceAllTypeSynonyms ty1