packages feed

brainfuck-monad (empty) → 0.0.1

raw patch · 4 files changed

+176/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ Control/Monad/BrainFuck.hs view
@@ -0,0 +1,129 @@+{-# LANGUAGE EmptyDataDecls #-}++module Control.Monad.BrainFuck where++import qualified Control.Monad as M++newtype BrainFuck a = BrainFuck (DataPointer -> ([Char], DataPointer, a))++type DataPointer = Integer++-- | Retrieve the inner function+func :: BrainFuck f -> DataPointer -> ([Char], DataPointer, f)+func (BrainFuck f) = f++-- | Evaluate the monad and get a brainfuck program+brainfuck :: BrainFuck f -> String+brainfuck (BrainFuck f) = bytes where (bytes, _, _) = f 0++instance Monad BrainFuck where+	return ret = BrainFuck $ \loc -> ([], loc, ret)+	a >>= b = BrainFuck $ \start -> let+		(left, mid, val) = func a start+		(right, end, ret) = func (b val) mid+		in (left ++ right, end, ret)++next, prev, incr, decr, output, input, open, close :: BrainFuck ()+-- | move data pointer right+next = cmd' succ '>'+-- | move data pointer left+prev = cmd' pred '<'+-- | increment data+incr = cmd '+'+-- | decrement data+decr = cmd '-'+-- | output byte at data pointer+output = cmd '.'+-- | input byte, storing at data pointer+input = cmd ','+-- | if byte at data pointer is zero, jump to command after close+open = cmd '['+-- | if byte at data pointer is nonzero, jump to command after matching open+close = cmd ']'++add, sub :: Int -> BrainFuck ()+add = multi incr+sub = multi decr++-- | Adds an arbitrary character to the program.+-- Should not be used directly.+cmd :: Char -> BrainFuck ()+cmd = cmd' 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, ())++-- | Run an action multiple times.+multi :: BrainFuck () -> Int -> BrainFuck ()+multi c n = do+	_ <- sequence (replicate n c)+	return ()++-- | Gets the current address of the data pointer.+addr :: BrainFuck DataPointer+addr = BrainFuck $ \loc -> ([], loc, loc)++-- | Moves the data pointer to a specific address.+setAddr :: Integer -> BrainFuck ()+setAddr n = do+	a <- addr+	if a > n+		then prev >> setAddr n+		else if a < n+			then next >> setAddr n+			else return ()++-- | The loop is only entered if the byte at the data pointer is not zero.+--+-- On entry, the loop body is run, and then it loops when+-- the byte at the data pointer is not zero.+loopUnless0 :: BrainFuck () -> BrainFuck ()+loopUnless0 a = do+	open+	a+	close++data Constants++-- | Let's run programs with data cells 0-8 reserved to always contain+-- the numbers 0 to 8.+--+-- 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+		next+	a (undefined :: Constants)++-- | Sets data pointer to point to one of the Constants.+at :: Constants -> Integer -> BrainFuck ()+at _ = setAddr++-- | Run an action in a loop, until it sets its data pointer to 0.+loop :: Constants -> BrainFuck () -> BrainFuck ()+loop constants a = do+	here <- addr+	at constants 1+	loopUnless0 $ do+		setAddr here+		a++-- | Runs an action in an infinite loop.+forever :: Constants -> BrainFuck () -> BrainFuck ()+forever constants a = loop constants $ do+	a+	at constants 1++-- | Prints out the ASCII table, starting with space, repeatedly.+-- +-- TODO: Only print printable characters.+demo :: String+demo = brainfuckConstants $ \constants -> do+	add 32+	forever constants $ do+		add 1+		output
+ LICENSE view
@@ -0,0 +1,22 @@+Copyright 2014 Joey Hess <id@joeyh.name>.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++THIS SOFTWARE IS PROVIDED BY AUTHORS AND CONTRIBUTORS ``AS IS'' AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF+SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ brainfuck-monad.cabal view
@@ -0,0 +1,23 @@+Name: brainfuck-monad+Version: 0.0.1+Cabal-Version: >= 1.8+License: BSD3+Maintainer: Joey Hess <id@joeyh.name>+Author: Joey Hess+Stability: Stable+Copyright: 2014 Joey Hess+License-File: LICENSE+Build-Type: Simple+Category: Utility+Synopsis: BrainFuck monad+Description:+ This is a BrainFuck monad, for generating brainfuck programs.++Library+  GHC-Options: -Wall+  Exposed-Modules: Control.Monad.BrainFuck+  Build-Depends: base (>= 4.5), base < 5++source-repository head+  type: git+  location: git://git.kitenet.net/brainfuck-monad.git