Implemented OUT and reimplemented IN with IO
This commit is contained in:
parent
4dc1eeb3c3
commit
d8ad0add0e
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue