/examples/BF.hs

https://github.com/mainland/haskell-src-meta · Haskell · 182 lines · 110 code · 38 blank · 34 comment · 5 complexity · 5773912f23b738dcc3d0fa458fd8835f MD5 · raw file

  1. {-# LANGUAGE BangPatterns, TemplateHaskell #-}
  2. module Language.Haskell.Meta.QQ.BF (
  3. bf,bf2,bfHelloWorld
  4. ) where
  5. import Language.Haskell.Meta (parsePat)
  6. import Language.Haskell.TH.Lib
  7. import Language.Haskell.TH.Quote
  8. import Language.Haskell.TH.Syntax
  9. import Data.Char
  10. import Data.IntMap(IntMap)
  11. import qualified Data.IntMap as IM
  12. bf :: QuasiQuoter
  13. bf = QuasiQuoter { quoteExp = bfExpQ, quotePat = bfPatQ }
  14. bf2 :: QuasiQuoter
  15. bf2 = QuasiQuoter { quoteExp = bf2ExpQ, quotePat = bfPatQ }
  16. bf2ExpQ :: String -> ExpQ
  17. bf2ExpQ s = [|eval (parse s)|]
  18. bfExpQ :: String -> ExpQ
  19. bfExpQ s = [|eval_ (parse s)|]
  20. bfPatQ :: String -> PatQ
  21. bfPatQ s = do
  22. let p = (parsePat
  23. . show
  24. . parse) s
  25. case p of
  26. Left e -> fail e
  27. Right p -> return p
  28. instance Lift Bf where
  29. lift Inp = [|Inp|]
  30. lift Out = [|Out|]
  31. lift Inc = [|Inc|]
  32. lift Dec = [|Dec|]
  33. lift MovL = [|MovL|]
  34. lift MovR = [|MovR|]
  35. lift (While xs) = [|While $(lift xs)|]
  36. type Ptr = Int
  37. newtype Mem = Mem (IntMap Int) deriving (Show)
  38. data Bf = Inp
  39. | Out
  40. | Inc
  41. | Dec
  42. | MovL
  43. | MovR
  44. | While [Bf]
  45. deriving (Eq,Ord,Read,Show)
  46. data Status = D Ptr Mem
  47. | W Int Status
  48. | R (Int -> Status)
  49. -- ghci> exec (parse helloWorld)
  50. -- Hello World!
  51. -- (4,Mem (fromList [(0,0),(1,87),(2,100),(3,33),(4,10)]))
  52. bfHelloWorld :: String
  53. bfHelloWorld = "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>."
  54. eval_ :: [Bf] -> (String -> String)
  55. eval_ is = go (run 0 initMem is)
  56. where go (D p m) _ = []
  57. go (W n s) cs = chr n : go s cs
  58. go (R cont) [] = "*** Exception: bf blocked on input"
  59. go (R cont) (c:cs) = go ((cont . ord) c) cs
  60. eval :: [Bf] -> String -> (String, (Ptr, Mem))
  61. eval is = go [] (run 0 initMem is)
  62. where go acc (D p m) _ = (reverse acc, (p, m))
  63. go acc (W n s) cs = go (chr n:acc) s cs
  64. go _ (R cont) [] = ("*** Exception: bf blocked on input",(-1, Mem IM.empty))
  65. go acc (R cont) (c:cs) = go acc ((cont . ord) c) cs
  66. exec :: [Bf] -> IO (Ptr, Mem)
  67. exec is = go (run 0 initMem is)
  68. where go (D p m) = return (p, m)
  69. go (W n s) = putChar (chr n) >> go s
  70. go (R cont) = go . cont . ord =<< getChar
  71. run :: Ptr -> Mem -> [Bf] -> Status
  72. run dp m is = step dp m is (\dp m -> D dp m)
  73. step :: Ptr -> Mem -> [Bf] -> (Ptr -> Mem -> Status) -> Status
  74. step dp m [] k = k dp m
  75. step dp m (Inc:is) k = step dp (inc dp m) is k
  76. step dp m (Dec:is) k = step dp (dec dp m) is k
  77. step dp m (MovL:is) k = step (dp-1) m is k
  78. step dp m (MovR:is) k = step (dp+1) m is k
  79. step dp m (Inp:is) k = R (\c -> step dp (wr m dp c) is k)
  80. step dp m (Out:is) k = W (rd m dp) (step dp m is k)
  81. step dp m (While xs:is) k = let go dp m = if rd m dp == 0
  82. then step dp m is k
  83. else step dp m xs go
  84. in go dp m
  85. initMem :: Mem
  86. initMem = Mem IM.empty
  87. inc :: Ptr -> (Mem -> Mem)
  88. dec :: Ptr -> (Mem -> Mem)
  89. rd :: Mem -> Ptr -> Int
  90. wr :: Mem -> Ptr -> Int -> Mem
  91. upd :: Mem -> Ptr -> (Int -> Int) -> Mem
  92. inc p m = upd m p (+1)
  93. dec p m = upd m p (subtract 1)
  94. rd (Mem m) p = maybe 0 id (IM.lookup p m)
  95. wr (Mem m) p n = Mem (IM.insert p n m)
  96. upd m p f = wr m p (f (rd m p))
  97. parse :: String -> [Bf]
  98. parse s = go 0 [] s (\_ xs _ -> xs)
  99. where go :: Int -> [Bf] -> String
  100. -> (Int -> [Bf] -> String -> o) -> o
  101. go !n acc [] k = k n (reverse acc) []
  102. go !n acc (',':cs) k = go (n+1) (Inp:acc) cs k
  103. go !n acc ('.':cs) k = go (n+1) (Out:acc) cs k
  104. go !n acc ('+':cs) k = go (n+1) (Inc:acc) cs k
  105. go !n acc ('-':cs) k = go (n+1) (Dec:acc) cs k
  106. go !n acc ('<':cs) k = go (n+1) (MovL:acc) cs k
  107. go !n acc ('>':cs) k = go (n+1) (MovR:acc) cs k
  108. go !n acc ('[':cs) k = go (n+1) [] cs (\n xs cs ->
  109. go n (While xs:acc) cs k)
  110. go !n acc (']':cs) k = k (n+1) (reverse acc) cs
  111. go !n acc (c :cs) k = go n acc cs k
  112. test0 = do
  113. a <- readFile "prime.bf"
  114. return (parse a)
  115. {-
  116. data Bf = Inp
  117. | Out
  118. | Inc
  119. | Dec
  120. | MovL
  121. | MovR
  122. | While [Bf]
  123. | Error String
  124. deriving (Eq,Ord,Read,Show)
  125. parse :: String -> [Bf]
  126. parse s = let p n s = case go n [] s of
  127. (_,xs,[]) -> xs
  128. (n,xs, s) -> xs ++ p n s
  129. in p 0 s
  130. where go :: Int -> [Bf] -> [Char] -> (Int, [Bf], String)
  131. go !n acc [] = (n, reverse acc, [])
  132. go !n acc (',':cs) = go (n+1) (Inp:acc) cs
  133. go !n acc ('.':cs) = go (n+1) (Out:acc) cs
  134. go !n acc ('+':cs) = go (n+1) (Inc:acc) cs
  135. go !n acc ('-':cs) = go (n+1) (Dec:acc) cs
  136. go !n acc ('<':cs) = go (n+1) (MovL:acc) cs
  137. go !n acc ('>':cs) = go (n+1) (MovR:acc) cs
  138. go !n acc ('[':cs) = case go (n+1) [] cs of
  139. (n,xs,cs) -> go n (While xs:acc) cs
  140. go !n acc (']':cs) = (n+1, reverse acc, cs)
  141. go !n acc (c :cs) = (n+1, [Error ("go error: char "++show n
  142. ++" illegal character: "++show c)], [])
  143. -}