@@ -368,13 +368,17 @@ typeConstraintsForBinders m nval ret ((binder, val):bs) = do
368368 cs3 <- typeConstraintsForBinders m nval ret bs
369369 return ((TypeConstraint n2 (TUnknown ret)) : cs1 ++ cs2 ++ cs3)
370370
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."
376+
371377typeConstraintsForStatement :: M.Map Ident Int -> M.Map Ident Int -> Int -> Statement -> Check ([TypeConstraint], Bool, M.Map Ident Int)
372378typeConstraintsForStatement m mass ret (VariableIntroduction name val) = do
373− case M.lookup name (m `M.union` mass) of
374− Nothing -> do
375− (cs1, n1) <- typeConstraints m val
376− return $ (cs1, False, M.insert name n1 mass)
377− Just ty -> throwError $ "Variable with name " ++ show name ++ " already exists."
379+ assignVariable name (m `M.union` mass)
380+ (cs1, n1) <- typeConstraints m val
381+ return $ (cs1, False, M.insert name n1 mass)
378382typeConstraintsForStatement m mass ret (Assignment tgt val) = do
379383 (cs1, n1) <- typeConstraints m val
380384 cs2 <- typeConstraintsForAssignmentTarget m mass n1 tgt
@@ -386,14 +390,21 @@ typeConstraintsForStatement m mass ret (While val inner) = do
386390typeConstraintsForStatement m mass ret (If ifst) = do
387391 (cs, allCodePathsReturn) <- typeConstraintsForIfStatement m mass ret ifst
388392 return $ (cs, allCodePathsReturn, mass)
389−typeConstraintsForStatement m mass ret (For (init, cond, cont) inner) = do
390− (cs1, b1, mass1) <- typeConstraintsForStatement m mass ret init
391− guardWith "Cannot return from inside for" $ not b1
392− (cs2, n1) <- typeConstraints (m `M.union` mass1) cond
393− (cs3, b2, mass2) <- typeConstraintsForStatement (m `M.union` mass1) mass1 ret cont
394− guardWith "Cannot return from inside for" $ not b2
395− (cs4, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass2) mass2 ret inner
396− return $ ((TypeConstraint n1 Boolean) : cs1 ++ cs2 ++ cs3 ++ cs4, allCodePathsReturn, mass)
393+typeConstraintsForStatement m mass ret (For ident start end inner) = do
394+ assignVariable ident (m `M.union` mass)
395+ (cs1, n1) <- typeConstraints (m `M.union` mass) start
396+ (cs2, n2) <- typeConstraints (m `M.union` mass) end
397+ let mass1 = M.insert ident n1 mass
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)
402+ val <- fresh
403+ (cs1, n1) <- typeConstraints (m `M.union` mass) vals
404+ let mass1 = M.insert ident val mass
405+ (cs2, allCodePathsReturn, _) <- typeConstraintsForBlock (m `M.union` mass1) mass1 ret inner
406+ guardWith "Cannot return from within a foreach block" $ not allCodePathsReturn
407+ return $ ((TypeConstraint n1 (Array (TUnknown val))) : cs1 ++ cs2, False, mass)
397408typeConstraintsForStatement m mass ret (Return val) = do
398409 (cs1, n1) <- typeConstraints (m `M.union` mass) val
399410 return ((TypeConstraint n1 (TUnknown ret)) : cs1, True, mass)