packages feed

yabi (empty) → 0.1.0.0

raw patch · 4 files changed

+125/−0 lines, 4 filesdep +basedep +word8setup-changed

Dependencies added: base, word8

Files

+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2014 Francesco Gazzetta++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ yabi.cabal view
@@ -0,0 +1,22 @@+name:                yabi+version:             0.1.0.0+synopsis:            Yet Another Brainfuck Interpreter+description:         Yet Another Brainfuck Interpreter+homepage:            https://github.com/fgaz/yabi+license:             MIT+license-file:        LICENSE+author:              Francesco Gazzetta+maintainer:          fgaz@users.noreply.github.com+-- copyright:           +category:            Compilers/Interpreters+build-type:          Simple+-- extra-source-files:  +cabal-version:       >=1.10++executable yabi+  main-is:             yabi.hs+  -- other-modules:       +  -- other-extensions:    +  build-depends:       base ==4.*, word8+  -- hs-source-dirs:      +  default-language:    Haskell2010
+ yabi.hs view
@@ -0,0 +1,81 @@+import Data.Word8 (Word8)+import Data.Char (ord, chr)+import System.Environment (getArgs)+import System.IO (readFile, putChar, getChar, stdout, stdin, hSetBuffering, BufferMode (NoBuffering))+import System.Exit (exitFailure)++--the memory & program zippers+type Memory = ([Word8],[Word8]) -- the memory zipper: (left, pointer:right)+type Program = ([Char],[Char]) -- the instructions zipper: (todo,done)++--the default memory, an infinite zipper filled with zeros+defaultMemory :: ([Word8],[Word8])+defaultMemory = ((repeat 0),(repeat 0))++--breaks a string when the brackets are balanced+-- an open bracket adds 1 to the balance, a closed one subtracts 1+breakWhenBalanced :: Int -> String -> (String, String)+breakWhenBalanced 0 str = ("",str)+breakWhenBalanced balance (s:str) | s == '[' = let (first, second) = breakWhenBalanced (balance+1) str in (s:first, second)+                                  | s == ']' = let (first, second) = breakWhenBalanced (balance-1) str in (s:first, second)+                                  | otherwise = let (first, second) = breakWhenBalanced balance str in (s:first, second)+breakWhenBalanced balance [] = error $ "malformed code, brackets balance off by " ++ (show balance)++--the actual interpreter+bf :: Program -> Memory -> IO ()+bf ([], _) _ = return () --end of program+--move the pointer+bf ('>':commands, done) (ml, m:mr) = bf (commands, '>':done) (m:ml, mr)+bf ('<':commands, done) (m:ml, mr) = bf (commands, '<':done) (ml, m:mr)+--change the pointed byte+bf ('+':commands, done) (ml, m:mr) = bf (commands, '+':done) (ml, (m+1):mr)+bf ('-':commands, done) (ml, m:mr) = bf (commands, '-':done) (ml, (m-1):mr)+--output of pointed byte+bf ('.':commands, done) (ml, m:mr) = do+                                       putChar $ chr $ fromIntegral m+                                       bf (commands, '.':done) (ml, m:mr)+--input to pointed byte+bf (',':commands, done) (ml, _:mr) = do+                                       char <- getChar+                                       let m = fromIntegral $ ord char+                                       bf (commands, ',':done) (ml, m:mr)+--if pointed byte == 0 then jump forward to the corresponding ]+bf ('[':commands, done) (ml, m:mr) | m == 0 = bf (commands', done') (ml, m:mr)+                                   | otherwise = bf (commands, '[':done) (ml, m:mr)+    where (token, commands') = breakWhenBalanced 1 commands+          done' = (reverse token) ++ '[':done+--if pointed byte /= 0 then jump back to the corresponding [+bf (']':commands, done) (ml, m:mr) | m /= 0 = bf (commands', done') (ml, m:mr)+                                   | otherwise = bf (commands, ']':done) (ml, m:mr) --the interpreter works even without this line and "| m /= 0" on the line above, but this way is faster+    where (token, done') = breakWhenBalanced (-1) done+          commands' = (reverse token) ++ ']':commands++--debug+--memory dump ('#', according to Urban Müller's original interpreter)+bf ('#':commands, done) (ml,m:mr) = do+                                   putStrLn "Memory dump:"+                                   putStrLn $ "  " ++ (show $ takeWhile (/=0) ml) ++ " >" ++ (show m) ++ "< " ++ (show $ takeWhile (/=0) mr)+                                   bf (commands, '#':done) (ml,m:mr)+--program dump (i picked a random not-widely-used character for this)+bf ('§':commands, done) (ml,mr) = do+                                   putStrLn "Program dump:"+                                   putStrLn $ "  " ++ (reverse done) ++ "|" ++ commands+                                   putStrLn $ (replicate (length done + 2) ' ') ++ "^"+                                   bf (commands, '§':done) (ml,mr)+--catch-all pattern. I have yet to discover a way to fall down there+bf _ _ = error "malformed code"++main :: IO ()+main = do+    args <- getArgs+    if length args /= 1 then do+        putStrLn "Usage: brainfuck path"+        exitFailure+    else return ()+    rawProgram <- readFile $ head args+    let program = (filter (`elem` "><+-.,[]#§") rawProgram, [])+    --disable buffering+    hSetBuffering stdout NoBuffering+    hSetBuffering stdin NoBuffering+    --start the interpreter+    bf program defaultMemory