brainfuck-monad 0.0.1 → 0.1.0
raw patch · 2 files changed
+61/−35 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Control.Monad.BrainFuck: at :: Constants -> Integer -> BrainFuck ()
- Control.Monad.BrainFuck: cmd :: Char -> BrainFuck ()
- Control.Monad.BrainFuck: cmd' :: (DataPointer -> DataPointer) -> Char -> BrainFuck ()
+ Control.Monad.BrainFuck: Constants :: NumConstants -> Integer -> Constants
+ Control.Monad.BrainFuck: cat :: String
+ Control.Monad.BrainFuck: char :: Char -> BrainFuck ()
+ Control.Monad.BrainFuck: helloworld :: String
+ Control.Monad.BrainFuck: opcode :: Char -> BrainFuck ()
+ Control.Monad.BrainFuck: opcode' :: (DataPointer -> DataPointer) -> Char -> BrainFuck ()
+ Control.Monad.BrainFuck: pointAt :: Constants -> Integer -> BrainFuck ()
+ Control.Monad.BrainFuck: type NumConstants = Int
+ Control.Monad.BrainFuck: unchar :: Char -> BrainFuck ()
+ Control.Monad.BrainFuck: withChar :: Char -> BrainFuck a -> BrainFuck a
- Control.Monad.BrainFuck: brainfuckConstants :: (Constants -> BrainFuck a) -> String
+ Control.Monad.BrainFuck: brainfuckConstants :: NumConstants -> (Constants -> BrainFuck a) -> String
Files
- Control/Monad/BrainFuck.hs +59/−33
- brainfuck-monad.cabal +2/−2
Control/Monad/BrainFuck.hs view
@@ -1,8 +1,7 @@-{-# LANGUAGE EmptyDataDecls #-}- module Control.Monad.BrainFuck where import qualified Control.Monad as M+import qualified Data.Char as Char newtype BrainFuck a = BrainFuck (DataPointer -> ([Char], DataPointer, a)) @@ -25,21 +24,21 @@ next, prev, incr, decr, output, input, open, close :: BrainFuck () -- | move data pointer right-next = cmd' succ '>'+next = opcode' succ '>' -- | move data pointer left-prev = cmd' pred '<'+prev = opcode' pred '<' -- | increment data-incr = cmd '+'+incr = opcode '+' -- | decrement data-decr = cmd '-'+decr = opcode '-' -- | output byte at data pointer-output = cmd '.'+output = opcode '.' -- | input byte, storing at data pointer-input = cmd ','+input = opcode ',' -- | if byte at data pointer is zero, jump to command after close-open = cmd '['+open = opcode '[' -- | if byte at data pointer is nonzero, jump to command after matching open-close = cmd ']'+close = opcode ']' add, sub :: Int -> BrainFuck () add = multi incr@@ -47,14 +46,14 @@ -- | Adds an arbitrary character to the program. -- Should not be used directly.-cmd :: Char -> BrainFuck ()-cmd = cmd' id+opcode :: Char -> BrainFuck ()+opcode = opcode' id -- | Adds an arbitrary character to the program, -- and updates the data pointer. -- Should not be used directly.-cmd' :: (DataPointer -> DataPointer) -> Char -> BrainFuck ()-cmd' f x = BrainFuck $ \loc -> ([x], f loc, ())+opcode' :: (DataPointer -> DataPointer) -> Char -> BrainFuck ()+opcode' f x = BrainFuck $ \loc -> ([x], f loc, ()) -- | Run an action multiple times. multi :: BrainFuck () -> Int -> BrainFuck ()@@ -62,6 +61,23 @@ _ <- sequence (replicate n c) return () +-- | Assuming that the data pointer points to a 0, changes+-- it to the value of a Char.+char :: Char.Char -> BrainFuck ()+char = multi incr . Char.ord++-- | Undoes `char`+unchar :: Char.Char -> BrainFuck ()+unchar = multi decr . Char.ord++-- | Runs an action with the data pointer pointing at a Char.+withChar :: Char.Char -> BrainFuck a -> BrainFuck a+withChar c a = do+ char c+ r <- a+ unchar c+ return r+ -- | Gets the current address of the data pointer. addr :: BrainFuck DataPointer addr = BrainFuck $ \loc -> ([], loc, loc)@@ -76,38 +92,40 @@ then next >> setAddr n else return () --- | The loop is only entered if the byte at the data pointer is not zero.+-- | The loop is only run if the data pointer doesn't point to 0. ----- On entry, the loop body is run, and then it loops when--- the byte at the data pointer is not zero.+-- On entry, the loop body is run, and then it loops, until the data+-- pointer points to 0. loopUnless0 :: BrainFuck () -> BrainFuck () loopUnless0 a = do open a close -data Constants+data Constants = Constants NumConstants Integer --- | Let's run programs with data cells 0-8 reserved to always contain--- the numbers 0 to 8.+type NumConstants = Int++-- | Let's run programs with data addresses 0..n reserved to always contain+-- the numbers n..0 -- -- These constants will make brainfuck quite a bit easier to use!-brainfuckConstants :: (Constants -> BrainFuck a) -> String-brainfuckConstants a = brainfuck $ do- M.forM_ [0..8] $ \n -> do- add n+brainfuckConstants :: NumConstants -> (Constants -> BrainFuck a) -> String+brainfuckConstants numconstants a = brainfuck $ do+ M.forM_ [0..numconstants] $ \n -> do+ add (numconstants - n) next- a (undefined :: Constants)+ a (Constants numconstants 0) -- | Sets data pointer to point to one of the Constants.-at :: Constants -> Integer -> BrainFuck ()-at _ = setAddr+pointAt :: Constants -> Integer -> BrainFuck ()+pointAt (Constants numconstants c) i = setAddr (c + fromIntegral numconstants - i) --- | Run an action in a loop, until it sets its data pointer to 0.+-- | Run an action in a loop, until the data pointer points to 0. loop :: Constants -> BrainFuck () -> BrainFuck () loop constants a = do here <- addr- at constants 1+ pointAt constants 1 loopUnless0 $ do setAddr here a@@ -116,14 +134,22 @@ forever :: Constants -> BrainFuck () -> BrainFuck () forever constants a = loop constants $ do a- at constants 1+ pointAt constants 1 --- | Prints out the ASCII table, starting with space, repeatedly.+-- | Prints out the ASCII characters, starting with space, repeatedly. -- -- TODO: Only print printable characters. demo :: String-demo = brainfuckConstants $ \constants -> do- add 32+demo = brainfuckConstants 1 $ \constants -> do+ add $ Char.ord ' ' forever constants $ do add 1 output++cat :: String+cat = brainfuckConstants 1 $ flip forever $ input >> output++helloworld :: String+helloworld = brainfuck $+ M.forM_ "hello, world!" $+ flip withChar output
brainfuck-monad.cabal view
@@ -1,5 +1,5 @@ Name: brainfuck-monad-Version: 0.0.1+Version: 0.1.0 Cabal-Version: >= 1.8 License: BSD3 Maintainer: Joey Hess <id@joeyh.name>@@ -8,7 +8,7 @@ Copyright: 2014 Joey Hess License-File: LICENSE Build-Type: Simple-Category: Utility+Category: Compilers/Interpreters Synopsis: BrainFuck monad Description: This is a BrainFuck monad, for generating brainfuck programs.