{-# LANGUAGE PatternGuards, Trustworthy #-}
module Cryptol.TypeCheck.SimpleSolver ( simplify , simplifyStep) where

import Cryptol.TypeCheck.Type hiding
  ( tSub, tMul, tDiv, tMod, tExp, tMin, tLenFromThenTo)
import Cryptol.TypeCheck.Solver.Types
import Cryptol.TypeCheck.Solver.Numeric.Fin(cryIsFinType)
import Cryptol.TypeCheck.Solver.Numeric(cryIsEqual, cryIsNotEqual, cryIsGeq, cryIsPrime)
import Cryptol.TypeCheck.Solver.Class
  ( solveZeroInst, solveLogicInst, solveRingInst
  , solveIntegralInst, solveFieldInst, solveRoundInst
  , solveEqInst, solveCmpInst, solveSignedCmpInst
  , solveLiteralInst
  , solveLiteralLessThanInst
  , solveValidFloat, solveFLiteralInst
  )

import Cryptol.Utils.Debug(ppTrace)
import Cryptol.TypeCheck.PP


simplify :: Ctxt -> Prop -> Prop
simplify :: Ctxt -> Prop -> Prop
simplify Ctxt
ctxt Prop
p =
  case Ctxt -> Prop -> Solved
simplifyStep Ctxt
ctxt Prop
p of
    Solved
Unsolvable  -> case Prop -> Maybe Prop
tIsError Prop
p of
                     Maybe Prop
Nothing -> Prop -> Prop
tError Prop
p
                     Maybe Prop
_       -> Prop
p
    Solved
Unsolved    -> Doc -> Prop -> Prop
forall p. Doc -> p -> p
dbg Doc
msg Prop
p
      where msg :: Doc
msg = String -> Doc
text String
"unsolved:" Doc -> Doc -> Doc
<+> Prop -> Doc
forall a. PP a => a -> Doc
pp Prop
p
    SolvedIf [Prop]
ps -> Doc -> Prop -> Prop
forall p. Doc -> p -> p
dbg Doc
msg (Prop -> Prop) -> Prop -> Prop
forall a b. (a -> b) -> a -> b
$ [Prop] -> Prop
pAnd ((Prop -> Prop) -> [Prop] -> [Prop]
forall a b. (a -> b) -> [a] -> [b]
map (Ctxt -> Prop -> Prop
simplify Ctxt
ctxt) [Prop]
ps)
     where msg :: Doc
msg = case [Prop]
ps of
                    [] -> String -> Doc
text String
"solved:" Doc -> Doc -> Doc
<+> Prop -> Doc
forall a. PP a => a -> Doc
pp Prop
p
                    [Prop]
_  -> Prop -> Doc
forall a. PP a => a -> Doc
pp Prop
p Doc -> Doc -> Doc
<+> String -> Doc
text String
"~~~>" Doc -> Doc -> Doc
<+>
                          [Doc] -> Doc
vcat (Doc -> [Doc] -> [Doc]
punctuate Doc
comma ((Prop -> Doc) -> [Prop] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map Prop -> Doc
forall a. PP a => a -> Doc
pp [Prop]
ps))

  where
  dbg :: Doc -> p -> p
dbg Doc
msg p
x
    | Bool
False     = Doc -> p -> p
forall p. Doc -> p -> p
ppTrace Doc
msg p
x
    | Bool
otherwise = p
x


simplifyStep :: Ctxt -> Prop -> Solved
simplifyStep :: Ctxt -> Prop -> Solved
simplifyStep Ctxt
ctxt Prop
prop =
  case Prop -> Prop
tNoUser Prop
prop of
    TCon (PC PC
PTrue)  []        -> [Prop] -> Solved
SolvedIf []
    TCon (PC PC
PAnd)   [Prop
l,Prop
r]     -> [Prop] -> Solved
SolvedIf [Prop
l,Prop
r]

    TCon (PC PC
PZero)  [Prop
ty]      -> Prop -> Solved
solveZeroInst Prop
ty
    TCon (PC PC
PLogic) [Prop
ty]      -> Prop -> Solved
solveLogicInst Prop
ty
    TCon (PC PC
PRing)  [Prop
ty]      -> Prop -> Solved
solveRingInst Prop
ty
    TCon (PC PC
PField) [Prop
ty]      -> Prop -> Solved
solveFieldInst Prop
ty
    TCon (PC PC
PIntegral) [Prop
ty]   -> Prop -> Solved
solveIntegralInst Prop
ty
    TCon (PC PC
PRound) [Prop
ty]      -> Prop -> Solved
solveRoundInst Prop
ty

    TCon (PC PC
PEq)    [Prop
ty]      -> Prop -> Solved
solveEqInst Prop
ty
    TCon (PC PC
PCmp)   [Prop
ty]      -> Prop -> Solved
solveCmpInst Prop
ty
    TCon (PC PC
PSignedCmp) [Prop
ty]  -> Prop -> Solved
solveSignedCmpInst Prop
ty
    TCon (PC PC
PLiteral) [Prop
t1,Prop
t2] -> Prop -> Prop -> Solved
solveLiteralInst Prop
t1 Prop
t2
    TCon (PC PC
PLiteralLessThan) [Prop
t1,Prop
t2] -> Prop -> Prop -> Solved
solveLiteralLessThanInst Prop
t1 Prop
t2
    TCon (PC PC
PFLiteral) [Prop
t1,Prop
t2,Prop
t3,Prop
t4] -> Prop -> Prop -> Prop -> Prop -> Solved
solveFLiteralInst Prop
t1 Prop
t2 Prop
t3 Prop
t4

    TCon (PC PC
PValidFloat) [Prop
t1,Prop
t2] -> Prop -> Prop -> Solved
solveValidFloat Prop
t1 Prop
t2
    TCon (PC PC
PPrime) [Prop
ty]      -> Ctxt -> Prop -> Solved
cryIsPrime Ctxt
ctxt Prop
ty
    TCon (PC PC
PFin)   [Prop
ty]      -> Ctxt -> Prop -> Solved
cryIsFinType Ctxt
ctxt Prop
ty

    TCon (PC PC
PEqual) [Prop
t1,Prop
t2]   -> Ctxt -> Prop -> Prop -> Solved
cryIsEqual Ctxt
ctxt Prop
t1 Prop
t2
    TCon (PC PC
PNeq)  [Prop
t1,Prop
t2]    -> Ctxt -> Prop -> Prop -> Solved
cryIsNotEqual Ctxt
ctxt Prop
t1 Prop
t2
    TCon (PC PC
PGeq)  [Prop
t1,Prop
t2]    -> Ctxt -> Prop -> Prop -> Solved
cryIsGeq Ctxt
ctxt Prop
t1 Prop
t2

    Prop
_                          -> Solved
Unsolved