module Program where import Check import Control.Monad.Except import qualified Data.Map.Strict as M import Elaborator import Errors import Eval (Env, checkBeta) import qualified Eval import Expr (Expr) import qualified Expr import IR import Parser (parseProgram) import Preprocessor (runPreprocessor) insertDef :: Text -> Expr -> Expr -> Env -> Env insertDef name ty body = M.insert name (Eval.Def ty body) handleDef :: IRDef -> StateT Env Result () handleDef (Axiom name ty) = do env <- get whenLeft_ (checkType env $ elaborate ty) throwError modify $ insertDef name (elaborate ty) (Expr.Axiom name) handleDef (Def name Nothing irBody) = do env <- get let body = elaborate irBody let ty = checkType env body either throwError (modify . flip (insertDef name) body) ty handleDef (Def name (Just irTy) irBody) = do env <- get let body = elaborate irBody let ty = elaborate irTy let mty' = checkType env body whenLeft_ mty' throwError whenRight_ mty' $ \ty' -> do case checkBeta env ty ty' of Left err -> throwError err Right False -> throwError $ NotEquivalent ty ty' body Right True -> modify $ insertDef name ty' body evalDef :: Env -> IRDef -> Result Env evalDef = flip (execStateT . handleDef) handleProgram :: IRProgram -> Result Env handleProgram = flip execStateT M.empty . mapM_ handleDef handleAndParseProgram :: String -> Text -> Either String Env handleAndParseProgram filename input = (first toString . handleProgram) =<< parseProgram filename input handleAndParseFile :: String -> ExceptT String IO Env handleAndParseFile filename = toString `withExceptT` runPreprocessor filename >>= hoistEither . handleAndParseProgram filename