-- 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.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)