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

Tree @master (Download .tar.gz)

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