{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE LambdaCase #-}

-- | Main library entry point.

module JL where

import           Data.Aeson
import           Data.ByteString.Lazy (ByteString)
import qualified Data.Map.Strict as M
import           Data.Text (Text)
import qualified Data.Text.IO as T
import           JL.Functions
import           JL.Inferer
import           JL.Interpreter
import           JL.Parser
import           JL.Printer
import           JL.Serializer
import           JL.Types

repl :: Text -> ByteString -> IO ()
repl :: Text -> ByteString -> IO ()
repl Text
inp ByteString
js =
  case ByteString -> Maybe Value
forall a. FromJSON a => ByteString -> Maybe a
decode ByteString
js of
    Maybe Value
Nothing -> [Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error [Char]
"Invalid JSON"
    Just Value
j ->
      case [Char] -> Text -> Either SomeException Expression
forall (m :: * -> *).
MonadThrow m =>
[Char] -> Text -> m Expression
parseText [Char]
"" Text
inp of
        Left SomeException
err -> [Char] -> IO ()
forall a. HasCallStack => [Char] -> a
error (SomeException -> [Char]
forall a. Show a => a -> [Char]
show SomeException
err)
        Right Expression
expr0 -> do
          Text -> IO ()
T.putStrLn
            (Expression -> Text
prettyExp Expression
expr Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" : " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
             Type -> Text
prettyType (Map Variable Type -> Expression -> [TypeVariable] -> Type
infer Map Variable Type
context Expression
expr ((Int -> TypeVariable) -> [Int] -> [TypeVariable]
forall a b. (a -> b) -> [a] -> [b]
map Int -> TypeVariable
TypeVariable [Int
1 ..])))
          Text -> IO ()
T.putStrLn
            (Core -> Text
prettyCore
               (Core -> Core
eval ((Core -> (Variable, Core) -> Core)
-> Core -> [(Variable, Core)] -> Core
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Core
e (Variable
v, Core
f) -> Variable -> Core -> Core -> Core
subst Variable
v Core
f Core
e) (Expression -> Core
desugar Expression
expr) (Map Variable Core -> [(Variable, Core)]
forall k a. Map k a -> [(k, a)]
M.toList Map Variable Core
scope))))
          where expr :: Expression
expr = Expression -> Expression -> Expression
ApplicationExpression Expression
expr0 (Value -> Expression
valueToExpression Value
j)