@@ -8,98 +8,112 @@ import Test.QuickCheck.Gen
8import qualified Data.Set as Set
8import qualified Data.Set as Set
9import qualified Parse.Helpers (reserveds)
9import qualified Parse.Helpers (reserveds)
11−import SourceSyntax.Literal
11+import qualified SourceSyntax.Literal as L
12−import SourceSyntax.Pattern
12+import qualified SourceSyntax.Pattern as P
13−import SourceSyntax.Type hiding (listOf)
13+import qualified SourceSyntax.Type as T
15−instance Arbitrary Literal where
15+instance Arbitrary L.Literal where
16− arbitrary = oneof [ IntNum <$> arbitrary
18+ [ L.IntNum <$> arbitrary
17− , FloatNum <$> (arbitrary `suchThat` noE)
19+ , L.FloatNum <$> (arbitrary `suchThat` noE)
18− , Chr <$> arbitrary
20+ , L.Chr <$> arbitrary
19− -- This is too permissive
21+ -- This is too permissive
20− , Str <$> arbitrary
22+ , L.Str <$> arbitrary
21− -- Booleans aren't actually source syntax
23+ -- Booleans aren't actually source syntax
22− -- , Boolean <$> arbitrary
24+ -- , Boolean <$> arbitrary
24− shrink l = case l of
27+ shrink lit =
25− IntNum n -> IntNum <$> shrink n
29+ L.IntNum n -> L.IntNum <$> shrink n
26− FloatNum f -> FloatNum <$> (filter noE . shrink $ f)
30+ L.FloatNum f -> L.FloatNum <$> (filter noE . shrink $ f)
27− Chr c -> Chr <$> shrink c
31+ L.Chr c -> L.Chr <$> shrink c
28− Str s -> Str <$> shrink s
32+ L.Str s -> L.Str <$> shrink s
29− Boolean b -> Boolean <$> shrink b
33+ L.Boolean b -> L.Boolean <$> shrink b
31noE :: Double -> Bool
35noE :: Double -> Bool
32noE = notElem 'e' . show
36noE = notElem 'e' . show
38+genVector :: Int -> (Int -> Gen a) -> Gen [a]
39+genVector n generator = do
41+ let m = n `div` (len + 1)
42+ vectorOf len $ generator m
35−instance Arbitrary Pattern where
44+instance Arbitrary P.Pattern where
36 arbitrary = sized pat
45 arbitrary = sized pat
37− where pat :: Int -> Gen Pattern
47+ pat :: Int -> Gen P.Pattern
38− pat n = oneof [ pure PAnything
48+ pat n =
39− , PVar <$> lowVar
51+ , P.Var <$> lowVar
40− , PRecord <$> (listOf1 lowVar)
52+ , P.Record <$> (listOf1 lowVar)
41− , PLiteral <$> arbitrary
53+ , P.Literal <$> arbitrary
42− , PAlias <$> lowVar <*> pat (n-1)
54+ , P.Alias <$> lowVar <*> pat (n-1)
43− , PData <$> capVar <*> sizedPats
55+ , P.Data <$> capVar <*> genVector n pat
45− where sizedPats = do
57+
47− let m = n `div` (len + 1)
50− shrink pat = case pat of
58+ shrink pat =
51− PAnything -> []
59+ case pat of
52− PVar v -> PVar <$> shrinkWHead v
61+ P.Var v -> P.Var <$> shrinkWHead v
53− PRecord fs -> PRecord <$> (filter (all $ not . null) . filter (not . null) $ shrink fs)
62+ P.Literal l -> P.Literal <$> shrink l
54− PLiteral l -> PLiteral <$> shrink l
55− PAlias s p -> p : (PAlias <$> shrinkWHead s <*> shrink p)
63+ P.Alias s p -> p : (P.Alias <$> shrinkWHead s <*> shrink p)
56− PData s ps -> ps ++ (PData <$> shrinkWHead s <*> shrink ps)
64+ P.Data s ps -> ps ++ (P.Data <$> shrinkWHead s <*> shrink ps)
66+ P.Record <$> filter (all notNull) (filter notNull (shrink fs))
58shrinkWHead :: Arbitrary a => [a] -> [[a]]
70shrinkWHead :: Arbitrary a => [a] -> [[a]]
59shrinkWHead [] = error "Should be nonempty"
71shrinkWHead [] = error "Should be nonempty"
60shrinkWHead (x:xs) = (x:) <$> shrink xs
72shrinkWHead (x:xs) = (x:) <$> shrink xs
62−instance Arbitrary Type where
74+instance Arbitrary T.Type where
63 arbitrary = sized tipe
75 arbitrary = sized tipe
64− where tipe :: Int -> Gen Type
77+ tipe :: Int -> Gen T.Type
79+ let depthTipe = tipe =<< choose (0,n)
80+ field = (,) <$> lowVar <*> depthTipe
81+ fields = genVector n (\m -> (,) <$> lowVar <*> tipe m)
82+ fields1 = (:) <$> field <*> fields
65− tipe n = oneof [ Lambda <$> depthTipe <*> depthTipe
85+ [ T.Lambda <$> depthTipe <*> depthTipe
66− , Var <$> lowVar
86+ , T.Var <$> lowVar
67− , Data <$> capVar <*> depthTipes
87+ , T.Data <$> capVar <*> genVector n tipe
68− , Record <$> fields <*> pure Nothing
88+ , T.Record <$> fields <*> pure Nothing
69− , Record <$> fields1 <*> (Just <$> lowVar)
89+ , T.Record <$> fields1 <*> (Just <$> lowVar)
71− where depthTipe = choose (0,n) >>= tipe
91+
74− let m = n `div` (len + 1)
75− vectorOf len $ tipe m
77− field = (,) <$> lowVar <*> depthTipe
80− let m = n `div` (len + 1)
81− vectorOf len $ (,) <$> lowVar <*> tipe m
82− fields1 = (:) <$> field <*> fields
84− shrink tipe = case tipe of
92+ shrink tipe =
85− Lambda s t -> s : t : (Lambda <$> shrink s <*> shrink t)
94+ T.Lambda s t -> s : t : (T.Lambda <$> shrink s <*> shrink t)
86− Var _ -> []
95+ T.Var _ -> []
87− Data n ts -> ts ++ (Data <$> shrinkWHead n <*> shrink ts)
96+ T.Data n ts -> ts ++ (T.Data <$> shrinkWHead n <*> shrink ts)
88− Record fs t -> map snd fs ++ case t of
97+ T.Record fs t -> map snd fs ++ record
89− Nothing -> Record <$> shrinkList shrinkField fs <*> pure Nothing
101+ Nothing -> T.Record <$> shrinkList shrinkField fs <*> pure Nothing
90− Just _ ->
102+ Just _ ->
92− fields <- filter (not . null) $ shrinkList shrinkField fs
103+ do fields <- filter (not . null) $ shrinkList shrinkField fs
93− return $ Record fields t
104+ return $ T.Record fields t
94− where shrinkField (n,t) = (,) <$> shrinkWHead n <*> shrink t
106+ shrinkField (n,t) = (,) <$> shrinkWHead n <*> shrink t
96lowVar :: Gen String
108lowVar :: Gen String
97lowVar = notReserved $ (:) <$> lower <*> listOf varLetter
109lowVar = notReserved $ (:) <$> lower <*> listOf varLetter
98− where lower = elements ['a'..'z']
111+ lower = elements ['a'..'z']
100capVar :: Gen String
113capVar :: Gen String
101capVar = notReserved $ (:) <$> upper <*> listOf varLetter
114capVar = notReserved $ (:) <$> upper <*> listOf varLetter
102− where upper = elements ['A'..'Z']
116+ upper = elements ['A'..'Z']
104varLetter :: Gen Char
118varLetter :: Gen Char
105varLetter = elements $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ ['\'', '_']
119varLetter = elements $ ['a'..'z'] ++ ['A'..'Z'] ++ ['0'..'9'] ++ ['\'', '_']
@@ -109,5 +123,6 @@ notReserved = flip exceptFor Parse.Helpers.reserveds
110exceptFor :: (Ord a) => Gen a -> [a] -> Gen a
124exceptFor :: (Ord a) => Gen a -> [a] -> Gen a
111exceptFor g xs = g `suchThat` notAnX
125exceptFor g xs = g `suchThat` notAnX
112− where notAnX = flip Set.notMember xset
127+ notAnX = flip Set.notMember xset
113− xset = Set.fromList xs
128+ xset = Set.fromList xs