package Boolify(Boolify(..)) where import List import Vector import Enum --@ \subsubsection{Boolify} --@ --@ \index{Boolify@\te{Boolify} (class)|textbf} --@ The \te{Boolify} class contains a single method \te{boolify}. --@ This method is applicable to functions. When applied it --@ will return an equivalent function, which has been built --@ only from Boolean primitives (\te{\&\&}, \te{||}, and \te{not}). --@ --@ \begin{libverbatim} --@ typeclass Boolify #(type a); --@ function a boolify(a x1); --@ endtypeclass --@ \end{libverbatim} class Boolify a where boolify :: a -> a --@ (A curried function can be boolified, if the uncurried can. --@ This instance allows multi-argument functions to be --@ boolified. Note that in BSV0.5 multi-argument functions are --@ usually handled internally in their curried form, and both versions --@ pretty-print in the same way. The relevant instance is therefore --@ not shown here, as it would look either trivial or far too complicated.) instance (Boolify ((a, b) -> c)) => Boolify (a -> b -> c) where boolify = curry · boolify · uncurry --@ --@ A function where the argument and result can be turned into --@ bits can be boolified. --@ \begin{libverbatim} --@ instance Boolify #(a -> b) --@ provisos (Bounded#(a), Bits#(a, sa), Bits#(b, sb)); --@ \end{libverbatim} instance (Bounded a, Bits a sa, Bits b sb) => Boolify (a -> b) where boolify f x = let bx = pack x genBit k = List.any (\ a -> genTerm (fromInteger k) a (f a)) enumAll genTerm k a b = let ba = pack a bb = pack b in bb[k:k] == 1 && eqByBit bx ba in unpack (pack (map genBit genList)) eqByBit :: Bit n -> Bit n -> Bool eqByBit x bs = List.all (\ i -> let { n = fromInteger i } in x[n:n] == bs[n:n]) (upto 0 (valueOf n - 1))