{-# Language BlockArguments #-}
{-# Language OverloadedStrings #-}
module Cryptol.Eval.What4.Float (floatPrims) where
import Data.Map(Map)
import qualified Data.Map as Map
import qualified What4.Interface as W4
import Control.Monad.IO.Class
import Cryptol.TypeCheck.Solver.InfNat(Nat'(..))
import Cryptol.Eval.Value
import Cryptol.Eval.Generic
import Cryptol.Eval.What4.Value
import qualified Cryptol.Eval.What4.SFloat as W4
import Cryptol.Utils.Ident(PrimIdent, floatPrim)
floatPrims :: W4.IsSymExprBuilder sym => What4 sym -> Map PrimIdent (Value sym)
floatPrims sym4@(What4 sym) =
Map.fromList [ (floatPrim i,v) | (i,v) <- nonInfixTable ]
where
(~>) = (,)
nonInfixTable =
[ "fpNaN" ~> fpConst (W4.fpNaN sym)
, "fpPosInf" ~> fpConst (W4.fpPosInf sym)
, "fpFromBits" ~> ilam \e -> ilam \p -> wlam sym4 \w ->
VFloat <$> liftIO (W4.fpFromBinary sym e p w)
, "fpToBits" ~> ilam \e -> ilam \p -> flam \x ->
pure $ VWord (e+p)
$ WordVal <$> liftIO (W4.fpToBinary sym x)
, "=.=" ~> ilam \_ -> ilam \_ -> flam \x -> pure $ flam \y ->
VBit <$> liftIO (W4.fpEq sym x y)
, "fpIsFinite" ~> ilam \_ -> ilam \_ -> flam \x ->
VBit <$> liftIO do inf <- W4.fpIsInf sym x
nan <- W4.fpIsNaN sym x
weird <- W4.orPred sym inf nan
W4.notPred sym weird
, "fpAdd" ~> fpBinArithV sym4 fpPlus
, "fpSub" ~> fpBinArithV sym4 fpMinus
, "fpMul" ~> fpBinArithV sym4 fpMult
, "fpDiv" ~> fpBinArithV sym4 fpDiv
, "fpFromRational" ~>
ilam \e -> ilam \p -> wlam sym4 \r -> pure $ lam \x ->
do rat <- fromVRational <$> x
VFloat <$> fpCvtFromRational sym4 e p r rat
, "fpToRational" ~>
ilam \_e -> ilam \_p -> flam \fp ->
VRational <$> fpCvtToRational sym4 fp
]
fpConst ::
W4.IsExprBuilder sym =>
(Integer -> Integer -> IO (W4.SFloat sym)) ->
Value sym
fpConst mk =
ilam \ e ->
VNumPoly \ ~(Nat p) ->
VFloat <$> liftIO (mk e p)