Compare commits

..

1 Commits

Author SHA1 Message Date
Claudio Maggioni (maggicl)
5f8a2cadf3 Implemented OUT and reimplemented IN with IO 2020-11-01 00:28:51 +01:00

View File

@ -35,15 +35,14 @@ type Program = [Instruction]
data State = State {
tape :: Tape,
dp :: Int,
output :: String,
program :: Program,
ip :: Int } deriving (Show)
data Execution a = Working a | Crash Error | Done String deriving (Show)
data Execution a = Working a | Crash Error | Done deriving (Show)
instance Monad Execution where
(Crash e) >>= _ = Crash e
(Done t) >>= _ = Done t
Done >>= _ = Done
(Working d) >>= f = f d
instance Functor Execution where
@ -87,22 +86,21 @@ execIn p = do chr <- getChar
tp <- pure $ fromEnum chr
return $ Working p { tape = tapeHelp (tape p) (dp p) (\_ -> Byte tp) }
execOut :: State -> State
execOut p = p { output = output p ++ [chr char]}
where char = tape p !! dp p
execOut :: State -> IO (Execution State)
execOut p = putChar (chr (tape p !! dp p)) >> (return . Working $ p)
findMatching :: Program -> Instruction -> Int -> Maybe Int
findMatching prg toFind = fmHelper $ -1
where (oppos, limit, next) = case toFind of
LoopEnd -> (LoopStart, length prg, (+1))
LoopStart -> (LoopEnd, 0, (-1+))
findMatching prg par = fmHelper $ -1
where (oppos, limit, next) = case par of
LoopStart -> (LoopEnd, length prg, (+1))
LoopEnd -> (LoopStart, 0, (-1+))
fmHelper :: Int -> Int -> Maybe Int
fmHelper acc s
| s == limit = Nothing
| acc == 0 && c == toFind = Just s
| c == toFind = fmHelper (acc - 1) $ next s
| c == oppos = fmHelper (acc + 1) $ next s
| acc == 0 && c == oppos = Just s
| c == oppos = fmHelper (acc - 1) $ next s
| c == par = fmHelper (acc + 1) $ next s
| otherwise = fmHelper acc $ next s
where c = prg !! s
@ -119,13 +117,13 @@ execute :: State -> IO (Execution State)
execute w = runInstr w >>= andThen
where instrFor :: State -> State -> IO (Execution State)
instrFor w = case (program w !! ip w) of
TapeLeft -> fmap return $ execTapeLeft
TapeRight -> return . return . execTapeRight
Add -> return . return . (execUpdate Add)
Sub -> return . return . (execUpdate Sub)
TapeLeft -> return . execTapeLeft
TapeRight -> return . Working . execTapeRight
Add -> return . Working . (execUpdate Add)
Sub -> return . Working . (execUpdate Sub)
In -> execIn
Out -> return . return . execOut
l -> fmap return $ execLoop l
Out -> execOut
l -> return . execLoop l
andThen :: Execution State -> IO (Execution State)
andThen s = case s >>= checkDone of
@ -137,7 +135,7 @@ execute w = runInstr w >>= andThen
checkDone :: State -> Execution State
checkDone ps
| (length . program) ps == newIP = Done $ output ps
| (length . program) ps == newIP = Done
| otherwise = Working $ ps { ip = newIP }
where newIP = ip ps + 1
@ -146,10 +144,9 @@ initState :: Program -> State
initState p = State {
tape = [Byte 0],
dp = 0,
output = "",
program = p,
ip = 0}
run :: String -> IO (Execution State)
run "" = return $ Done ""
run s = execute . initState . catMaybes . fmap parseInstr $ s
run s = case catMaybes . fmap parseInstr $ s of [] -> return Done
l -> execute . initState $ l