git @ Cat's Eye Technologies Burro / master src / Language / Turmac / Simulator.hs
master

Tree @master (Download .tar.gz)

Simulator.hs @masterraw · history · blame

-- SPDX-FileCopyrightText: Chris Pressey, the creator of this work, has dedicated it to the public domain.
-- For more information, please refer to <https://unlicense.org/>
-- SPDX-License-Identifier: Unlicense

module Language.Turmac.Simulator where

import Data.Maybe (isJust)

import Language.Turmac.Model

-- | Single step of TM execution
step :: [TMRule] -> Configuration -> Configuration 
step rules cfg@(Configuration tape pos state)
    | isHaltState state = cfg  -- Don't continue if halted
    | otherwise = case findRule rules state (readSymbol tape) of
        Just (_, _, newSym, newState, dir) -> 
            Configuration 
                (moveInDir dir (writeSymbol newSym tape))
                (pos + toInteger dir)
                (newState)
        Nothing -> error $ "No rules for state " ++ show state ++ 
                         " and symbol " ++ show (readSymbol tape)

-- | Find matching rule for current state and symbol
findRule :: [TMRule] -> StateId -> Symbol -> Maybe TMRule
findRule rules state sym = 
    case [r | r@(s, sym', _, _, _) <- rules, s == state, sym' == sym] of
        [] -> Nothing
        (r:_) -> Just r

-- | Move tape in given direction
moveInDir :: Direction -> Tape -> Tape
moveInDir (-1) = moveLeft
moveInDir 1 = moveRight
moveInDir d = error $ "Invalid direction: " ++ show d

-- | Run TM until it halts, return history of configurations and final state
simulate :: [TMRule] -> Configuration -> ([Configuration], Configuration)
simulate rules config = go [] config
  where
    go history cfg@(Configuration _ _ _) | isHalted cfg =
        (reverse (cfg:history), cfg)
    go history cfg =
        go (cfg:history) (step rules cfg)

-- | Run TM until it halts, return only final configuration  
execute :: [TMRule] -> Configuration -> Configuration
execute rules config = snd $ simulate rules config