add full block type checking

This commit is contained in:

View File

@ -79,7 +79,7 @@ typeCheckMethodDeclaration (MethodDeclaration retType name params body) classFie
-- Combine class fields with method parameters to form the initial symbol table for the method -- Combine class fields with method parameters to form the initial symbol table for the method
methodParams = [(dataType, identifier) | ParameterDeclaration dataType identifier <- params] methodParams = [(dataType, identifier) | ParameterDeclaration dataType identifier <- params]
-- Ensure method parameters shadow class fields if names collide -- Ensure method parameters shadow class fields if names collide
initialSymtab = classFields ++ methodParams initialSymtab = classFields ++ methodParams
-- Type check the body of the method using the combined symbol table -- Type check the body of the method using the combined symbol table
checkedBody = typeCheckStatement body initialSymtab classes checkedBody = typeCheckStatement body initialSymtab classes
bodyType = getTypeFromStmt checkedBody bodyType = getTypeFromStmt checkedBody
@ -265,35 +265,27 @@ typeCheckStatement (While cond stmt) symtab classes =
typeCheckStatement (Block statements) symtab classes = typeCheckStatement (Block statements) symtab classes =
let let
-- Helper function to process each statement and manage the symbol table processStatements (accSts, currentSymtab, types) stmt =
processStatements (accSts, currentSymtab) stmt = let
case stmt of checkedStmt = typeCheckStatement stmt currentSymtab classes
stmtType = getTypeFromStmt checkedStmt
in case stmt of
LocalVariableDeclaration (VariableDeclaration dataType identifier maybeExpr) -> LocalVariableDeclaration (VariableDeclaration dataType identifier maybeExpr) ->
let let
-- Type check the expression if it exists
checkedExpr = fmap (\expr -> typeCheckExpression expr currentSymtab classes) maybeExpr checkedExpr = fmap (\expr -> typeCheckExpression expr currentSymtab classes) maybeExpr
-- Update the symbol table with the new variable
newSymtab = (dataType, identifier) : currentSymtab newSymtab = (dataType, identifier) : currentSymtab
newStmt = typeCheckStatement (LocalVariableDeclaration (VariableDeclaration dataType identifier checkedExpr)) newSymtab classes in (accSts ++ [checkedStmt], newSymtab, types)
in (accSts ++ [newStmt], newSymtab)
_ -> If {} -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "Void" then types ++ [stmtType] else types)
-- For other statements, just type check using the current symbol table While _ _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "Void" then types ++ [stmtType] else types)
let checkedStmt = typeCheckStatement stmt currentSymtab classes Return _ -> (accSts ++ [checkedStmt], currentSymtab, if stmtType /= "Void" then types ++ [stmtType])
in (accSts ++ [checkedStmt], currentSymtab) _ -> (accSts ++ [checkedStmt], currentSymtab, types)
-- Fold over the list of statements starting with the initial symbol table -- Initial accumulator: empty statements list, initial symbol table, empty types list
(checkedStatements, finalSymtab) = foldl processStatements ([], symtab) statements (checkedStatements, finalSymtab, collectedTypes) = foldl processStatements ([], symtab, []) statements
-- Determine the type of the block by examining the types of return statements -- Determine the block's type: unify all collected types, default to "Void" if none
blockType = if any isReturnStatement checkedStatements blockType = if null collectedTypes then "Void" else foldl1 unifyReturnTypes collectedTypes
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
in TypedStatement blockType (Block checkedStatements) in TypedStatement blockType (Block checkedStatements)
@ -307,7 +299,7 @@ typeCheckStatement (Return expr) symtab classes =
Nothing -> Nothing Nothing -> Nothing
in case expr' of in case expr' of
Just e' -> TypedStatement (getTypeFromExpr e') (Return (Just e')) Just e' -> TypedStatement (getTypeFromExpr e') (Return (Just e'))
Nothing -> TypedStatement "void" (Return Nothing) Nothing -> TypedStatement "Void" (Return Nothing)
-- ********************************** Type Checking: Helpers ********************************** -- ********************************** Type Checking: Helpers **********************************