{-# LANGUAGE BlockArguments #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where import Control.Exception import qualified Data.ByteString.Lazy as Bsl import qualified Data.Text.Encoding as T import qualified Data.Map.Strict as Map import qualified Data.Text.IO as T import qualified Data.Text as T import Data.Text ( Text ) import Data.Foldable import Elab.Monad import Elab.Eval import Elab import Presyntax.Presyntax (Posn(Posn)) import Presyntax.Parser import Presyntax.Tokens import Presyntax.Lexer import System.Exit import Syntax.Pretty main :: IO () main = do t <- Bsl.readFile "test.tt" let Right tks = runAlex t parseProg env <- runElab (checkProgram tks) emptyEnv `catch` \e -> displayAndDie (T.decodeUtf8 (Bsl.toStrict t)) (e :: SomeException) for_ (Map.toList (getEnv env)) $ \(n, x) -> putStrLn $ show n ++ " : " ++ showValue (zonk (fst x)) displayAndDie :: Exception e => Text -> e -> IO a displayAndDie lines e = do () <- throwIO e `catches` displayExceptions lines exitFailure displayExceptions :: Text -> [Handler ()] displayExceptions lines = [ Handler \(WhileChecking a b e) -> do T.putStrLn $ squiggleUnder a b lines displayExceptions' lines e , Handler \(NotEqual ta tb) -> do putStrLn . unlines $ [ "\x1b[1;31merror\x1b[0m: Mismatch between actual and expected types:" , " * \x1b[1mActual\x1b[0m: " ++ showValue (zonk ta) , " * \x1b[1mExpected\x1b[0m: " ++ showValue (zonk tb) ] ] displayExceptions' :: Exception e => Text -> e -> IO () displayExceptions' lines e = displayAndDie lines e `catch` \(_ :: ExitCode) -> pure () squiggleUnder :: Posn -> Posn -> Text -> Text squiggleUnder (Posn l c) (Posn l' c') file | l == l' = let line = T.pack (show l) <> " | " <> T.lines file !! (l - 1) padding = T.replicate (length (show l)) (T.singleton ' ') <> " |" squiggle = T.replicate c " " <> T.pack "\x1b[1;31m" <> T.replicate (c' - c) "~" <> T.pack "\x1b[0m" in T.unlines [ padding, line, padding <> squiggle ] | otherwise = T.pack (show (Posn l c, Posn l' c'))