@@ -368,13 +368,17 @@ typeConstraintsForBinders m nval ret ((binder, val):bs) = do
368 cs3 <- typeConstraintsForBinders m nval ret bs
368 cs3 <- typeConstraintsForBinders m nval ret bs
369 return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
369 return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
371+assignVariable :: Ident -> M.Map Ident Int -> Check ()
372+assignVariable name m =
373+ case M.lookup name m of
374+ Nothing -> return ()
375+ Just _ -> throwError $ "Variable with name " ++ show name ++ " already exists."
371typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
377typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
372typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
378typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
373− case M.lookup name (m `M.union` mass) of
379+ assignVariable name (m `M.union` mass)
375− (cs1, n1) <- typeConstraints m val
380+ (cs1, n1) <- typeConstraints m val
376− return $ (cs1, False, M.insert name n1 mass)
381+ return $ (cs1, False, M.insert name n1 mass)
377− Just ty -> throwError $ "Variable with name " ++ show name ++ " already exists."
378typeConstraintsForStatement m mass ret (Assignment tgt val) = do
382typeConstraintsForStatement m mass ret (Assignment tgt val) = do
379 (cs1, n1) <- typeConstraints m val
383 (cs1, n1) <- typeConstraints m val
380 cs2 <- typeConstraintsForAssignmentTarget m mass n1 tgt
384 cs2 <- typeConstraintsForAssignmentTarget m mass n1 tgt
@@ -386,14 +390,21 @@ typeConstraintsForStatement m mass ret (While val inner) = do
386typeConstraintsForStatement m mass ret (If ifst) = do
390typeConstraintsForStatement m mass ret (If ifst) = do
387 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
391 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
388 return $ (cs, allCodePathsReturn, mass)
392 return $ (cs, allCodePathsReturn, mass)
389−typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
393+typeConstraintsForStatement m mass ret (For ident start end inner) = do
390− (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
394+ assignVariable ident (m `M.union` mass)
391− guardWith "Cannot return from inside for" $ not b1
395+ (cs1, n1) <- typeConstraints (m `M.union` mass) start
392− (cs2, n1) <- typeConstraints (m `M.union` mass1) cond
396+ (cs2, n2) <- typeConstraints (m `M.union` mass) end
393− (cs3, b2, mass2) <- typeConstraintsForStatement (m `M.union` mass1) mass1 ret cont
397+ let mass1 = M.insert ident n1 mass
394− guardWith "Cannot return from inside for" $ not b2
398+ (cs3, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
399+ return $ ((TypeConstraint n1 Number) : (TypeConstraint n2 Number) : cs1 ++ cs2 ++ cs3, allCodePathsReturn, mass)
400+typeConstraintsForStatement m mass ret (ForEach ident vals inner) = do
401+ assignVariable ident (m `M.union` mass)
403+ (cs1, n1) <- typeConstraints (m `M.union` mass) vals
404+ let mass1 = M.insert ident val mass
395− (cs4, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass2) mass2 ret inner
405+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
406+ guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
396− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3 ++ cs4, allCodePathsReturn, mass)
407+ return $ ((TypeConstraint n1 (Array (TUnknown val))) : cs1 ++ cs2, False, mass)
397typeConstraintsForStatement m mass ret (Return val) = do
408typeConstraintsForStatement m mass ret (Return val) = do
398 (cs1, n1) <- typeConstraints (m `M.union` mass) val
409 (cs1, n1) <- typeConstraints (m `M.union` mass) val
399 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)
410 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)