Guest User

Untitled

a guest
Mar 26th, 2018
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.88 KB | None | 0 0
  1. module Lib
  2. ( interpret
  3. ) where
  4.  
  5. import Data.Char
  6. import Data.List
  7.  
  8. interpret :: [Char] -> IO (Either String [Int])
  9. interpret program = do
  10. step [] program [0] 0
  11.  
  12. -- TODO: memory should be of type Byte
  13. -- TODO: error handling
  14. -- TODO: introduce types
  15. -- TODO: fix matching brackets bug
  16. step :: [Char] -> [Char] -> [Int] -> Int -> IO (Either String [Int])
  17. step _ [] memory _ = return . Right $ memory
  18. step previousProgram currentProgram memory pointer = do
  19. let Just (instruction, nextProgram) = uncons currentProgram
  20. let (previousMemory, currentMemory) = splitAt pointer memory
  21. let currentMemoryCell = head currentMemory
  22. let nextMemory = tail currentMemory
  23. case instruction of
  24. '>' -> if pointer == length memory - 1
  25. then step (previousProgram ++ [instruction]) nextProgram (memory ++ [0]) (length memory)
  26. else step (previousProgram ++ [instruction]) nextProgram memory (pointer + 1)
  27. '<' -> if pointer == 0
  28. then step (previousProgram ++ [instruction]) nextProgram ([0] ++ memory) 0
  29. else step (previousProgram ++ [instruction]) nextProgram memory (pointer - 1)
  30. '+' -> step (previousProgram ++ [instruction]) nextProgram (previousMemory ++ [currentMemoryCell + 1] ++ nextMemory) pointer
  31. '-' -> step (previousProgram ++ [instruction]) nextProgram (previousMemory ++ [currentMemoryCell - 1] ++ nextMemory) pointer
  32. '.' -> do
  33. putChar . chr $ currentMemoryCell
  34. step (previousProgram ++ [instruction]) nextProgram memory pointer
  35. ',' -> do
  36. newCurrentChar <- getChar
  37. let newCurrent = ord newCurrentChar
  38. step (previousProgram ++ [instruction]) nextProgram (previousMemory ++ [newCurrent] ++ nextMemory) pointer
  39. '[' -> case currentMemoryCell of
  40. 0 -> case findMatchingLoopClose nextProgram 0 0 of
  41. Left err -> return . Left $ err
  42. Right advancement -> step (previousProgram ++ [instruction] ++ (take advancement currentProgram)) (drop (advancement + 1) currentProgram) memory pointer
  43. _ -> step (previousProgram ++ [instruction]) nextProgram memory pointer
  44. ']' -> case currentMemoryCell of
  45. 0 -> step (previousProgram ++ [instruction]) nextProgram memory pointer
  46. _ -> case findMatchingLoopOpen previousProgram 0 0 of
  47. Left err -> return . Left $ err
  48. Right decrease -> do
  49. let newStart = (length previousProgram) - decrease
  50. step (take newStart previousProgram) ((drop newStart previousProgram) ++ currentProgram) memory pointer
  51.  
  52. findMatchingLoopClose :: [Char] -> Int -> Int -> Either String Int
  53. findMatchingLoopClose [] _ _ = Left "findMatchingLoopClose: No matching ] found"
  54. findMatchingLoopClose (instruction:remainingProgram) index nestingCounter = case instruction of
  55. '[' -> findMatchingLoopClose remainingProgram (index + 1) (nestingCounter + 1)
  56. ']' -> if nestingCounter == 0
  57. then Right index
  58. else findMatchingLoopClose remainingProgram (index + 1) (nestingCounter - 1)
  59. _ -> findMatchingLoopClose remainingProgram (index + 1) nestingCounter
  60.  
  61. findMatchingLoopOpen :: [Char] -> Int -> Int -> Either String Int
  62. findMatchingLoopOpen = findMatchingLoopOpen' . reverse
  63.  
  64. findMatchingLoopOpen' :: [Char] -> Int -> Int -> Either String Int
  65. findMatchingLoopOpen' [] _ _ = Left "findMatchingLoopOpen: No matching [ found"
  66. findMatchingLoopOpen' (instruction:remainingProgram) index nestingCounter = case instruction of
  67. ']' -> findMatchingLoopOpen' remainingProgram (index + 1) (nestingCounter + 1)
  68. '[' -> if nestingCounter == 0
  69. then Right index
  70. else findMatchingLoopOpen' remainingProgram (index + 1) (nestingCounter - 1)
  71. _ -> findMatchingLoopOpen' remainingProgram (index + 1) nestingCounter
Advertisement
Add Comment
Please, Sign In to add comment