module FreeC.Pass.KindCheckPass
( kindCheckPass
, checkType
) where
import Control.Monad ( when )
import Data.Maybe ( fromMaybe )
import FreeC.Environment ( lookupArity )
import qualified FreeC.IR.Syntax as IR
import FreeC.Monad.Converter
import FreeC.Monad.Reporter
import FreeC.Pass
import FreeC.Pretty ( showPretty )
kindCheckPass :: Pass IR.Module IR.Module
kindCheckPass ast = do
mapM_ checkTypeDecl (IR.modTypeDecls ast)
mapM_ checkTypeSig (IR.modTypeSigs ast)
mapM_ checkFuncDecl (IR.modFuncDecls ast)
return ast
checkTypeDecl :: IR.TypeDecl -> Converter ()
checkTypeDecl (IR.DataDecl _ _ _ conDecls) = mapM_ checkConDecl conDecls
checkTypeDecl (IR.TypeSynDecl _ _ _ typeExpr) = checkType typeExpr
checkConDecl :: IR.ConDecl -> Converter ()
checkConDecl (IR.ConDecl _ _ types) = mapM_ checkType types
checkTypeSig :: IR.TypeSig -> Converter ()
checkTypeSig (IR.TypeSig _ _ typeScheme) = checkTypeScheme typeScheme
checkTypeScheme :: IR.TypeScheme -> Converter ()
checkTypeScheme (IR.TypeScheme _ _ typeExpr) = checkType typeExpr
checkFuncDecl :: IR.FuncDecl -> Converter ()
checkFuncDecl (IR.FuncDecl _ _ _ varPats retType rhs) = do
mapM_ checkVarPat varPats
mapM_ checkType retType
checkExpr rhs
checkExpr :: IR.Expr -> Converter ()
checkExpr (IR.Con _ _ typeScheme)
= mapM_ checkTypeScheme typeScheme
checkExpr (IR.Var _ _ typeScheme)
= mapM_ checkTypeScheme typeScheme
checkExpr (IR.App _ lhs rhs typeScheme) = do
checkExpr lhs
checkExpr rhs
mapM_ checkTypeScheme typeScheme
checkExpr (IR.TypeAppExpr _ lhs rhs typeScheme) = do
checkExpr lhs
checkType rhs
mapM_ checkTypeScheme typeScheme
checkExpr (IR.If _ cond thenExpr elseExpr typeScheme) = do
checkExpr cond
checkExpr thenExpr
checkExpr elseExpr
mapM_ checkTypeScheme typeScheme
checkExpr (IR.Case _ scrutinee alts typeScheme) = do
checkExpr scrutinee
mapM_ checkAlt alts
mapM_ checkTypeScheme typeScheme
checkExpr (IR.Undefined _ typeScheme)
= mapM_ checkTypeScheme typeScheme
checkExpr (IR.ErrorExpr _ _ typeScheme)
= mapM_ checkTypeScheme typeScheme
checkExpr (IR.Trace _ _ expr typeScheme) = do
checkExpr expr
mapM_ checkTypeScheme typeScheme
checkExpr (IR.IntLiteral _ _ typeScheme)
= mapM_ checkTypeScheme typeScheme
checkExpr (IR.Lambda _ args rhs typeScheme) = do
mapM_ checkVarPat args
checkExpr rhs
mapM_ checkTypeScheme typeScheme
checkExpr (IR.Let _ binds expr typeScheme) = do
mapM_ checkBind binds
checkExpr expr
mapM_ checkTypeScheme typeScheme
checkAlt :: IR.Alt -> Converter ()
checkAlt (IR.Alt _ _ varPats rhs) = do
mapM_ checkVarPat varPats
checkExpr rhs
checkVarPat :: IR.VarPat -> Converter ()
checkVarPat (IR.VarPat _ _ typeExpr _) = mapM_ checkType typeExpr
checkType :: IR.Type -> Converter ()
checkType = checkType' 0
checkBind :: IR.Bind -> Converter ()
checkBind (IR.Bind _ varPat expr) = do
checkVarPat varPat
checkExpr expr
checkType' :: Int -> IR.Type -> Converter ()
checkType' depth (IR.TypeVar srcSpan varId) = when (depth /= 0)
$ reportFatal
$ Message srcSpan Error
$ "Type variable "
++ varId
++ " occurs on left-hand side of type application."
checkType' depth (IR.TypeCon srcSpan ident) = do
arity <- inEnv $ fromMaybe (-1) . lookupArity IR.TypeScope ident
when (arity /= depth)
$ reportFatal
$ Message srcSpan Error
$ "Type constructor "
++ showPretty ident
++ " is applied to wrong number of arguments: Expected "
++ show arity
++ " but was "
++ show depth
++ "."
checkType' depth (IR.TypeApp _ lhs rhs) = do
checkType' (depth + 1) lhs
checkType rhs
checkType' depth (IR.FuncType srcSpan lhs rhs)
| depth /= 0 = reportFatal
$ Message srcSpan Error
$ "Function type occurs on left-hand side of type application."
| otherwise = do
checkType lhs
checkType rhs