mirror of
https://github.com/github/semantic.git
synced 2024-12-01 09:15:01 +03:00
57 lines
1.3 KiB
Haskell
57 lines
1.3 KiB
Haskell
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||
|
|
||
|
module Generators
|
||
|
( literal
|
||
|
, name
|
||
|
, variable
|
||
|
, boolean
|
||
|
, lambda
|
||
|
, apply
|
||
|
, ifthenelse
|
||
|
) where
|
||
|
|
||
|
import Prelude hiding (span)
|
||
|
|
||
|
import Hedgehog hiding (Var)
|
||
|
import qualified Hedgehog.Gen as Gen
|
||
|
import qualified Hedgehog.Range as Range
|
||
|
|
||
|
import Data.Core
|
||
|
import Data.Name
|
||
|
|
||
|
-- The 'prune' call here ensures that we don't spend all our time just generating
|
||
|
-- fresh names for variables, since the length of variable names is not an
|
||
|
-- interesting property as they parse regardless.
|
||
|
name :: MonadGen m => m Name
|
||
|
name = Gen.prune (User <$> names) where
|
||
|
names = Gen.string (Range.linear 1 10) Gen.lower
|
||
|
|
||
|
boolean :: MonadGen m => m Core
|
||
|
boolean = Bool <$> Gen.bool
|
||
|
|
||
|
variable :: MonadGen m => m Core
|
||
|
variable = Var <$> name
|
||
|
|
||
|
ifthenelse :: MonadGen m => m Core -> m Core
|
||
|
ifthenelse bod = Gen.subterm3 boolean bod bod If
|
||
|
|
||
|
apply :: MonadGen m => m Core -> m Core
|
||
|
apply gen = go where
|
||
|
go = Gen.recursive
|
||
|
Gen.choice
|
||
|
[ Gen.subterm2 gen gen (:$)]
|
||
|
[ Gen.subterm2 go go (:$) -- balanced
|
||
|
, Gen.subtermM go (\x -> Lam <$> name <*> pure x)
|
||
|
]
|
||
|
|
||
|
lambda :: MonadGen m => m Core -> m Core
|
||
|
lambda bod = do
|
||
|
arg <- name
|
||
|
Gen.subterm bod (Lam arg)
|
||
|
|
||
|
atoms :: MonadGen m => [m Core]
|
||
|
atoms = [boolean, variable, pure Unit, pure Frame]
|
||
|
|
||
|
literal :: MonadGen m => m Core
|
||
|
literal = Gen.recursive Gen.choice atoms [lambda literal]
|