{-# LANGUAGE PatternGuards, OverloadedStrings #-}
module Cryptol.TypeCheck.Solver.Class
( classStep
, solveZeroInst
, solveLogicInst
, solveArithInst
, solveCmpInst
, solveSignedCmpInst
, solveLiteralInst
, expandProp
) where
import Cryptol.TypeCheck.Type
import Cryptol.TypeCheck.SimpType (tAdd,tWidth)
import Cryptol.TypeCheck.Solver.Types
import Cryptol.TypeCheck.PP
classStep :: Prop -> Solved
classStep p = case tNoUser p of
TCon (PC PLogic) [ty] -> solveLogicInst (tNoUser ty)
TCon (PC PArith) [ty] -> solveArithInst (tNoUser ty)
TCon (PC PCmp) [ty] -> solveCmpInst (tNoUser ty)
_ -> Unsolved
solveZeroInst :: Type -> Solved
solveZeroInst ty = case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCBit) [] -> SolvedIf []
TCon (TC TCInteger) [] -> SolvedIf []
TCon (TC TCIntMod) [n] -> SolvedIf [ pFin n, n >== tOne ]
TCon (TC TCSeq) [_, a] -> SolvedIf [ pZero a ]
TCon (TC TCFun) [_, b] -> SolvedIf [ pZero b ]
TCon (TC (TCTuple _)) es -> SolvedIf [ pZero e | e <- es ]
TRec fs -> SolvedIf [ pZero ety | (_,ety) <- fs ]
_ -> Unsolved
solveLogicInst :: Type -> Solved
solveLogicInst ty = case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCBit) [] -> SolvedIf []
TCon (TC TCSeq) [_, a] -> SolvedIf [ pLogic a ]
TCon (TC TCFun) [_, b] -> SolvedIf [ pLogic b ]
TCon (TC (TCTuple _)) es -> SolvedIf [ pLogic e | e <- es ]
TRec fs -> SolvedIf [ pLogic ety | (_,ety) <- fs ]
_ -> Unsolved
solveArithInst :: Type -> Solved
solveArithInst ty = case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCSeq) [n, e] -> solveArithSeq n e
TCon (TC TCFun) [_,b] -> SolvedIf [ pArith b ]
TCon (TC (TCTuple _)) es -> SolvedIf [ pArith e | e <- es ]
TCon (TC TCBit) [] ->
Unsolvable $ TCErrorMessage "Arithmetic cannot be done on individual bits."
TCon (TC TCInteger) [] -> SolvedIf []
TCon (TC TCIntMod) [n] -> SolvedIf [ pFin n, n >== tOne ]
TRec fs -> SolvedIf [ pArith ety | (_,ety) <- fs ]
_ -> Unsolved
solveArithSeq :: Type -> Type -> Solved
solveArithSeq n ty = case tNoUser ty of
TCon (TC TCBit) [] -> SolvedIf [ pFin n ]
TVar {} -> Unsolved
_ -> SolvedIf [ pArith ty ]
solveCmpInst :: Type -> Solved
solveCmpInst ty = case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCBit) [] -> SolvedIf []
TCon (TC TCInteger) [] -> SolvedIf []
TCon (TC TCIntMod) [n] -> SolvedIf [ pFin n, n >== tOne ]
TCon (TC TCSeq) [n,a] -> SolvedIf [ pFin n, pCmp a ]
TCon (TC (TCTuple _)) es -> SolvedIf (map pCmp es)
TCon (TC TCFun) [_,_] ->
Unsolvable $ TCErrorMessage "Comparisons may not be performed on functions."
TRec fs -> SolvedIf [ pCmp e | (_,e) <- fs ]
_ -> Unsolved
solveSignedCmpSeq :: Type -> Type -> Solved
solveSignedCmpSeq n ty = case tNoUser ty of
TCon (TC TCBit) [] -> SolvedIf [ pFin n, n >== tNum (1 :: Integer) ]
TVar {} -> Unsolved
_ -> SolvedIf [ pFin n, pSignedCmp ty ]
solveSignedCmpInst :: Type -> Solved
solveSignedCmpInst ty = case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCBit) [] -> Unsolvable $ TCErrorMessage "Signed comparisons may not be performed on bits"
TCon (TC TCSeq) [n,a] -> solveSignedCmpSeq n a
TCon (TC (TCTuple _)) es -> SolvedIf (map pSignedCmp es)
TCon (TC TCFun) [_,_] ->
Unsolvable $ TCErrorMessage "Signed comparisons may not be performed on functions."
TRec fs -> SolvedIf [ pSignedCmp e | (_,e) <- fs ]
_ -> Unsolved
solveLiteralInst :: Type -> Type -> Solved
solveLiteralInst val ty
| TCon (TError _ e) _ <- tNoUser val = Unsolvable e
| otherwise =
case tNoUser ty of
TCon (TError _ e) _ -> Unsolvable e
TCon (TC TCInteger) [] -> SolvedIf [ pFin val ]
TCon (TC TCIntMod) [modulus] ->
SolvedIf [ pFin val, pFin modulus, modulus >== tAdd val tOne ]
TCon (TC TCSeq) [bits, elTy]
| TCon (TC TCBit) [] <- ety ->
SolvedIf [ pFin val, pFin bits, bits >== tWidth val ]
| TVar _ <- ety -> Unsolved
where ety = tNoUser elTy
TVar _ -> Unsolved
_ -> Unsolvable $ TCErrorMessage $ show
$ "Type" <+> quotes (pp ty) <+> "does not support literals."
expandProp :: Prop -> [Prop]
expandProp prop =
prop :
case tNoUser prop of
TCon (PC pc) [ty] ->
case (pc, tNoUser ty) of
(PArith, TCon (TC TCSeq) [n,a])
| TCon (TC TCBit) _ <- ty1 -> [pFin n]
| TCon _ _ <- ty1 -> expandProp (pArith ty1)
| TRec {} <- ty1 -> expandProp (pArith ty1)
where
ty1 = tNoUser a
(PArith, TCon (TC TCFun) [_,b]) -> expandProp (pArith b)
(PArith, TCon (TC (TCTuple _)) ts) -> concatMap (expandProp . pArith) ts
(PArith, TRec fs) -> concatMap (expandProp . pArith. snd) fs
(PCmp, TCon (TC TCSeq) [n,a]) -> pFin n : expandProp (pCmp a)
(PCmp, TCon (TC (TCTuple _)) ts) -> concatMap (expandProp . pCmp) ts
(PCmp, TRec fs) -> concatMap (expandProp . pCmp . snd) fs
_ -> []
_ -> []