{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
module Jikka.Main.Subcommand.Convert (run) where
import Data.Text (Text, pack)
import qualified Jikka.CPlusPlus.Convert as FromCore
import qualified Jikka.CPlusPlus.Format as FormatCPlusPlus
import qualified Jikka.CPlusPlus.Language.Expr as CPlusPlus
import Jikka.Common.Alpha
import Jikka.Common.Error
import qualified Jikka.Core.Convert as Convert
import qualified Jikka.Core.Format as FormatCore
import qualified Jikka.Core.Language.Expr as Core
import qualified Jikka.Core.Parse as ParseCore
import Jikka.Main.Target
import qualified Jikka.Python.Convert.ToRestrictedPython as ToRestrictedPython
import qualified Jikka.Python.Language.Expr as Python
import qualified Jikka.Python.Parse as ParsePython
import qualified Jikka.RestrictedPython.Convert as ToCore
import qualified Jikka.RestrictedPython.Format as FormatRestrictedPython
import qualified Jikka.RestrictedPython.Language.Expr as RestrictedPython
data Program
= PythonProgram Python.Program
| RestrictedPythonProgram RestrictedPython.Program
| CoreProgram Core.Program
| CPlusPlusProgram CPlusPlus.Program
deriving (Program -> Program -> Bool
(Program -> Program -> Bool)
-> (Program -> Program -> Bool) -> Eq Program
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Program -> Program -> Bool
$c/= :: Program -> Program -> Bool
== :: Program -> Program -> Bool
$c== :: Program -> Program -> Bool
Eq, Eq Program
Eq Program
-> (Program -> Program -> Ordering)
-> (Program -> Program -> Bool)
-> (Program -> Program -> Bool)
-> (Program -> Program -> Bool)
-> (Program -> Program -> Bool)
-> (Program -> Program -> Program)
-> (Program -> Program -> Program)
-> Ord Program
Program -> Program -> Bool
Program -> Program -> Ordering
Program -> Program -> Program
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Program -> Program -> Program
$cmin :: Program -> Program -> Program
max :: Program -> Program -> Program
$cmax :: Program -> Program -> Program
>= :: Program -> Program -> Bool
$c>= :: Program -> Program -> Bool
> :: Program -> Program -> Bool
$c> :: Program -> Program -> Bool
<= :: Program -> Program -> Bool
$c<= :: Program -> Program -> Bool
< :: Program -> Program -> Bool
$c< :: Program -> Program -> Bool
compare :: Program -> Program -> Ordering
$ccompare :: Program -> Program -> Ordering
$cp1Ord :: Eq Program
Ord, ReadPrec [Program]
ReadPrec Program
Int -> ReadS Program
ReadS [Program]
(Int -> ReadS Program)
-> ReadS [Program]
-> ReadPrec Program
-> ReadPrec [Program]
-> Read Program
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Program]
$creadListPrec :: ReadPrec [Program]
readPrec :: ReadPrec Program
$creadPrec :: ReadPrec Program
readList :: ReadS [Program]
$creadList :: ReadS [Program]
readsPrec :: Int -> ReadS Program
$creadsPrec :: Int -> ReadS Program
Read, Int -> Program -> ShowS
[Program] -> ShowS
Program -> String
(Int -> Program -> ShowS)
-> (Program -> String) -> ([Program] -> ShowS) -> Show Program
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Program] -> ShowS
$cshowList :: [Program] -> ShowS
show :: Program -> String
$cshow :: Program -> String
showsPrec :: Int -> Program -> ShowS
$cshowsPrec :: Int -> Program -> ShowS
Show)
parseProgram :: (MonadAlpha m, MonadError Error m) => Target -> FilePath -> Text -> m Program
parseProgram :: Target -> String -> Text -> m Program
parseProgram Target
source String
path Text
input = case Target
source of
Target
PythonTarget -> Program -> Program
PythonProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Text -> m Program
forall (m :: * -> *).
MonadError Error m =>
String -> Text -> m Program
ParsePython.run String
path Text
input
Target
RestrictedPythonTarget -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from restricted Python"
Target
CoreTarget -> Program -> Program
CoreProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Text -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
String -> Text -> m Program
ParseCore.run String
path Text
input
Target
CPlusPlusTarget -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from C++"
convertProgram :: (MonadAlpha m, MonadError Error m) => Program -> Target -> m Program
convertProgram :: Program -> Target -> m Program
convertProgram Program
prog Target
target = case (Program
prog, Target
target) of
(PythonProgram Program
_, Target
PythonTarget) -> Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return Program
prog
(RestrictedPythonProgram Program
_, Target
RestrictedPythonTarget) -> Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return Program
prog
(CoreProgram Program
prog, Target
CoreTarget) -> Program -> Program
CoreProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
Convert.run Program
prog
(CPlusPlusProgram Program
_, Target
CPlusPlusTarget) -> Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return Program
prog
(RestrictedPythonProgram Program
_, Target
PythonTarget) -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from restricted Python to Python"
(CoreProgram Program
_, Target
PythonTarget) -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from core to Python"
(CoreProgram Program
_, Target
RestrictedPythonTarget) -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from core to restricted Python"
(PythonProgram Program
prog, Target
_) -> do
Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
ToRestrictedPython.run Program
prog
Program -> Target -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> Target -> m Program
convertProgram (Program -> Program
RestrictedPythonProgram Program
prog) Target
target
(RestrictedPythonProgram Program
prog, Target
CoreTarget) -> do
(Program
prog, IOFormat
_) <- Program -> m (Program, IOFormat)
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m (Program, IOFormat)
ToCore.run Program
prog
Program -> Program
CoreProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
Convert.run Program
prog
(RestrictedPythonProgram Program
prog, Target
CPlusPlusTarget) -> do
(Program
prog, IOFormat
format) <- Program -> m (Program, IOFormat)
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m (Program, IOFormat)
ToCore.run Program
prog
Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
Convert.run Program
prog
Program -> Program
CPlusPlusProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Program -> Maybe IOFormat -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> Maybe IOFormat -> m Program
FromCore.run Program
prog (IOFormat -> Maybe IOFormat
forall a. a -> Maybe a
Just IOFormat
format)
(CoreProgram Program
prog, Target
CPlusPlusTarget) -> do
Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
Convert.run Program
prog
Program -> Program
CPlusPlusProgram (Program -> Program) -> m Program -> m Program
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Program -> Maybe IOFormat -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> Maybe IOFormat -> m Program
FromCore.run Program
prog Maybe IOFormat
forall a. Maybe a
Nothing
(CPlusPlusProgram Program
_, Target
_) -> String -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a
throwCommandLineError String
"cannot convert from C++"
formatProgram :: (MonadAlpha m, MonadError Error m) => Program -> m Text
formatProgram :: Program -> m Text
formatProgram = \case
PythonProgram Program
prog -> Text -> m Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> m Text) -> (String -> Text) -> String -> m Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
pack (String -> m Text) -> String -> m Text
forall a b. (a -> b) -> a -> b
$ Program -> String
forall a. Show a => a -> String
show Program
prog
RestrictedPythonProgram Program
prog -> Program -> m Text
forall (m :: * -> *). Applicative m => Program -> m Text
FormatRestrictedPython.run Program
prog
CoreProgram Program
prog -> Program -> m Text
forall (m :: * -> *). Applicative m => Program -> m Text
FormatCore.run Program
prog
CPlusPlusProgram Program
prog -> Program -> m Text
forall (m :: * -> *). Applicative m => Program -> m Text
FormatCPlusPlus.run Program
prog
run :: Target -> Target -> FilePath -> Text -> Either Error Text
run :: Target -> Target -> String -> Text -> Either Error Text
run Target
source Target
target String
path Text
input = (AlphaT (Either Error) Text -> Int -> Either Error Text)
-> Int -> AlphaT (Either Error) Text -> Either Error Text
forall a b c. (a -> b -> c) -> b -> a -> c
flip AlphaT (Either Error) Text -> Int -> Either Error Text
forall (m :: * -> *) a. Functor m => AlphaT m a -> Int -> m a
evalAlphaT Int
0 (AlphaT (Either Error) Text -> Either Error Text)
-> AlphaT (Either Error) Text -> Either Error Text
forall a b. (a -> b) -> a -> b
$ do
Program
prog <- Target -> String -> Text -> AlphaT (Either Error) Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Target -> String -> Text -> m Program
parseProgram Target
source String
path Text
input
Program
prog <- Program -> Target -> AlphaT (Either Error) Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> Target -> m Program
convertProgram Program
prog Target
target
Program -> AlphaT (Either Error) Text
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Text
formatProgram Program
prog