brainfuck-monad 0.4.0 → 0.5.0
raw patch · 4 files changed
+90/−13 lines, 4 filesdep +directorydep +processsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: directory, process
API changes (from Hackage documentation)
- Control.Monad.BrainFuck: instance Monad BrainFuck
+ Control.Monad.BrainFuck: compile :: FilePath -> BrainFuck () -> IO ()
+ Control.Monad.BrainFuck: demo' :: BrainFuck ()
+ Control.Monad.BrainFuck: instance GHC.Base.Applicative Control.Monad.BrainFuck.BrainFuck
+ Control.Monad.BrainFuck: instance GHC.Base.Functor Control.Monad.BrainFuck.BrainFuck
+ Control.Monad.BrainFuck: instance GHC.Base.Monad Control.Monad.BrainFuck.BrainFuck
+ Control.Monad.BrainFuck: ld :: FilePath -> FilePath -> IO ()
+ Control.Monad.BrainFuck: movfuscate :: BrainFuck () -> IO ASM
+ Control.Monad.BrainFuck: nasm :: FilePath -> ASM -> IO FilePath
+ Control.Monad.BrainFuck: type ASM = String
Files
- CHANGELOG +12/−0
- Control/Monad/BrainFuck.hs +70/−9
- Setup.hs +3/−0
- brainfuck-monad.cabal +5/−4
+ CHANGELOG view
@@ -0,0 +1,12 @@+brainfuck-monad (0.5.0) unstable; urgency=medium++ * Applicative instance.+ * Can use movfuscator to build elf executables.++ -- Joey Hess <id@joeyh.name> Fri, 25 Sep 2015 16:01:03 -0400++brainfuck-monad (0.4.0) unstable; urgency=low++ * First release.++ -- Joey Hess <joeyh@debian.org> Wed, 02 Apr 2014 13:57:42 -0400
Control/Monad/BrainFuck.hs view
@@ -1,10 +1,19 @@+{-# LANGUAGE DeriveFunctor #-}+ module Control.Monad.BrainFuck where import qualified Control.Monad as M+import Control.Applicative+import Control.Monad (ap) import qualified Data.Char as Char import Data.Word (Word8)+import System.Process+import System.IO+import System.Exit+import System.Directory newtype BrainFuck a = BrainFuck (DataPointer -> ([Char], DataPointer, a))+ deriving (Functor) type DataPointer = Integer @@ -17,13 +26,17 @@ brainfuck (BrainFuck f) = bytes where (bytes, _, _) = f 0 instance Monad BrainFuck where- return ret = BrainFuck $ \loc -> ([], loc, ret)+ return = pure 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 ()+instance Applicative BrainFuck where+ pure v = BrainFuck $ \loc -> ([], loc, v)+ (<*>) = ap++next, prev, incr, decr, output, input, open, close, debug :: BrainFuck () -- | move data pointer right next = opcode' succ '>' -- | move data pointer left@@ -163,9 +176,9 @@ -- current memory cell, or allocate and use new ones, and will not -- exit the loop. forever :: BrainFuck a -> BrainFuck ()-forever a = loopFrom 1 $ \i ->- alloc' $ \scratch -> do- a+forever a = loopFrom 1 $ \_i ->+ alloc' $ \_scratch -> do+ _ <- a return () -- | Copies the value of a cell.@@ -255,7 +268,7 @@ setAddr c1 loopUnless0 $ do decr- loopFrom y $ \c2 -> do+ loopFrom y $ \_c2 -> do decr setAddr x incr@@ -269,7 +282,7 @@ -- Get to letter 104 ('a' is 97) quickly by multiplication. start = do zero- x <- addr+ _x <- addr add 13 mult 8 return (13 * 8)@@ -289,7 +302,10 @@ -- | Prints out the alphabet, repeatedly, with some whitespace fun -- to make it more interesting. demo :: String-demo = brainfuck $ alloc' $ \tilt -> do+demo = brainfuck demo'++demo' :: BrainFuck () +demo' = alloc' $ \tilt -> do settilt alloc' $ \tc -> do decr -- set to 255@@ -297,7 +313,7 @@ copy tilt wc forever $ alloc' $ \c -> do set (fromIntegral start)- loopFrom (fromIntegral numchars) $ \i -> do+ loopFrom (fromIntegral numchars) $ \_i -> do decr withAddr wc decr@@ -397,3 +413,48 @@ -- Any sequence of > and < at the end of a program is a noop. trimend = reverse . dropWhile (`elem` "><") . reverse +-- | Uses the MOVfuscator v1 to build a Linux executable from a BrainFuck+-- monad action. The executable is implemented entirely using the+-- MOV instruction. It may be a little slow, especially when loops are+-- involved.+--+-- Prereq: Clone https://github.com/xoreaxeaxeax/movfuscator, build the v1+-- brainfuck to MOV compiler (in the poc/) directory, and put it in PATH.+-- Also apt-get install nasm.+compile :: FilePath -> BrainFuck () -> IO ()+compile dest b = movfuscate b >>= nasm dest >>= ld dest++type ASM = String++movfuscate :: BrainFuck () -> IO ASM+movfuscate b = do+ (Just hin, Just hout, Nothing, h) <- createProcess $+ (proc "movfuscator" [])+ { std_out = CreatePipe+ , std_in = CreatePipe+ }+ hPutStr hin $ optimize $ brainfuck b+ hClose hin+ asm <- hGetContents hout+ writeFile "asm" asm+ c <- waitForProcess h+ case c of+ ExitSuccess -> return ()+ _ -> error ("movfuscator exited nonzero")+ return asm++nasm :: FilePath -> ASM -> IO FilePath+nasm dest a = do+ -- nasm needs a real file, can't use stdin+ writeFile asmfile a+ callProcess "nasm" ["-felf", asmfile, "-o", objfile]+ removeFile asmfile+ return objfile+ where+ asmfile = dest ++ ".asm"+ objfile = dest ++ ".o"++ld :: FilePath -> FilePath -> IO ()+ld dest objfile = do+ callProcess "ld" ["-melf_i386", objfile, "-o", dest]+ removeFile objfile
Setup.hs view
@@ -1,2 +1,5 @@+{- cabal setup file -}+ import Distribution.Simple+ main = defaultMain
brainfuck-monad.cabal view
@@ -1,5 +1,5 @@ Name: brainfuck-monad-Version: 0.4.0+Version: 0.5.0 Cabal-Version: >= 1.8 License: BSD3 Maintainer: Joey Hess <id@joeyh.name>@@ -12,12 +12,13 @@ Synopsis: BrainFuck monad Description: This is a BrainFuck monad, for generating brainfuck programs.+Extra-Source-Files: CHANGELOG Library- GHC-Options: -Wall+ GHC-Options: -Wall -fno-warn-tabs Exposed-Modules: Control.Monad.BrainFuck- Build-Depends: base (>= 4.5), base < 5+ Build-Depends: base (>= 4.5), base < 5, process, directory source-repository head type: git- location: git://git.kitenet.net/brainfuck-monad.git+ location: git://git.joeyh.name/brainfuck-monad.git