add full block type checking
This commit is contained in:
parent
62bd191314
commit
0debfe995d
40
src/Ast.hs
40
src/Ast.hs
@ -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
|
||||
methodParams = [(dataType, identifier) | ParameterDeclaration dataType identifier <- params]
|
||||
-- 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
|
||||
checkedBody = typeCheckStatement body initialSymtab classes
|
||||
bodyType = getTypeFromStmt checkedBody
|
||||
@ -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 **********************************
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user