-- |
-- Module : Test.ListableExpr
-- Copyright : (c) 2019-2025 Rudy Matela
-- License : 3-Clause BSD (see the file LICENSE)
-- Maintainer : Rudy Matela <rudy@matela.com.br>
--
-- This module exports a 'Listable' 'Expr' instance.
-- This instance does not, by any means, list all possible expressions.
-- It lists expressions based on a subset of the symbols exported by
-- "Data.Express.Fixtures".
--
-- This is only intended to be used for testing,
-- so this will not be exported on @ express.cabal @.
module Test.ListableExpr
(
-- * The Expr type
Expr
-- * Expressions of a type
, IntE (..)
, BoolE (..)
, IntsE (..)
, CharE (..)
, IntE0 (..)
, IntEV (..)
, BoolE0 (..)
, BoolEV (..)
, IntsE0 (..)
, IntsEV (..)
, CharE0 (..)
, CharEV (..)
-- ** Functional values
, IntToIntE (..)
, IntToIntToIntE (..)
, BoolToBoolE (..)
, BoolToBoolToBoolE (..)
, SameTypeE (..)
, unSameTypeE
, SameTypedPairsE (..)
-- * Terminal expressions
, E0 (..)
, EV (..)
-- * Ill typed expressions
, Ill (..)
)
where
import Test.LeanCheck
import Test.LeanCheck.Function.ShowFunction
import Data.Express.Fixtures
import Data.Function (on)
-- | Terminal constants.
newtype E0 = E0 { unE0 :: Expr }
-- | Variables.
newtype EV = EV { unEV :: Expr }
-- | Expression of 'Int' type.
newtype IntE = IntE { unIntE :: Expr }
-- | Constant terminal value of 'Int' type.
newtype IntE0 = IntE0 { unIntE0 :: Expr }
-- | Variable of 'Int' type.
newtype IntEV = IntEV { unIntEV :: Expr }
-- | Functions from Int to Int
newtype IntToIntE = IntToIntE { unIntToIntE :: Expr }
newtype IntToIntToIntE = IntToIntToIntE { unIntToIntToIntE :: Expr }
-- | Expression of 'Bool' type.
newtype BoolE = BoolE { unBoolE :: Expr }
-- | Constant terminal value of 'Bool' type.
newtype BoolE0 = BoolE0 { unBoolE0 :: Expr }
-- | Varialbe of 'Bool' type.
newtype BoolEV = BoolEV { unBoolEV :: Expr }
-- | Functions from Bool to Bool
newtype BoolToBoolE = BoolToBoolE { unBoolToBoolE :: Expr }
newtype BoolToBoolToBoolE = BoolToBoolToBoolE { unBoolToBoolToBoolE :: Expr }
newtype CharE = CharE { unCharE :: Expr }
newtype CharE0 = CharE0 { unCharE0 :: Expr }
newtype CharEV = CharEV { unCharEV :: Expr }
data SameTypeE = SameTypeE Expr Expr
unSameTypeE :: SameTypeE -> (Expr,Expr)
unSameTypeE (SameTypeE e1 e2) = (e1,e2)
data SameTypedPairsE = SameTypedPairsE { unSameTypedPairsE :: [(Expr,Expr)] }
-- | Ill typed expressions.
newtype Ill = Ill { unIll :: Expr }
instance Show E0 where show (E0 e) = show e
instance Show EV where show (EV e) = show e
instance Show IntE where show (IntE e) = show e
instance Show IntE0 where show (IntE0 e) = show e
instance Show IntEV where show (IntEV e) = show e
instance Show IntToIntE where show (IntToIntE e) = show e
instance Show IntToIntToIntE where show (IntToIntToIntE e) = show e
instance Show BoolE where show (BoolE e) = show e
instance Show BoolE0 where show (BoolE0 e) = show e
instance Show BoolEV where show (BoolEV e) = show e
instance Show BoolToBoolE where show (BoolToBoolE e) = show e
instance Show BoolToBoolToBoolE where show (BoolToBoolToBoolE e) = show e
instance Show IntsE where show (IntsE e) = show e
instance Show IntsE0 where show (IntsE0 e) = show e
instance Show IntsEV where show (IntsEV e) = show e
instance Show CharE where show (CharE e) = show e
instance Show CharE0 where show (CharE0 e) = show e
instance Show CharEV where show (CharEV e) = show e
instance Show SameTypeE where show (SameTypeE e1 e2) = show (e1,e2)
instance Show SameTypedPairsE where show (SameTypedPairsE ees) = show ees
-- | Expression of 'Ints' type.
newtype IntsE = IntsE { unIntsE :: Expr }
-- | Constant terminal value of 'Ints' type.
newtype IntsE0 = IntsE0 { unIntsE0 :: Expr }
-- | Varialbe of 'Ints' type.
newtype IntsEV = IntsEV { unIntsEV :: Expr }
instance Show Ill where show (Ill e) = show e
instance Listable IntE where
tiers = mapT IntE
$ cons0 i_
\/ cons1 unIntEV
\/ cons1 unIntE0
\/ cons2 (\(IntToIntE f) (IntE xx) -> f :$ xx)
\/ cons1 (head' . unIntsE) `ofWeight` 2
\/ cons1 (ord' . unCharE) `ofWeight` 2
instance Listable IntE0 where
tiers = (IntE0 . val) `mapT` (tiers :: [[Int]])
instance Listable IntEV where
list = map IntEV $ listVars "x" (undefined :: Int)
instance Listable IntToIntE where
tiers = mapT IntToIntE
$ cons0 idE
\/ cons0 negateE `addWeight` 1
\/ cons0 absE `addWeight` 1
\/ cons2 (\(IntToIntToIntE ef) (IntE ex) -> ef :$ ex)
\/ toTiers (listVars "f" (undefined :: Int -> Int)) `addWeight` 2
instance Listable IntToIntToIntE where
list = map IntToIntToIntE [plus, times]
instance Listable IntsE where
tiers = mapT IntsE
$ cons0 is_
\/ cons1 unIntsEV
\/ cons1 unIntsE0
\/ cons2 (\(IntE ex) (IntsE exs) -> ex -:- exs)
\/ cons1 (tail' . unIntsE) `ofWeight` 2
\/ cons2 (\(IntsE exs) (IntsE eys) -> exs -++- eys) `ofWeight` 2
\/ cons1 (\(IntsE exs) -> sort' exs) `ofWeight` 3
\/ cons2 (\(IntE ex) (IntsE exs) -> insert' ex exs) `ofWeight` 3
instance Listable IntsE0 where
tiers = (IntsE0 . val) `mapT` (tiers :: [[ [Int] ]])
instance Listable IntsEV where
list = map IntsEV $ listVars "xs" (undefined :: [Int])
instance Listable BoolE where
tiers = mapT BoolE
$ cons0 b_
\/ cons1 unBoolEV
\/ cons1 unBoolE0
\/ cons2 (\(BoolToBoolE ef) (BoolE ep) -> ef :$ ep)
\/ cons2 ((-==-) `on` unIntE) `addWeight` 2
\/ cons2 ((-==-) `on` unBoolE) `addWeight` 2
\/ cons2 ((-<=-) `on` unIntE) `addWeight` 3
\/ cons2 ((-<=-) `on` unBoolE) `addWeight` 3
\/ cons2 ((-<-) `on` unIntE) `addWeight` 4
\/ cons2 ((-<-) `on` unBoolE) `addWeight` 4
\/ cons2 ((-/=-) `on` unIntE) `addWeight` 5
\/ cons2 ((-/=-) `on` unBoolE) `addWeight` 5
\/ cons1 (odd' . unIntE) `addWeight` 2
\/ cons1 (even' . unIntE) `addWeight` 2
\/ cons2 (\(IntE ex) (IntsE exs) -> elem' ex exs) `addWeight` 2
instance Listable BoolE0 where
tiers = (BoolE0 . val) `mapT` (tiers :: [[Bool]])
instance Listable BoolEV where
list = map BoolEV $ listVars "p" (undefined :: Bool)
instance Listable BoolToBoolE where
tiers = mapT BoolToBoolE
$ cons0 notE
\/ cons2 (\(BoolToBoolToBoolE ef) (BoolE ex) -> ef :$ ex)
instance Listable BoolToBoolToBoolE where
list = map BoolToBoolToBoolE [orE, andE, implies]
instance Listable CharE where
tiers = mapT CharE $ cons0 c_
\/ cons1 unCharEV
\/ cons1 unCharE0
instance Listable CharEV where
list = map CharEV $ listVars "c" (undefined :: Char)
instance Listable CharE0 where
tiers = (CharE0 . val) `mapT` (tiers :: [[Char]])
instance Listable SameTypeE where
tiers = cons1 (\(IntE e1, IntE e2) -> SameTypeE e1 e2) `ofWeight` 0
\/ cons1 (\(BoolE e1, BoolE e2) -> SameTypeE e1 e2) `ofWeight` 1
\/ cons1 (\(IntsE e1, IntsE e2) -> SameTypeE e1 e2) `ofWeight` 1
\/ cons1 (\(CharE e1, CharE e2) -> SameTypeE e1 e2) `ofWeight` 2
\/ cons1 (\(IntToIntE e1, IntToIntE e2) -> SameTypeE e1 e2) `ofWeight` 2
\/ cons1 (\(BoolToBoolE e1, BoolToBoolE e2) -> SameTypeE e1 e2) `ofWeight` 2
\/ cons1 (\(BoolToBoolToBoolE e1, BoolToBoolToBoolE e2) -> SameTypeE e1 e2) `ofWeight` 2
\/ cons1 (\(IntToIntToIntE e1, IntToIntToIntE e2) -> SameTypeE e1 e2) `ofWeight` 2
instance Listable SameTypedPairsE where
tiers = cons1 (SameTypedPairsE . map unSameTypeE) `ofWeight` 0
instance Listable E0 where
tiers = mapT E0
$ cons1 unIntE0 `ofWeight` 0
\/ cons1 unBoolE0 `ofWeight` 1
\/ cons1 unIntsE0 `ofWeight` 1
instance Listable EV where
tiers = mapT EV
$ cons1 unIntEV `ofWeight` 0
\/ cons1 unBoolEV `ofWeight` 1
\/ cons1 unIntsEV `ofWeight` 1
instance Listable Expr where
tiers = reset (cons1 unIntE)
\/ cons1 unBoolE
\/ cons1 unCharE
\/ cons1 unIntsE
\/ cons1 unIntToIntE `addWeight` 1
\/ cons1 unIntToIntToIntE `addWeight` 1
\/ cons1 unBoolToBoolE `addWeight` 2
\/ cons1 unBoolToBoolToBoolE `addWeight` 2
-- | This listable instance only produces Ill typed expressions
instance Listable Ill where
tiers = mapT Ill
$ cons2 (\(IntE ef) (IntE ex) -> ef :$ ex) `ofWeight` 0
\/ cons2 (\(IntToIntE ef) (IntToIntE ex) -> ef :$ ex)
\/ cons2 (\(Ill ef) ex -> ef :$ ex)
\/ cons2 (\ef (Ill ex)-> ef :$ ex)
instance ShowFunction Expr where bindtiers = bindtiersShow