|
0 |
module Language.Turmac.Simulator where
|
|
1 |
|
|
2 |
import Language.Turmac.Model
|
|
3 |
|
|
4 |
-- | Single step of TM execution
|
|
5 |
step :: [TMRule] -> Configuration -> Configuration
|
|
6 |
step rules st@(Configuration tape state halted)
|
|
7 |
| halted = st -- Don't continue if halted
|
|
8 |
| otherwise = case findRule rules state (readSymbol tape) of
|
|
9 |
Just (_, _, newSym, newState, dir) ->
|
|
10 |
Configuration
|
|
11 |
(moveInDir dir (writeSymbol newSym tape))
|
|
12 |
(if newState == "H" then state else newState)
|
|
13 |
(newState == "H")
|
|
14 |
Nothing -> error $ "No rules for state " ++ show state ++
|
|
15 |
" and symbol " ++ show (readSymbol tape)
|
|
16 |
|
|
17 |
-- | Find matching rule for current state and symbol
|
|
18 |
findRule :: [TMRule] -> StateId -> Symbol -> Maybe TMRule
|
|
19 |
findRule rules state sym =
|
|
20 |
case [r | r@(s, sym', _, _, _) <- rules, s == state, sym' == sym] of
|
|
21 |
[] -> Nothing
|
|
22 |
(r:_) -> Just r
|
|
23 |
|
|
24 |
-- | Move tape in given direction
|
|
25 |
moveInDir :: Direction -> Tape -> Tape
|
|
26 |
moveInDir (-1) = moveLeft
|
|
27 |
moveInDir 1 = moveRight
|
|
28 |
moveInDir d = error $ "Invalid direction: " ++ show d
|
|
29 |
|
|
30 |
-- | Run TM until it halts, return history of configurations and final state
|
|
31 |
simulate :: [TMRule] -> Configuration -> ([Configuration], Configuration)
|
|
32 |
simulate rules config = go [] config
|
|
33 |
where
|
|
34 |
go history st@(Configuration _ _ True) =
|
|
35 |
(reverse (st:history), st)
|
|
36 |
go history st =
|
|
37 |
go (st:history) (step rules st)
|
|
38 |
|
|
39 |
-- | Run TM until it halts, return only final configuration
|
|
40 |
execute :: [TMRule] -> Configuration -> Configuration
|
|
41 |
execute rules config = snd $ simulate rules config
|