Compare commits
6 commits
cbccc8253b
...
1b20f4ef71
Author | SHA1 | Date | |
---|---|---|---|
1b20f4ef71 | |||
40ce94ab7b | |||
f05da30c8a | |||
d012307d19 | |||
9484d097d4 | |||
95f86c8660 |
9 changed files with 217 additions and 13 deletions
|
@ -29,6 +29,7 @@ library
|
||||||
Language.Brainfuck.Instruction
|
Language.Brainfuck.Instruction
|
||||||
Language.Brainfuck.Instruction.Compressed
|
Language.Brainfuck.Instruction.Compressed
|
||||||
Language.Brainfuck.Instruction.Extended
|
Language.Brainfuck.Instruction.Extended
|
||||||
|
Language.Brainfuck.Interpreter
|
||||||
other-modules:
|
other-modules:
|
||||||
Paths_bf_optimize
|
Paths_bf_optimize
|
||||||
autogen-modules:
|
autogen-modules:
|
||||||
|
@ -37,7 +38,9 @@ library
|
||||||
src
|
src
|
||||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
|
||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
QuickCheck
|
||||||
|
, base >=4.7 && <5
|
||||||
|
, quickcheck-instances
|
||||||
, text
|
, text
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
@ -52,8 +55,10 @@ executable bf-optimize-exe
|
||||||
app
|
app
|
||||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
QuickCheck
|
||||||
|
, base >=4.7 && <5
|
||||||
, bf-optimize
|
, bf-optimize
|
||||||
|
, quickcheck-instances
|
||||||
, text
|
, text
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
@ -62,6 +67,8 @@ test-suite bf-optimize-test
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
main-is: Spec.hs
|
main-is: Spec.hs
|
||||||
other-modules:
|
other-modules:
|
||||||
|
Arbitrary.InvalidBrainfuckText
|
||||||
|
Arbitrary.ValidBrainfuckText
|
||||||
Paths_bf_optimize
|
Paths_bf_optimize
|
||||||
autogen-modules:
|
autogen-modules:
|
||||||
Paths_bf_optimize
|
Paths_bf_optimize
|
||||||
|
@ -69,8 +76,10 @@ test-suite bf-optimize-test
|
||||||
test
|
test
|
||||||
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N
|
||||||
build-depends:
|
build-depends:
|
||||||
base >=4.7 && <5
|
QuickCheck
|
||||||
|
, base >=4.7 && <5
|
||||||
, bf-optimize
|
, bf-optimize
|
||||||
|
, quickcheck-instances
|
||||||
, text
|
, text
|
||||||
, vector
|
, vector
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
|
|
@ -23,6 +23,8 @@ dependencies:
|
||||||
- base >= 4.7 && < 5
|
- base >= 4.7 && < 5
|
||||||
- text
|
- text
|
||||||
- vector
|
- vector
|
||||||
|
- QuickCheck
|
||||||
|
- quickcheck-instances
|
||||||
|
|
||||||
ghc-options:
|
ghc-options:
|
||||||
- -Wall
|
- -Wall
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
{-# LANGUAGE ImportQualifiedPost #-}
|
{-# LANGUAGE ImportQualifiedPost #-}
|
||||||
{-# LANGUAGE ViewPatterns #-}
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
module Language.Brainfuck (parse, ParseFailure) where
|
{-# LANGUAGE LambdaCase #-}
|
||||||
|
module Language.Brainfuck (parse, ParseFailure, render) where
|
||||||
|
|
||||||
import Control.Monad ((<$!>))
|
import Control.Monad ((<$!>))
|
||||||
import Control.Monad.ST (runST, ST)
|
import Control.Monad.ST (runST, ST)
|
||||||
|
@ -14,11 +15,12 @@ import Data.Vector qualified as Vector
|
||||||
import Data.Vector.Mutable qualified as MutableVector
|
import Data.Vector.Mutable qualified as MutableVector
|
||||||
|
|
||||||
import Language.Brainfuck.Instruction ( Instruction(..) )
|
import Language.Brainfuck.Instruction ( Instruction(..) )
|
||||||
|
import qualified Data.List as List
|
||||||
|
|
||||||
data ParseFailure
|
data ParseFailure
|
||||||
= UnexpectedClosingBracket Int -- closing bracket position
|
= UnexpectedClosingBracket Int -- closing bracket position
|
||||||
| UnmatchedOpenBracket Int -- opening bracket position
|
| UnmatchedOpenBracket Int -- opening bracket position
|
||||||
deriving stock (Show)
|
deriving stock (Show, Eq)
|
||||||
|
|
||||||
-- | Convert a Text to a list of instructions, discard all comments.
|
-- | Convert a Text to a list of instructions, discard all comments.
|
||||||
--
|
--
|
||||||
|
@ -83,3 +85,21 @@ parse text = runST $ do
|
||||||
|
|
||||||
-- >>> parse $ Text.pack "[]]"
|
-- >>> parse $ Text.pack "[]]"
|
||||||
-- Left (UnexpectedClosingBracket 2)
|
-- Left (UnexpectedClosingBracket 2)
|
||||||
|
|
||||||
|
render :: Vector Instruction -> Text
|
||||||
|
render = Text.concat . List.map renderSingle . Vector.toList
|
||||||
|
where
|
||||||
|
renderSingle = \case
|
||||||
|
Increment -> Text.singleton '+'
|
||||||
|
Decrement -> Text.singleton '-'
|
||||||
|
MoveLeft -> Text.singleton '<'
|
||||||
|
MoveRight -> Text.singleton '>'
|
||||||
|
ReadByte -> Text.singleton ','
|
||||||
|
PutByte -> Text.singleton '.'
|
||||||
|
Loop body -> Text.concat [Text.singleton '[', render body, Text.singleton ']']
|
||||||
|
|
||||||
|
-- >>> import Test.QuickCheck.Instances.Vector ()
|
||||||
|
-- >>> import Test.QuickCheck.Arbitrary (arbitrary)
|
||||||
|
-- >>> render <$> Gen.generate arbitrary
|
||||||
|
-- "<,<>,<,."
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
module Language.Brainfuck.Instruction (Instruction(..)) where
|
module Language.Brainfuck.Instruction (Instruction(..)) where
|
||||||
|
|
||||||
import Data.Vector ( Vector )
|
import Data.Vector ( Vector )
|
||||||
|
import Test.QuickCheck.Gen (Gen)
|
||||||
|
import Test.QuickCheck.Arbitrary (Arbitrary (arbitrary))
|
||||||
|
import Test.QuickCheck.Instances.Vector ()
|
||||||
|
|
||||||
|
import qualified Test.QuickCheck.Gen as Gen
|
||||||
|
|
||||||
data Instruction
|
data Instruction
|
||||||
= Increment
|
= Increment
|
||||||
|
@ -12,3 +18,20 @@ data Instruction
|
||||||
| PutByte
|
| PutByte
|
||||||
| Loop (Vector Instruction)
|
| Loop (Vector Instruction)
|
||||||
deriving stock (Show, Eq)
|
deriving stock (Show, Eq)
|
||||||
|
|
||||||
|
instance Arbitrary Instruction where
|
||||||
|
arbitrary :: Gen Instruction
|
||||||
|
arbitrary = Gen.oneof $
|
||||||
|
[ pure Increment
|
||||||
|
, pure Decrement
|
||||||
|
, pure MoveLeft
|
||||||
|
, pure MoveRight
|
||||||
|
, pure ReadByte
|
||||||
|
, pure PutByte
|
||||||
|
, Loop <$> reduceSize 8 arbitrary
|
||||||
|
]
|
||||||
|
where
|
||||||
|
reduceSize d g = Gen.sized $ \ s -> Gen.resize (s `div` d) g
|
||||||
|
|
||||||
|
-- >>> Gen.generate (Gen.resize 30 arbitrary) :: IO [Instruction]
|
||||||
|
-- [MoveLeft,Decrement,PutByte,Decrement,Decrement,Increment,ReadByte,MoveLeft,Increment,Loop [],MoveRight,Increment,Increment,Loop [],MoveLeft,Loop [],MoveRight,ReadByte,ReadByte,MoveLeft,Decrement,MoveRight,MoveLeft,Loop [PutByte,Increment,Loop []],Decrement]
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
{-# LANGUAGE ImportQualifiedPost #-}
|
{-# LANGUAGE ImportQualifiedPost #-}
|
||||||
module Language.Brainfuck.Instruction.Compressed ( CompressedInstruction(..), compress ) where
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
module Language.Brainfuck.Instruction.Compressed ( CompressedInstruction(..), compress, uncompress ) where
|
||||||
|
|
||||||
import Data.Bifunctor ( Bifunctor(first) )
|
import Data.Bifunctor ( Bifunctor(first) )
|
||||||
import Data.Vector ( Vector )
|
import Data.Vector ( Vector )
|
||||||
import Data.Word ( Word8 )
|
import Data.Word ( Word8 )
|
||||||
import Numeric.Natural ( Natural )
|
import Numeric.Natural ( Natural )
|
||||||
|
import Test.QuickCheck.Gen (Gen)
|
||||||
|
import Test.QuickCheck.Arbitrary (Arbitrary(arbitrary))
|
||||||
|
import Test.QuickCheck.Instances.Natural ()
|
||||||
|
|
||||||
import Data.Vector qualified as Vector
|
import Data.Vector qualified as Vector
|
||||||
|
|
||||||
|
import Test.QuickCheck.Gen qualified as Gen
|
||||||
|
|
||||||
import Language.Brainfuck.Instruction ( Instruction )
|
import Language.Brainfuck.Instruction ( Instruction )
|
||||||
import Language.Brainfuck.Instruction qualified as Instruction
|
import Language.Brainfuck.Instruction qualified as Instruction
|
||||||
|
|
||||||
|
@ -21,6 +27,20 @@ data CompressedInstruction
|
||||||
| Loop (Vector CompressedInstruction)
|
| Loop (Vector CompressedInstruction)
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance Arbitrary CompressedInstruction where
|
||||||
|
arbitrary :: Gen CompressedInstruction
|
||||||
|
arbitrary = Gen.oneof
|
||||||
|
[ Add <$> arbitrary
|
||||||
|
, Subtract <$> arbitrary
|
||||||
|
, MoveRight <$> arbitrary
|
||||||
|
, MoveLeft <$> arbitrary
|
||||||
|
, pure ReadByte
|
||||||
|
, pure PutByte
|
||||||
|
, Loop <$> resize (`div` 8) arbitrary
|
||||||
|
]
|
||||||
|
where
|
||||||
|
resize f x = Gen.sized $ \ s -> Gen.resize (f s) x
|
||||||
|
|
||||||
compress :: Vector Instruction -> Vector CompressedInstruction
|
compress :: Vector Instruction -> Vector CompressedInstruction
|
||||||
compress instructions = Vector.fromList (go instructions)
|
compress instructions = Vector.fromList (go instructions)
|
||||||
where
|
where
|
||||||
|
@ -51,3 +71,18 @@ compress instructions = Vector.fromList (go instructions)
|
||||||
-- >>> compress . Vector.fromList $ replicate 300 Instruction.MoveRight
|
-- >>> compress . Vector.fromList $ replicate 300 Instruction.MoveRight
|
||||||
-- [MoveRight 300]
|
-- [MoveRight 300]
|
||||||
|
|
||||||
|
uncompress :: Vector CompressedInstruction -> Vector Instruction
|
||||||
|
uncompress = Vector.concatMap uncompressSingle
|
||||||
|
where
|
||||||
|
uncompressSingle instruction = let
|
||||||
|
repeated x times = Vector.replicate (fromIntegral times) x
|
||||||
|
|
||||||
|
in case instruction of
|
||||||
|
Add times -> repeated Instruction.Increment times
|
||||||
|
Subtract times -> repeated Instruction.Decrement times
|
||||||
|
MoveRight times -> repeated Instruction.MoveRight times
|
||||||
|
MoveLeft times -> repeated Instruction.MoveLeft times
|
||||||
|
PutByte -> Vector.singleton Instruction.PutByte
|
||||||
|
ReadByte -> Vector.singleton Instruction.ReadByte
|
||||||
|
Loop body -> Vector.singleton $ Instruction.Loop (uncompress body)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
{-# LANGUAGE PatternSynonyms #-}
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
|
{-# LANGUAGE StrictData #-}
|
||||||
module Language.Brainfuck.Instruction.Extended (Operation(..), Interaction(..), ExtendedInstruction(Modify, Move, Interact, Jump), pattern IfNonZero, pattern WithOffset, mkIfNonZero, mkWithOffset, translationSize, parse) where
|
module Language.Brainfuck.Instruction.Extended (Operation(..), Interaction(..), ExtendedInstruction(Modify, Move, Interact, Jump), pattern IfNonZero, pattern WithOffset, mkIfNonZero, mkWithOffset, translationSize, parse) where
|
||||||
|
|
||||||
import Data.Word (Word8)
|
import Data.Word (Word8)
|
||||||
import Language.Brainfuck.Instruction.Compressed (CompressedInstruction)
|
|
||||||
import Data.Vector (Vector)
|
import Data.Vector (Vector)
|
||||||
|
import Numeric.Natural (Natural)
|
||||||
|
|
||||||
|
import Language.Brainfuck.Instruction.Compressed (CompressedInstruction)
|
||||||
|
|
||||||
import qualified Data.Vector as Vector
|
import qualified Data.Vector as Vector
|
||||||
import qualified Language.Brainfuck.Instruction.Compressed as CompressedInstruction
|
import qualified Language.Brainfuck.Instruction.Compressed as CompressedInstruction
|
||||||
import Numeric.Natural (Natural)
|
|
||||||
|
|
||||||
data Operation
|
data Operation
|
||||||
= Add
|
= Add
|
||||||
|
@ -18,7 +22,7 @@ data Interaction
|
||||||
| Write
|
| Write
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
pattern WithOffset :: Int -> ExtendedInstruction -> ExtendedInstruction
|
pattern WithOffset :: Integer -> ExtendedInstruction -> ExtendedInstruction
|
||||||
pattern WithOffset offset embedded <- AtOffset offset embedded
|
pattern WithOffset offset embedded <- AtOffset offset embedded
|
||||||
where
|
where
|
||||||
WithOffset offset embedded = mkWithOffset offset embedded
|
WithOffset offset embedded = mkWithOffset offset embedded
|
||||||
|
@ -29,7 +33,7 @@ pattern IfNonZero instruction <- WhenNonZero instruction
|
||||||
IfNonZero instruction = mkIfNonZero instruction
|
IfNonZero instruction = mkIfNonZero instruction
|
||||||
|
|
||||||
data ExtendedInstruction
|
data ExtendedInstruction
|
||||||
= AtOffset Int ExtendedInstruction -- invariant, WithOffset may not nest itself
|
= AtOffset Integer ExtendedInstruction -- invariant, WithOffset may not nest itself
|
||||||
| WhenNonZero ExtendedInstruction -- invariant, IfNonZero may not nest itself
|
| WhenNonZero ExtendedInstruction -- invariant, IfNonZero may not nest itself
|
||||||
| Modify Operation Word8
|
| Modify Operation Word8
|
||||||
| Move Integer
|
| Move Integer
|
||||||
|
@ -42,7 +46,7 @@ mkIfNonZero = \case
|
||||||
WhenNonZero i -> WhenNonZero i
|
WhenNonZero i -> WhenNonZero i
|
||||||
instruction -> WhenNonZero instruction
|
instruction -> WhenNonZero instruction
|
||||||
|
|
||||||
mkWithOffset :: Int -> ExtendedInstruction -> ExtendedInstruction
|
mkWithOffset :: Integer -> ExtendedInstruction -> ExtendedInstruction
|
||||||
mkWithOffset offset = \case
|
mkWithOffset offset = \case
|
||||||
AtOffset offset' i -> AtOffset (offset + offset') i
|
AtOffset offset' i -> AtOffset (offset + offset') i
|
||||||
instruction -> AtOffset offset instruction
|
instruction -> AtOffset offset instruction
|
||||||
|
@ -92,4 +96,3 @@ translationSize = Vector.sum . Vector.map instructionTranslationSize
|
||||||
--
|
--
|
||||||
-- >>> parse [CompressedInstruction.Add 5, CompressedInstruction.Loop [CompressedInstruction.Loop [CompressedInstruction.ReadByte], CompressedInstruction.PutByte]]
|
-- >>> parse [CompressedInstruction.Add 5, CompressedInstruction.Loop [CompressedInstruction.Loop [CompressedInstruction.ReadByte], CompressedInstruction.PutByte]]
|
||||||
-- [Modify Add 5,Jump 4,Jump 1,Interact Read,WhenNonZero (Jump (-2)),Interact Write,WhenNonZero (Jump (-5))]
|
-- [Modify Add 5,Jump 4,Jump 1,Interact Read,WhenNonZero (Jump (-2)),Interact Write,WhenNonZero (Jump (-5))]
|
||||||
|
|
||||||
|
|
26
test/Arbitrary/InvalidBrainfuckText.hs
Normal file
26
test/Arbitrary/InvalidBrainfuckText.hs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
module Arbitrary.InvalidBrainfuckText (InvalidBrainfuckText(..)) where
|
||||||
|
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Test.QuickCheck.Gen (Gen)
|
||||||
|
import Test.QuickCheck.Arbitrary (Arbitrary (arbitrary))
|
||||||
|
|
||||||
|
import qualified Data.Text as Text
|
||||||
|
import qualified Test.QuickCheck.Gen as Gen
|
||||||
|
import qualified Arbitrary.ValidBrainfuckText as ValidBrainfuckText
|
||||||
|
|
||||||
|
newtype InvalidBrainfuckText = InvalidBrainfuckText { get :: Text }
|
||||||
|
deriving stock Show
|
||||||
|
|
||||||
|
instance Arbitrary InvalidBrainfuckText where
|
||||||
|
arbitrary :: Gen InvalidBrainfuckText
|
||||||
|
arbitrary = do
|
||||||
|
validText <- ValidBrainfuckText.get <$> arbitrary
|
||||||
|
|
||||||
|
index <- Gen.choose (0, Text.length validText)
|
||||||
|
badBrace <- Gen.oneof $ map pure "[]"
|
||||||
|
let (prefix, suffix) = Text.splitAt index validText
|
||||||
|
|
||||||
|
pure . InvalidBrainfuckText $ Text.concat [prefix, Text.singleton badBrace, suffix]
|
||||||
|
|
48
test/Arbitrary/ValidBrainfuckText.hs
Normal file
48
test/Arbitrary/ValidBrainfuckText.hs
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
{-# LANGUAGE InstanceSigs #-}
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
module Arbitrary.ValidBrainfuckText (ValidBrainfuckText(..)) 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 ValidBrainfuckText = ValidBrainfuckText { get :: Text }
|
||||||
|
deriving stock Show
|
||||||
|
|
||||||
|
instance Arbitrary ValidBrainfuckText where
|
||||||
|
arbitrary :: Gen ValidBrainfuckText
|
||||||
|
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 ValidBrainfuckText)
|
||||||
|
-- ValidBrainfuckText {get = "<[><]>[>],>+,[.-K.]+.>[<],z[p[[<]]+<],<[+]+[P[+][[e]]+,]+,.[-][[<],>>++]+"}
|
||||||
|
|
||||||
|
|
40
test/Spec.hs
40
test/Spec.hs
|
@ -1,2 +1,40 @@
|
||||||
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
|
import Data.Vector (Vector)
|
||||||
|
|
||||||
|
import Test.QuickCheck.All (quickCheckAll)
|
||||||
|
import System.Exit (exitFailure, exitSuccess)
|
||||||
|
|
||||||
|
import Language.Brainfuck.Instruction (Instruction)
|
||||||
|
|
||||||
|
import qualified Data.Either as Either
|
||||||
|
import qualified Language.Brainfuck as Brainfuck
|
||||||
|
import qualified Arbitrary.ValidBrainfuckText as ValidBrainfuckText
|
||||||
|
import qualified Arbitrary.InvalidBrainfuckText as InValidBrainfuckText
|
||||||
|
import qualified Language.Brainfuck.Instruction.Compressed as CompressedInstruction
|
||||||
|
|
||||||
|
-- | ValidBrainfuckText will produce a text with comments, it must be parsed correctly
|
||||||
|
prop_acceptValidTexts :: ValidBrainfuckText.ValidBrainfuckText -> Bool
|
||||||
|
prop_acceptValidTexts = Either.isRight . Brainfuck.parse . ValidBrainfuckText.get
|
||||||
|
|
||||||
|
-- | InvalidBrainfuckText will insert unbalanced brackets, they must be rejected
|
||||||
|
prop_rejectInvalidTexts :: InValidBrainfuckText.InvalidBrainfuckText -> Bool
|
||||||
|
prop_rejectInvalidTexts = Either.isLeft . Brainfuck.parse . InValidBrainfuckText.get
|
||||||
|
|
||||||
|
-- | Does rendering and parsing a vector of instructions yield the exact same result?
|
||||||
|
prop_renderParseInverse :: Vector Instruction -> Bool
|
||||||
|
prop_renderParseInverse source = Right source == (Brainfuck.parse . Brainfuck.render $ source)
|
||||||
|
|
||||||
|
-- | Compressing and Uncompressing should be inverse. The opposite must not be true, since `compress $ replicate 300 Increment` is `Add 44`
|
||||||
|
prop_CompressUncompressInverse :: Vector Instruction -> Bool
|
||||||
|
prop_CompressUncompressInverse source = source == (CompressedInstruction.uncompress . CompressedInstruction.compress) source
|
||||||
|
|
||||||
|
return [] -- template haskell guard
|
||||||
|
runQuickCheck :: IO Bool
|
||||||
|
runQuickCheck = $quickCheckAll
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = putStrLn "Test suite not yet implemented"
|
main = do
|
||||||
|
quickCheckGood <- runQuickCheck
|
||||||
|
|
||||||
|
if quickCheckGood then exitSuccess else exitFailure
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue