{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE DerivingStrategies #-} module Arbitrary.ValidBrainfuckProgram (ValidBrainfuckProgram(..)) where import Data.Text (Text) import Test.QuickCheck.Arbitrary (Arbitrary (arbitrary)) import Test.QuickCheck.Gen (Gen, sized, frequency, oneof, resize) import Data.Coerce (coerce) import qualified Data.Text as Text newtype ValidBrainfuckProgram = ValidBrainfuckProgram { get :: Text } deriving stock Show instance Arbitrary ValidBrainfuckProgram where arbitrary :: Gen ValidBrainfuckProgram arbitrary = coerce . fmap Text.pack $ character [] where character rest = do body <- frequency [ (1, comment) , (9, operator) ] sized $ \ size -> frequency [ (1 , pure body) , (size, character body) ] where operator = let simpleOperator = oneof $ map (pure . (:rest)) "+-<>,." loopOperator = fmap ('[':) . sized $ \ s -> resize (s `div` 8) (character (']':rest)) in frequency [ (3, simpleOperator) , (1, loopOperator) ] comment = do commentChar <- oneof $ map pure "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" pure $ commentChar : rest -- >>> import Test.QuickCheck.Gen (generate) -- >>> generate $ (arbitrary :: Gen ValidBrainfuckProgram) -- ValidBrainfuckProgram {get = "<-"}