@@ -15,11 +15,12 @@
1515{-# LANGUAGE DeriveDataTypeable, FlexibleContexts #-}
1616
1717module Language.PureScript.TypeChecker.Types (
18− typeOf
18+ typesOf
1919) where
2020
2121import Data.List
2222import Data.Maybe (fromMaybe)
23+import Data.Either (lefts, rights)
2324import qualified Data.Data as D
2425import Data.Generics
2526 (mkT, something, everywhere, everywhereBut, mkQ, extQ)
@@ -36,6 +37,7 @@ import Language.PureScript.Unknown
3637
3738import Control.Monad.State
3839import Control.Monad.Error
40+import Control.Monad.Reader
3941
4042import Control.Applicative
4143import Control.Arrow (Arrow(..))
@@ -131,41 +133,57 @@ unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 +
131133 ret1 `unifyTypes` ret2
132134 unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
133135 unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
134− modulePath <- checkModulePath `fmap` get
135− guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (qualify modulePath c1 == qualify modulePath c2)
136+ env <- getEnv
137+ moduleName <- substCurrentModule `fmap` ask
138+ guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (typeConstructorsAreEqual env moduleName c1 c2)
136139 unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
137140 t3 `unifyTypes` t5
138141 t4 `unifyTypes` t6
139142 unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
140143 unifyTypes' t3 t4 = throwError $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
141144
142−isFunction :: Value -> Bool
143−isFunction (Abs _ _) = True
144−isFunction (TypedValue untyped _) = isFunction untyped
145−isFunction _ = False
146−
147−typeOf :: Maybe Ident -> Value -> Check Type
148−typeOf name val = do
149− (ty, sub, checks) <- runSubst $ case name of
150− Just ident | isFunction val ->
151− case val of
152− TypedValue value ty -> do
153− kind <- liftCheck $ kindOf ty
154− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
155− ty' <- replaceAllTypeSynonyms ty
156− modulePath <- checkModulePath <$> get
157− bindNames (M.singleton (modulePath, ident) (ty, LocalVariable)) $ check value ty'
158− return ty'
159− _ -> do
160− me <- fresh
161− modulePath <- checkModulePath <$> get
162− ty <- bindNames (M.singleton (modulePath, ident) (me, LocalVariable)) $ infer val
163− ty ~~ me
164− return ty
165− _ -> infer val
166− escapeCheck checks ty sub
167− skolemEscapeCheck ty
168− return $ varIfUnknown $ desaturateAllTypeSynonyms $ setifyAll ty
145+typeConstructorsAreEqual :: Environment -> ModuleName -> Qualified ProperName -> Qualified ProperName -> Bool
146+typeConstructorsAreEqual env moduleName c1 c2 =
147+ let
148+ c1' = qualify moduleName c1
149+ c2' = qualify moduleName c2
150+ in
151+ canonicalize env c1' == canonicalize env c2'
152+ where
153+ canonicalize :: Environment -> (ModuleName, ProperName) -> (ModuleName, ProperName)
154+ canonicalize _ key = case key `M.lookup` types env of
155+ Just (_, DataAlias mn' pn') -> (mn', pn')
156+ _ -> key
157+
158+typesOf :: ModuleName -> [(Ident, Value)] -> Check [Type]
159+typesOf moduleName vals = do
160+ (tys, sub, checks) <- runSubst (SubstContext moduleName) $ do
161+ let es = map isTyped vals
162+ typed = lefts es
163+ untyped = rights es
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)
168+ tys <- forM es $ \e -> case e of
169+ Left (_, ty, val) -> do
170+ kind <- liftCheck $ kindOf moduleName ty
171+ guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
172+ ty' <- replaceAllTypeSynonyms ty
173+ bindNames dict $ check val ty'
174+ return ty'
175+ Right (ident, val) -> do
176+ ty <- bindNames dict $ infer val
177+ ty ~~ fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
178+ return ty
179+ return tys
180+ forM tys $ flip (escapeCheck checks) sub
181+ forM tys $ skolemEscapeCheck
182+ return $ map (varIfUnknown . desaturateAllTypeSynonyms . setifyAll) tys
183+
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)
169187
170188escapeCheck :: [AnyUnifiable] -> Type -> Substitution -> Check ()
171189escapeCheck checks ty sub =
@@ -234,11 +252,12 @@ replaceVarWithUnknown ident ty = do
234252 ru <- fresh
235253 return $ replaceRowVars ident ru . replaceTypeVars ident tu $ ty
236254
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
238256replaceAllTypeSynonyms d = do
239257 env <- getEnv
240− let syns = map (\((path, name), (args, _)) -> (Qualified path name, length args)) . M.toList $ typeSynonyms env
241− either throwError return $ saturateAllTypeSynonyms syns d
258+ moduleName <- substCurrentModule <$> ask
259+ let syns = map (\((path, name), (args, _)) -> (Qualified (Just path) name, length args)) . M.toList $ typeSynonyms env
260+ either throwError return $ saturateAllTypeSynonyms moduleName syns d
242261
243262desaturateAllTypeSynonyms :: (D.Data d) => d -> d
244263desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
@@ -249,8 +268,8 @@ desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
249268expandTypeSynonym :: Qualified ProperName -> [Type] -> Subst Type
250269expandTypeSynonym name args = do
251270 env <- getEnv
252− modulePath <- checkModulePath `fmap` get
253− case M.lookup (qualify modulePath name) (typeSynonyms env) of
271+ moduleName <- substCurrentModule `fmap` ask
272+ case M.lookup (qualify moduleName name) (typeSynonyms env) of
254273 Just (synArgs, body) -> return $ replaceAllTypeVars (zip synArgs args) body
255274 Nothing -> error "Type synonym was not defined"
256275
@@ -308,7 +327,8 @@ infer' (Accessor prop val) = do
308327 Just ty -> return ty
309328infer' (Abs args ret) = do
310329 ts <- replicateM (length args) fresh
311− bindLocalVariables (zip args ts) $ do
330+ moduleName <- substCurrentModule <$> ask
331+ bindLocalVariables moduleName (zip args ts) $ do
312332 body <- infer' ret
313333 return $ Function ts body
314334infer' app@(App _ _) = do
@@ -318,7 +338,8 @@ infer' app@(App _ _) = do
318338 checkFunctionApplications ft argss ret
319339 return ret
320340infer' (Var var) = do
321− ty <- lookupVariable var
341+ moduleName <- substCurrentModule <$> ask
342+ ty <- lookupVariable moduleName var
322343 replaceAllTypeSynonyms ty
323344infer' (Block ss) = do
324345 ret <- fresh
@@ -327,8 +348,8 @@ infer' (Block ss) = do
327348 return ret
328349infer' (Constructor c) = do
329350 env <- getEnv
330− modulePath <- checkModulePath `fmap` get
331− case M.lookup (qualify modulePath c) (dataConstructors env) of
351+ moduleName <- substCurrentModule `fmap` ask
352+ case M.lookup (qualify moduleName c) (dataConstructors env) of
332353 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
333354 Just ty -> replaceAllTypeSynonyms ty
334355infer' (Case vals binders) = do
@@ -343,7 +364,8 @@ infer' (IfThenElse cond th el) = do
343364 t2 ~~ t3
344365 return t2
345366infer' (TypedValue val ty) = do
346− kind <- liftCheck $ kindOf ty
367+ moduleName <- substCurrentModule <$> ask
368+ kind <- liftCheck $ kindOf moduleName ty
347369 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
348370 ty' <- replaceAllTypeSynonyms ty
349371 check val ty'
@@ -440,16 +462,16 @@ inferBinder val (BooleanBinder _) = val ~~ Boolean >> return M.empty
440462inferBinder val (VarBinder name) = return $ M.singleton name val
441463inferBinder val (NullaryBinder ctor) = do
442464 env <- getEnv
443− modulePath <- checkModulePath <$> get
444− case M.lookup (qualify modulePath ctor) (dataConstructors env) of
465+ moduleName <- substCurrentModule <$> ask
466+ case M.lookup (qualify moduleName ctor) (dataConstructors env) of
445467 Just ty -> do
446468 ty `subsumes` val
447469 return M.empty
448470 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
449471inferBinder val (UnaryBinder ctor binder) = do
450472 env <- getEnv
451− modulePath <- checkModulePath <$> get
452− case M.lookup (qualify modulePath ctor) (dataConstructors env) of
473+ moduleName <- substCurrentModule <$> ask
474+ case M.lookup (qualify moduleName ctor) (dataConstructors env) of
453475 Just ty -> do
454476 fn <- replaceAllVarsWithUnknowns ty
455477 case fn of
@@ -490,8 +512,9 @@ inferBinder val (NamedBinder name binder) = do
490512checkBinders :: [Type] -> Type -> [([Binder], Maybe Guard, Value)] -> Subst ()
491513checkBinders _ _ [] = return ()
492514checkBinders nvals ret ((binders, grd, val):bs) = do
515+ moduleName <- substCurrentModule <$> ask
493516 m1 <- M.unions <$> zipWithM inferBinder nvals binders
494− bindLocalVariables (M.toList m1) $ do
517+ bindLocalVariables moduleName (M.toList m1) $ do
495518 check val ret
496519 case grd of
497520 Nothing -> return ()
@@ -501,8 +524,8 @@ checkBinders nvals ret ((binders, grd, val):bs) = do
501524assignVariable :: Ident -> Subst ()
502525assignVariable name = do
503526 env <- checkEnv <$> get
504− modulePath <- checkModulePath <$> get
505− case M.lookup (modulePath, name) (names env) of
527+ moduleName <- substCurrentModule <$> ask
528+ case M.lookup (moduleName, name) (names env) of
506529 Just (_, LocalVariable) -> throwError $ "Variable with name " ++ show name ++ " already exists."
507530 _ -> return ()
508531
@@ -525,16 +548,18 @@ checkStatement mass ret (If ifst) = do
525548 allCodePathsReturn <- checkIfStatement mass ret ifst
526549 return (allCodePathsReturn, mass)
527550checkStatement mass ret (For ident start end inner) = do
551+ moduleName <- substCurrentModule <$> ask
528552 assignVariable ident
529553 check start Number
530554 check end Number
531− (allCodePathsReturn, _) <- bindLocalVariables [(ident, Number)] $ checkBlock mass ret inner
555+ (allCodePathsReturn, _) <- bindLocalVariables moduleName [(ident, Number)] $ checkBlock mass ret inner
532556 return (allCodePathsReturn, mass)
533557checkStatement mass ret (ForEach ident vals inner) = do
558+ moduleName <- substCurrentModule <$> ask
534559 assignVariable ident
535560 val <- fresh
536561 check vals (Array val)
537− (allCodePathsReturn, _) <- bindLocalVariables [(ident, val)] $ checkBlock mass ret inner
562+ (allCodePathsReturn, _) <- bindLocalVariables moduleName [(ident, val)] $ checkBlock mass ret inner
538563 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
539564 return (False, mass)
540565checkStatement mass _ (ValueStatement val) = do
@@ -562,8 +587,9 @@ checkElseStatement mass ret (ElseIf ifst) = checkIfStatement mass ret ifst
562587checkBlock :: M.Map Ident Type -> Type -> [Statement] -> Subst (Bool, M.Map Ident Type)
563588checkBlock mass _ [] = return (False, mass)
564589checkBlock mass ret (s:ss) = do
590+ moduleName <- substCurrentModule <$> ask
565591 (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
567593 (True, []) -> return (True, mass1)
568594 (True, _) -> throwError "Unreachable code"
569595 (False, ss') -> checkBlock mass1 ret ss'
@@ -602,18 +628,21 @@ check' (Binary op left right) ty = checkBinary op left right ty
602628check' (ArrayLiteral vals) (Array ty) = forM_ vals (\val -> check val ty)
603629check' (Indexer index vals) ty = check index Number >> check vals (Array ty)
604630check' (Abs args ret) (Function argTys retTy) = do
631+ moduleName <- substCurrentModule <$> ask
605632 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
607634check' app@(App _ _) ret = do
608635 let (f, argss) = unfoldApplication app
609636 ft <- infer f
610637 checkFunctionApplications ft argss ret
611638check' (Var var) ty = do
612− ty1 <- lookupVariable var
639+ moduleName <- substCurrentModule <$> ask
640+ ty1 <- lookupVariable moduleName var
613641 repl <- replaceAllTypeSynonyms ty1
614642 repl `subsumes` ty
615643check' (TypedValue val ty1) ty2 = do
616− kind <- liftCheck $ kindOf ty1
644+ moduleName <- substCurrentModule <$> ask
645+ kind <- liftCheck $ kindOf moduleName ty1
617646 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
618647 ty1 `subsumes` ty2
619648 check val ty1
@@ -643,8 +672,8 @@ check' (Block ss) ret = do
643672 guardWith "Block is missing a return statement" allCodePathsReturn
644673check' (Constructor c) ty = do
645674 env <- getEnv
646− modulePath <- checkModulePath <$> get
647− case M.lookup (qualify modulePath c) (dataConstructors env) of
675+ moduleName <- substCurrentModule <$> ask
676+ case M.lookup (qualify moduleName c) (dataConstructors env) of
648677 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
649678 Just ty1 -> do
650679 repl <- replaceAllTypeSynonyms ty1