packages feed

yices-easy-0.1: Yices/Easy/Sugar.hs

-- | Syntactic sugar for embedding Yices expressions in Haskell.
--
-- Defines a number of aliases and infix operators, and a
-- @'Num'@ instance for @'Expr'@.
--
-- This is not an essential part of the interface. Expressions
-- may be built using @Yices.Easy.Types@ directly.
--
-- This is a quick hack.  There are several other projects working
-- on vastly more sophisticated SMT EDSLs, so this one is unlikely
-- to receive much attention.  That said, suggestions and patches
-- are always welcome.

{-# OPTIONS_GHC
  -fno-warn-orphans #-}

module Yices.Easy.Sugar
 ( -- * Types
   real, int, nat, bool

   -- * Booleans
 , true, false
 , (||.), (&&.)

   -- * Application
 , ($.)

   -- * Scalar arithmetic
   
   -- | We also provide @instance 'Num' 'Expr'@,
   -- so you can use @('+')@, @('*')@, @('-')@,
   -- @'negate'@, @'fromInteger'@, and integer
   -- literals.
 , add, mul, sub

   -- * Scalar comparison
 , (==.), (/=.), (>.), (>=.), (<.), (<=.)

   -- * Literal bitvectors
 , bv

   -- * Bitvector arithmetic
 , (+@), (-@), (*@)

   -- * Signed bitvector comarpsion
 , (>@), (>=@), (<@), (<=@)
 
   -- * Unsigned bitvector comparison
 , (>@@), (>=@@), (<@@), (<=@@)

   -- * Bitvector concatenation
 , (++@)

   -- * Bitwise operations
 , (|@), (&@), (^@)
 ) where


import Yices.Easy.Types


real, int, nat, bool :: Type
real = TyName "real"
int  = TyName "int"
nat  = TyName "nat"
bool = TyName "bool"


true, false :: Expr
true  = LitBool True
false = LitBool False


infixr 0 $.
($.) :: Expr -> [Expr] -> Expr
($.) = Apply


instance Num Expr where
  x + y = Arith Add [x,y]
  x * y = Arith Mul [x,y]
  x - y = Arith Sub [x,y]
  abs    = error "Expr: cannot use abs"
  signum = error "Expr: cannot use signum"
  fromInteger = LitNum . FromString . show

add, mul, sub :: [Expr] -> Expr
add = Arith Add
mul = Arith Mul
sub = Arith Sub


infix 4 ==.
infix 4 /=.
infix 4 >.
infix 4 >=.
infix 4 <.
infix 4 <=.

(==.), (/=.), (>.), (>=.), (<.), (<=.) :: Expr -> Expr -> Expr
(==.) = Compare Eq
(/=.) = Compare Ne
(>.)  = Compare Gt
(>=.) = Compare Ge
(<.)  = Compare Lt
(<=.) = Compare Le


infixr 2 ||.
infixr 3 &&.

(||.), (&&.) :: Expr -> Expr -> Expr
x ||. y = Logic Or  [x,y]
x &&. y = Logic And [x,y]


infixl 6 +@
infixl 6 -@
infixl 7 *@

(+@), (-@), (*@) :: Expr -> Expr -> Expr
(+@) = BitArith Add
(*@) = BitArith Mul
(-@) = BitArith Sub


infix 4 >@
infix 4 >=@
infix 4 <@
infix 4 <=@
infix 4 >@@
infix 4 >=@@
infix 4 <@@
infix 4 <=@@

(>@), (>=@), (<@), (<=@), (>@@), (>=@@), (<@@), (<=@@) :: Expr -> Expr -> Expr
(>@)   = BitCompare Signed   Gt
(>=@)  = BitCompare Signed   Ge
(<@)   = BitCompare Signed   Lt
(<=@)  = BitCompare Signed   Le
(>@@)  = BitCompare Unsigned Gt
(>=@@) = BitCompare Unsigned Ge
(<@@)  = BitCompare Unsigned Lt
(<=@@) = BitCompare Unsigned Le


infixr 5 ++@

(++@) :: Expr -> Expr -> Expr
(++@) = BitConcat


infixr 5 |@
infixr 7 &@
infixr 7 ^@

(|@), (&@), (^@) :: Expr -> Expr -> Expr
(|@) = BitLogic Or
(&@) = BitLogic And
(^@) = BitLogic Xor


-- | @bv s n@ has value @n@ and size at least @s@.
bv :: Size -> Integer -> Expr
bv _ n
  | n < 0 = error "Yices.Easy.Sugar.bv: negative Integer not allowed"
bv s n = LitBitvec . FromBits $ getBits s n where
  getBits b 0 = replicate b B0
  getBits b k = let (d,m) = k `divMod` 2 in toEnum (fromIntegral m) : getBits (b-1) d