add full block type checking
This commit is contained in:
parent
62bd191314
commit
0debfe995d
38
src/Ast.hs
38
src/Ast.hs
@ -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 **********************************
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user