Convert Program to use Seq Char
authorMichael Welch <michaelgwelch@gmail.com>
Sun, 19 Feb 2012 22:02:48 +0000 (16:02 -0600)
committerMichael Welch <michaelgwelch@gmail.com>
Sun, 19 Feb 2012 22:02:48 +0000 (16:02 -0600)
haskell/brainmess.hs
haskell/program.hs

index 7dc3170..9801c52 100644 (file)
@@ -8,5 +8,5 @@ main :: IO ()
 main = do
             args <- getArgs
             prog <- readFile $ args !! 0
-            run (Program prog 0) tape
+            run (createProgram prog) tape
             return ()
index b701552..69bb282 100644 (file)
@@ -1,39 +1,46 @@
 module Program where
 import Tape
 import Data.Char
+import Data.Sequence
 import Debug.Trace
+import Prelude hiding (length, take, drop)
 
 -- The Program value constructor should be kept hidden
-data Program = Program String Int deriving (Show, Eq)
+data Program = Program (Seq Char) Int deriving (Show, Eq)
+
+createProgram :: String -> Program
+createProgram s = Program (fromList s) 0
 
--- probably inefficient (rethink later)
--- I'm not sure if behind the scenes haskell isn't a little smart about strings
 endOfProgram :: Program -> Bool
 endOfProgram (Program cs pos) = pos == (length cs)
 
 fetch :: Program -> (Program, Char)
-fetch (Program cs pos) = ((Program cs (pos+1)), cs !! pos)
+fetch (Program cs pos) = ((Program cs (pos+1)), index cs pos)
 
 jumpForward :: Program -> Program
-jumpForward (Program s p) = (Program s ((match s (p-1) 1)+1))
+jumpForward (Program s p) = (Program s ((match s (p-1))+1))
 
 jumpBackward :: Program -> Program
-jumpBackward (Program s p) = (Program s (match s (p-1) (-1)))
+jumpBackward (Program s p) = (Program s (match s (p-1)))
+
+
+match :: Seq Char -> Int -> Int
+match cs p | (index cs p) == '[' = matchForward (viewl (drop (p+1) cs)) (p+1) 1 
+           | (index cs p) == ']' = matchBackward (viewr (take p cs)) (p-1) 1 
+           | otherwise = error "match: Current char is not '[' or ']'"
 
 
-match :: String -> Int -> Int -> Int
-match s p i = match' s (p+i) 1 i
+matchForward :: ViewL Char -> Int -> Int -> Int
+matchForward _ p 0 = (p-1)
+matchForward ('[' :< cs) p n = matchForward (viewl cs) (p+1) (n+1)
+matchForward (']' :< cs) p n = matchForward (viewl cs) (p+1) (n-1)
+matchForward (_ :< cs) p n = matchForward (viewl cs) (p+1) n
 
-match' :: String -> Int -> Int -> Int -> Int
-{-match' s p n i | trace ("match'" ++ show s ++ " " ++ show p ++ " " ++ 
-    show n ++ " " ++ show i) False = undefined
--}
-match' s p 0 i = p-i
-match' s p n i = match' s (p+i) n' i
-               where current = s !! p
-                     n' = if (current == '[') then n+i
-                          else if (current == ']') then n-i
-                          else n
+matchBackward :: ViewR Char -> Int -> Int -> Int
+matchBackward _ p 0 = (p+1)
+matchBackward (cs :> '[') p n = matchBackward (viewr cs) (p-1) (n-1)
+matchBackward (cs :> ']') p n = matchBackward (viewr cs) (p-1) (n+1)
+matchBackward (cs :> _) p n = matchBackward (viewr cs) (p-1) n
 
 execute :: Char -> Program -> Tape -> IO Char -> (Char -> IO ()) 
            -> IO (Program, Tape)
@@ -55,8 +62,9 @@ execute ']' p t _ _ = if ((get t) /= 0) then return ((jumpBackward p), t)
 execute _ p t _ _ = return (p, t)
 
 run :: Program -> Tape -> IO (Program, Tape)
+run p t | (endOfProgram p) = return (p, t)
 run p t = do
             let (p',i) = fetch p
             (p'',t') <- execute i p' t getChar putChar
-            if (endOfProgram p'') then return (p'',t') else (run p'' t')
+            run p'' t'