1-----------------------------------------------------------------------------
3-- Module : PureScript.TypeChecker.Types
4-- Copyright : (c) Phil Freeman 2013
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
13-----------------------------------------------------------------------------
15{-# LANGUAGE DeriveDataTypeable #-}
17module PureScript.TypeChecker.Types (
25import qualified Data.Data as D
26import Data.Generics (everywhere, everywhereM, everything, mkT, mkM, mkQ, extM, extQ)
28import PureScript.Values
29import PureScript.Types
30import PureScript.Kinds
31import PureScript.Names
32import PureScript.TypeChecker.Monad
33import PureScript.TypeChecker.Kinds
34import PureScript.TypeChecker.Synonyms
35import PureScript.CodeGen.Pretty.Types
36import PureScript.CodeGen.Pretty.Kinds
37import PureScript.CodeGen.Pretty.Values
39import Control.Monad.State
40import Control.Monad.Error
42import Control.Applicative
43import Control.Arrow (Kleisli(..), (***), (&&&))
44import qualified Control.Category as C
46import qualified Data.Map as M
48data TypeConstraintOrigin
51 | AssignmentTargetOrigin Ident deriving (Show, D.Data, D.Typeable)
53prettyPrintOrigin :: TypeConstraintOrigin -> String
54prettyPrintOrigin (ValueOrigin val) = prettyPrintValue val
55prettyPrintOrigin (BinderOrigin binder) = prettyPrintBinder binder
56prettyPrintOrigin (AssignmentTargetOrigin ident) = show ident
59 = TypeConstraint Int Type TypeConstraintOrigin
60 | RowConstraint Int Row TypeConstraintOrigin deriving (Show, D.Data, D.Typeable)
62newtype TypeSolution = TypeSolution { runTypeSolution :: (Int -> Type, Int -> Row) }
64emptyTypeSolution :: TypeSolution
65emptyTypeSolution = TypeSolution (TUnknown, RUnknown)
67typeOf :: Ident -> Value -> Check PolyType
69 (cs, n) <- case val of
72 (cs, n) <- typeConstraints (M.singleton name me) val
73 return (TypeConstraint me (TUnknown n) (ValueOrigin val): cs, n)
74 _ -> typeConstraints M.empty val
75 desugared <- replaceAllTypeSynonyms cs
76 solution <- solveTypeConstraints desugared emptyTypeSolution
77 let ty = fst (runTypeSolution solution) n
78 allUnknownsBecameQuantified desugared solution ty
79 return $ varIfUnknown $ desaturateAllTypeSynonyms ty
81allUnknownsBecameQuantified :: [TypeConstraint] -> TypeSolution -> Type -> Check ()
82allUnknownsBecameQuantified cs solution ty = do
84 typesMentioned = findUnknownTypes ty
85 unknownTypes = nub $ flip concatMap cs $ \c -> case c of
86 TypeConstraint u t _ -> u : findUnknownTypes t
87 RowConstraint _ r _ -> findUnknownTypes r
88 unsolvedTypes = filter (\n -> TUnknown n == fst (runTypeSolution solution) n) unknownTypes
89 guardWith "Unsolved type variable" $ null $ unsolvedTypes \\ typesMentioned
91 rowsMentioned = findUnknownRows ty
92 unknownRows = nub $ flip concatMap cs $ \c -> case c of
93 TypeConstraint _ t _ -> findUnknownRows t
94 RowConstraint u r _ -> u : findUnknownRows r
95 unsolvedRows = filter (\n -> RUnknown n == snd (runTypeSolution solution) n) unknownRows
96 guardWith "Unsolved row variable" $ null $ unsolvedRows \\ rowsMentioned
98findUnknownTypes :: (D.Data d) => d -> [Int]
99findUnknownTypes = everything (++) (mkQ [] f)
105findTypeVars :: (D.Data d) => d -> [String]
106findTypeVars = everything (++) (mkQ [] f)
108 f :: Type -> [String]
112findUnknownRows :: (D.Data d) => d -> [Int]
113findUnknownRows = everything (++) (mkQ [] f)
119varIfUnknown :: Type -> PolyType
122 (ty', m) = flip runState M.empty $ everywhereM (flip extM g $ mkM f) ty
124 PolyType (sort $ nub $ M.elems m ++ findTypeVars ty) ty'
126 f :: Type -> State (M.Map Int String) Type
131 let name = "t" ++ show (M.size m)
132 put $ M.insert n name m
133 return $ TypeVar name
134 Just name -> return $ TypeVar name
136 g :: Row -> State (M.Map Int String) Row
141 let name = "r" ++ show (M.size m)
142 put $ M.insert n name m
144 Just name -> return $ RowVar name
147replaceTypeVars :: M.Map String Type -> Type -> Type
148replaceTypeVars m = everywhere (mkT replace)
150 replace (TypeVar v) = case M.lookup v m of
155replaceVarsWithUnknowns :: [String] -> Type -> Check Type
156replaceVarsWithUnknowns idents = flip evalStateT M.empty . everywhereM (flip extM f $ mkM g)
158 f :: Type -> StateT (M.Map String Int) Check Type
159 f (TypeVar var) | var `elem` idents = do
162 case M.lookup var m of
164 put (M.insert var n m)
166 Just u -> return $ TUnknown u
168 g :: Row -> StateT (M.Map String Int) Check Row
169 g (RowVar var) | var `elem` idents = do
172 case M.lookup var m of
174 put (M.insert var n m)
176 Just u -> return $ RUnknown u
179replaceAllTypeSynonyms :: (D.Data d) => d -> Check d
180replaceAllTypeSynonyms d = do
182 let syns = map (\(name, (args, _)) -> (name, length args)) . M.toList $ typeSynonyms env
183 either throwError return $ saturateAllTypeSynonyms syns d
185desaturateAllTypeSynonyms :: (D.Data d) => d -> d
186desaturateAllTypeSynonyms = everywhere (mkT $ replace)
188 replace (SaturatedTypeSynonym name args) = foldl (\t arg -> TypeApp t arg) (TypeConstructor name) args
191replaceType :: (D.Data d) => Int -> Type -> d -> d
192replaceType n t = everywhere (mkT go)
194 go (TUnknown m) | m == n = t
197replaceRow :: (D.Data d) => Int -> Row -> d -> d
198replaceRow n r = everywhere (mkT go)
200 go (RUnknown m) | m == n = r
203typeOccursCheck :: Int -> Type -> Check ()
204typeOccursCheck u (TUnknown _) = return ()
205typeOccursCheck u t = when (occursCheck u t) $ throwError $ "Occurs check failed: " ++ show u ++ " = " ++ prettyPrintType t
207rowOccursCheck :: Int -> Row -> Check ()
208rowOccursCheck u (RUnknown _) = return ()
209rowOccursCheck u r = when (occursCheck u r) $ throwError $ "Occurs check failed: " ++ show u ++ " = " ++ prettyPrintRow r
211occursCheck :: (D.Data d) => Int -> d -> Bool
212occursCheck u = everything (||) $ flip extQ g $ mkQ False f
214 f (TUnknown u') | u' == u = True
216 g (RUnknown u') | u' == u = True
219typeConstraints :: M.Map Ident Int -> Value -> Check ([TypeConstraint], Int)
220typeConstraints _ v@(NumericLiteral _) = do
222 return ([TypeConstraint me Number (ValueOrigin v)], me)
223typeConstraints _ v@(StringLiteral _) = do
225 return ([TypeConstraint me String (ValueOrigin v)], me)
226typeConstraints _ v@(BooleanLiteral _) = do
228 return ([TypeConstraint me Boolean (ValueOrigin v)], me)
229typeConstraints m v@(ArrayLiteral vals) = do
230 all <- mapM (typeConstraints m) vals
231 let (cs, ns) = (concat . map fst &&& map snd) all
233 return (cs ++ zipWith (\n el -> TypeConstraint me (Array $ TUnknown n) (ValueOrigin el)) ns vals, me)
234typeConstraints m u@(Unary op val) = do
235 (cs, n1) <- typeConstraints m val
237 return (cs ++ unaryOperatorConstraints u op n1 me, me)
238typeConstraints m b@(Binary op left right) = do
239 (cs1, n1) <- typeConstraints m left
240 (cs2, n2) <- typeConstraints m right
242 return (cs1 ++ cs2 ++ binaryOperatorConstraints b op n1 n2 me, me)
243typeConstraints m v@(ObjectLiteral ps) = do
244 all <- mapM (typeConstraints m . snd) ps
245 let (cs, ns) = (concat . map fst &&& map snd) all
247 let tys = zipWith (\(name, _) u -> (name, TUnknown u)) ps ns
248 return ((TypeConstraint me (Object (typesToRow tys)) (ValueOrigin v)) : cs, me)
250 typesToRow [] = REmpty
251 typesToRow ((name, ty):tys) = RCons name ty (typesToRow tys)
252typeConstraints m v@(Indexer index val) = do
253 (cs1, n1) <- typeConstraints m index
254 (cs2, n2) <- typeConstraints m val
256 return ((TypeConstraint n1 Number (ValueOrigin index)) : (TypeConstraint n2 (Array (TUnknown me)) (ValueOrigin v)) : cs1 ++ cs2, me)
257typeConstraints m v@(Accessor prop val) = do
258 (cs, n1) <- typeConstraints m val
261 return ((TypeConstraint n1 (Object (RCons prop (TUnknown me) (RUnknown rest))) (ValueOrigin v)) : cs, me)
262typeConstraints m v@(Abs args ret) = do
263 ns <- replicateM (length args) fresh
264 let m' = m `M.union` M.fromList (zipWith (,) args ns)
265 (cs, n') <- typeConstraints m' ret
267 return ((TypeConstraint me (Function (map TUnknown ns) (TUnknown n')) (ValueOrigin v)) : cs, me)
268typeConstraints m v@(App f xs) = do
269 (cs1, n1) <- typeConstraints m f
270 all <- mapM (typeConstraints m) xs
271 let (cs2, ns) = (concat . map fst &&& map snd) all
273 return ((TypeConstraint n1 (Function (map TUnknown ns) (TUnknown me)) (ValueOrigin v)) : cs1 ++ cs2, me)
274typeConstraints m v@(Var var) =
275 case M.lookup var m of
278 case M.lookup var (names env) of
279 Nothing -> throwError $ show var ++ " is undefined"
280 Just (PolyType idents ty, _) -> do
282 replaced <- replaceVarsWithUnknowns idents ty
283 return ([TypeConstraint me replaced (ValueOrigin v)], me)
286 return ([TypeConstraint u (TUnknown me) (ValueOrigin v)], me)
287typeConstraints m (Block ss) = do
289 (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m M.empty ret ss
290 guardWith "Block is missing a return statement" allCodePathsReturn
292typeConstraints m v@(Constructor c) = do
294 case M.lookup c (dataConstructors env) of
295 Nothing -> throwError $ "Constructor " ++ c ++ " is undefined"
296 Just (PolyType idents ty) -> do
298 replaced <- replaceVarsWithUnknowns idents ty
299 return ([TypeConstraint me replaced (ValueOrigin v)], me)
300typeConstraints m (Case val binders) = do
301 (cs1, n1) <- typeConstraints m val
303 cs2 <- typeConstraintsForBinders m n1 ret binders
304 return (cs1 ++ cs2, ret)
305typeConstraints m v@(IfThenElse cond th el) = do
306 (cs1, n1) <- typeConstraints m cond
307 (cs2, n2) <- typeConstraints m th
308 (cs3, n3) <- typeConstraints m el
309 return (TypeConstraint n1 Boolean (ValueOrigin cond) : TypeConstraint n2 (TUnknown n3) (ValueOrigin v) : cs1 ++ cs2 ++ cs3, n2)
310typeConstraints m v@(TypedValue val poly@(PolyType idents ty)) = do
312 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
313 (cs, n1) <- typeConstraints m val
314 return (TypeConstraint n1 ty (ValueOrigin v) : cs, n1)
316unaryOperatorConstraints :: Value -> UnaryOperator -> Int -> Int -> [TypeConstraint]
317unaryOperatorConstraints v Negate val result = [TypeConstraint val Number (ValueOrigin v), TypeConstraint result Number (ValueOrigin v)]
318unaryOperatorConstraints v Not val result = [TypeConstraint val Boolean (ValueOrigin v), TypeConstraint result Boolean (ValueOrigin v)]
319unaryOperatorConstraints v BitwiseNot val result = [TypeConstraint val Number (ValueOrigin v), TypeConstraint result Number (ValueOrigin v)]
321binaryOperatorConstraints :: Value -> BinaryOperator -> Int -> Int -> Int -> [TypeConstraint]
322binaryOperatorConstraints v Add = symBinOpConstraints v Number
323binaryOperatorConstraints v Subtract = symBinOpConstraints v Number
324binaryOperatorConstraints v Multiply = symBinOpConstraints v Number
325binaryOperatorConstraints v Divide = symBinOpConstraints v Number
326binaryOperatorConstraints v Modulus = symBinOpConstraints v Number
327binaryOperatorConstraints v LessThan = asymBinOpConstraints v Number Boolean
328binaryOperatorConstraints v LessThanOrEqualTo = asymBinOpConstraints v Number Boolean
329binaryOperatorConstraints v GreaterThan = asymBinOpConstraints v Number Boolean
330binaryOperatorConstraints v GreaterThanOrEqualTo = asymBinOpConstraints v Number Boolean
331binaryOperatorConstraints v BitwiseAnd = symBinOpConstraints v Number
332binaryOperatorConstraints v BitwiseOr = symBinOpConstraints v Number
333binaryOperatorConstraints v BitwiseXor = symBinOpConstraints v Number
334binaryOperatorConstraints v ShiftLeft = symBinOpConstraints v Number
335binaryOperatorConstraints v ShiftRight = symBinOpConstraints v Number
336binaryOperatorConstraints v ZeroFillShiftRight = symBinOpConstraints v Number
337binaryOperatorConstraints v EqualTo = equalityBinOpConstraints v
338binaryOperatorConstraints v NotEqualTo = equalityBinOpConstraints v
339binaryOperatorConstraints v And = symBinOpConstraints v Boolean
340binaryOperatorConstraints v Or = symBinOpConstraints v Boolean
341binaryOperatorConstraints v Concat = symBinOpConstraints v String
343equalityBinOpConstraints :: Value -> Int -> Int -> Int -> [TypeConstraint]
344equalityBinOpConstraints v left right result = [TypeConstraint left (TUnknown right) (ValueOrigin v), TypeConstraint result Boolean (ValueOrigin v)]
346symBinOpConstraints :: Value -> Type -> Int -> Int -> Int -> [TypeConstraint]
347symBinOpConstraints v ty left right result = asymBinOpConstraints v ty ty left right result
349asymBinOpConstraints :: Value -> Type -> Type -> Int -> Int -> Int -> [TypeConstraint]
350asymBinOpConstraints v ty res left right result = [TypeConstraint left ty (ValueOrigin v), TypeConstraint right ty (ValueOrigin v), TypeConstraint result res (ValueOrigin v)]
352typeConstraintsForBinder :: Int -> Binder -> Check ([TypeConstraint], M.Map Ident Int)
353typeConstraintsForBinder _ NullBinder = return ([], M.empty)
354typeConstraintsForBinder val b@(StringBinder _) = constantBinder b val String
355typeConstraintsForBinder val b@(NumberBinder _) = constantBinder b val Number
356typeConstraintsForBinder val b@(BooleanBinder _) = constantBinder b val Boolean
357typeConstraintsForBinder val b@(VarBinder name) = do
359 return ([TypeConstraint me (TUnknown val) (BinderOrigin b)], M.singleton name me)
360typeConstraintsForBinder val b@(NullaryBinder ctor) = do
362 case M.lookup ctor (dataConstructors env) of
363 Just (PolyType args ret) -> do
364 ret' <- replaceVarsWithUnknowns args ret
365 return ([TypeConstraint val ret' (BinderOrigin b)], M.empty)
366 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
367typeConstraintsForBinder val b@(UnaryBinder ctor binder) = do
369 case M.lookup ctor (dataConstructors env) of
370 Just (PolyType idents f@(Function [_] _)) -> do
372 (Function [ty] ret) <- replaceVarsWithUnknowns idents f
373 (cs, m1) <- typeConstraintsForBinder obj binder
374 return ((TypeConstraint val ret (BinderOrigin b)) : (TypeConstraint obj ty (BinderOrigin b)) : cs, m1)
375 Just _ -> throwError $ ctor ++ " is not a unary constructor"
376 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
377typeConstraintsForBinder val b@(ObjectBinder props) = do
380 (cs, m1) <- typeConstraintsForProperties row (RUnknown rest) props
381 return ((TypeConstraint val (Object (RUnknown row)) (BinderOrigin b)) : cs, m1)
383 typeConstraintsForProperties :: Int -> Row -> [(String, Binder)] -> Check ([TypeConstraint], M.Map Ident Int)
384 typeConstraintsForProperties nrow row [] = return ([RowConstraint nrow row (BinderOrigin b)], M.empty)
385 typeConstraintsForProperties nrow row ((name, binder):binders) = do
387 (cs1, m1) <- typeConstraintsForBinder propTy binder
388 (cs2, m2) <- typeConstraintsForProperties nrow (RCons name (TUnknown propTy) row) binders
389 return (cs1 ++ cs2, M.union m1 m2)
390typeConstraintsForBinder val b@(ArrayBinder binders rest) = do
392 all <- mapM (typeConstraintsForBinder el) binders
393 let (cs1, m1) = (concat . map fst &&& M.unions . map snd) all
394 let arrayConstraint = TypeConstraint val (Array (TUnknown el)) (BinderOrigin b)
396 Nothing -> return (arrayConstraint : cs1, m1)
398 (cs2, m2) <- typeConstraintsForBinder val binder
399 return (arrayConstraint : cs1 ++ cs2, M.union m1 m2)
400typeConstraintsForBinder val b@(NamedBinder name binder) = do
402 (cs, m) <- typeConstraintsForBinder val binder
403 return (TypeConstraint me (TUnknown val) (BinderOrigin b) : cs, M.insert name me m)
404typeConstraintsForBinder val b@(GuardedBinder cond binder) = do
405 (cs1, m) <- typeConstraintsForBinder val binder
406 (cs2, n) <- typeConstraints m cond
407 return (TypeConstraint n Boolean (ValueOrigin cond) : cs1 ++ cs2, m)
409constantBinder :: Binder -> Int -> Type -> Check ([TypeConstraint], M.Map Ident Int)
410constantBinder b val ty = return ([TypeConstraint val ty (BinderOrigin b)], M.empty)
412typeConstraintsForBinders :: M.Map Ident Int -> Int -> Int -> [(Binder, Value)] -> Check [TypeConstraint]
413typeConstraintsForBinders _ _ _ [] = return []
414typeConstraintsForBinders m nval ret ((binder, val):bs) = do
415 (cs1, m1) <- typeConstraintsForBinder nval binder
416 (cs2, n2) <- typeConstraints (M.union m m1) val
417 cs3 <- typeConstraintsForBinders m nval ret bs
418 return ((TypeConstraint n2 (TUnknown ret) (BinderOrigin binder)) : cs1 ++ cs2 ++ cs3)
420assignVariable :: Ident -> M.Map Ident Int -> Check ()
421assignVariable name m =
422 case M.lookup name m of
424 Just _ -> throwError $ "Variable with name " ++ show name ++ " already exists."
426typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
427typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
428 assignVariable name (m `M.union` mass)
429 (cs1, n1) <- typeConstraints m val
430 return $ (cs1, False, M.insert name n1 mass)
431typeConstraintsForStatement m mass ret (Assignment ident val) = do
432 (cs1, n1) <- typeConstraints m val
433 case M.lookup ident mass of
434 Nothing -> throwError $ "No local variable with name " ++ show ident
436 return (TypeConstraint n1 (TUnknown ty) (AssignmentTargetOrigin ident) : cs1, False, mass)
437typeConstraintsForStatement m mass ret (While val inner) = do
438 (cs1, n1) <- typeConstraints m val
439 (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret inner
440 return $ ((TypeConstraint n1 Boolean (ValueOrigin val)) : cs1 ++ cs2, allCodePathsReturn, mass)
441typeConstraintsForStatement m mass ret (If ifst) = do
442 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
443 return $ (cs, allCodePathsReturn, mass)
444typeConstraintsForStatement m mass ret (For ident start end inner) = do
445 assignVariable ident (m `M.union` mass)
446 (cs1, n1) <- typeConstraints (m `M.union` mass) start
447 (cs2, n2) <- typeConstraints (m `M.union` mass) end
448 let mass1 = M.insert ident n1 mass
449 (cs3, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
450 return $ ((TypeConstraint n1 Number (ValueOrigin start)) : (TypeConstraint n2 Number (ValueOrigin end)) : cs1 ++ cs2 ++ cs3, allCodePathsReturn, mass)
451typeConstraintsForStatement m mass ret (ForEach ident vals inner) = do
452 assignVariable ident (m `M.union` mass)
454 (cs1, n1) <- typeConstraints (m `M.union` mass) vals
455 let mass1 = M.insert ident val mass
456 (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
457 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
458 return $ ((TypeConstraint n1 (Array (TUnknown val)) (ValueOrigin vals)) : cs1 ++ cs2, False, mass)
459typeConstraintsForStatement m mass ret (Return val) = do
460 (cs1, n1) <- typeConstraints (m `M.union` mass) val
461 return ((TypeConstraint n1 (TUnknown ret) (ValueOrigin val)) : cs1, True, mass)
463typeConstraintsForIfStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> IfStatement -> Check ([TypeConstraint], Bool)
464typeConstraintsForIfStatement m mass ret (IfStatement val thens Nothing) = do
465 (cs1, n1) <- typeConstraints m val
466 (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret thens
467 return ((TypeConstraint n1 Boolean (ValueOrigin val)) : cs1 ++ cs2, allCodePathsReturn)
468typeConstraintsForIfStatement m mass ret (IfStatement val thens (Just elses)) = do
469 (cs1, n1) <- typeConstraints m val
470 (cs2, allCodePathsReturn1, _) <- typeConstraintsForBlock m mass ret thens
471 (cs3, allCodePathsReturn2) <- typeConstraintsForElseStatement m mass ret elses
472 return ((TypeConstraint n1 Boolean (ValueOrigin val)) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2)
474typeConstraintsForElseStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> ElseStatement -> Check ([TypeConstraint], Bool)
475typeConstraintsForElseStatement m mass ret (Else elses) = do
476 (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret elses
477 return (cs, allCodePathsReturn)
478typeConstraintsForElseStatement m mass ret (ElseIf ifst) = do
479 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
480 return (cs, allCodePathsReturn)
482typeConstraintsForBlock :: M.Map Ident Int -> M.Map Ident Int -> Int -> [Statement] -> Check ([TypeConstraint], Bool, M.Map Ident Int)
483typeConstraintsForBlock _ mass _ [] = return ([], False, mass)
484typeConstraintsForBlock m mass ret (s:ss) = do
485 (cs1, b1, mass1) <- typeConstraintsForStatement (m `M.union` mass) mass ret s
487 (True, []) -> return (cs1, True, mass1)
488 (True, _) -> throwError "Unreachable code"
490 (cs2, b2, mass2) <- typeConstraintsForBlock m mass1 ret ss
491 return (cs1 ++ cs2, b2, mass2)
493solveTypeConstraints :: [TypeConstraint] -> TypeSolution -> Check TypeSolution
494solveTypeConstraints [] s = return s
495solveTypeConstraints all@(TypeConstraint n t o:cs) s = do
496 (cs', s') <- rethrow (\err -> "Error in " ++ prettyPrintOrigin o ++ ": " ++ err) $ do
498 let s' = let (f, g) = runTypeSolution s
499 in TypeSolution (replaceType n t . f, replaceType n t . g)
500 cs' <- fmap concat $ mapM (substituteTypeInConstraint n t) cs
502 solveTypeConstraints cs' s'
503solveTypeConstraints (RowConstraint n r o:cs) s = do
504 (cs', s') <- rethrow (\err -> "Error in " ++ prettyPrintOrigin o ++ ": " ++ err) $ do
506 let s' = let (f, g) = runTypeSolution s
507 in TypeSolution $ (replaceRow n r . f, replaceRow n r . g)
508 cs' <- fmap concat $ mapM (substituteRowInConstraint n r) cs
510 solveTypeConstraints cs' s'
512substituteTypeInConstraint :: Int -> Type -> TypeConstraint -> Check [TypeConstraint]
513substituteTypeInConstraint n s (TypeConstraint m t v)
514 | n == m = unifyTypes v s t
515 | otherwise = return [TypeConstraint m (replaceType n s t) v]
516substituteTypeInConstraint n s (RowConstraint m r v)
517 = return [RowConstraint m (replaceType n s r) v]
519substituteRowInConstraint :: Int -> Row -> TypeConstraint -> Check [TypeConstraint]
520substituteRowInConstraint n r (TypeConstraint m t v)
521 = return [TypeConstraint m (replaceRow n r t) v]
522substituteRowInConstraint n r (RowConstraint m r1 v)
523 | m == n = unifyRows v r r1
524 | otherwise = return [RowConstraint m (replaceRow n r r1) v]
526unifyTypes :: TypeConstraintOrigin -> Type -> Type -> Check [TypeConstraint]
527unifyTypes _ (TUnknown u1) (TUnknown u2) | u1 == u2 = return []
528unifyTypes o (TUnknown u) t = do
530 return [TypeConstraint u t o]
531unifyTypes o t (TUnknown u) = do
533 return [TypeConstraint u t o]
534unifyTypes o (SaturatedTypeSynonym name1 args1) (SaturatedTypeSynonym name2 args2) | name1 == name2 =
535 fmap concat $ zipWithM (unifyTypes o) args1 args2
536unifyTypes o (SaturatedTypeSynonym name args) ty = do
538 case M.lookup name (typeSynonyms env) of
539 Just (synArgs, body) -> do
540 let m = M.fromList $ zip synArgs args
541 let replaced = replaceTypeVars m body
542 unifyTypes o replaced ty
543 Nothing -> error "Type synonym was not defined"
544unifyTypes o ty s@(SaturatedTypeSynonym _ _) = unifyTypes o s ty
545unifyTypes _ Number Number = return []
546unifyTypes _ String String = return []
547unifyTypes _ Boolean Boolean = return []
548unifyTypes o (Array s) (Array t) = unifyTypes o s t
549unifyTypes o (Object row1) (Object row2) = unifyRows o row1 row2
550unifyTypes o (Function args1 ret1) (Function args2 ret2) = do
551 guardWith "Function applied to incorrect number of args" $ length args1 == length args2
552 cs1 <- fmap concat $ zipWithM (unifyTypes o) args1 args2
553 cs2 <- unifyTypes o ret1 ret2
555unifyTypes _ (TypeVar v1) (TypeVar v2) | v1 == v2 = return []
556unifyTypes _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = return []
557unifyTypes o (TypeApp t1 t2) (TypeApp t3 t4) = do
558 cs1 <- unifyTypes o t1 t3
559 cs2 <- unifyTypes o t2 t4
561unifyTypes _ t1 t2 = throwError $ "Cannot unify " ++ prettyPrintType t1 ++ " with " ++ prettyPrintType t2 ++ "."
563unifyRows :: TypeConstraintOrigin -> Row -> Row -> Check [TypeConstraint]
566 (s1, r1') = toList r1
567 (s2, r2') = toList r2
568 int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
569 sd1 = [ (name, t1) | (name, t1) <- s1, not (elem name (map fst s2)) ]
570 sd2 = [ (name, t2) | (name, t2) <- s2, not (elem name (map fst s1)) ]
572 cs1 <- fmap concat $ mapM (uncurry $ unifyTypes o) int
573 cs2 <- unifyRows' o sd1 r1' sd2 r2'
576 unifyRows' :: TypeConstraintOrigin -> [(String, Type)] -> Row -> [(String, Type)] -> Row -> Check [TypeConstraint]
577 unifyRows' o [] (RUnknown u) sd r = do
579 return [RowConstraint u (fromList (sd, r)) o]
580 unifyRows' o sd r [] (RUnknown u) = do
582 return [RowConstraint u (fromList (sd, r)) o]
583 unifyRows' o ((name, ty):row) r others (RUnknown u) = do
585 cs <- unifyRows' o row r others (RUnknown u')
586 return (RowConstraint u (RCons name ty (RUnknown u')) o : cs)
587 unifyRows' _ [] REmpty [] REmpty = return []
588 unifyRows' _ sd1 r1 sd2 r2 = throwError $ "Cannot unify " ++ prettyPrintRow (fromList (sd1, r1)) ++ " with " ++ prettyPrintRow (fromList (sd2, r2)) ++ "."
589 toList :: Row -> ([(String, Type)], Row)
590 toList (RCons name ty row) = let (tys, rest) = toList row
591 in ((name, ty):tys, rest)
593 fromList :: ([(String, Type)], Row) -> Row
595 fromList ((name, t):ts, r) = RCons name t (fromList (ts, r))
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