feat[compressed]: ability to uncompress
This commit is contained in:
parent
f05da30c8a
commit
40ce94ab7b
3 changed files with 41 additions and 2 deletions
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -96,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))]
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ import qualified Data.Either as Either
|
||||||
import qualified Language.Brainfuck as Brainfuck
|
import qualified Language.Brainfuck as Brainfuck
|
||||||
import qualified Arbitrary.ValidBrainfuckText as ValidBrainfuckText
|
import qualified Arbitrary.ValidBrainfuckText as ValidBrainfuckText
|
||||||
import qualified Arbitrary.InvalidBrainfuckText as InValidBrainfuckText
|
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
|
-- | ValidBrainfuckText will produce a text with comments, it must be parsed correctly
|
||||||
prop_acceptValidTexts :: ValidBrainfuckText.ValidBrainfuckText -> Bool
|
prop_acceptValidTexts :: ValidBrainfuckText.ValidBrainfuckText -> Bool
|
||||||
|
@ -24,6 +25,10 @@ prop_rejectInvalidTexts = Either.isLeft . Brainfuck.parse . InValidBrainfuckText
|
||||||
prop_renderParseInverse :: Vector Instruction -> Bool
|
prop_renderParseInverse :: Vector Instruction -> Bool
|
||||||
prop_renderParseInverse source = Right source == (Brainfuck.parse . Brainfuck.render $ source)
|
prop_renderParseInverse source = Right source == (Brainfuck.parse . Brainfuck.render $ source)
|
||||||
|
|
||||||
|
-- | Compressing and Uncompressing should be inverse
|
||||||
|
prop_CompressUncompressInverse :: Vector Instruction -> Bool
|
||||||
|
prop_CompressUncompressInverse source = source == CompressedInstruction.uncompress . CompressedInstruction.compress
|
||||||
|
|
||||||
return [] -- template haskell guard
|
return [] -- template haskell guard
|
||||||
runQuickCheck :: IO Bool
|
runQuickCheck :: IO Bool
|
||||||
runQuickCheck = $quickCheckAll
|
runQuickCheck = $quickCheckAll
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue