Implemented OUT and reimplemented IN with IO

This commit is contained in:
Claudio Maggioni (maggicl) 2020-10-31 23:45:03 +01:00
parent 4dc1eeb3c3
commit d8ad0add0e
1 changed files with 31 additions and 20 deletions

View File

@ -69,21 +69,26 @@ errorDesc LoopNoMatch = "ERROR: '[' or ']' not working. Matching parenthesis not
incrIP :: State -> State
incrIP p = p { ip = ip p + 1 }
execUpdate :: Instruction -> State -> Execution State
execUpdate i p = Working p { tape = newTape }
execUpdate :: Instruction -> State -> State
execUpdate i p = p { tape = newTape }
where newTape = tapeHelp (tape p) (dp p) (updateCell i)
execTapeLeft :: State -> Execution State
execTapeLeft p = case dp p of 0 -> Crash NegTape
n -> Working p { dp = n - 1 }
execTapeRight :: State -> Execution State
execTapeRight p = Working p { tape = tape p ++ newTape, dp = dp p + 1 }
execTapeRight :: State -> State
execTapeRight p = p { tape = tape p ++ newTape, dp = dp p + 1 }
where newTape = case dp p == length (tape p) - 1 of True -> [Byte 0]
_ -> []
execOut :: State -> Execution State
execOut p = Working p { output = output p ++ [chr char]}
execIn :: State -> IO (Execution State)
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
findMatching :: Program -> Instruction -> Int -> Maybe Int
@ -110,19 +115,24 @@ execLoop d w = case posOrF of Just n -> Working w { ip = n }
posOrF = case jump of True -> findMatching (program w) d (ip w)
_ -> Just $ ip w
execute :: State -> Execution State
execute w = do ran <- (traceShowId $ runInstr w)
newStatus <- checkDone ran
execute newStatus
where instrFor w = case (program w !! ip w) of
TapeLeft -> execTapeLeft
TapeRight -> execTapeRight
Add -> execUpdate Add
Sub -> execUpdate Sub
Out -> execOut
l -> execLoop l
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)
In -> execIn
Out -> return . return . execOut
l -> fmap return $ execLoop l
runInstr :: State -> Execution State
andThen :: Execution State -> IO (Execution State)
andThen s = case s >>= checkDone of
Working s -> execute s
t -> return t
runInstr :: State -> IO (Execution State)
runInstr w = instrFor w $ w
checkDone :: State -> Execution State
@ -131,6 +141,7 @@ execute w = do ran <- (traceShowId $ runInstr w)
| otherwise = Working $ ps { ip = newIP }
where newIP = ip ps + 1
initState :: Program -> State
initState p = State {
tape = [Byte 0],
@ -139,6 +150,6 @@ initState p = State {
program = p,
ip = 0}
run :: String -> Execution State
run "" = Done ""
run :: String -> IO (Execution State)
run "" = return $ Done ""
run s = execute . initState . catMaybes . fmap parseInstr $ s