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