module Copilot.Compile.SBV.Copilot2SBV
( c2sExpr
, Inputs(..)
, Ext
, ExtQue
, ExtInput(..)
, QueInput(..)
, QueueIn(..)
)
where
import Prelude hiding (id)
import Data.Map (Map)
import qualified Data.Map as M
import qualified Data.SBV as S
import Copilot.Compile.SBV.Common
import qualified Copilot.Compile.SBV.Queue as Q
import qualified Copilot.Compile.SBV.Witness as W
import Copilot.Core (Op1 (..), Op2 (..), Op3 (..), badUsage)
import qualified Copilot.Core as C
import qualified Copilot.Core.Type as C
import Copilot.Core.Error (badUsage, impossible)
import Copilot.Core.Type.Equality ((=~=), coerce, cong)
import Data.Maybe (fromJust)
type Ext = (C.Name, ExtInput)
type ExtQue = (C.Id, QueInput)
data Inputs = Inputs
{ extVars :: [Ext]
, extArrs :: [Ext]
, extFuns :: [Ext]
, extQues :: [ExtQue] }
data ExtInput = forall a. ExtInput
{ extInput :: S.SBV a
, extType :: C.Type a }
data QueInput = forall a. QueInput
{ arrInput :: QueueIn a }
data QueueIn a = QueueIn
{ queue :: [S.SBV a]
, quePtr :: S.SBV Q.QueueSize
, arrType :: C.Type a }
data Local = forall a . Local
{ localSBVExpr :: S.SBV a
, localType :: C.Type a }
type Env = Map C.Name Local
lookupInput :: Eq a => a -> [(a,b)] -> b
lookupInput id prs =
case lookup id prs of
Nothing -> impossible "lookupInput" "copilot-sbv"
Just val -> val
c2sExpr :: Inputs -> C.Expr a -> S.SBV a
c2sExpr inputs e = c2sExpr_ e M.empty inputs
c2sExpr_ :: C.Expr a -> Env -> Inputs -> S.SBV a
c2sExpr_ e0 env inputs = case e0 of
C.Const t x ->
case W.symWordInst t of W.SymWordInst -> S.literal x
C.Drop t i id -> drop1 t que
where
que :: QueInput
que = lookupInput id (extQues inputs)
drop1 :: C.Type a -> QueInput -> S.SBV a
drop1 t1 QueInput { arrInput = QueueIn { queue = que'
, quePtr = qPtr
, arrType = t2 } } =
let Just p = t2 =~= t1 in
case W.symWordInst t2 of
W.SymWordInst ->
case W.hasSignAndSizeInst t2 of
W.HasSignAndSizeInst ->
coerce (cong p) (Q.lookahead i que' qPtr)
C.Local t1 _ name e1 e2 ->
let e1' = c2sExpr_ e1 env inputs in
let env' = M.insert name (Local e1' t1) env in
c2sExpr_ e2 env' inputs
C.Var t1 name ->
case M.lookup name env of
Just Local
{ localSBVExpr = e
, localType = t2
} ->
let Just p = t2 =~= t1
in coerce (cong p) e
C.ExternVar t name _ ->
getSBV t ext
where
ext :: ExtInput
ext = lookupInput name (extVars inputs)
getSBV :: C.Type a -> ExtInput -> S.SBV a
getSBV t1 ExtInput { extInput = ext'
, extType = t2 } =
let Just p = t2 =~= t1 in
coerce (cong p) ext'
C.ExternArray _ t name _ _ _ tag ->
getSBV t getExtArr
where
getExtArr :: ExtInput
getExtArr = lookupInput (mkExtTmpTag name (tag)) (extArrs inputs)
getSBV t1 ExtInput { extInput = v
, extType = t2 }
= let Just p = t2 =~= t1 in
coerce (cong p) v
C.ExternFun t name _ _ tag ->
getSBV t getExtFun
where
getExtFun :: ExtInput
getExtFun = lookupInput (mkExtTmpTag name (tag)) (extFuns inputs)
getSBV t1 ExtInput { extType = t2
, extInput = v }
= let Just p = t2 =~= t1 in
coerce (cong p) v
C.Op1 op e ->
let res1 = c2sExpr_ e env inputs in
c2sOp1 op res1
C.Op2 op e1 e2 ->
let res1 = c2sExpr_ e1 env inputs in
let res2 = c2sExpr_ e2 env inputs in
c2sOp2 op res1 res2
C.Op3 op e1 e2 e3 ->
let res1 = c2sExpr_ e1 env inputs in
let res2 = c2sExpr_ e2 env inputs in
let res3 = c2sExpr_ e3 env inputs in
c2sOp3 op res1 res2 res3
C.Label t s e -> case W.symWordInst t of
W.SymWordInst -> S.label s (c2sExpr_ e env inputs)
noFloatOpsErr :: String -> a
noFloatOpsErr op =
badUsage ("The operation you used is not supported by the SBV backend: "
++ "operator " ++ op ++ " not supported. Please change it with your math skills to something supported.")
c2sOp1 :: C.Op1 a b -> S.SBV a -> S.SBV b
c2sOp1 op = case op of
Not -> (S.bnot)
Abs t -> case W.symWordInst t of
W.SymWordInst -> abs
Sign t -> case W.symWordInst t of
W.SymWordInst -> signum
BwNot t -> case W.bitsInst t of
W.BitsInst -> (S.complement)
Cast t0 t1 -> case W.castInst t0 t1 of
W.CastInst -> W.sbvCast
Recip _ -> noFloatOpsErr "recip"
Exp C.Float -> exp
Exp C.Double -> exp
Sqrt C.Float -> sqrt
Sqrt C.Double -> sqrt
Log C.Float -> log
Log C.Double -> log
Sin C.Float -> sin
Sin C.Double -> S.uninterpret "sin"
Cos C.Float -> cos
Cos C.Double -> S.uninterpret "cos"
Tan C.Float -> tan
Tan C.Double -> tan
Asin C.Float -> asin
Asin C.Double -> asin
Acos C.Float -> acos
Acos C.Double -> acos
Atan C.Float -> atan
Atan C.Double -> atan
Sinh C.Float -> sinh
Sinh C.Double -> sinh
Cosh C.Float -> cosh
Cosh C.Double -> cosh
Tanh C.Float -> tanh
Tanh C.Double -> tanh
Asinh C.Float -> asinh
Asinh C.Double -> asinh
Acosh C.Float -> acosh
Acosh C.Double -> acosh
Atanh C.Float -> atanh
Atanh C.Double -> atanh
c2sOp2 :: C.Op2 a b c -> S.SBV a -> S.SBV b -> S.SBV c
c2sOp2 op = case op of
And -> (S.&&&)
Or -> (S.|||)
Add t -> case W.symWordInst t of W.SymWordInst -> (+)
Sub t -> case W.symWordInst t of W.SymWordInst -> ()
Mul t -> case W.symWordInst t of W.SymWordInst -> (*)
Eq t -> case W.eqInst t of W.EqInst -> (S..==)
Ne t -> case W.eqInst t of W.EqInst -> (S../=)
Le t -> case W.ordInst t of W.OrdInst -> (S..<=)
Ge t -> case W.ordInst t of W.OrdInst -> (S..>=)
Lt t -> case W.ordInst t of W.OrdInst -> (S..<)
Gt t -> case W.ordInst t of W.OrdInst -> (S..>)
Div t -> case W.divInst t of W.BVDivisibleInst ->
\x y -> fst (S.sQuotRem x y)
Mod t -> case W.divInst t of W.BVDivisibleInst ->
\x y -> snd (S.sQuotRem x y)
BwAnd t -> case W.bitsInst t of W.BitsInst -> (S..&.)
BwOr t -> case W.bitsInst t of W.BitsInst -> (S..|.)
BwXor t -> case W.bitsInst t of W.BitsInst -> (S.xor)
BwShiftL tvec tidx ->
case W.integralInst tvec of
W.IntegralInst ->
\vec idx -> case (W.integralInst tidx) of
W.IntegralInst -> S.sShiftLeft vec idx
BwShiftR tvec tidx ->
case W.integralInst tvec of
W.IntegralInst ->
\vec idx -> case (W.integralInst tidx) of
W.IntegralInst -> S.sShiftRight vec idx
Fdiv C.Float -> case W.numInst C.Float of W.NumInst -> (/)
Fdiv C.Double -> case W.numInst C.Double of W.NumInst -> (/)
Pow C.Float -> (**)
Pow C.Double -> (**)
Logb C.Float -> logBase
Logb C.Double -> logBase
c2sOp3 :: C.Op3 a b c d -> S.SBV a -> S.SBV b -> S.SBV c -> S.SBV d
c2sOp3 op = case op of
Mux t ->
case W.mergeableInst t of
W.MergeableInst -> \b c1 c2 -> S.ite b c1 c2