Advertisement
Guest User

Rofth-FTG

a guest
Apr 23rd, 2020
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Control.Monad ((>=>))
  2.  
  3. data Elem a = Leaf | Node a | Branch (Elem a) (Elem a) deriving(Show)
  4.  
  5. data Ins i d
  6.     = PutState
  7.     | TakeState
  8.     | Exec
  9.     | Define
  10.     | Lookup
  11.     | Lit d
  12.     | Ins i
  13.     deriving(Eq, Show)
  14.  
  15. data RunErr
  16.     = TypeErr
  17.     | OutOfRange
  18.     | InsErr
  19.     deriving(Show)
  20.  
  21. toList :: [a] -> Elem a
  22. toList [] = Leaf
  23. toList (x:xs) = Branch (Node x) (toList xs)
  24.  
  25. unwrapNode :: Elem a -> Either RunErr a
  26. unwrapNode (Node a) = Right a
  27. unwrapNode _ = Left TypeErr
  28.  
  29. {- STACK/LIST OPERATIONS -}
  30.  
  31. top :: Elem a -> Either RunErr (Elem a)
  32. top (Branch x _) = Right x
  33. top Leaf = Left OutOfRange
  34. top (Node _) = Left TypeErr
  35.  
  36. pop :: Elem a -> Either RunErr (Elem a)
  37. pop (Branch _ xs) = Right xs
  38. pop Leaf = Left OutOfRange
  39. pop (Node _) = Left TypeErr
  40.  
  41. tpop :: Elem a -> Either RunErr (Elem a, Elem a) -- (top, pop)
  42. tpop (Branch x xs) = Right (x, xs)
  43. tpop Leaf = Left OutOfRange
  44. tpop (Node _) = Left TypeErr
  45.  
  46. push :: Elem a -> Elem a -> Either RunErr (Elem a)
  47. push x = Right . Branch x
  48.  
  49. append :: Elem a -> Elem a -> Either RunErr (Elem a)
  50. append e (Branch x xs) = (append e xs) >>= (\xs' -> return (Branch x xs'))
  51. append e Leaf = Right (Branch e Leaf)
  52. append _ _ = Left TypeErr
  53.  
  54. updateFirst :: (Elem a -> Either RunErr (Elem a)) -> Elem a -> Either RunErr (Elem a)
  55. updateFirst fn (Branch a b) = do
  56.     v <- fn a
  57.     return (Branch v b)
  58. updateFirst _ _ = Left TypeErr
  59.  
  60. updateSecond :: (Elem a -> Either RunErr (Elem a)) -> Elem a -> Either RunErr (Elem a)
  61. updateSecond fn (Branch a b) = fn b >>= (return . Branch a)
  62. updateSecond _ _ = Left TypeErr
  63.  
  64. {- MAP OPERATIONS -}
  65.  
  66. indexMap :: (Eq a) => a -> Elem a -> Either RunErr (Elem a)
  67. indexMap a map = do
  68.     e <- top map
  69.     case e of
  70.         (Branch (Node a') e) | a == a' -> return e
  71.         (Branch (Node _) _) -> do
  72.             map' <- pop map
  73.            indexMap a map'
  74.         _ -> Left TypeErr
  75.  
  76. appendMap :: a -> Elem a -> Elem a -> Either RunErr (Elem a)
  77. appendMap k v = append (Branch (Node k) v)
  78.  
  79. {- STATE OPERATIONS -}
  80. incIns :: Elem (Ins i d) -> Either RunErr (Elem (Ins i d)) -- increment ins
  81. incIns s = updateFirst (updateFirst pop) s
  82.  
  83. retProc :: Elem (Ins i d) -> Either RunErr (Elem (Ins i d)) -- return from process
  84. retProc s = updateFirst pop s
  85.  
  86. nextIns :: Elem (Ins i d) -> Either RunErr (Ins i d, Elem (Ins i d)) -- next ins, new state
  87. nextIns s = case (top >=> top >=> top >=> unwrapNode) s of
  88.     Right ins -> incIns s >>= (return . (,) ins)
  89.     Left err -> retProc s >>= nextIns
  90.  
  91. single :: (Eq i, Eq d) => (i -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))) -> (Ins i d) -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))
  92. single fn (Ins i) s = fn i s
  93. single _ PutState s = updateSecond (updateFirst (push s)) s
  94. single _ TakeState s = (pop >=> top >=> top) s
  95. single _ Exec s = do
  96.     proc <- (pop >=> top >=> top) s
  97.     updateFirst (push proc) s
  98. single _ Define s = do
  99.     k <- (pop >=> top >=> top >=> unwrapNode) s
  100.     v <- (pop >=> top >=> pop >=> top) s
  101.     updateSecond
  102.         (   updateFirst (pop >=> pop)
  103.         >=> updateSecond (appendMap k v)) s
  104. single _ Lookup s = do
  105.     k <- (pop >=> top >=> top >=> unwrapNode) s
  106.     v <- (pop >=> pop >=> indexMap k) s
  107.     updateSecond
  108.         (updateFirst (pop >=> push v)) s
  109. single _ i@(Lit _) s = updateSecond (updateFirst (push (Node i))) s
  110.  
  111. doStep :: (Eq i, Eq d) => (i -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))) -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))
  112. doStep fn s = do
  113.     (ins, s') <- nextIns s
  114.    single fn ins s'
  115.  
  116. runPrg :: (Eq i, Eq d) => (i -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))) -> Elem (Ins i d) -> Either RunErr (Elem (Ins i d))
  117. runPrg fn s = case top s of
  118.     Right (Branch Leaf Leaf) -> return s
  119.     _ -> do
  120.         s' <- doStep fn s
  121.        runPrg fn s'
  122.  
  123. load :: [Ins i d] -> Elem (Ins i d)
  124. load ls = Branch (Branch (toList ls) Leaf) (Branch Leaf Leaf)
  125.  
  126. showOutput :: (Show i, Show d) => Elem (Ins i d) -> String
  127. showOutput = \y -> case (pop >=> top >=> top) y of
  128.     Right x -> show x
  129.     _ -> "No top item on stack"
  130.  
  131. execPrg :: (Eq i, Eq d, Show i, Show d) => [Ins i d] -> String -- now you can do 'execPrg [Lit "hello, world", ...]' etc.
  132. execPrg ls = case runPrg undefined (load ls) of
  133.     Right out -> showOutput out
  134.     Left err -> show err
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement