add full block type checking

This commit is contained in:

View File

@ -265,35 +265,27 @@ typeCheckStatement (While cond stmt) symtab classes =
typeCheckStatement (Block statements) symtab classes =
let
-- Helper function to process each statement and manage the symbol table
processStatements (accSts, currentSymtab) stmt =
case stmt of
processStatements (accSts, currentSymtab, types) stmt =
let
checkedStmt = typeCheckStatement stmt currentSymtab classes
stmtType = getTypeFromStmt checkedStmt
in case stmt of
LocalVariableDeclaration (VariableDeclaration dataType identifier maybeExpr) ->
let
-- Type check the expression if it exists
checkedExpr = fmap (\expr -> typeCheckExpression expr currentSymtab classes) maybeExpr
-- Update the symbol table with the new variable
newSymtab = (dataType, identifier) : currentSymtab
newStmt = typeCheckStatement (LocalVariableDeclaration (VariableDeclaration dataType identifier checkedExpr)) newSymtab classes
in (accSts ++ [newStmt], newSymtab)
in (accSts ++ [checkedStmt], newSymtab, types)
_ ->
-- For other statements, just type check using the current symbol table
let checkedStmt = typeCheckStatement stmt currentSymtab classes
in (accSts ++ [checkedStmt], currentSymtab)
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])
_ -> (accSts ++ [checkedStmt], currentSymtab, types)
-- Fold over the list of statements starting with the initial symbol table
(checkedStatements, finalSymtab) = foldl processStatements ([], symtab) statements
-- Initial accumulator: empty statements list, initial symbol table, empty types list
(checkedStatements, finalSymtab, collectedTypes) = foldl processStatements ([], symtab, []) statements
-- Determine the type of the block by examining the types of return statements
blockType = if any isReturnStatement checkedStatements
then foldl1 unifyReturnTypes [getTypeFromStmt s | s <- checkedStatements, isReturnStatement s]
else "Void"
-- Function to check if a statement is a return statement
isReturnStatement (Return _) = True
isReturnStatement _ = False
-- Determine the block's type: unify all collected types, default to "Void" if none
blockType = if null collectedTypes then "Void" else foldl1 unifyReturnTypes collectedTypes
in TypedStatement blockType (Block checkedStatements)
@ -307,7 +299,7 @@ typeCheckStatement (Return expr) symtab classes =
Nothing -> Nothing
in case expr' of
Just e' -> TypedStatement (getTypeFromExpr e') (Return (Just e'))
Nothing -> TypedStatement "void" (Return Nothing)
Nothing -> TypedStatement "Void" (Return Nothing)
-- ********************************** Type Checking: Helpers **********************************