module Language.ImProve.Core ( E (..) , V (..) , Name , AllE (..) , NumE , Statement (..) ) where import Data.Ratio type Name = String data V a = V Bool [Name] a class AllE a where showConst :: a -> String showType :: a -> String zero :: (Name -> a -> m (V a)) -> a instance AllE Bool where showConst a = case a of True -> "1" False -> "0" showType _ = "int" zero = const False instance AllE Int where showConst = show showType _ = "int" zero = const 0 instance AllE Float where showConst = show showType _ = "float" zero = const 0 class AllE a => NumE a instance NumE Int instance NumE Float data E a where Ref :: AllE a => V a -> E a Const :: AllE a => a -> E a Add :: NumE a => E a -> E a -> E a Sub :: NumE a => E a -> E a -> E a Mul :: NumE a => E a -> a -> E a Div :: NumE a => E a -> a -> E a Mod :: E Int -> Int -> E Int Not :: E Bool -> E Bool And :: E Bool -> E Bool -> E Bool Or :: E Bool -> E Bool -> E Bool Eq :: AllE a => E a -> E a -> E Bool Lt :: NumE a => E a -> E a -> E Bool Gt :: NumE a => E a -> E a -> E Bool Le :: NumE a => E a -> E a -> E Bool Ge :: NumE a => E a -> E a -> E Bool Mux :: AllE a => E Bool -> E a -> E a -> E a instance Show (E a) where show = undefined instance Eq (E a) where (==) = undefined instance (Num a, AllE a, NumE a) => Num (E a) where (+) = Add (-) = Sub (*) = error "general multiplication not supported, use (*.)" negate a = 0 - a abs a = Mux (Lt a 0) (negate a) a signum a = Mux (Eq a 0) 0 $ Mux (Lt a 0) (-1) 1 fromInteger = Const . fromInteger instance Fractional (E Float) where (/) = error "general division not supported, use (/.)" recip a = 1 / a fromRational r = Const $ fromInteger (numerator r) / fromInteger (denominator r) data Statement = AssignBool (V Bool ) (E Bool ) | AssignInt (V Int ) (E Int ) | AssignFloat (V Float) (E Float) | Branch [Name] (E Bool) Statement Statement | Sequence Statement Statement | Assert [Name] (E Bool) | Assume [Name] (E Bool) | Null