-- 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.Analyzer ( checkComplete, checkDeterministic ) where import Data.List (nub) import Language.Turmac.Model (TMRule, isHaltState) -- -- Static Analysis -- data RuleCondition = MissingRule String String | SuperpositiousRule String String Int stateAlphabet :: [TMRule] -> [String] stateAlphabet rules = let currentStates = [s | (s, _, _, _, _) <- rules] nextStates = [s | (_, _, _, s, _) <- rules, not $ isHaltState s] in nub $ currentStates ++ nextStates symbolAlphabet :: [TMRule] -> [String] symbolAlphabet rules = let readSymbols = [sym | (_, sym, _, _, _) <- rules] writeSymbols = [sym | (_, _, sym, _, _) <- rules] in nub $ readSymbols ++ writeSymbols ++ ["_"] matchingRules :: [TMRule] -> String -> String -> [TMRule] matchingRules rules state symbol = [r | r@(s, sym, _, _, _) <- rules, s == state, sym == symbol] surveyRules :: [TMRule] -> [RuleCondition] surveyRules rules = [ issue | state <- stateAlphabet rules , symbol <- symbolAlphabet rules , let n = length (matchingRules rules state symbol) , issue <- case n of 0 -> [MissingRule state symbol] 1 -> [] _ -> [SuperpositiousRule state symbol n] ] checkComplete :: [TMRule] -> Either [RuleCondition] [TMRule] checkComplete rules = let conditions = [c | c@(MissingRule _ _) <- surveyRules rules] in if length conditions == 0 then (Right rules) else (Left conditions) checkDeterministic :: [TMRule] -> Either [RuleCondition] [TMRule] checkDeterministic rules = let conditions = [c | c@(SuperpositiousRule _ _ _) <- surveyRules rules] in if length conditions == 0 then (Right rules) else (Left conditions)