@@ -1,16 +1,21 @@
1{-# OPTIONS_GHC -fno-warn-orphans #-}
1{-# OPTIONS_GHC -fno-warn-orphans #-}
2module Tests.Property.Arbitrary where
2module Tests.Property.Arbitrary where
4−import Control.Applicative ((<$>))
4+import Control.Applicative ((<$>), (<*>), pure)
5import Test.QuickCheck.Arbitrary
5import Test.QuickCheck.Arbitrary
6import Test.QuickCheck.Gen
6import Test.QuickCheck.Gen
8+import qualified Data.Set as Set
9+import qualified Parse.Helpers (reserveds)
8import SourceSyntax.Literal
11import SourceSyntax.Literal
12+import SourceSyntax.Pattern
10instance Arbitrary Literal where
14instance Arbitrary Literal where
11 arbitrary = oneof [ IntNum <$> arbitrary
15 arbitrary = oneof [ IntNum <$> arbitrary
12 , FloatNum <$> arbitrary
16 , FloatNum <$> arbitrary
13 , Chr <$> arbitrary
17 , Chr <$> arbitrary
18+ -- This is too permissive
14 , Str <$> arbitrary
19 , Str <$> arbitrary
15 -- Booleans aren't actually source syntax
20 -- Booleans aren't actually source syntax
16 -- , Boolean <$> arbitrary
21 -- , Boolean <$> arbitrary
@@ -21,3 +26,47 @@ instance Arbitrary Literal where
21 Chr c -> Chr <$> shrink c
26 Chr c -> Chr <$> shrink c
22 Str s -> Str <$> shrink s
27 Str s -> Str <$> shrink s
23 Boolean b -> Boolean <$> shrink b
28 Boolean b -> Boolean <$> shrink b
30+instance Arbitrary Pattern where
31+ arbitrary = sized pat
32+ where pat :: Int -> Gen Pattern
33+ pat n = oneof [ pure PAnything
35+ , PRecord <$> (listOf1 lowVar)
36+ , PLiteral <$> arbitrary
37+ , PAlias <$> lowVar <*> pat (n-1)
38+ , PData <$> capVar <*> sizedPats
42+ let m = n `div` len in
45+ shrink pat = case pat of
47+ PVar v -> PVar <$> shrinkWHead v
48+ PRecord fs -> PRecord <$> (filter (all $ not.null) . filter (not.null) $ shrink fs)
49+ PLiteral l -> PLiteral <$> shrink l
50+ PAlias s p -> p : (PAlias <$> shrinkWHead s <*> shrink p)
51+ PData s ps -> ps ++ (PData <$> shrinkWHead s <*> shrink ps)
52+ where shrinkWHead (x:xs) = (x:) <$> shrink xs
55+lowVar = notReserved $ (:) <$> lower <*> listOf varLetter
56+ where lower = elements ['a'..'z']
59+capVar = notReserved $ (:) <$> upper <*> listOf varLetter
60+ where upper = elements ['A'..'Z']
63+varLetter = elements $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ ['\'', '_']
65+notReserved :: Gen String -> Gen String
66+notReserved = flip exceptFor Parse.Helpers.reserveds
68+exceptFor :: (Ord a) => Gen a -> [a] -> Gen a
69+exceptFor g xs = suchThat g notAnX
70+ where notAnX = flip Set.notMember xset
71+ xset = Set.fromList xs