{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
module Jikka.Core.Convert.CloseAll
( run,
rule,
reduceAll,
reduceAny,
)
where
import Jikka.Common.Alpha
import Jikka.Common.Error
import Jikka.Core.Language.BuiltinPatterns
import Jikka.Core.Language.Expr
import Jikka.Core.Language.Lint
import Jikka.Core.Language.RewriteRules
import Jikka.Core.Language.Util
reduceAll :: MonadAlpha m => RewriteRule m
reduceAll :: RewriteRule m
reduceAll =
let return' :: a -> m (Maybe a)
return' = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m (Maybe a)) -> (a -> Maybe a) -> a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just
in ([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
forall (m :: * -> *).
([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
RewriteRule (([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m)
-> ([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
forall a b. (a -> b) -> a -> b
$ \[(VarName, Type)]
_ -> \case
All' (Nil' Type
_) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' Expr
LitTrue
All' (Cons' Type
_ Expr
x Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
And' Expr
x (Expr -> Expr
All' Expr
xs)
All' (Reversed' Type
_ Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
All' Expr
xs
All' (Sorted' Type
_ Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
All' Expr
xs
All' (Filter' Type
_ Expr
f Expr
xs) -> do
VarName
x <- m VarName
forall (m :: * -> *). MonadAlpha m => m VarName
genVarName'
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
All' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x Type
BoolTy (Expr -> Expr -> Expr
Implies' (Expr -> Expr -> Expr
App Expr
f (VarName -> Expr
Var VarName
x)) (VarName -> Expr
Var VarName
x))) Expr
xs)
All' (Map' Type
_ Type
_ Expr
f Expr
xs) -> case Expr
f of
Lam VarName
x Type
_ (Not' Expr
e) -> do
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
Not' (Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x Type
BoolTy Expr
e) Expr
xs))
Lam VarName
x Type
_ (And' Expr
e1 Expr
e2) -> do
VarName
x1 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
VarName
x2 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
And' (Expr -> Expr
All' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x1 Type
BoolTy Expr
e1) Expr
xs)) (Expr -> Expr
All' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x2 Type
BoolTy Expr
e2) Expr
xs))
Expr
_ -> Maybe Expr -> m (Maybe Expr)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Expr
forall a. Maybe a
Nothing
Expr
_ -> Maybe Expr -> m (Maybe Expr)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Expr
forall a. Maybe a
Nothing
reduceAny :: MonadAlpha m => RewriteRule m
reduceAny :: RewriteRule m
reduceAny =
let return' :: a -> m (Maybe a)
return' = Maybe a -> m (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m (Maybe a)) -> (a -> Maybe a) -> a -> m (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Maybe a
forall a. a -> Maybe a
Just
in ([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
forall (m :: * -> *).
([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
RewriteRule (([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m)
-> ([(VarName, Type)] -> Expr -> m (Maybe Expr)) -> RewriteRule m
forall a b. (a -> b) -> a -> b
$ \[(VarName, Type)]
_ -> \case
Any' (Nil' Type
_) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' Expr
LitFalse
Any' (Cons' Type
_ Expr
x Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
Or' Expr
x (Expr -> Expr
Any' Expr
xs)
Any' (Reversed' Type
_ Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
Any' Expr
xs
Any' (Sorted' Type
_ Expr
xs) -> Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
Any' Expr
xs
Any' (Filter' Type
_ Expr
f Expr
xs) -> do
VarName
x <- m VarName
forall (m :: * -> *). MonadAlpha m => m VarName
genVarName'
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x Type
BoolTy (Expr -> Expr -> Expr
And' (Expr -> Expr -> Expr
App Expr
f (VarName -> Expr
Var VarName
x)) (VarName -> Expr
Var VarName
x))) Expr
xs)
Any' (Map' Type
_ Type
_ Expr
f Expr
xs) -> case Expr
f of
Lam VarName
x Type
_ (Not' Expr
e) -> do
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr
Not' (Expr -> Expr
All' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x Type
BoolTy Expr
e) Expr
xs))
Lam VarName
x Type
_ (Or' Expr
e1 Expr
e2) -> do
VarName
x1 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
VarName
x2 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
Or' (Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x1 Type
BoolTy Expr
e1) Expr
xs)) (Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x2 Type
BoolTy Expr
e2) Expr
xs))
Lam VarName
x Type
_ (Implies' Expr
e1 Expr
e2) -> do
VarName
x1 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
VarName
x2 <- VarName -> m VarName
forall (m :: * -> *). MonadAlpha m => VarName -> m VarName
genVarName VarName
x
Expr -> m (Maybe Expr)
forall a. a -> m (Maybe a)
return' (Expr -> m (Maybe Expr)) -> Expr -> m (Maybe Expr)
forall a b. (a -> b) -> a -> b
$ Expr -> Expr -> Expr
Or' (Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x1 Type
BoolTy (Expr -> Expr
Negate' Expr
e1)) Expr
xs)) (Expr -> Expr
Any' (Type -> Type -> Expr -> Expr -> Expr
Map' Type
BoolTy Type
BoolTy (VarName -> Type -> Expr -> Expr
Lam VarName
x2 Type
BoolTy Expr
e2) Expr
xs))
Expr
_ -> Maybe Expr -> m (Maybe Expr)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Expr
forall a. Maybe a
Nothing
Expr
_ -> Maybe Expr -> m (Maybe Expr)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe Expr
forall a. Maybe a
Nothing
rule :: MonadAlpha m => RewriteRule m
rule :: RewriteRule m
rule =
[RewriteRule m] -> RewriteRule m
forall a. Monoid a => [a] -> a
mconcat
[ RewriteRule m
forall (m :: * -> *). MonadAlpha m => RewriteRule m
reduceAll,
RewriteRule m
forall (m :: * -> *). MonadAlpha m => RewriteRule m
reduceAny
]
runProgram :: (MonadAlpha m, MonadError Error m) => Program -> m Program
runProgram :: Program -> m Program
runProgram = RewriteRule m -> Program -> m Program
forall (m :: * -> *).
MonadError Error m =>
RewriteRule m -> Program -> m Program
applyRewriteRuleProgram' RewriteRule m
forall (m :: * -> *). MonadAlpha m => RewriteRule m
rule
run :: (MonadAlpha m, 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.CloseAll" (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 :: * -> *).
(MonadAlpha 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