never executed always true always false
    1 module HelVM.HelMA.Automata.BrainFuck.Common.TapeOfSymbols
    2   ( FullTape
    3   , addAndClearSymbol
    4   , clearSymbol
    5   , dupAndClearSymbol
    6   , incSymbol
    7   , moveHead
    8   , moveHeadLeft
    9   , moveHeadRight
   10   , mulAddAndClearSymbol
   11   , mulDupAndClearSymbol
   12   , newTape
   13   , nextSymbol
   14   , prevSymbol
   15   , setSymbol
   16   , subAndClearSymbol
   17   , triAndClearSymbol
   18   , writeSymbol
   19   ) where
   20 
   21 import           HelVM.HelMA.Automata.BrainFuck.Common.Symbol
   22 
   23 import           Control.Monad.Extra
   24 
   25 -- | Complex instructions
   26 
   27 triAndClearSymbol ∷ (Symbol e) ⇒ Integer → Integer → Integer → FullTapeD e
   28 triAndClearSymbol f1 f2 f3 tape = tape & stepSymbol f1 & stepSymbol f2 & stepSymbol f3 & backAndClear back where
   29   back = negate (f1 + f2 + f3)
   30   stepSymbol = step symbol
   31   symbol = readSymbol tape
   32 
   33 mulDupAndClearSymbol ∷ (Symbol e) ⇒ Integer → Integer → Integer → Integer → FullTapeD e
   34 mulDupAndClearSymbol m1 m2 f1 f2 tape = tape & step ms1 f1 & step ms2 f2 & backAndClear back where
   35   back = negate (f1 + f2)
   36   ms1 = symbol * fromIntegral m1
   37   ms2 = symbol * fromIntegral m2
   38   symbol = readSymbol tape
   39 
   40 dupAndClearSymbol ∷ (Symbol e) ⇒ Integer → Integer → FullTapeD e
   41 dupAndClearSymbol f1 f2 tape = tape & stepSymbol f1 & stepSymbol f2 & backAndClear back where
   42   back = negate (f1 + f2)
   43   stepSymbol = step symbol
   44   symbol = readSymbol tape
   45 
   46 mulAddAndClearSymbol ∷ (Symbol e) ⇒ Integer → Integer → FullTapeD e
   47 mulAddAndClearSymbol mul forward tape = tape & step mulSymbol forward & backAndClear back where
   48   back = negate forward
   49   mulSymbol = symbol * fromIntegral mul
   50   symbol = readSymbol tape
   51 
   52 addAndClearSymbol ∷ (Symbol e) ⇒ Integer → FullTapeD e
   53 addAndClearSymbol = changeAndClearSymbol id
   54 
   55 subAndClearSymbol ∷ (Symbol e) ⇒ Integer → FullTapeD e
   56 subAndClearSymbol = changeAndClearSymbol negate
   57 
   58 changeAndClearSymbol ∷ (Symbol e) ⇒ (e → e) → Integer → FullTapeD e
   59 changeAndClearSymbol f forward tape = tape & step symbol forward & backAndClear back where
   60   back = negate forward
   61   symbol = f $ readSymbol tape
   62 
   63 step ∷ (Symbol e) ⇒ e → Integer → FullTapeD e
   64 step symbol forward = addSymbol symbol . moveHead forward
   65 
   66 backAndClear ∷ (Symbol e) ⇒ Integer → FullTapeD e
   67 backAndClear back = clearSymbol . moveHead back
   68 
   69 -- | Change symbols
   70 
   71 setSymbol ∷ (Symbol e) ⇒ Integer → FullTapeD e
   72 setSymbol i = modifyCell $ const $ fromIntegral i
   73 
   74 incSymbol ∷ (Symbol e) ⇒ Integer → FullTapeD e
   75 incSymbol i = addSymbol $ fromIntegral i
   76 
   77 addSymbol ∷ (Symbol e) ⇒ e → FullTapeD e
   78 addSymbol e = modifyCell $ inc e
   79 
   80 clearSymbol ∷ (Symbol e) ⇒ FullTapeD e
   81 clearSymbol = modifyCell $ const def
   82 
   83 nextSymbol ∷ (Symbol e) ⇒ FullTapeD e
   84 nextSymbol = modifyCell next
   85 
   86 prevSymbol ∷ (Symbol e) ⇒ FullTapeD e
   87 prevSymbol = modifyCell prev
   88 
   89 writeSymbol ∷ (Symbol e) ⇒ Char → FullTapeD e
   90 writeSymbol symbol = modifyCell (const $ fromChar symbol)
   91 
   92 modifyCell ∷ D e → FullTapeD e
   93 modifyCell f (left , cell : right) = (left , f cell : right)
   94 modifyCell _ (_ , [])              = error "End of the Tape"
   95 
   96 readSymbol ∷ FullTape e → e
   97 readSymbol (_ , cell : _) = cell
   98 readSymbol (_ , [])       = error "End of the Tape"
   99 
  100 -- | Moves
  101 
  102 moveHead ∷ (Symbol e) ⇒ Integer → FullTapeD e
  103 moveHead = changeTape moveHeadRight moveHeadLeft
  104 
  105 changeTape ∷ FullTapeD e → FullTapeD e → Integer → FullTapeD e
  106 changeTape lf gf i t = loop atc (i , t) where
  107   atc (i' , t') = (check . compare0) i' where
  108     check LT = Left (i' - 1 , lf t')
  109     check GT = Left (i' + 1 , gf t')
  110     check EQ = Right t'
  111 
  112 moveHeadRight ∷ (Symbol e) ⇒ FullTapeD e
  113 moveHeadRight (cell : left , right) = pad (left , cell : right)
  114 moveHeadRight ([] , _)              = error "End of the Tape"
  115 
  116 moveHeadLeft ∷ (Symbol e) ⇒ FullTapeD e
  117 moveHeadLeft (left , cell : right) = pad (cell : left , right)
  118 moveHeadLeft (_ , [])              = error "End of the Tape"
  119 
  120 pad ∷ (Symbol e) ⇒ FullTapeD e
  121 pad ([] , [])    = newTape
  122 pad ([] , right) = ([def] , right)
  123 pad (left , [])  = (left , [def])
  124 pad tape         = tape
  125 
  126 -- | Constructors
  127 
  128 newTape ∷ (Symbol e) ⇒ FullTape e
  129 newTape = ([def] , [def])
  130 
  131 -- | Types
  132 
  133 type D a = a → a
  134 type FullTape e = (HalfTape e , HalfTape e)
  135 type FullTapeD e = D (FullTape e)
  136 
  137 type HalfTape e = [e]