@@ -15,8 +15,6 @@
15{-# LANGUAGE DeriveDataTypeable #-}
15{-# LANGUAGE DeriveDataTypeable #-}
17module Language.PureScript.TypeChecker.Types (
17module Language.PureScript.TypeChecker.Types (
@@ -35,56 +33,127 @@ import Language.PureScript.TypeChecker.Monad
35import Language.PureScript.TypeChecker.Kinds
33import Language.PureScript.TypeChecker.Kinds
36import Language.PureScript.TypeChecker.Synonyms
34import Language.PureScript.TypeChecker.Synonyms
37import Language.PureScript.Pretty
35import Language.PureScript.Pretty
36+import Language.PureScript.Unknown
39import Control.Monad.State
38import Control.Monad.State
40import Control.Monad.Error
39import Control.Monad.Error
42import Control.Applicative
41import Control.Applicative
43−import Control.Arrow (Kleisli(..), (***), (&&&), first)
42+import Control.Arrow (Arrow(..), Kleisli(..), (***), (&&&), second)
44import qualified Control.Category as C
43import qualified Control.Category as C
46import qualified Data.Map as M
45import qualified Data.Map as M
48−data TypeConstraintOrigin
47+instance Unifiable Type where
49− = ValueOrigin Value
48+ unknown = TUnknown
50− | BinderOrigin Binder
49+ isUnknown (TUnknown u) = Just u
51− | AssignmentTargetOrigin Ident deriving (Show, D.Data, D.Typeable)
50+ isUnknown _ = Nothing
52−
51+ TUnknown u1 ~~ TUnknown u2 | u1 == u2 = return ()
53−prettyPrintOrigin :: TypeConstraintOrigin -> String
52+ TUnknown u ~~ t = replace u t
54−prettyPrintOrigin (ValueOrigin val) = prettyPrintValue val
53+ t ~~ TUnknown u = replace u t
55−prettyPrintOrigin (BinderOrigin binder) = prettyPrintBinder binder
54+ SaturatedTypeSynonym name1 args1 ~~ SaturatedTypeSynonym name2 args2 | name1 == name2 =
56−prettyPrintOrigin (AssignmentTargetOrigin ident) = show ident
55+ zipWithM_ (~~) args1 args2
57−
56+ SaturatedTypeSynonym name args ~~ ty = do
58−data TypeConstraint
57+ env <- lift getEnv
59− = TypeConstraint Int Type TypeConstraintOrigin
58+ modulePath <- checkModulePath `fmap` lift get
60− | RowConstraint Int Row TypeConstraintOrigin deriving (Show, D.Data, D.Typeable)
59+ case M.lookup (qualify modulePath name) (typeSynonyms env) of
61−
60+ Just (synArgs, body) -> do
62−newtype TypeSolution = TypeSolution { runTypeSolution :: (Int -> Type, Int -> Row) }
61+ let m = M.fromList $ zip synArgs args
63−
62+ let replaced = replaceTypeVars m body
64−emptyTypeSolution :: TypeSolution
63+ replaced ~~ ty
65−emptyTypeSolution = TypeSolution (TUnknown, RUnknown)
64+ Nothing -> error "Type synonym was not defined"
65+ ty ~~ s@(SaturatedTypeSynonym _ _) = s ~~ ty
66+ ForAll idents ty1 ~~ ty2 = do
67+ sk <- skolemize idents ty1
69+ ty ~~ f@(ForAll _ _) = f ~~ ty
70+ Number ~~ Number = return ()
71+ String ~~ String = return ()
72+ Boolean ~~ Boolean = return ()
73+ Array s ~~ Array t = s ~~ t
74+ Object row1 ~~ Object row2 = row1 ~~ row2
75+ Function args1 ret1 ~~ Function args2 ret2 = do
76+ guardWith "Function applied to incorrect number of args" $ length args1 == length args2
77+ zipWithM_ (~~) args1 args2
79+ TypeVar v1 ~~ TypeVar v2 | v1 == v2 = return ()
80+ TypeConstructor c1 ~~ TypeConstructor c2 = do
81+ modulePath <- checkModulePath `fmap` lift get
82+ guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (qualify modulePath c1 == qualify modulePath c2)
83+ TypeApp t1 t2 ~~ TypeApp t3 t4 = do
86+ Skolem s1 ~~ Skolem s2 | s1 == s2 = return ()
87+ t1 ~~ t2 = throwError $ "Cannot unify " ++ prettyPrintType t1 ++ " with " ++ prettyPrintType t2 ++ "."
88+ apply s (TUnknown u) = runSubstitution s u
89+ apply s (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name $ map (apply s) tys
90+ apply s (ForAll idents ty) = ForAll idents $ apply s ty
91+ apply s (Array t) = Array (apply s t)
92+ apply s (Object r) = Object (apply s r)
93+ apply s (Function args ret) = Function (map (apply s) args) (apply s ret)
94+ apply s (TypeApp t1 t2) = TypeApp (apply s t1) (apply s t2)
96+ unknowns (TUnknown (Unknown u)) = [u]
97+ unknowns (SaturatedTypeSynonym _ tys) = concatMap unknowns tys
98+ unknowns (ForAll idents ty) = unknowns ty
99+ unknowns (Array t) = unknowns t
100+ unknowns (Object r) = unknowns r
101+ unknowns (Function args ret) = concatMap unknowns args ++ unknowns ret
102+ unknowns (TypeApp t1 t2) = unknowns t1 ++ unknowns t2
105+instance Unifiable Row where
107+ isUnknown (RUnknown u) = Just u
108+ isUnknown _ = Nothing
111+ (s1, r1') = rowToList r1
112+ (s2, r2') = rowToList r2
113+ int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
114+ sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
115+ sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
117+ forM_ int (uncurry (~~))
118+ unifyRows sd1 r1' sd2 r2'
120+ unifyRows :: [(String, Type)] -> Row -> [(String, Type)] -> Row -> Subst Check ()
121+ unifyRows [] (RUnknown u) sd r = replace u (rowFromList (sd, r))
122+ unifyRows sd r [] (RUnknown u) = replace u (rowFromList (sd, r))
123+ unifyRows ns@((name, ty):row) r others u@(RUnknown un) = do
125+ forM row $ \(_, ty) -> occursCheck un ty
127+ u ~~ RCons name ty u'
128+ unifyRows row r others u'
129+ unifyRows [] REmpty [] REmpty = return ()
130+ unifyRows [] (RowVar v1) [] (RowVar v2) | v1 == v2 = return ()
131+ unifyRows sd1 r1 sd2 r2 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd1, r1)) ++ " with " ++ prettyPrintRow (rowFromList (sd2, r2)) ++ "."
132+ apply s (RUnknown u) = runSubstitution s u
133+ apply s (RCons name ty r) = RCons name (apply s ty) (apply s r)
135+ unknowns (RUnknown (Unknown u)) = [u]
136+ unknowns (RCons _ ty r) = unknowns ty ++ unknowns r
67isFunction :: Value -> Bool
139isFunction :: Value -> Bool
68isFunction (Abs _ _) = True
140isFunction (Abs _ _) = True
69isFunction (TypedValue untyped _) = isFunction untyped
141isFunction (TypedValue untyped _) = isFunction untyped
70isFunction _ = False
142isFunction _ = False
72−allConstraints :: Ident -> Value -> Check ([TypeConstraint], Int)
73−allConstraints name val | isFunction val = do
75− (cs, n) <- typeConstraints (M.singleton name me) val
76− return (TypeConstraint me (TUnknown n) (ValueOrigin val): cs, n)
77−allConstraints _ val = typeConstraints M.empty val
79−typeOf :: Ident -> Value -> Check Type
144+typeOf :: Maybe Ident -> Value -> Check Type
80typeOf name val = do
145typeOf name val = do
81− (cs, n) <- allConstraints name val
146+ ty <- runSubst $ case name of
147+ Just ident -> do me <- fresh
148+ ty <- infer (M.singleton ident me) val
151+ Nothing -> infer M.empty val
82− desugared <- replaceAllTypeSynonyms cs
152+ --desugared <- replaceAllTypeSynonyms cs
83− solution <- solveTypeConstraints desugared emptyTypeSolution
84− let ty = fst (runTypeSolution solution) n
85− allUnknownsBecameQuantified desugared solution ty
153+ --TODO: allUnknownsBecameQuantified desugared solution ty
86 return $ varIfUnknown $ desaturateAllTypeSynonyms $ setifyAll ty
154 return $ varIfUnknown $ desaturateAllTypeSynonyms $ setifyAll ty
88allUnknownsBecameQuantified :: [TypeConstraint] -> TypeSolution -> Type -> Check ()
157allUnknownsBecameQuantified :: [TypeConstraint] -> TypeSolution -> Type -> Check ()
89allUnknownsBecameQuantified cs solution ty = do
158allUnknownsBecameQuantified cs solution ty = do
@@ -102,19 +171,27 @@ allUnknownsBecameQuantified cs solution ty = do
102 unsolvedRows = filter (\n -> RUnknown n == snd (runTypeSolution solution) n) unknownRows
171 unsolvedRows = filter (\n -> RUnknown n == snd (runTypeSolution solution) n) unknownRows
103 guardWith "Unsolved row variable" $ null $ unsolvedRows \\ rowsMentioned
172 guardWith "Unsolved row variable" $ null $ unsolvedRows \\ rowsMentioned
174+findUnknownTypes :: (D.Data d) => d -> [Unknown Type]
175+findUnknownTypes = everything (++) (mkQ [] f)
177+ f :: Type -> [Unknown Type]
178+ f (TUnknown n) = [n]
181+findUnknownRows :: (D.Data d) => d -> [Unknown Row]
182+findUnknownRows = everything (++) (mkQ [] f)
184+ f :: Row -> [Unknown Row]
185+ f (RUnknown n) = [n]
105setify :: Row -> Row
189setify :: Row -> Row
106setify = rowFromList . first (M.toList . M.fromList) . rowToList
190setify = rowFromList . first (M.toList . M.fromList) . rowToList
108setifyAll :: (D.Data d) => d -> d
192setifyAll :: (D.Data d) => d -> d
109setifyAll = everywhere (mkT setify)
193setifyAll = everywhere (mkT setify)
111−findUnknownTypes :: (D.Data d) => d -> [Int]
112−findUnknownTypes = everything (++) (mkQ [] f)
115− f (TUnknown n) = [n]
118findTypeVars :: (D.Data d) => d -> [String]
195findTypeVars :: (D.Data d) => d -> [String]
119findTypeVars = everything (++) (mkQ [] f)
196findTypeVars = everything (++) (mkQ [] f)
@@ -122,13 +199,6 @@ findTypeVars = everything (++) (mkQ [] f)
122 f (TypeVar v) = [v]
199 f (TypeVar v) = [v]
125−findUnknownRows :: (D.Data d) => d -> [Int]
126−findUnknownRows = everything (++) (mkQ [] f)
129− f (RUnknown n) = [n]
132varIfUnknown :: Type -> Type
202varIfUnknown :: Type -> Type
133varIfUnknown ty =
203varIfUnknown ty =
@@ -137,7 +207,7 @@ varIfUnknown ty =
137 ForAll (sort $ nub $ M.elems m ++ findTypeVars ty) ty'
207 ForAll (sort $ nub $ M.elems m ++ findTypeVars ty) ty'
139 f :: Type -> State (M.Map Int String) Type
209 f :: Type -> State (M.Map Int String) Type
140− f (TUnknown n) = do
210+ f (TUnknown (Unknown n)) = do
142 case M.lookup n m of
212 case M.lookup n m of
143 Nothing -> do
213 Nothing -> do
@@ -147,7 +217,7 @@ varIfUnknown ty =
147 Just name -> return $ TypeVar name
217 Just name -> return $ TypeVar name
148 f t = return t
218 f t = return t
149 g :: Row -> State (M.Map Int String) Row
219 g :: Row -> State (M.Map Int String) Row
150− g (RUnknown n) = do
220+ g (RUnknown (Unknown n)) = do
152 case M.lookup n m of
222 case M.lookup n m of
153 Nothing -> do
223 Nothing -> do
@@ -165,28 +235,28 @@ replaceTypeVars m = everywhere (mkT replace)
165 _ -> TypeVar v
235 _ -> TypeVar v
166 replace t = t
236 replace t = t
168−replaceVarsWithUnknowns :: [String] -> Type -> Check Type
238+replaceVarsWithUnknowns :: [String] -> Type -> Subst Check Type
169replaceVarsWithUnknowns idents = flip evalStateT M.empty . everywhereM (flip extM f $ mkM g)
239replaceVarsWithUnknowns idents = flip evalStateT M.empty . everywhereM (flip extM f $ mkM g)
171− f :: Type -> StateT (M.Map String Int) Check Type
241+ f :: Type -> StateT (M.Map String Int) (Subst Check) Type
172 f (TypeVar var) | var `elem` idents = do
242 f (TypeVar var) | var `elem` idents = do
174− n <- lift fresh
244+ n <- lift fresh'
175 case M.lookup var m of
245 case M.lookup var m of
176 Nothing -> do
246 Nothing -> do
177 put (M.insert var n m)
247 put (M.insert var n m)
178− return $ TUnknown n
248+ return $ TUnknown (Unknown n)
179− Just u -> return $ TUnknown u
249+ Just u -> return $ TUnknown (Unknown u)
180 f t = return t
250 f t = return t
181− g :: Row -> StateT (M.Map String Int) Check Row
251+ g :: Row -> StateT (M.Map String Int) (Subst Check) Row
182 g (RowVar var) | var `elem` idents = do
252 g (RowVar var) | var `elem` idents = do
184− n <- lift fresh
254+ n <- lift fresh'
185 case M.lookup var m of
255 case M.lookup var m of
186 Nothing -> do
256 Nothing -> do
187 put (M.insert var n m)
257 put (M.insert var n m)
188− return $ RUnknown n
258+ return $ RUnknown (Unknown n)
189− Just u -> return $ RUnknown u
259+ Just u -> return $ RUnknown (Unknown u)
190 g r = return r
260 g r = return r
192replaceAllTypeSynonyms :: (D.Data d) => d -> Check d
262replaceAllTypeSynonyms :: (D.Data d) => d -> Check d
@@ -201,443 +271,352 @@ desaturateAllTypeSynonyms = everywhere (mkT replace)
201 replace (SaturatedTypeSynonym name args) = foldl TypeApp (TypeConstructor name) args
271 replace (SaturatedTypeSynonym name args) = foldl TypeApp (TypeConstructor name) args
202 replace t = t
272 replace t = t
204−replaceType :: (D.Data d) => Int -> Type -> d -> d
205−replaceType n t = everywhere (mkT go)
207− go (TUnknown m) | m == n = t
210−replaceRow :: (D.Data d) => Int -> Row -> d -> d
211−replaceRow n r = everywhere (mkT go)
213− go (RUnknown m) | m == n = r
216−typeOccursCheck :: Int -> Type -> Check ()
217−typeOccursCheck u (TUnknown _) = return ()
218−typeOccursCheck u t = when (occursCheck u t) $ throwError $ "Occurs check failed: " ++ show u ++ " = " ++ prettyPrintType t
220−rowOccursCheck :: Int -> Row -> Check ()
221−rowOccursCheck u (RUnknown _) = return ()
222−rowOccursCheck u r = when (occursCheck u r) $ throwError $ "Occurs check failed: " ++ show u ++ " = " ++ prettyPrintRow r
224−occursCheck :: (D.Data d) => Int -> d -> Bool
225−occursCheck u = everything (||) $ flip extQ g $ mkQ False f
227− f (TUnknown u') | u' == u = True
229− g (RUnknown u') | u' == u = True
232ensureNoDuplicateProperties :: [(String, Value)] -> Check ()
274ensureNoDuplicateProperties :: [(String, Value)] -> Check ()
233ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
275ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
235−typeConstraints :: M.Map Ident Int -> Value -> Check ([TypeConstraint], Int)
277+infer :: M.Map Ident Type -> Value -> Subst Check Type
236−typeConstraints _ v@(NumericLiteral _) = do
278+infer _ (NumericLiteral _) = return Number
238− return ([TypeConstraint me Number (ValueOrigin v)], me)
239−typeConstraints _ v@(StringLiteral _) = do
279+infer _ (StringLiteral _) = return String
241− return ([TypeConstraint me String (ValueOrigin v)], me)
242−typeConstraints _ v@(BooleanLiteral _) = do
280+infer _ (BooleanLiteral _) = return Boolean
244− return ([TypeConstraint me Boolean (ValueOrigin v)], me)
245−typeConstraints m v@(ArrayLiteral vals) = do
281+infer m (ArrayLiteral vals) = do
246− all <- mapM (typeConstraints m) vals
282+ ts <- mapM (infer m) vals
247− let (cs, ns) = (concatMap fst &&& map snd) all
248− me <- fresh
283+ arr <- fresh
249− return (cs ++ zipWith (\n el -> TypeConstraint me (Array $ TUnknown n) (ValueOrigin el)) ns vals, me)
284+ forM_ ts $ \t -> arr ~~ Array t
250−typeConstraints m u@(Unary op val) = do
286+infer m (Unary op val) = do
251− (cs, n1) <- typeConstraints m val
287+ t <- infer m val
252− me <- fresh
288+ inferUnary op t
253− return (cs ++ unaryOperatorConstraints u op n1 me, me)
254−typeConstraints m b@(Binary op left right) = do
289+infer m (Binary op left right) = do
255− (cs1, n1) <- typeConstraints m left
290+ t1 <- infer m left
256− (cs2, n2) <- typeConstraints m right
291+ t2 <- infer m right
257− me <- fresh
292+ inferBinary op t1 t2
258− return (cs1 ++ cs2 ++ binaryOperatorConstraints b op n1 n2 me, me)
259−typeConstraints m v@(ObjectLiteral ps) = do
293+infer m (ObjectLiteral ps) = do
260− ensureNoDuplicateProperties ps
294+ lift $ ensureNoDuplicateProperties ps
261− all <- mapM (typeConstraints m . snd) ps
295+ ts <- mapM (infer m . snd) ps
262− let (cs, ns) = (concatMap fst &&& map snd) all
264− let tys = zipWith (\(name, _) u -> (name, TUnknown u)) ps ns
296+ let fields = zipWith (\(name, _) t -> (name, t)) ps ts
265− return (TypeConstraint me (Object (typesToRow tys)) (ValueOrigin v) : cs, me)
297+ return $ Object $ typesToRow fields
266−typeConstraints m v@(ObjectUpdate o ps) = do
298+infer m (ObjectUpdate o ps) = do
267− ensureNoDuplicateProperties ps
299+ lift $ ensureNoDuplicateProperties ps
268− (cs1, n1) <- typeConstraints m o
300+ obj <- infer m o
269− all <- mapM (typeConstraints m . snd) ps
270− let (cs2, ns) = (concatMap fst &&& map snd) all
271 row <- fresh
301 row <- fresh
302+ ts <- mapM (infer m . snd) ps
272− let tys = zipWith (\(name, _) u -> (name, TUnknown u)) ps ns
303+ let tys = zipWith (\(name, _) t -> (name, t)) ps ts
273− return (TypeConstraint n1 (Object (rowFromList (tys, RUnknown row))) (ValueOrigin v) : cs1 ++ cs2, n1)
304+ obj ~~ Object (rowFromList (tys, row))
274−typeConstraints m v@(Indexer index val) = do
306+infer m (Indexer index val) = do
275− (cs1, n1) <- typeConstraints m index
307+ el <- fresh
276− (cs2, n2) <- typeConstraints m val
308+ t1 <- infer m index
277− me <- fresh
309+ t2 <- infer m val
278− return (TypeConstraint n1 Number (ValueOrigin index) : TypeConstraint n2 (Array (TUnknown me)) (ValueOrigin v) : cs1 ++ cs2, me)
310+ t1 ~~ Number
279−typeConstraints m v@(Accessor prop val) = do
313+infer m (Accessor prop val) = do
280− (cs, n1) <- typeConstraints m val
314+ obj <- infer m val
281− me <- fresh
315+ field <- fresh
282 rest <- fresh
316 rest <- fresh
283− return (TypeConstraint n1 (Object (RCons prop (TUnknown me) (RUnknown rest))) (ValueOrigin v) : cs, me)
317+ obj ~~ Object (RCons prop field rest)
284−typeConstraints m v@(Abs args ret) = do
319+infer m v@(Abs args ret) = do
285− ns <- replicateM (length args) fresh
320+ ts <- replicateM (length args) fresh
286− let m' = m `M.union` M.fromList (zip args ns)
321+ let m' = m `M.union` M.fromList (zip args ts)
287− (cs, n') <- typeConstraints m' ret
322+ body <- infer m' ret
323+ return $ Function ts body
324+infer m v@(App f xs) = do
326+ ts <- mapM (infer m) xs
288 me <- fresh
327 me <- fresh
289− return (TypeConstraint me (Function (map TUnknown ns) (TUnknown n')) (ValueOrigin v) : cs, me)
328+ t1 ~~ Function ts me
290−typeConstraints m v@(App f xs) = do
329+ return me
291− (cs1, n1) <- typeConstraints m f
292− all <- mapM (typeConstraints m) xs
293− let (cs2, ns) = (concatMap fst &&& map snd) all
295− return (TypeConstraint n1 (Function (map TUnknown ns) (TUnknown me)) (ValueOrigin v) : cs1 ++ cs2, me)
296−typeConstraints m v@(Var var@(Qualified mp name)) = do
330+infer m v@(Var var@(Qualified mp name)) = do
297 case mp of
331 case mp of
298 ModulePath [] ->
332 ModulePath [] ->
299 case M.lookup name m of
333 case M.lookup name m of
300− Just u -> do
334+ Just ty -> lift $ replaceAllTypeSynonyms ty
302− return ([TypeConstraint u (TUnknown me) (ValueOrigin v)], me)
303 Nothing -> lookupGlobal
335 Nothing -> lookupGlobal
304 _ -> lookupGlobal
336 _ -> lookupGlobal
306 lookupGlobal = do
338 lookupGlobal = do
307− env <- getEnv
339+ env <- lift getEnv
308− modulePath <- checkModulePath `fmap` get
340+ modulePath <- checkModulePath `fmap` lift get
309 case M.lookup (qualify modulePath var) (names env) of
341 case M.lookup (qualify modulePath var) (names env) of
310 Nothing -> throwError $ show var ++ " is undefined"
342 Nothing -> throwError $ show var ++ " is undefined"
311− Just (ForAll idents ty, _) -> do
343+ Just (ty, _) -> lift $ replaceAllTypeSynonyms ty
313− replaced <- replaceVarsWithUnknowns idents ty
314− return ([TypeConstraint me replaced (ValueOrigin v)], me)
315−typeConstraints m (Block ss) = do
344+infer m (Block ss) = do
316 ret <- fresh
345 ret <- fresh
317− (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m M.empty ret ss
346+ (allCodePathsReturn, _) <- checkBlock m M.empty ret ss
318 guardWith "Block is missing a return statement" allCodePathsReturn
347 guardWith "Block is missing a return statement" allCodePathsReturn
319− return (cs, ret)
348+ return ret
320−typeConstraints m v@(Constructor c) = do
349+infer m v@(Constructor c) = do
321− env <- getEnv
350+ env <- lift getEnv
322− modulePath <- checkModulePath `fmap` get
351+ modulePath <- checkModulePath `fmap` lift get
323 case M.lookup (qualify modulePath c) (dataConstructors env) of
352 case M.lookup (qualify modulePath c) (dataConstructors env) of
324 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
353 Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
325− Just (ForAll idents ty) -> do
327− replaced <- replaceVarsWithUnknowns idents ty
354+ Just (ForAll idents ty) -> replaceVarsWithUnknowns idents ty
328− return ([TypeConstraint me replaced (ValueOrigin v)], me)
329−typeConstraints m (Case val binders) = do
355+infer m (Case val binders) = do
330− (cs1, n1) <- typeConstraints m val
356+ t1 <- infer m val
331 ret <- fresh
357 ret <- fresh
332− cs2 <- typeConstraintsForBinders m n1 ret binders
358+ cs2 <- checkBinders m t1 ret binders
333− return (cs1 ++ cs2, ret)
359+ return ret
334−typeConstraints m v@(IfThenElse cond th el) = do
360+infer m v@(IfThenElse cond th el) = do
335− (cs1, n1) <- typeConstraints m cond
361+ t1 <- infer m cond
336− (cs2, n2) <- typeConstraints m th
362+ t2 <- infer m th
337− (cs3, n3) <- typeConstraints m el
363+ t3 <- infer m el
338− return (TypeConstraint n1 Boolean (ValueOrigin cond) : TypeConstraint n2 (TUnknown n3) (ValueOrigin v) : cs1 ++ cs2 ++ cs3, n2)
364+ t1 ~~ Boolean
339−typeConstraints m v@(TypedValue val ty) = do
367+infer m v@(TypedValue val ty) = do
340− kind <- kindOf ty
368+ kind <- lift $ kindOf ty
341 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
369 guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
370+ ty' <- lift $ replaceAllTypeSynonyms ty
342− typeCheck m val ty
371+ cs <- check m val ty'
343− me <- fresh
372+ return ty'
344− return ([TypeConstraint me ty (ValueOrigin v)], me)
373+
345−
374+inferUnary :: UnaryOperator -> Type -> Subst Check Type
346−typeCheck :: M.Map Ident Int -> Value -> Type -> Check ()
375+inferUnary Negate val = do
347−typeCheck _ _ _ = return ()
376+ val ~~ Number
349−unaryOperatorConstraints :: Value -> UnaryOperator -> Int -> Int -> [TypeConstraint]
378+inferUnary Not val = do
350−unaryOperatorConstraints v Negate val result = [TypeConstraint val Number (ValueOrigin v), TypeConstraint result Number (ValueOrigin v)]
379+ val ~~ Boolean
351−unaryOperatorConstraints v Not val result = [TypeConstraint val Boolean (ValueOrigin v), TypeConstraint result Boolean (ValueOrigin v)]
380+ return Boolean
352−unaryOperatorConstraints v BitwiseNot val result = [TypeConstraint val Number (ValueOrigin v), TypeConstraint result Number (ValueOrigin v)]
381+inferUnary BitwiseNot val = do
354−binaryOperatorConstraints :: Value -> BinaryOperator -> Int -> Int -> Int -> [TypeConstraint]
383+ return Number
355−binaryOperatorConstraints v Add = symBinOpConstraints v Number
384+
356−binaryOperatorConstraints v Subtract = symBinOpConstraints v Number
385+inferBinary :: BinaryOperator -> Type -> Type -> Subst Check Type
357−binaryOperatorConstraints v Multiply = symBinOpConstraints v Number
386+inferBinary Add = inferSymBinary Number
358−binaryOperatorConstraints v Divide = symBinOpConstraints v Number
387+inferBinary Subtract = inferSymBinary Number
359−binaryOperatorConstraints v Modulus = symBinOpConstraints v Number
388+inferBinary Multiply = inferSymBinary Number
360−binaryOperatorConstraints v LessThan = asymBinOpConstraints v Number Boolean
389+inferBinary Divide = inferSymBinary Number
390+inferBinary Modulus = inferSymBinary Number
391+inferBinary LessThan = inferAsymBinary Number Boolean
361−binaryOperatorConstraints v LessThanOrEqualTo = asymBinOpConstraints v Number Boolean
392+inferBinary LessThanOrEqualTo = inferAsymBinary Number Boolean
362−binaryOperatorConstraints v GreaterThan = asymBinOpConstraints v Number Boolean
393+inferBinary GreaterThan = inferAsymBinary Number Boolean
363−binaryOperatorConstraints v GreaterThanOrEqualTo = asymBinOpConstraints v Number Boolean
394+inferBinary GreaterThanOrEqualTo = inferAsymBinary Number Boolean
364−binaryOperatorConstraints v BitwiseAnd = symBinOpConstraints v Number
395+inferBinary BitwiseAnd = inferSymBinary Number
365−binaryOperatorConstraints v BitwiseOr = symBinOpConstraints v Number
396+inferBinary BitwiseOr = inferSymBinary Number
366−binaryOperatorConstraints v BitwiseXor = symBinOpConstraints v Number
397+inferBinary BitwiseXor = inferSymBinary Number
367−binaryOperatorConstraints v ShiftLeft = symBinOpConstraints v Number
398+inferBinary ShiftLeft = inferSymBinary Number
368−binaryOperatorConstraints v ShiftRight = symBinOpConstraints v Number
399+inferBinary ShiftRight = inferSymBinary Number
369−binaryOperatorConstraints v ZeroFillShiftRight = symBinOpConstraints v Number
400+inferBinary ZeroFillShiftRight = inferSymBinary Number
370−binaryOperatorConstraints v EqualTo = equalityBinOpConstraints v
401+inferBinary EqualTo = inferEqBinary
371−binaryOperatorConstraints v NotEqualTo = equalityBinOpConstraints v
402+inferBinary NotEqualTo = inferEqBinary
372−binaryOperatorConstraints v And = symBinOpConstraints v Boolean
403+inferBinary And = inferSymBinary Boolean
373−binaryOperatorConstraints v Or = symBinOpConstraints v Boolean
404+inferBinary Or = inferSymBinary Boolean
374−binaryOperatorConstraints v Concat = symBinOpConstraints v String
405+inferBinary Concat = inferSymBinary String
376−equalityBinOpConstraints :: Value -> Int -> Int -> Int -> [TypeConstraint]
407+inferEqBinary :: Type -> Type -> Subst Check Type
377−equalityBinOpConstraints v left right result = [TypeConstraint left (TUnknown right) (ValueOrigin v), TypeConstraint result Boolean (ValueOrigin v)]
408+inferEqBinary left right = do
379−symBinOpConstraints :: Value -> Type -> Int -> Int -> Int -> [TypeConstraint]
410+ return Boolean
380−symBinOpConstraints v ty = asymBinOpConstraints v ty ty
411+
381−
412+inferSymBinary :: Type -> Type -> Type -> Subst Check Type
382−asymBinOpConstraints :: Value -> Type -> Type -> Int -> Int -> Int -> [TypeConstraint]
413+inferSymBinary ty = inferAsymBinary ty ty
383−asymBinOpConstraints v ty res left right result = [TypeConstraint left ty (ValueOrigin v), TypeConstraint right ty (ValueOrigin v), TypeConstraint result res (ValueOrigin v)]
414+
384−
415+inferAsymBinary :: Type -> Type -> Type -> Type -> Subst Check Type
385−typeConstraintsForBinder :: Int -> Binder -> Check ([TypeConstraint], M.Map Ident Int)
416+inferAsymBinary input output left right = do
421+inferBinder :: Type -> Binder -> Subst Check (M.Map Ident Type)
386−typeConstraintsForBinder _ NullBinder = return ([], M.empty)
422+inferBinder _ NullBinder = return M.empty
387−typeConstraintsForBinder val b@(StringBinder _) = constantBinder b val String
423+inferBinder val (StringBinder _) = val ~~ String >> return M.empty
388−typeConstraintsForBinder val b@(NumberBinder _) = constantBinder b val Number
424+inferBinder val (NumberBinder _) = val ~~ Number >> return M.empty
389−typeConstraintsForBinder val b@(BooleanBinder _) = constantBinder b val Boolean
425+inferBinder val (BooleanBinder _) = val ~~ Boolean >> return M.empty
390−typeConstraintsForBinder val b@(VarBinder name) = do
426+inferBinder val (VarBinder name) = return $ M.singleton name val
392− return ([TypeConstraint me (TUnknown val) (BinderOrigin b)], M.singleton name me)
393−typeConstraintsForBinder val b@(NullaryBinder ctor) = do
427+inferBinder val (NullaryBinder ctor) = do
394− env <- getEnv
428+ env <- lift getEnv
395− modulePath <- checkModulePath `fmap` get
429+ modulePath <- checkModulePath `fmap` lift get
396 case M.lookup (qualify modulePath ctor) (dataConstructors env) of
430 case M.lookup (qualify modulePath ctor) (dataConstructors env) of
397 Just (ForAll args ret) -> do
431 Just (ForAll args ret) -> do
398 ret' <- replaceVarsWithUnknowns args ret
432 ret' <- replaceVarsWithUnknowns args ret
399− return ([TypeConstraint val ret' (BinderOrigin b)], M.empty)
433+ val ~~ ret'
400 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
435 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
401−typeConstraintsForBinder val b@(UnaryBinder ctor binder) = do
436+inferBinder val b@(UnaryBinder ctor binder) = do
402− env <- getEnv
437+ env <- lift getEnv
403− modulePath <- checkModulePath `fmap` get
438+ modulePath <- checkModulePath `fmap` lift get
404 case M.lookup (qualify modulePath ctor) (dataConstructors env) of
439 case M.lookup (qualify modulePath ctor) (dataConstructors env) of
405 Just (ForAll idents f@(Function [_] _)) -> do
440 Just (ForAll idents f@(Function [_] _)) -> do
406 obj <- fresh
441 obj <- fresh
407 (Function [ty] ret) <- replaceVarsWithUnknowns idents f
442 (Function [ty] ret) <- replaceVarsWithUnknowns idents f
408− (cs, m1) <- typeConstraintsForBinder obj binder
443+ m1 <- inferBinder obj binder
409− return (TypeConstraint val ret (BinderOrigin b) : TypeConstraint obj ty (BinderOrigin b) : cs, m1)
444+ val ~~ ret
410 Just _ -> throwError $ show ctor ++ " is not a unary constructor"
447 Just _ -> throwError $ show ctor ++ " is not a unary constructor"
411 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
448 _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
412−typeConstraintsForBinder val b@(ObjectBinder props) = do
449+inferBinder val b@(ObjectBinder props) = do
413 row <- fresh
450 row <- fresh
414 rest <- fresh
451 rest <- fresh
415− (cs, m1) <- typeConstraintsForProperties row (RUnknown rest) props
452+ m1 <- inferRowProperties row rest props
416− return (TypeConstraint val (Object (RUnknown row)) (BinderOrigin b) : cs, m1)
453+ val ~~ Object row
418− typeConstraintsForProperties :: Int -> Row -> [(String, Binder)] -> Check ([TypeConstraint], M.Map Ident Int)
456+ inferRowProperties :: Row -> Row -> [(String, Binder)] -> Subst Check (M.Map Ident Type)
419− typeConstraintsForProperties nrow row [] = return ([RowConstraint nrow row (BinderOrigin b)], M.empty)
457+ inferRowProperties nrow row [] = nrow ~~ row >> return M.empty
420− typeConstraintsForProperties nrow row ((name, binder):binders) = do
458+ inferRowProperties nrow row ((name, binder):binders) = do
421 propTy <- fresh
459 propTy <- fresh
422− (cs1, m1) <- typeConstraintsForBinder propTy binder
460+ m1 <- inferBinder propTy binder
423− (cs2, m2) <- typeConstraintsForProperties nrow (RCons name (TUnknown propTy) row) binders
461+ m2 <- inferRowProperties nrow (RCons name propTy row) binders
424− return (cs1 ++ cs2, m1 `M.union` m2)
462+ return $ m1 `M.union` m2
425−typeConstraintsForBinder val b@(ArrayBinder binders rest) = do
463+inferBinder val (ArrayBinder binders rest) = do
426 el <- fresh
464 el <- fresh
427− all <- mapM (typeConstraintsForBinder el) binders
465+ m1 <- M.unions <$> mapM (inferBinder el) binders
428− let (cs1, m1) = (concatMap fst &&& M.unions . map snd) all
466+ val ~~ Array el
429− let arrayConstraint = TypeConstraint val (Array (TUnknown el)) (BinderOrigin b)
430 case rest of
467 case rest of
431− Nothing -> return (arrayConstraint : cs1, m1)
468+ Nothing -> return m1
432 Just binder -> do
469 Just binder -> do
433− (cs2, m2) <- typeConstraintsForBinder val binder
470+ m2 <- inferBinder val binder
434− return (arrayConstraint : cs1 ++ cs2, m1 `M.union` m2)
471+ return $ m1 `M.union` m2
435−typeConstraintsForBinder val b@(NamedBinder name binder) = do
472+inferBinder val (NamedBinder name binder) = do
436− me <- fresh
473+ m <- inferBinder val binder
437− (cs, m) <- typeConstraintsForBinder val binder
438− return (TypeConstraint me (TUnknown val) (BinderOrigin b) : cs, M.insert name me m)
474+ return $ M.insert name val m
440−typeConstraintsForGuardedBinder :: M.Map Ident Int -> Int -> Binder -> Check ([TypeConstraint], M.Map Ident Int)
476+inferGuardedBinder :: M.Map Ident Type -> Type -> Binder -> Subst Check (M.Map Ident Type)
441−typeConstraintsForGuardedBinder m val b@(GuardedBinder cond binder) = do
477+inferGuardedBinder m val b@(GuardedBinder cond binder) = do
442− (cs1, m1) <- typeConstraintsForBinder val binder
478+ m1 <- inferBinder val binder
443− (cs2, n) <- typeConstraints (m `M.union` m1) cond
479+ ty <- infer (m `M.union` m1) cond
444− return (TypeConstraint n Boolean (ValueOrigin cond) : cs1 ++ cs2, m1)
480+ ty ~~ Boolean
445−typeConstraintsForGuardedBinder m val b = typeConstraintsForBinder val b >>= return
481+ return m1
446−
482+inferGuardedBinder m val b = inferBinder val b >>= return
447−constantBinder :: Binder -> Int -> Type -> Check ([TypeConstraint], M.Map Ident Int)
483+
448−constantBinder b val ty = return ([TypeConstraint val ty (BinderOrigin b)], M.empty)
484+checkBinders :: M.Map Ident Type -> Type -> Type -> [(Binder, Value)] -> Subst Check ()
449−
485+checkBinders _ _ _ [] = return ()
450−typeConstraintsForBinders :: M.Map Ident Int -> Int -> Int -> [(Binder, Value)] -> Check [TypeConstraint]
451−typeConstraintsForBinders _ _ _ [] = return []
452−typeConstraintsForBinders m nval ret ((binder, val):bs) = do
486+checkBinders m nval ret ((binder, val):bs) = do
453− (cs1, m1) <- typeConstraintsForGuardedBinder m nval binder
487+ m1 <- inferGuardedBinder m nval binder
454− (cs2, n2) <- typeConstraints (m `M.union` m1) val
488+ t <- infer (m `M.union` m1) val
455− cs3 <- typeConstraintsForBinders m nval ret bs
489+ t ~~ ret
456− return (TypeConstraint n2 (TUnknown ret) (BinderOrigin binder) : cs1 ++ cs2 ++ cs3)
490+ checkBinders m nval ret bs
458−assignVariable :: Ident -> M.Map Ident Int -> Check ()
492+assignVariable :: Ident -> M.Map Ident Type -> Subst Check ()
459assignVariable name m =
493assignVariable name m =
460 case M.lookup name m of
494 case M.lookup name m of
461 Nothing -> return ()
495 Nothing -> return ()
462 Just _ -> throwError $ "Variable with name " ++ show name ++ " already exists."
496 Just _ -> throwError $ "Variable with name " ++ show name ++ " already exists."
464−typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
498+checkStatement :: M.Map Ident Type -> M.Map Ident Type -> Type -> Statement -> Subst Check (Bool, M.Map Ident Type)
465−typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
499+checkStatement m mass ret (VariableIntroduction name val) = do
466 assignVariable name (m `M.union` mass)
500 assignVariable name (m `M.union` mass)
467− (cs1, n1) <- typeConstraints m val
501+ t <- infer m val
468− return (cs1, False, M.insert name n1 mass)
502+ return (False, M.insert name t mass)
469−typeConstraintsForStatement m mass ret (Assignment ident val) = do
503+checkStatement m mass ret (Assignment ident val) = do
470− (cs1, n1) <- typeConstraints m val
504+ t <- infer m val
471 case M.lookup ident mass of
505 case M.lookup ident mass of
472 Nothing -> throwError $ "No local variable with name " ++ show ident
506 Nothing -> throwError $ "No local variable with name " ++ show ident
473− Just ty ->
507+ Just ty -> do t ~~ ty
474− return (TypeConstraint n1 (TUnknown ty) (AssignmentTargetOrigin ident) : cs1, False, mass)
508+ return (False, mass)
475−typeConstraintsForStatement m mass ret (While val inner) = do
509+checkStatement m mass ret (While val inner) = do
476− (cs1, n1) <- typeConstraints m val
510+ t1 <- infer m val
477− (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret inner
512+ (allCodePathsReturn, _) <- checkBlock m mass ret inner
478− return (TypeConstraint n1 Boolean (ValueOrigin val) : cs1 ++ cs2, allCodePathsReturn, mass)
513+ return (allCodePathsReturn, mass)
479−typeConstraintsForStatement m mass ret (If ifst) = do
514+checkStatement m mass ret (If ifst) = do
480− (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
515+ allCodePathsReturn <- checkIfStatement m mass ret ifst
481− return (cs, allCodePathsReturn, mass)
516+ return (allCodePathsReturn, mass)
482−typeConstraintsForStatement m mass ret (For ident start end inner) = do
517+checkStatement m mass ret (For ident start end inner) = do
483 assignVariable ident (m `M.union` mass)
518 assignVariable ident (m `M.union` mass)
484− (cs1, n1) <- typeConstraints (m `M.union` mass) start
519+ t1 <- infer (m `M.union` mass) start
485− (cs2, n2) <- typeConstraints (m `M.union` mass) end
521+ t2 <- infer (m `M.union` mass) end
486− let mass1 = M.insert ident n1 mass
523+ let mass1 = M.insert ident Number mass
487− (cs3, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
524+ (allCodePathsReturn, _) <- checkBlock (m `M.union` mass1) mass1 ret inner
488− return (TypeConstraint n1 Number (ValueOrigin start) : TypeConstraint n2 Number (ValueOrigin end) : cs1 ++ cs2 ++ cs3, allCodePathsReturn, mass)
525+ return (allCodePathsReturn, mass)
489−typeConstraintsForStatement m mass ret (ForEach ident vals inner) = do
526+checkStatement m mass ret (ForEach ident vals inner) = do
490 assignVariable ident (m `M.union` mass)
527 assignVariable ident (m `M.union` mass)
491 val <- fresh
528 val <- fresh
492− (cs1, n1) <- typeConstraints (m `M.union` mass) vals
529+ t1 <- infer (m `M.union` mass) vals
493 let mass1 = M.insert ident val mass
531 let mass1 = M.insert ident val mass
494− (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
532+ (allCodePathsReturn, _) <- checkBlock (m `M.union` mass1) mass1 ret inner
495 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
533 guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
496− return (TypeConstraint n1 (Array (TUnknown val)) (ValueOrigin vals) : cs1 ++ cs2, False, mass)
534+ return (False, mass)
497−typeConstraintsForStatement m mass ret (Return val) = do
535+checkStatement m mass ret (Return val) = do
498− (cs1, n1) <- typeConstraints (m `M.union` mass) val
536+ check (m `M.union` mass) val ret
499− return (TypeConstraint n1 (TUnknown ret) (ValueOrigin val) : cs1, True, mass)
537+ return (True, mass)
501−typeConstraintsForIfStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> IfStatement -> Check ([TypeConstraint], Bool)
539+checkIfStatement :: M.Map Ident Type -> M.Map Ident Type -> Type -> IfStatement -> Subst Check Bool
502−typeConstraintsForIfStatement m mass ret (IfStatement val thens Nothing) = do
540+checkIfStatement m mass ret (IfStatement val thens Nothing) = do
503− (cs1, n1) <- typeConstraints m val
541+ t1 <- infer m val
504− (cs2, _, _) <- typeConstraintsForBlock m mass ret thens
543+ _ <- checkBlock m mass ret thens
505− return (TypeConstraint n1 Boolean (ValueOrigin val) : cs1 ++ cs2, False)
544+ return False
506−typeConstraintsForIfStatement m mass ret (IfStatement val thens (Just elses)) = do
545+checkIfStatement m mass ret (IfStatement val thens (Just elses)) = do
507− (cs1, n1) <- typeConstraints m val
546+ t1 <- infer m val
508− (cs2, allCodePathsReturn1, _) <- typeConstraintsForBlock m mass ret thens
548+ (allCodePathsReturn1, _) <- checkBlock m mass ret thens
509− (cs3, allCodePathsReturn2) <- typeConstraintsForElseStatement m mass ret elses
549+ allCodePathsReturn2 <- checkElseStatement m mass ret elses
510− return (TypeConstraint n1 Boolean (ValueOrigin val) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2)
550+ return $ allCodePathsReturn1 && allCodePathsReturn2
512−typeConstraintsForElseStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> ElseStatement -> Check ([TypeConstraint], Bool)
552+checkElseStatement :: M.Map Ident Type -> M.Map Ident Type -> Type -> ElseStatement -> Subst Check Bool
513−typeConstraintsForElseStatement m mass ret (Else elses) = do
553+checkElseStatement m mass ret (Else elses) = fst <$> checkBlock m mass ret elses
514− (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret elses
554+checkElseStatement m mass ret (ElseIf ifst) = checkIfStatement m mass ret ifst
515− return (cs, allCodePathsReturn)
555+
516−typeConstraintsForElseStatement m mass ret (ElseIf ifst) = do
517− (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
518− return (cs, allCodePathsReturn)
520−typeConstraintsForBlock :: M.Map Ident Int -> M.Map Ident Int -> Int -> [Statement] -> Check ([TypeConstraint], Bool, M.Map Ident Int)
556+checkBlock :: M.Map Ident Type -> M.Map Ident Type -> Type -> [Statement] -> Subst Check (Bool, M.Map Ident Type)
521−typeConstraintsForBlock _ mass _ [] = return ([], False, mass)
557+checkBlock _ mass _ [] = return (False, mass)
522−typeConstraintsForBlock m mass ret (s:ss) = do
558+checkBlock m mass ret (s:ss) = do
523− (cs1, b1, mass1) <- typeConstraintsForStatement (m `M.union` mass) mass ret s
559+ (b1, mass1) <- checkStatement (m `M.union` mass) mass ret s
524 case (b1, ss) of
560 case (b1, ss) of
525− (True, []) -> return (cs1, True, mass1)
561+ (True, []) -> return (True, mass1)
526 (True, _) -> throwError "Unreachable code"
562 (True, _) -> throwError "Unreachable code"
527 (False, ss) -> do
563 (False, ss) -> do
528− (cs2, b2, mass2) <- typeConstraintsForBlock m mass1 ret ss
564+ (b2, mass2) <- checkBlock m mass1 ret ss
529− return (cs1 ++ cs2, b2, mass2)
565+ return (b2, mass2)
531−solveTypeConstraints :: [TypeConstraint] -> TypeSolution -> Check TypeSolution
567+skolemize :: [String] -> Type -> Subst Check Type
532−solveTypeConstraints [] s = return s
533−solveTypeConstraints all@(TypeConstraint n t o:cs) s = do
534− (cs', s') <- rethrow (\err -> "Error in " ++ prettyPrintOrigin o ++ ": " ++ err) $ do
536− let s' = let (f, g) = runTypeSolution s
537− in TypeSolution (replaceType n t . f, replaceType n t . g)
538− cs' <- fmap concat $ mapM (substituteTypeInConstraint n t) cs
540− solveTypeConstraints cs' s'
541−solveTypeConstraints (RowConstraint n r o:cs) s = do
542− (cs', s') <- rethrow (\err -> "Error in " ++ prettyPrintOrigin o ++ ": " ++ err) $ do
544− let s' = let (f, g) = runTypeSolution s
545− in TypeSolution (replaceRow n r . f, replaceRow n r . g)
546− cs' <- fmap concat $ mapM (substituteRowInConstraint n r) cs
548− solveTypeConstraints cs' s'
550−substituteTypeInConstraint :: Int -> Type -> TypeConstraint -> Check [TypeConstraint]
551−substituteTypeInConstraint n s (TypeConstraint m t v)
552− | n == m = unifyTypes v s t
553− | otherwise = return [TypeConstraint m (replaceType n s t) v]
554−substituteTypeInConstraint n s (RowConstraint m r v)
555− = return [RowConstraint m (replaceType n s r) v]
557−substituteRowInConstraint :: Int -> Row -> TypeConstraint -> Check [TypeConstraint]
558−substituteRowInConstraint n r (TypeConstraint m t v)
559− = return [TypeConstraint m (replaceRow n r t) v]
560−substituteRowInConstraint n r (RowConstraint m r1 v)
561− | m == n = unifyRows v r r1
562− | otherwise = return [RowConstraint m (replaceRow n r r1) v]
564−unifyTypes :: TypeConstraintOrigin -> Type -> Type -> Check [TypeConstraint]
565−unifyTypes _ (TUnknown u1) (TUnknown u2) | u1 == u2 = return []
566−unifyTypes o (TUnknown u) t = do
568− return [TypeConstraint u t o]
569−unifyTypes o t (TUnknown u) = do
571− return [TypeConstraint u t o]
572−unifyTypes o (SaturatedTypeSynonym name1 args1) (SaturatedTypeSynonym name2 args2) | name1 == name2 =
573− fmap concat $ zipWithM (unifyTypes o) args1 args2
574−unifyTypes o (SaturatedTypeSynonym name args) ty = do
576− modulePath <- checkModulePath `fmap` get
577− case M.lookup (qualify modulePath name) (typeSynonyms env) of
578− Just (synArgs, body) -> do
579− let m = M.fromList $ zip synArgs args
580− let replaced = replaceTypeVars m body
581− unifyTypes o replaced ty
582− Nothing -> error "Type synonym was not defined"
583−unifyTypes o ty s@(SaturatedTypeSynonym _ _) = unifyTypes o s ty
584−unifyTypes o (ForAll idents ty1) ty2 =do
585− sk <- skolemize idents ty1
587−unifyTypes o ty f@(ForAll _ _) = unifyTypes o f ty
588−unifyTypes _ Number Number = return []
589−unifyTypes _ String String = return []
590−unifyTypes _ Boolean Boolean = return []
591−unifyTypes o (Array s) (Array t) = unifyTypes o s t
592−unifyTypes o (Object row1) (Object row2) = unifyRows o row1 row2
593−unifyTypes o (Function args1 ret1) (Function args2 ret2) = do
594− guardWith "Function applied to incorrect number of args" $ length args1 == length args2
595− cs1 <- fmap concat $ zipWithM (unifyTypes o) args1 args2
596− cs2 <- unifyTypes o ret1 ret2
598−unifyTypes _ (TypeVar v1) (TypeVar v2) | v1 == v2 = return []
599−unifyTypes _ (TypeConstructor c1) (TypeConstructor c2) = do
600− modulePath <- checkModulePath `fmap` get
601− guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (qualify modulePath c1 == qualify modulePath c2)
603−unifyTypes o (TypeApp t1 t2) (TypeApp t3 t4) = do
604− cs1 <- unifyTypes o t1 t3
605− cs2 <- unifyTypes o t2 t4
607−unifyTypes _ (Skolem s1) (Skolem s2) | s1 == s2 = return []
608−unifyTypes _ t1 t2 = throwError $ "Cannot unify " ++ prettyPrintType t1 ++ " with " ++ prettyPrintType t2 ++ "."
610−unifyRows :: TypeConstraintOrigin -> Row -> Row -> Check [TypeConstraint]
613− (s1, r1') = rowToList r1
614− (s2, r2') = rowToList r2
615− int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
616− sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
617− sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
619− cs1 <- fmap concat $ mapM (uncurry $ unifyTypes o) int
620− cs2 <- unifyRows' o sd1 r1' sd2 r2'
623− unifyRows' :: TypeConstraintOrigin -> [(String, Type)] -> Row -> [(String, Type)] -> Row -> Check [TypeConstraint]
624− unifyRows' o [] (RUnknown u) sd r = do
626− return [RowConstraint u (rowFromList (sd, r)) o]
627− unifyRows' o sd r [] (RUnknown u) = do
629− return [RowConstraint u (rowFromList (sd, r)) o]
630− unifyRows' o ns@((name, ty):row) r others (RUnknown u) | not (occursCheck u (ty, row)) = do
632− cs <- unifyRows' o row r others (RUnknown u')
633− return (RowConstraint u (RCons name ty (RUnknown u')) o : cs)
634− unifyRows' _ [] REmpty [] REmpty = return []
635− unifyRows' _ [] (RowVar v1) [] (RowVar v2) | v1 == v2 = return []
636− unifyRows' _ sd1 r1 sd2 r2 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd1, r1)) ++ " with " ++ prettyPrintRow (rowFromList (sd2, r2)) ++ "."
638−skolemize :: [String] -> Type -> Check Type
639skolemize idents ty = do
568skolemize idents ty = do
640− sks <- replicateM (length idents) fresh
569+ sks <- replicateM (length idents) fresh'
641 let m = M.fromList (zip idents (map Skolem sks))
570 let m = M.fromList (zip idents (map Skolem sks))
642 return $ replaceTypeVars m ty
571 return $ replaceTypeVars m ty
573+check :: M.Map Ident Type -> Value -> Type -> Subst Check ()
574+check m (NumericLiteral _) Number = return ()
575+check m (StringLiteral _) String = return ()
576+check m (BooleanLiteral _) Boolean = return ()
577+check m (Unary Negate val) Number = check m val Number
578+check m (Unary Not val) Boolean = check m val Boolean
579+check m (Unary BitwiseNot val) Number = check m val Number
580+check m (Binary _ t1 t2) Number = check m t1 Number >> check m t2 Number
581+check m (ArrayLiteral vals) (Array ty) = forM_ vals (\val -> check m val ty)
582+check m (Indexer index vals) ty = check m index Number >> check m vals (Array ty)
583+check m (Abs args ret) (Function argTys retTy) = do
584+ guardWith "Incorrect number of function arguments" (length args == length argTys)
585+ let bindings = M.fromList (zip args argTys)
586+ check (bindings `M.union` m) ret retTy
587+check m (App f xs) ret = do
589+ checkFunctionApplication m ft xs ret
590+check m val (ForAll idents ty) = do
591+ sk <- skolemize idents ty
593+check m val u@(TUnknown _) = do
596+check _ val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
598+checkFunctionApplication :: M.Map Ident Type -> Type -> [Value] -> Type -> Subst Check ()
599+checkFunctionApplication m (Function argTys retTy) args ret = do
600+ guardWith "Incorrect number of function arguments" (length args == length argTys)
601+ zipWithM (check m) args argTys
603+checkFunctionApplication m (ForAll idents ty) args ret = do
604+ replaced <- replaceVarsWithUnknowns idents ty
605+ checkFunctionApplication m replaced args ret
606+checkFunctionApplication _ fnTy args ret = throwError $ "Cannot apply function of type "
607+ ++ prettyPrintType fnTy
608+ ++ " to arguments " ++ intercalate ", " (map prettyPrintValue args)
609+ ++ ". Expecting value of type " ++ prettyPrintType ret ++ "."
612+ | Binary BinaryOperator Value Value
613+ | ObjectLiteral [(String, Value)]
614+ | Accessor String Value
615+ | ObjectUpdate Value [(String, Value)]
616+ | Var (Qualified Ident)
617+ | IfThenElse Value Value Value
619+ | Constructor (Qualified ProperName)
620+ | Case Value [(Binder, Value)]
621+ | TypedValue Value PolyType