{- | Internal monad for the resolution algorithm - we keep some state for the list of created values - we collect the applied functions as "Operations" - we might exit with a Left value if we can't build a value -} module Data.Registry.Internal.Stack where import Data.Registry.Internal.Operations import Data.Registry.Internal.Types import Protolude -- | Monadic stack for the resolution algorithm type Stack a = StateT (Values, Operations) (Either Text) a -- | Return a value from the Stack if possible runStack :: Stack a -> Values -> Either Text a runStack sa vs = evalStateT sa (vs, []) -- | Return the state of the stack after executing the action -- This returns the list of built values execStack :: Stack a -> Values -> Either Text Values execStack sa vs = fst <$> execStateT sa (vs, []) -- | Return the list of applied functions after resolution evalStack :: Stack a -> Values -> Either Text Operations evalStack sa vs = snd <$> execStateT sa (vs, []) -- | Get the current list of values getValues :: Stack Values getValues = fst <$> get -- | Get the current list of operations getOperation :: Stack Operations getOperation = snd <$> get -- | Modify the current list of values modifyValues :: (Values -> Values) -> Stack () modifyValues f = modify (\(vs, ops) -> (f vs, ops)) -- | Get the current list of values modifyOperations :: (Operations -> Operations) -> Stack () modifyOperations f = modify (\(vs, ops) -> (vs, f ops)) -- | Store a function application in the list of operations functionApplied :: Value -> [Value] -> Stack () functionApplied output inputs = modifyOperations (AppliedFunction output inputs:)