{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# OPTIONS_GHC -Wall -Werror #-}
module Data.SBV.Tools.STree (STree, readSTree, writeSTree, mkSTree) where
import Data.SBV.Core.Data
import Data.SBV.Core.Model
import Data.Proxy
type STree i e = STreeInternal (SBV i) (SBV e)
data STreeInternal i e = SLeaf e
| SBin (STreeInternal i e) (STreeInternal i e)
deriving Show
instance SymVal e => Mergeable (STree i e) where
symbolicMerge f b (SLeaf i) (SLeaf j) = SLeaf (symbolicMerge f b i j)
symbolicMerge f b (SBin l r) (SBin l' r') = SBin (symbolicMerge f b l l') (symbolicMerge f b r r')
symbolicMerge _ _ _ _ = error "SBV.STree.symbolicMerge: Impossible happened while merging states"
readSTree :: (SFiniteBits i, SymVal e) => STree i e -> SBV i -> SBV e
readSTree s i = walk (blastBE i) s
where walk [] (SLeaf v) = v
walk (b:bs) (SBin l r) = ite b (walk bs r) (walk bs l)
walk _ _ = error $ "SBV.STree.readSTree: Impossible happened while reading: " ++ show i
writeSTree :: (SFiniteBits i, SymVal e) => STree i e -> SBV i -> SBV e -> STree i e
writeSTree s i j = walk (blastBE i) s
where walk [] _ = SLeaf j
walk (b:bs) (SBin l r) = SBin (ite b l (walk bs l)) (ite b (walk bs r) r)
walk _ _ = error $ "SBV.STree.writeSTree: Impossible happened while reading: " ++ show i
mkSTree :: forall i e. HasKind i => [SBV e] -> STree i e
mkSTree ivals
| isReal (Proxy @i)
= error "SBV.STree.mkSTree: Cannot build a real-valued sized tree"
| not (isBounded (Proxy @i))
= error "SBV.STree.mkSTree: Cannot build an infinitely large tree"
| reqd /= given
= error $ "SBV.STree.mkSTree: Required " ++ show reqd ++ " elements, received: " ++ show given
| True
= go ivals
where reqd = 2 ^ intSizeOf (Proxy @i)
given = length ivals
go [] = error "SBV.STree.mkSTree: Impossible happened, ran out of elements"
go [l] = SLeaf l
go ns = let (l, r) = splitAt (length ns `div` 2) ns in SBin (go l) (go r)