diff --git a/src/Typecheck.hs b/src/Typecheck.hs index 5e5efc5..b03155a 100644 --- a/src/Typecheck.hs +++ b/src/Typecheck.hs @@ -2,6 +2,7 @@ module Typecheck where import Data.List (find) import Data.Maybe import Ast +import Debug.Trace (trace) typeCheckCompilationUnit :: CompilationUnit -> CompilationUnit typeCheckCompilationUnit classes = map (`typeCheckClass` classes) classes @@ -256,21 +257,27 @@ typeCheckStatement (While cond stmt) symtab classes = typeCheckStatement (Block statements) symtab classes = let processStatements (accSts, currentSymtab, types) stmt = - let - checkedStmt = typeCheckStatement stmt currentSymtab classes - stmtType = getTypeFromStmt checkedStmt - in case stmt of + case stmt of LocalVariableDeclaration (VariableDeclaration dataType identifier maybeExpr) -> let + alreadyDefined = any (\(id, _) -> id == identifier) currentSymtab + newSymtab = if alreadyDefined + then error ("Variable " ++ identifier ++ " already defined in this scope.") + else (identifier, dataType) : currentSymtab checkedExpr = fmap (\expr -> typeCheckExpression expr currentSymtab classes) maybeExpr - newSymtab = (identifier, dataType) : currentSymtab + checkedStmt = typeCheckStatement stmt newSymtab classes in (accSts ++ [checkedStmt], newSymtab, types) - If {} -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) - While _ _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) - Return _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) - Block _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) - _ -> (accSts ++ [checkedStmt], currentSymtab, types) + _ -> + let + checkedStmt = typeCheckStatement stmt currentSymtab classes + stmtType = getTypeFromStmt checkedStmt + in case stmt of + If {} -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) + While _ _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) + Return _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) + Block _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "void" then types ++ [stmtType] else types) + _ -> (accSts ++ [checkedStmt], currentSymtab, types) -- Initial accumulator: empty statements list, initial symbol table, empty types list (checkedStatements, finalSymtab, collectedTypes) = foldl processStatements ([], symtab, []) statements @@ -280,6 +287,7 @@ typeCheckStatement (Block statements) symtab classes = in TypedStatement blockType (Block checkedStatements) + typeCheckStatement (Return expr) symtab classes = let methodReturnType = fromMaybe (error "Method return type not found in symbol table") (lookup "thisMeth" symtab) expr' = case expr of