{-# LANGUAGE FlexibleContexts #-}

-- |
-- Module      : Jikka.Core.Convert.ArithmeticalExpr
-- Description : sorts arithmetical exprs. / 算術式を整理します。
-- Copyright   : (c) Kimiyuki Onaka, 2021
-- License     : Apache License 2.0
-- Maintainer  : kimiyuki95@gmail.com
-- Stability   : experimental
-- Portability : portable
module Jikka.Core.Convert.ArithmeticalExpr
  ( run,
  )
where

import Jikka.Common.Error
import Jikka.Core.Language.ArithmeticalExpr
import Jikka.Core.Language.Expr
import Jikka.Core.Language.Lint
import Jikka.Core.Language.TypeCheck
import Jikka.Core.Language.Util

runExpr :: MonadError Error m => [(VarName, Type)] -> Expr -> m Expr
runExpr :: [(VarName, Type)] -> Expr -> m Expr
runExpr [(VarName, Type)]
env Expr
e = do
  Type
t <- [(VarName, Type)] -> Expr -> m Type
forall (m :: * -> *).
MonadError Error m =>
[(VarName, Type)] -> Expr -> m Type
typecheckExpr [(VarName, Type)]
env Expr
e
  if Type
t Type -> Type -> Bool
forall a. Eq a => a -> a -> Bool
== Type
IntTy
    then Expr -> m Expr
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr -> m Expr)
-> (ArithmeticalExpr -> Expr) -> ArithmeticalExpr -> m Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ArithmeticalExpr -> Expr
formatArithmeticalExpr (ArithmeticalExpr -> m Expr) -> ArithmeticalExpr -> m Expr
forall a b. (a -> b) -> a -> b
$ Expr -> ArithmeticalExpr
parseArithmeticalExpr Expr
e
    else Expr -> m Expr
forall (m :: * -> *) a. Monad m => a -> m a
return Expr
e

runProgram :: MonadError Error m => Program -> m Program
runProgram :: Program -> m Program
runProgram = ([(VarName, Type)] -> Expr -> m Expr) -> Program -> m Program
forall (m :: * -> *).
Monad m =>
([(VarName, Type)] -> Expr -> m Expr) -> Program -> m Program
mapExprProgramM [(VarName, Type)] -> Expr -> m Expr
forall (m :: * -> *).
MonadError Error m =>
[(VarName, Type)] -> Expr -> m Expr
runExpr -- Doesn't use RewriteRules because the rewriting may not terminate.

-- | `run` sorts arithmetical exprs.
--
-- == Examples
--
-- Before:
--
-- > 1 + a * 1 + b - b
--
-- After:
--
-- > a + 1
run :: MonadError Error m => Program -> m Program
run :: Program -> m Program
run Program
prog = String -> m Program -> m Program
forall (m :: * -> *) a. MonadError Error m => String -> m a -> m a
wrapError' String
"Jikka.Core.Convert.ArithmeticalExpr" (m Program -> m Program) -> m Program -> m Program
forall a b. (a -> b) -> a -> b
$ do
  m () -> m ()
forall (m :: * -> *) a. MonadError Error m => m a -> m a
precondition (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
    Program -> m ()
forall (m :: * -> *). MonadError Error m => Program -> m ()
ensureWellTyped Program
prog
  Program
prog <- Program -> m Program
forall (m :: * -> *). MonadError Error m => Program -> m Program
runProgram Program
prog
  m () -> m ()
forall (m :: * -> *) a. MonadError Error m => m a -> m a
postcondition (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
    Program -> m ()
forall (m :: * -> *). MonadError Error m => Program -> m ()
ensureWellTyped Program
prog
  Program -> m Program
forall (m :: * -> *) a. Monad m => a -> m a
return Program
prog