module Nominal.Variable (
Identifier,
Variable,
constantVar,
variable,
variableName,
iterationVariable,
iterationVariablesList,
isConstant,
constantValue,
setIdentifier,
hasIdentifierEquals,
hasIdentifierNotEquals,
clearIdentifier,
getIterationLevel,
changeIterationLevel,
toParts,
fromParts) where
import Control.DeepSeq (NFData)
import GHC.Generics (Generic)
import Data.Map (Map, findWithDefault)
import Data.Word (Word)
import Numeric (showIntAtBase)
import qualified Nominal.Text.Symbols as Symbols
type Identifier = Word
data Variable = Var String | IterationVariable Int Int (Maybe Identifier) | ConstantVar String deriving (Eq, Ord, Generic, NFData)
isConstant :: Variable -> Bool
isConstant (ConstantVar _) = True
isConstant _ = False
constantValue :: Variable -> String
constantValue (ConstantVar value) = value
constantValue _ = error "function constantValue can be applied only for constants"
variableNameBeforeIndex :: Int -> String
variableNameBeforeIndex level = showIntAtBase 25 (toEnum . (+97)) level ""
variableName :: Variable -> String
variableName (Var name) = name
variableName (IterationVariable level index _) = variableNameBeforeIndex level ++ Symbols.subscriptIndex index
instance Show Variable where
show v = if isConstant v then constantValue v else variableName v
toParts :: Variable -> Either String (Int, Int, Maybe Identifier)
toParts (Var name) = Left name
toParts (IterationVariable level index id) = Right (level, index, id)
fromParts :: Either String (Int, Int, Maybe Identifier) -> Variable
fromParts (Left name) = Var name
fromParts (Right (level, index, id)) = IterationVariable level index id
constantVar :: String -> Variable
constantVar = ConstantVar
variable :: String -> Variable
variable = Var
iterationVariable :: Int -> Int -> Variable
iterationVariable level index = IterationVariable level index Nothing
iterationVariablesList :: Int -> Int -> [Variable]
iterationVariablesList level size = fmap (iterationVariable level) [1..size]
onlyForIteration :: a -> (Int -> Int -> Maybe Identifier -> a) -> Variable -> a
onlyForIteration result _ (ConstantVar _) = result
onlyForIteration result _ (Var _) = result
onlyForIteration _ f (IterationVariable level index id) = f level index id
setIdentifier :: Identifier -> Variable -> Variable
setIdentifier id v = onlyForIteration v (\l i _ -> IterationVariable l i (Just id)) v
hasIdentifierEquals :: Identifier -> Variable -> Bool
hasIdentifierEquals t = onlyForIteration False (\_ _ id -> maybe False (== t) id)
hasIdentifierNotEquals :: Identifier -> Variable -> Bool
hasIdentifierNotEquals t = onlyForIteration False (\_ _ id -> maybe True (/= t) id)
clearIdentifier :: Variable -> Variable
clearIdentifier v = onlyForIteration v (\l i _ -> iterationVariable l i) v
getIterationLevel :: Variable -> Maybe Int
getIterationLevel = onlyForIteration Nothing (\l _ _ -> Just l)
changeIterationLevel :: Map Int Int -> Variable -> Variable
changeIterationLevel m v = onlyForIteration v (\l i id -> IterationVariable (findWithDefault l l m) i id) v