{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
module Ivory.Opts.BitShift
( bitShiftFold
) where
import Ivory.Opts.AssertFold
import qualified Ivory.Language.Syntax.AST as I
import qualified Ivory.Language.Syntax.Type as I
import Ivory.Language
bitShiftFold :: I.Proc -> I.Proc
bitShiftFold = procFold "bits" (expFoldDefault bitShiftAssert)
bitShiftAssert :: I.Type -> I.Expr -> FolderStmt ()
bitShiftAssert ty e = case e of
I.ExpOp op es -> go op es
_ -> return ()
where
go op es = case op of
I.ExpBitShiftL -> assrt
I.ExpBitShiftR -> assrt
_ -> return ()
where
assrt = case ty of
I.TyWord w -> case w of
I.Word8 -> mkAsst (iBitSize (0 :: Uint8))
I.Word16 -> mkAsst (iBitSize (0 :: Uint16))
I.Word32 -> mkAsst (iBitSize (0 :: Uint32))
I.Word64 -> mkAsst (iBitSize (0 :: Uint64))
_ -> return ()
mkAsst sz = insert $ I.CompilerAssert $ I.ExpOp (I.ExpLt False ty)
[es !! 1, fromIntegral sz]