-- SPDX-FileCopyrightText: Chris Pressey, the creator of this work, has dedicated it to the public domain. -- For more information, please refer to -- 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