@@ -18,8 +18,6 @@ module PureScript.TypeChecker.Types (
23import Data.List
21import Data.List
24import Data.Function
22import Data.Function
@@ -31,7 +29,7 @@ import Control.Monad.State
31import Control.Monad.Error
29import Control.Monad.Error
33import Control.Applicative
31import Control.Applicative
34−import Control.Arrow (Kleisli(..), (***))
32+import Control.Arrow (Kleisli(..), (***), (&&&))
35import qualified Control.Category as C
33import qualified Control.Category as C
37import qualified Data.Map as M
35import qualified Data.Map as M
@@ -47,8 +45,8 @@ emptyTypeSolution = TypeSolution (TUnknown, RUnknown)
48typeOf :: String -> Value -> Check Type
46typeOf :: String -> Value -> Check Type
49typeOf name val = do
47typeOf name val = do
50− let me = 0
48+ me <- fresh
51− (cs, n, _) <- typeConstraints 1 (M.singleton name me) val
49+ (cs, n) <- typeConstraints (M.singleton name me) val
52 solution <- solveTypeConstraints ((TypeConstraint me (TUnknown n)) : cs) emptyTypeSolution
50 solution <- solveTypeConstraints ((TypeConstraint me (TUnknown n)) : cs) emptyTypeSolution
53 return $ varIfUnknown $ fst (runTypeSolution solution) n
51 return $ varIfUnknown $ fst (runTypeSolution solution) n
@@ -81,103 +79,124 @@ varIfUnknown = flip evalState M.empty . varIfUnknown'
81 varIfUnknown'' (RCons name ty row) = RCons name ty <$> varIfUnknown'' row
79 varIfUnknown'' (RCons name ty row) = RCons name ty <$> varIfUnknown'' row
82 varIfUnknown'' r = return r
80 varIfUnknown'' r = return r
84−replaceVarsWithUnknowns :: Int -> Type -> (Type, Int)
82+replaceVarsWithUnknowns :: Type -> Check Type
85−replaceVarsWithUnknowns n = (id *** fst) . flip runState (n, M.empty) . replaceVarsWithUnknowns'
83+replaceVarsWithUnknowns = flip evalStateT M.empty . replaceVarsWithUnknowns'
87− replaceVarsWithUnknowns' :: Type -> State (Int, M.Map String Int) Type
85+ replaceVarsWithUnknowns' :: Type -> StateT (M.Map String Int) Check Type
88 replaceVarsWithUnknowns' (Array t) = Array <$> replaceVarsWithUnknowns' t
86 replaceVarsWithUnknowns' (Array t) = Array <$> replaceVarsWithUnknowns' t
89 replaceVarsWithUnknowns' (Object row) = Object <$> replaceVarsWithUnknowns'' row
87 replaceVarsWithUnknowns' (Object row) = Object <$> replaceVarsWithUnknowns'' row
90 replaceVarsWithUnknowns' (Function args ret) = Function <$> mapM replaceVarsWithUnknowns' args <*> replaceVarsWithUnknowns' ret
88 replaceVarsWithUnknowns' (Function args ret) = Function <$> mapM replaceVarsWithUnknowns' args <*> replaceVarsWithUnknowns' ret
91 replaceVarsWithUnknowns' (TypeApp t1 t2) = TypeApp <$> replaceVarsWithUnknowns' t1 <*> replaceVarsWithUnknowns' t2
89 replaceVarsWithUnknowns' (TypeApp t1 t2) = TypeApp <$> replaceVarsWithUnknowns' t1 <*> replaceVarsWithUnknowns' t2
92 replaceVarsWithUnknowns' (TypeVar var) = do
90 replaceVarsWithUnknowns' (TypeVar var) = do
93− (n, m) <- get
91+ m <- get
94 case M.lookup var m of
93 case M.lookup var m of
95 Nothing -> do
94 Nothing -> do
96− put (n + 1, M.insert var n m)
95+ put (M.insert var n m)
97 return $ TUnknown n
96 return $ TUnknown n
98 Just u -> return $ TUnknown u
97 Just u -> return $ TUnknown u
99 replaceVarsWithUnknowns' t = return t
98 replaceVarsWithUnknowns' t = return t
100− replaceVarsWithUnknowns'' :: Row -> State (Int, M.Map String Int) Row
99+ replaceVarsWithUnknowns'' :: Row -> StateT (M.Map String Int) Check Row
101 replaceVarsWithUnknowns'' (RowVar var) = do
100 replaceVarsWithUnknowns'' (RowVar var) = do
102− (n, m) <- get
101+ m <- get
103 case M.lookup var m of
103 case M.lookup var m of
104 Nothing -> do
104 Nothing -> do
105− put (n + 1, M.insert var n m)
105+ put (M.insert var n m)
106 return $ RUnknown n
106 return $ RUnknown n
107 Just u -> return $ RUnknown u
107 Just u -> return $ RUnknown u
108 replaceVarsWithUnknowns'' (RCons name ty row) = RCons name <$> replaceVarsWithUnknowns' ty <*> replaceVarsWithUnknowns'' row
108 replaceVarsWithUnknowns'' (RCons name ty row) = RCons name <$> replaceVarsWithUnknowns' ty <*> replaceVarsWithUnknowns'' row
109 replaceVarsWithUnknowns'' r = return r
109 replaceVarsWithUnknowns'' r = return r
111−typeConstraints :: Int -> M.Map String Int -> Value -> Check ([TypeConstraint], Int, Int)
111+typeConstraints :: M.Map String Int -> Value -> Check ([TypeConstraint], Int)
112−typeConstraints n _ (NumericLiteral _) = return ([TypeConstraint n Number], n, n)
112+typeConstraints _ (NumericLiteral _) = do
114+ return ([TypeConstraint me Number], me)
113−typeConstraints n _ (StringLiteral _) = return ([TypeConstraint n String], n, n)
115+typeConstraints _ (StringLiteral _) = do
117+ return ([TypeConstraint me String], me)
114−typeConstraints n _ (BooleanLiteral _) = return ([TypeConstraint n Boolean], n, n)
118+typeConstraints _ (BooleanLiteral _) = do
120+ return ([TypeConstraint me Boolean], me)
115−typeConstraints n m (ArrayLiteral vals) = do
121+typeConstraints m (ArrayLiteral vals) = do
116− (cs, ns, max1) <- typeConstraintsAll n m vals
122+ all <- mapM (typeConstraints m) vals
117− let me = max1 + 1
123+ let (cs, ns) = (concat . map fst &&& map snd) all
118− return (cs ++ map (TypeConstraint me . Array . TUnknown) ns, me, me)
125+ return (cs ++ map (TypeConstraint me . Array . TUnknown) ns, me)
119−typeConstraints n m (Unary op val) = do
126+typeConstraints m (Unary op val) = do
120− (cs, n1, max1) <- typeConstraints n m val
127+ (cs, n1) <- typeConstraints m val
121− let me = max1 + 1
128+ me <- fresh
122− return (cs ++ unaryOperatorConstraints op n1 me, me, me)
129+ return (cs ++ unaryOperatorConstraints op n1 me, me)
123−typeConstraints n m (Binary op left right) = do
130+typeConstraints m (Binary op left right) = do
124− (cs1, n1, max1) <- typeConstraints n m left
131+ (cs1, n1) <- typeConstraints m left
125− (cs2, n2, max2) <- typeConstraints (max1 + 1) m right
132+ (cs2, n2) <- typeConstraints m right
126− let me = max1 + 1
133+ me <- fresh
127− return (cs1 ++ cs2 ++ binaryOperatorConstraints op n1 n2 me, me, me)
134+ return (cs1 ++ cs2 ++ binaryOperatorConstraints op n1 n2 me, me)
128−typeConstraints n m (ObjectLiteral ps) = do
135+typeConstraints m (ObjectLiteral ps) = do
129− (cs, ns, max1) <- typeConstraintsAll n m (map snd ps)
136+ all <- mapM (typeConstraints m . snd) ps
130− let me = max1 + 1
137+ let (cs, ns) = (concat . map fst &&& map snd) all
131 let tys = zipWith (\(name, _) u -> (name, TUnknown u)) ps ns
139 let tys = zipWith (\(name, _) u -> (name, TUnknown u)) ps ns
132− return ((TypeConstraint me (Object (typesToRow tys))) : cs, me, me)
140+ return ((TypeConstraint me (Object (typesToRow tys))) : cs, me)
134 typesToRow [] = REmpty
142 typesToRow [] = REmpty
135 typesToRow ((name, ty):tys) = RCons name ty (typesToRow tys)
143 typesToRow ((name, ty):tys) = RCons name ty (typesToRow tys)
144+typeConstraints m (Indexer index val) = do
145+ (cs1, n1) <- typeConstraints m index
146+ (cs2, n2) <- typeConstraints m val
148+ return ((TypeConstraint n1 Number) : (TypeConstraint n2 (Array (TUnknown me))) : cs1 ++ cs2, me)
136−typeConstraints n m (Accessor prop val) = do
149+typeConstraints m (Accessor prop val) = do
137− (cs, n1, max1) <- typeConstraints n m val
150+ (cs, n1) <- typeConstraints m val
138− let me = max1 + 1
151+ me <- fresh
139− let rest = max1 + 2
152+ rest <- fresh
140− return ((TypeConstraint n1 (Object (RCons prop (TUnknown me) (RUnknown rest)))) : cs, me, rest)
153+ return ((TypeConstraint n1 (Object (RCons prop (TUnknown me) (RUnknown rest)))) : cs, me)
141−typeConstraints n m (Abs args ret) = do
154+typeConstraints m (Abs args ret) = do
142− let ns = [n..n + length args - 1]
155+ ns <- replicateM (length args) fresh
143− let next = n + length args
144 let m' = m `M.union` M.fromList (zipWith (,) args ns)
156 let m' = m `M.union` M.fromList (zipWith (,) args ns)
145− (cs, n', max1) <- typeConstraints next m' ret
157+ (cs, n') <- typeConstraints m' ret
146− let me = max1 + 1
158+ me <- fresh
147− return ((TypeConstraint me (Function (map TUnknown ns) (TUnknown n'))) : cs, me, me)
159+ return ((TypeConstraint me (Function (map TUnknown ns) (TUnknown n'))) : cs, me)
148−typeConstraints n m (App f xs) = do
160+typeConstraints m (App f xs) = do
149− (cs1, n1, max1) <- typeConstraints n m f
161+ (cs1, n1) <- typeConstraints m f
150− (cs2, ns, max2) <- typeConstraintsAll (max1 + 1) m xs
162+ all <- mapM (typeConstraints m) xs
151− let me = max2 + 1
163+ let (cs2, ns) = (concat . map fst &&& map snd) all
152− return ((TypeConstraint n1 (Function (map TUnknown ns) (TUnknown me))) : cs1 ++ cs2, me, me)
165+ return ((TypeConstraint n1 (Function (map TUnknown ns) (TUnknown me))) : cs1 ++ cs2, me)
153−typeConstraints n m (Var var) =
166+typeConstraints m (Var var) =
154 case M.lookup var m of
167 case M.lookup var m of
155 Nothing -> do
168 Nothing -> do
156− env <- get
169+ env <- getEnv
157 case M.lookup var (names env) of
170 case M.lookup var (names env) of
158 Nothing -> throwError $ var ++ " is undefined"
171 Nothing -> throwError $ var ++ " is undefined"
159− Just ty -> let (replaced, max1) = replaceVarsWithUnknowns (n + 1) ty
174+ replaced <- replaceVarsWithUnknowns ty
160− in return ([TypeConstraint n replaced], n, max1)
175+ return ([TypeConstraint me replaced], me)
161− Just u -> return ([TypeConstraint u (TUnknown n)], n, n)
178+ return ([TypeConstraint u (TUnknown me)], me)
162−typeConstraints n m (Block ss) = do
179+typeConstraints m (Block ss) = do
163− let ret = n + 1
180+ ret <- fresh
164− (cs, allCodePathsReturn, max1, _) <- typeConstraintsForBlock (ret + 1) m M.empty ret ss
181+ (cs, allCodePathsReturn, _) <- typeConstraintsForBlock m M.empty ret ss
165 guardWith "Block is missing a return statement" allCodePathsReturn
182 guardWith "Block is missing a return statement" allCodePathsReturn
166− return (cs, ret, max1)
183+ return (cs, ret)
167−typeConstraints n m (Constructor c) = do
184+typeConstraints m (Constructor c) = do
168− env <- get
185+ env <- getEnv
169 case M.lookup c (names env) of
186 case M.lookup c (names env) of
170 Nothing -> throwError $ c ++ " is undefined"
187 Nothing -> throwError $ c ++ " is undefined"
171− Just ty -> let (replaced, max1) = replaceVarsWithUnknowns (n + 1) ty
190+ replaced <- replaceVarsWithUnknowns ty
172− in return ([TypeConstraint n replaced], n, max1)
191+ return ([TypeConstraint me replaced], me)
173−typeConstraints n m (Case val binders) = do
192+typeConstraints m (Case val binders) = do
174− (cs1, n1, max1) <- typeConstraints n m val
193+ (cs1, n1) <- typeConstraints m val
175− let ret = max1 + 1
194+ ret <- fresh
176− (cs2, max2) <- typeConstraintsForBinders (ret + 1) m n1 ret binders
195+ cs2 <- typeConstraintsForBinders m n1 ret binders
177− return (cs1 ++ cs2, ret, max2)
196+ return (cs1 ++ cs2, ret)
178−typeConstraints n m (TypedValue val ty) = do
197+typeConstraints m (TypedValue val ty) = do
179− (cs, n1, max1) <- typeConstraints n m val
198+ (cs, n1) <- typeConstraints m val
180− return ([TypeConstraint n1 ty], n1, max1)
199+ return ([TypeConstraint n1 ty], n1)
181 -- TODO: Kind-check the type
200 -- TODO: Kind-check the type
183unaryOperatorConstraints :: UnaryOperator -> Int -> Int -> [TypeConstraint]
202unaryOperatorConstraints :: UnaryOperator -> Int -> Int -> [TypeConstraint]
@@ -213,114 +232,124 @@ equalityBinOpConstraints left right result = [TypeConstraint left (TUnknown righ
213symBinOpConstraints :: Type -> Int -> Int -> Int -> [TypeConstraint]
232symBinOpConstraints :: Type -> Int -> Int -> Int -> [TypeConstraint]
214symBinOpConstraints ty left right result = [TypeConstraint left ty, TypeConstraint right ty, TypeConstraint result ty]
233symBinOpConstraints ty left right result = [TypeConstraint left ty, TypeConstraint right ty, TypeConstraint result ty]
216−typeConstraintsForBinder :: Int -> M.Map String Int -> Int -> Binder -> Check ([TypeConstraint], Int, M.Map String Int)
235+typeConstraintsForBinder :: Int -> Binder -> Check ([TypeConstraint], M.Map String Int)
217−typeConstraintsForBinder n m val (VarBinder name) =
236+typeConstraintsForBinder val (StringBinder _) = constantBinder val String
237+typeConstraintsForBinder val (NumberBinder _) = constantBinder val Number
238+typeConstraintsForBinder val (BooleanBinder _) = constantBinder val Boolean
239+typeConstraintsForBinder val (VarBinder name) = do
218− return ([TypeConstraint n (TUnknown val)], n, M.insert name n m)
241+ return ([TypeConstraint me (TUnknown val)], M.singleton name me)
219−typeConstraintsForBinder n m val (NullaryBinder ctor) = do
242+typeConstraintsForBinder val (NullaryBinder ctor) = do
220− env <- get
243+ env <- getEnv
221 case M.lookup ctor (names env) of
244 case M.lookup ctor (names env) of
222 Just ret -> do
245 Just ret -> do
223− let (ret', max1) = replaceVarsWithUnknowns n ret
246+ ret' <- replaceVarsWithUnknowns ret
224− return ([TypeConstraint val ret'], max1, m)
247+ return ([TypeConstraint val ret'], M.empty)
225 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
248 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
226−typeConstraintsForBinder n m val (UnaryBinder ctor binder) = do
249+typeConstraintsForBinder val (UnaryBinder ctor binder) = do
227− env <- get
250+ env <- getEnv
228 case M.lookup ctor (names env) of
251 case M.lookup ctor (names env) of
229 Just f@(Function [ty] ret) -> do
252 Just f@(Function [ty] ret) -> do
230− let obj = n
253+ obj <- fresh
231− let (Function [ty'] ret', max1) = replaceVarsWithUnknowns (n + 1) f
254+ Function [ty'] ret' <- replaceVarsWithUnknowns f
232− (cs, max2, m1) <- typeConstraintsForBinder (max1 + 1) m obj binder
255+ (cs, m1) <- typeConstraintsForBinder obj binder
233− return ((TypeConstraint val ret') : (TypeConstraint obj ty') : cs, max2, m1)
256+ return ((TypeConstraint val ret') : (TypeConstraint obj ty') : cs, m1)
234 Just _ -> throwError $ ctor ++ " is not a unary constructor"
257 Just _ -> throwError $ ctor ++ " is not a unary constructor"
235 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
258 _ -> throwError $ "Constructor " ++ ctor ++ " is not defined"
236−typeConstraintsForBinder n m val (ObjectBinder props) = do
259+typeConstraintsForBinder val (ObjectBinder props) = do
237− let row = n
260+ row <- fresh
238− let rest = n + 1
261+ rest <- fresh
239− (cs, max1, m1) <- typeConstraintsForProperties (n + 2) m row (RUnknown rest) props
262+ (cs, m1) <- typeConstraintsForProperties row (RUnknown rest) props
240− return ((TypeConstraint val (Object (RUnknown row))) : cs, max1, m1)
263+ return ((TypeConstraint val (Object (RUnknown row))) : cs, m1)
242− typeConstraintsForProperties :: Int -> M.Map String Int -> Int -> Row -> [(String, Binder)] -> Check ([TypeConstraint], Int, M.Map String Int)
265+ typeConstraintsForProperties :: Int -> Row -> [(String, Binder)] -> Check ([TypeConstraint], M.Map String Int)
243− typeConstraintsForProperties n m nrow row [] = return ([RowConstraint nrow row], n, m)
266+ typeConstraintsForProperties nrow row [] = return ([RowConstraint nrow row], M.empty)
244− typeConstraintsForProperties n m nrow row ((name, binder):binders) = do
267+ typeConstraintsForProperties nrow row ((name, binder):binders) = do
245− let propTy = n
268+ propTy <- fresh
246− (cs1, max1, m1) <- typeConstraintsForBinder (n + 1) m propTy binder
269+ (cs1, m1) <- typeConstraintsForBinder propTy binder
247− (cs2, max2, m2) <- typeConstraintsForProperties (max1 + 1) m1 nrow (RCons name (TUnknown propTy) row) binders
270+ (cs2, m2) <- typeConstraintsForProperties nrow (RCons name (TUnknown propTy) row) binders
248− return (cs1 ++ cs2, max2, m2)
271+ return (cs1 ++ cs2, M.union m1 m2)
249−
272+typeConstraintsForBinder val (ArrayBinder binders rest) = do
274+ all <- mapM (typeConstraintsForBinder el) binders
275+ let (cs1, m1) = (concat . map fst &&& M.unions . map snd) all
276+ let arrayConstraint = TypeConstraint val (Array (TUnknown el))
278+ Nothing -> return (arrayConstraint : cs1, m1)
280+ (cs2, m2) <- typeConstraintsForBinder val binder
281+ return (arrayConstraint : cs1 ++ cs2, M.union m1 m2)
283+constantBinder :: Int -> Type -> Check ([TypeConstraint], M.Map String Int)
284+constantBinder val ty = return ([TypeConstraint val ty], M.empty)
250−typeConstraintsForBinders :: Int -> M.Map String Int -> Int -> Int -> [(Binder, Value)] -> Check ([TypeConstraint], Int)
286+typeConstraintsForBinders :: M.Map String Int -> Int -> Int -> [(Binder, Value)] -> Check [TypeConstraint]
251−typeConstraintsForBinders n _ _ _ [] = return ([], n)
287+typeConstraintsForBinders _ _ _ [] = return []
252−typeConstraintsForBinders n m nval ret ((binder, val):bs) = do
288+typeConstraintsForBinders m nval ret ((binder, val):bs) = do
253− (cs1, max1, m1) <- typeConstraintsForBinder n m nval binder
289+ (cs1, m1) <- typeConstraintsForBinder nval binder
254− (cs2, n2, max2) <- typeConstraints (max1 + 1) m1 val
290+ (cs2, n2) <- typeConstraints (M.union m m1) val
255− (cs3, max3) <- typeConstraintsForBinders (max2 + 1) m nval ret bs
291+ cs3 <- typeConstraintsForBinders m nval ret bs
256− return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3, max3)
292+ return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
258−typeConstraintsForStatement :: Int -> M.Map String Int -> M.Map String Int -> Int -> Statement -> Check ([TypeConstraint], Bool, Int, M.Map String Int)
294+typeConstraintsForStatement :: M.Map String Int -> M.Map String Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map String Int)
259−typeConstraintsForStatement n m mass ret (VariableIntroduction name val) = do
295+typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
260 case M.lookup name (m `M.union` mass) of
296 case M.lookup name (m `M.union` mass) of
261 Nothing -> do
297 Nothing -> do
262− (cs1, n1, max1) <- typeConstraints n m val
298+ (cs1, n1) <- typeConstraints m val
263− return $ (cs1, False, max1, M.insert name n1 mass)
299+ return $ (cs1, False, M.insert name n1 mass)
264 Just ty -> throwError $ "Variable with name " ++ name ++ " already exists."
300 Just ty -> throwError $ "Variable with name " ++ name ++ " already exists."
265−typeConstraintsForStatement n m mass ret (Assignment name val) = do
301+typeConstraintsForStatement m mass ret (Assignment name val) = do
266 case M.lookup name (m `M.union` mass) of
302 case M.lookup name (m `M.union` mass) of
267 Nothing -> throwError $ "No local variable with name " ++ name
303 Nothing -> throwError $ "No local variable with name " ++ name
268 Just ty -> do
304 Just ty -> do
269− (cs1, n1, max1) <- typeConstraints n m val
305+ (cs1, n1) <- typeConstraints m val
270− return ((TypeConstraint n1 (TUnknown ty)) : cs1, False, max1, mass)
306+ return ((TypeConstraint n1 (TUnknown ty)) : cs1, False, mass)
271−typeConstraintsForStatement n m mass ret (While val inner) = do
307+typeConstraintsForStatement m mass ret (While val inner) = do
272− (cs1, n1, max1) <- typeConstraints n m val
308+ (cs1, n1) <- typeConstraints m val
273− (cs2, allCodePathsReturn, max2, _) <- typeConstraintsForBlock (max1 + 1) m mass ret inner
309+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret inner
274− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, max2, mass)
310+ return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, mass)
275−typeConstraintsForStatement n m mass ret (IfThenElse val thens Nothing) = do
311+typeConstraintsForStatement m mass ret (IfThenElse val thens Nothing) = do
276− (cs1, n1, max1) <- typeConstraints n m val
312+ (cs1, n1) <- typeConstraints m val
277− (cs2, allCodePathsReturn, max2, _) <- typeConstraintsForBlock (max1 + 1) m mass ret thens
313+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock m mass ret thens
278− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, max2, mass)
314+ return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2, allCodePathsReturn, mass)
279−typeConstraintsForStatement n m mass ret (IfThenElse val thens (Just elses)) = do
315+typeConstraintsForStatement m mass ret (IfThenElse val thens (Just elses)) = do
280− (cs1, n1, max1) <- typeConstraints n m val
316+ (cs1, n1) <- typeConstraints m val
281− (cs2, allCodePathsReturn1, max2, _) <- typeConstraintsForBlock (max1 + 1) m mass ret thens
317+ (cs2, allCodePathsReturn1, _) <- typeConstraintsForBlock m mass ret thens
282− (cs3, allCodePathsReturn2, max3, _) <- typeConstraintsForBlock (max2 + 1) m mass ret elses
318+ (cs3, allCodePathsReturn2, _) <- typeConstraintsForBlock m mass ret elses
283− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2, max3, mass)
319+ return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3, allCodePathsReturn1 && allCodePathsReturn2, mass)
284−typeConstraintsForStatement n m mass ret (For (init, cond, cont) inner) = do
320+typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
285− (cs1, b1, max1, mass1) <- typeConstraintsForStatement n m mass ret init
321+ (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
286 guardWith "Cannot return from inside for" $ not b1
322 guardWith "Cannot return from inside for" $ not b1
287− (cs2, n1, max2) <- typeConstraints (max1 + 1) (m `M.union` mass1) cond
323+ (cs2, n1) <- typeConstraints (m `M.union` mass1) cond
288− (cs3, b2, max3, mass2) <- typeConstraintsForStatement (max2 + 1) (m `M.union` mass1) mass1 ret cont
324+ (cs3, b2, mass2) <- typeConstraintsForStatement (m `M.union` mass1) mass1 ret cont
289 guardWith "Cannot return from inside for" $ not b2
325 guardWith "Cannot return from inside for" $ not b2
290− (cs4, allCodePathsReturn, max4, _) <- typeConstraintsForBlock (max3 + 1) (m `M.union` mass2) mass2 ret inner
326+ (cs4, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass2) mass2 ret inner
291− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3 ++ cs4, allCodePathsReturn, max4, mass)
327+ return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3 ++ cs4, allCodePathsReturn, mass)
292−typeConstraintsForStatement n m mass ret (Return val) = do
328+typeConstraintsForStatement m mass ret (Return val) = do
293− (cs1, n1, max1) <- typeConstraints n m val
329+ (cs1, n1) <- typeConstraints m val
294− return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, max1, mass)
330+ return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
296−typeConstraintsForBlock :: Int -> M.Map String Int -> M.Map String Int -> Int -> [Statement] -> Check ([TypeConstraint], Bool, Int, M.Map String Int)
332+typeConstraintsForBlock :: M.Map String Int -> M.Map String Int -> Int -> [Statement] -> Check ([TypeConstraint], Bool, M.Map String Int)
297−typeConstraintsForBlock n _ mass _ [] = return ([], False, n, mass)
333+typeConstraintsForBlock _ mass _ [] = return ([], False, mass)
298−typeConstraintsForBlock n m mass ret (s:ss) = do
334+typeConstraintsForBlock m mass ret (s:ss) = do
299− (cs1, b1, max1, mass1) <- typeConstraintsForStatement n (m `M.union` mass) mass ret s
335+ (cs1, b1, mass1) <- typeConstraintsForStatement (m `M.union` mass) mass ret s
300 case (b1, ss) of
336 case (b1, ss) of
301− (True, []) -> return (cs1, True, max1, mass1)
337+ (True, []) -> return (cs1, True, mass1)
302 (True, _) -> throwError "Unreachable code"
338 (True, _) -> throwError "Unreachable code"
303 (False, ss) -> do
339 (False, ss) -> do
304− (cs2, b2, max2, mass2) <- typeConstraintsForBlock (max1 + 1) m mass1 ret ss
340+ (cs2, b2, mass2) <- typeConstraintsForBlock m mass1 ret ss
305− return (cs1 ++ cs2, b2, max2, mass2)
341+ return (cs1 ++ cs2, b2, mass2)
307−typeConstraintsAll :: Int -> M.Map String Int -> [Value] -> Check ([TypeConstraint], [Int], Int)
308−typeConstraintsAll n _ [] = return ([], [], n)
309−typeConstraintsAll n m (t:ts) = do
310− (cs, n', max1) <- typeConstraints n m t
311− (cs', ns, max2) <- typeConstraintsAll (max1 + 1) m ts
312− return (cs ++ cs', n':ns, max2)
314solveTypeConstraints :: [TypeConstraint] -> TypeSolution -> Check TypeSolution
343solveTypeConstraints :: [TypeConstraint] -> TypeSolution -> Check TypeSolution
315solveTypeConstraints [] s = return s
344solveTypeConstraints [] s = return s
316solveTypeConstraints all@(TypeConstraint n t:cs) s = do
345solveTypeConstraints all@(TypeConstraint n t:cs) s = do
317− guardWith "Occurs check failed" $ not $ typeOccursCheck n t
346+ guardWith "Occurs check failed" $ not $ typeOccursCheck False n t
318 let s' = let (f, g) = runTypeSolution s
347 let s' = let (f, g) = runTypeSolution s
319 in TypeSolution (replaceTypeInType n t . f, replaceTypeInRow n t . g)
348 in TypeSolution (replaceTypeInType n t . f, replaceTypeInRow n t . g)
320 cs' <- fmap concat $ mapM (substituteTypeInConstraint n t) cs
349 cs' <- fmap concat $ mapM (substituteTypeInConstraint n t) cs
321 solveTypeConstraints cs' s'
350 solveTypeConstraints cs' s'
322solveTypeConstraints (RowConstraint n r:cs) s = do
351solveTypeConstraints (RowConstraint n r:cs) s = do
323− guardWith "Occurs check failed" $ not $ rowOccursCheck n r
352+ guardWith "Occurs check failed" $ not $ rowOccursCheck False n r
324 let s' = let (f, g) = runTypeSolution s
353 let s' = let (f, g) = runTypeSolution s
325 in TypeSolution $ (replaceRowInType n r . f, replaceRowInRow n r . g)
354 in TypeSolution $ (replaceRowInType n r . f, replaceRowInRow n r . g)
326 cs' <- fmap concat $ mapM (substituteRowInConstraint n r) cs
355 cs' <- fmap concat $ mapM (substituteRowInConstraint n r) cs
@@ -367,10 +396,10 @@ replaceRowInRow _ _ other = other
367unifyTypes :: Type -> Type -> Check [TypeConstraint]
396unifyTypes :: Type -> Type -> Check [TypeConstraint]
368unifyTypes (TUnknown u1) (TUnknown u2) | u1 == u2 = return []
397unifyTypes (TUnknown u1) (TUnknown u2) | u1 == u2 = return []
369unifyTypes (TUnknown u) t = do
398unifyTypes (TUnknown u) t = do
370− guardWith "Occurs check failed for " $ not $ typeOccursCheck u t
399+ guardWith "Occurs check failed" $ not $ typeOccursCheck False u t
371 return [TypeConstraint u t]
400 return [TypeConstraint u t]
372unifyTypes t (TUnknown u) = do
401unifyTypes t (TUnknown u) = do
373− guardWith "Occurs check failed" $ not $ typeOccursCheck u t
402+ guardWith "Occurs check failed" $ not $ typeOccursCheck False u t
374 return [TypeConstraint u t]
403 return [TypeConstraint u t]
375unifyTypes Number Number = return []
404unifyTypes Number Number = return []
376unifyTypes String String = return []
405unifyTypes String String = return []
@@ -378,6 +407,7 @@ unifyTypes Boolean Boolean = return []
378unifyTypes (Array s) (Array t) = unifyTypes s t
407unifyTypes (Array s) (Array t) = unifyTypes s t
379unifyTypes (Object row1) (Object row2) = unifyRows row1 row2
408unifyTypes (Object row1) (Object row2) = unifyRows row1 row2
380unifyTypes (Function args1 ret1) (Function args2 ret2) = do
409unifyTypes (Function args1 ret1) (Function args2 ret2) = do
410+ guardWith "Function applied to incorrect number of args" $ length args1 == length args2
381 cs1 <- fmap concat $ zipWithM unifyTypes args1 args2
411 cs1 <- fmap concat $ zipWithM unifyTypes args1 args2
382 cs2 <- unifyTypes ret1 ret2
412 cs2 <- unifyTypes ret1 ret2
383 return $ cs1 ++ cs2
413 return $ cs1 ++ cs2
@@ -400,19 +430,19 @@ unifyRows r1 r2 =
400 sd2 = [ (name, t2) | (name, t2) <- s2, not (elem name (map fst s1)) ]
430 sd2 = [ (name, t2) | (name, t2) <- s2, not (elem name (map fst s1)) ]
401 in rethrow (const $ "Cannot unify " ++ show r1 ++ " with " ++ show r2) $ do
431 in rethrow (const $ "Cannot unify " ++ show r1 ++ " with " ++ show r2) $ do
402 cs1 <- fmap concat $ mapM (uncurry unifyTypes) int
432 cs1 <- fmap concat $ mapM (uncurry unifyTypes) int
403− cs2 <- unifyRows' (fromList (sd1, r1')) (fromList (sd2, r2'))
433+ cs2 <- unifyRows' sd1 r1' sd2 r2'
404 return $ cs1 ++ cs2
434 return $ cs1 ++ cs2
406− unifyRows' :: Row -> Row -> Check [TypeConstraint]
436+ unifyRows' :: [(String, Type)] -> Row -> [(String, Type)] -> Row -> Check [TypeConstraint]
407− unifyRows' r (RUnknown u) = do
437+ unifyRows' [] (RUnknown u) sd r = do
408− guardWith "Occurs check failed" $ not $ rowOccursCheck u r
438+ guardWith "Occurs check failed" $ not $ rowOccursCheck False u r
409− return [RowConstraint u r]
439+ return [RowConstraint u (fromList (sd, r))]
410− unifyRows' (RUnknown u) r = do
440+ unifyRows' ((name, ty):row) r others (RUnknown u) = do
411− guardWith "Occurs check failed" $ not $ rowOccursCheck u r
441+ u' <- fresh
442+ cs <- unifyRows' row r others (RUnknown u')
412− return [RowConstraint u r]
443+ return [ RowConstraint u (RCons name ty (RUnknown u')) ]
413− unifyRows' (RowVar v1) (RowVar v2) | v1 == v2 = return []
414− unifyRows' REmpty REmpty = return []
444+ unifyRows' [] REmpty [] REmpty = return []
415− unifyRows' r1 r2 = throwError $ "Cannot unify " ++ show r1 ++ " with " ++ show r2 ++ "."
445+ unifyRows' sd1 r1 sd2 r2 = throwError $ "Cannot unify " ++ show (fromList (sd1, r1)) ++ " with " ++ show (fromList (sd2, r2)) ++ "."
416 toList :: Row -> ([(String, Type)], Row)
446 toList :: Row -> ([(String, Type)], Row)
417 toList (RCons name ty row) = let (tys, rest) = toList row
447 toList (RCons name ty row) = let (tys, rest) = toList row
418 in ((name, ty):tys, rest)
448 in ((name, ty):tys, rest)
@@ -421,15 +451,15 @@ unifyRows r1 r2 =
421 fromList ([], r) = r
451 fromList ([], r) = r
422 fromList ((name, t):ts, r) = RCons name t (fromList (ts, r))
452 fromList ((name, t):ts, r) = RCons name t (fromList (ts, r))
424−typeOccursCheck :: Int -> Type -> Bool
454+typeOccursCheck :: Bool -> Int -> Type -> Bool
425−typeOccursCheck u (TUnknown u') | u == u' = True
455+typeOccursCheck b u (TUnknown u') | u == u' = b
426−typeOccursCheck u (Array t) = typeOccursCheck u t
456+typeOccursCheck _ u (Array t) = typeOccursCheck True u t
427−typeOccursCheck u (Object row) = rowOccursCheck u row
457+typeOccursCheck _ u (Object row) = rowOccursCheck True u row
428−typeOccursCheck u (Function args ret) = any (typeOccursCheck u) args || typeOccursCheck u ret
458+typeOccursCheck _ u (Function args ret) = any (typeOccursCheck True u) args || typeOccursCheck True u ret
429−typeOccursCheck u (TypeApp s t) = typeOccursCheck u s || typeOccursCheck u t
459+typeOccursCheck _ u (TypeApp s t) = typeOccursCheck True u s || typeOccursCheck True u t
430−typeOccursCheck _ _ = False
460+typeOccursCheck _ _ _ = False
432−rowOccursCheck :: Int -> Row -> Bool
462+rowOccursCheck :: Bool -> Int -> Row -> Bool
433−rowOccursCheck u (RUnknown u') | u == u' = True
463+rowOccursCheck b u (RUnknown u') | u == u' = b
434−rowOccursCheck u (RCons name ty row) = typeOccursCheck u ty || rowOccursCheck u row
464+rowOccursCheck _ u (RCons name ty row) = typeOccursCheck True u ty || rowOccursCheck True u row
435−rowOccursCheck _ _ = False
465+rowOccursCheck _ _ _ = False