{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}

-- |
-- Module      : Jikka.CPlusPlus.Convert.OptimizeRange
-- Description : reduces about @range@ function. / @range@ 関数について簡約します。
-- Copyright   : (c) Kimiyuki Onaka, 2020
-- License     : Apache License 2.0
-- Maintainer  : kimiyuki95@gmail.com
-- Stability   : experimental
-- Portability : portable
module Jikka.CPlusPlus.Convert.OptimizeRange
  ( run,
  )
where

import Jikka.CPlusPlus.Language.Expr
import Jikka.CPlusPlus.Language.Util
import Jikka.Common.Error

runExpr :: Monad m => Expr -> m Expr
runExpr :: Expr -> m Expr
runExpr = \case
  Call Function
At [Call Function
Range [Expr
_], Expr
i] -> Expr -> m Expr
forall (m :: * -> *) a. Monad m => a -> m a
return Expr
i
  Call Function
MethodSize [Call Function
Range [Expr
n]] -> Expr -> m Expr
forall (m :: * -> *) a. Monad m => a -> m a
return Expr
n
  Expr
e -> Expr -> m Expr
forall (m :: * -> *) a. Monad m => a -> m a
return Expr
e

runStatement :: Monad m => Statement -> m Statement
runStatement :: Statement -> m Statement
runStatement = \case
  ForEach Type
_ VarName
x (Call Function
Range [Expr
n]) [Statement]
body -> Statement -> m Statement
forall (m :: * -> *) a. Monad m => a -> m a
return (Statement -> m Statement) -> Statement -> m Statement
forall a b. (a -> b) -> a -> b
$ VarName -> Expr -> [Statement] -> Statement
repStatement VarName
x Expr
n [Statement]
body -- TODO: check n is not updated in body
  Statement
stmt -> Statement -> m Statement
forall (m :: * -> *) a. Monad m => a -> m a
return Statement
stmt

runProgram :: Monad m => Program -> m Program
runProgram :: Program -> m Program
runProgram = (Expr -> m Expr)
-> (Statement -> m Statement) -> Program -> m Program
forall (m :: * -> *).
Monad m =>
(Expr -> m Expr)
-> (Statement -> m Statement) -> Program -> m Program
mapExprStatementProgramM Expr -> m Expr
forall (m :: * -> *). Monad m => Expr -> m Expr
runExpr Statement -> m Statement
forall (m :: * -> *). Monad m => Statement -> m Statement
runStatement

-- | `run` replaces superfluous copying.
--
-- == Examples
--
-- Before:
--
-- > int b = range(a).size();
--
-- After:
--
-- > int b = a;
--
-- Before:
--
-- > for (int i : jikka::range(n)) {
-- >     ...
-- > }
--
-- After:
--
-- > for (int i = 0; i < n; ++ i) {
-- >     ...
-- > }
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.CPlusPlus.Convert.OptimizeRange" (m Program -> m Program) -> m Program -> m Program
forall a b. (a -> b) -> a -> b
$ do
  Program -> m Program
forall (m :: * -> *). Monad m => Program -> m Program
runProgram Program
prog