{-# LANGUAGE FlexibleContexts #-}

module Jikka.RestrictedPython.Convert
  ( run,
    run',
  )
where

import Jikka.Common.Alpha
import Jikka.Common.Error
import Jikka.Common.IOFormat
import qualified Jikka.Core.Language.Expr as Y
import qualified Jikka.RestrictedPython.Convert.Alpha as Alpha
import qualified Jikka.RestrictedPython.Convert.DefaultMain as DefaultMain
import qualified Jikka.RestrictedPython.Convert.ParseMain as ParseMain
import qualified Jikka.RestrictedPython.Convert.RemoveUnbalancedIf as RemoveUnbalancedIf
import qualified Jikka.RestrictedPython.Convert.RemoveUnreachable as RemoveUnreachable
import qualified Jikka.RestrictedPython.Convert.ResolveBuiltin as ResolveBuiltin
import qualified Jikka.RestrictedPython.Convert.SplitLoops as SplitLoops
import qualified Jikka.RestrictedPython.Convert.ToCore as ToCore
import qualified Jikka.RestrictedPython.Convert.TypeInfer as TypeInfer
import qualified Jikka.RestrictedPython.Convert.UseAppend as UseAppend
import qualified Jikka.RestrictedPython.Language.Expr as X

run' :: (MonadAlpha m, MonadError Error m) => X.Program -> m (X.Program, IOFormat)
run' :: Program -> m (Program, IOFormat)
run' Program
prog = do
  Program
prog <- Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> m Program) -> Program -> m Program
forall a b. (a -> b) -> a -> b
$ Program -> Program
RemoveUnreachable.run Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> m Program) -> Program -> m Program
forall a b. (a -> b) -> a -> b
$ Program -> Program
RemoveUnbalancedIf.run Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
UseAppend.run Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
ResolveBuiltin.run Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
Alpha.run Program
prog
  (Maybe IOFormat
format, Program
prog) <- Program -> m (Maybe IOFormat, Program)
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m (Maybe IOFormat, Program)
ParseMain.run Program
prog -- Run ParseMain before type inference because main function has different semantics.
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
TypeInfer.run Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
SplitLoops.run Program
prog
  IOFormat
format <- m IOFormat
-> (IOFormat -> m IOFormat) -> Maybe IOFormat -> m IOFormat
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Program -> m IOFormat
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m IOFormat
DefaultMain.run Program
prog) IOFormat -> m IOFormat
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe IOFormat
format
  (Program, IOFormat) -> m (Program, IOFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return (Program
prog, IOFormat
format)

run :: (MonadAlpha m, MonadError Error m) => X.Program -> m (Y.Program, IOFormat)
run :: Program -> m (Program, IOFormat)
run Program
prog = do
  (Program
prog, IOFormat
format) <- Program -> m (Program, IOFormat)
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m (Program, IOFormat)
run' Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *).
(MonadAlpha m, MonadError Error m) =>
Program -> m Program
ToCore.run Program
prog
  (Program, IOFormat) -> m (Program, IOFormat)
forall (m :: * -> *) a. Monad m => a -> m a
return (Program
prog, IOFormat
format)