module Rzk.Main where

import           Control.Monad       (forM)
import           System.Environment  (getArgs)
import           System.Exit         (exitFailure)

import qualified Language.Rzk.Syntax as Rzk
import           Rzk.TypeCheck

main :: IO ()
main :: IO ()
main = do
  [String]
args <- IO [String]
getArgs
  case [String]
args of
    String
"typecheck" : [String]
paths -> do
      [(String, Module)]
modules <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [String]
paths forall a b. (a -> b) -> a -> b
$ \String
path -> do
        String -> IO ()
putStrLn (String
"Loading file " forall a. Semigroup a => a -> a -> a
<> String
path)
        Either String Module
result <- String -> Either String Module
Rzk.parseModule forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
readFile String
path
        case Either String Module
result of
          Left String
err -> do
            String -> IO ()
putStrLn (String
"An error occurred when parsing file " forall a. Semigroup a => a -> a -> a
<> String
path)
            forall a. HasCallStack => String -> a
error String
err
          Right Module
rzkModule -> forall (m :: * -> *) a. Monad m => a -> m a
return (String
path, Module
rzkModule)
      case forall a.
TypeCheck VarIdent a
-> Either (TypeErrorInScopedContext VarIdent) a
defaultTypeCheck ([(String, Module)] -> TypeCheck VarIdent ()
typecheckModulesWithLocation [(String, Module)]
modules) of
        Left TypeErrorInScopedContext VarIdent
err -> do
          String -> IO ()
putStrLn String
"An error occurred when typechecking!"
          String -> IO ()
putStrLn forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
            [ String
"Type Error:"
            , TypeErrorInScopedContext VarIdent -> String
ppTypeErrorInScopedContext' TypeErrorInScopedContext VarIdent
err
            ]
          forall a. IO a
exitFailure
        Right () -> String -> IO ()
putStrLn String
"Everything is ok!"
    [String]
_ -> IO ()
ppUsage

ppUsage :: IO ()
ppUsage :: IO ()
ppUsage = String -> IO ()
putStrLn String
"rzk typecheck FILE"

typecheckString :: String -> Either String String
typecheckString :: String -> Either String String
typecheckString String
moduleString = do
  Module
rzkModule <- String -> Either String Module
Rzk.parseModule String
moduleString
  case forall a.
TypeCheck VarIdent a
-> Either (TypeErrorInScopedContext VarIdent) a
defaultTypeCheck (Module -> TypeCheck VarIdent [Decl']
typecheckModule Module
rzkModule) of
    Left TypeErrorInScopedContext VarIdent
err -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines
      [ String
"An error occurred when typechecking!"
      , String
"Rendering type error... (this may take a few seconds)"
      , [String] -> String
unlines
        [ String
"Type Error:"
        , TypeErrorInScopedContext VarIdent -> String
ppTypeErrorInScopedContext' TypeErrorInScopedContext VarIdent
err
        ]
      ]
    Right [Decl']
_ -> forall (f :: * -> *) a. Applicative f => a -> f a
pure String
"Everything is ok!"