{-# LANGUAGE ConstraintKinds #-}

module Language.Explorer.Pure
    ( Explorer
    , mkExplorer
    , mkExplorerNoSharing
    , execute
    , executeAll
    , revert
    , ExplorerM.toTree
    , incomingEdges
    , config
    , currRef
    , Ref
    , deref
    , leaves
    , getTrace
    , getTraces
    , getPathsFromTo
    , getPathFromTo
    , executionGraph
    , fromExport
    , toExport
    ) where

import qualified Language.Explorer.Monadic as ExplorerM
import Control.Monad.Identity

import qualified Data.IntMap as IntMap
import Data.List
import Data.Foldable

-- We shadow instead of exporting directly to make the user interaction
-- the same.
type Ref = ExplorerM.Ref
type Explorer a b o = ExplorerM.Explorer a Identity b o
type PureLanguage p c o = (Eq p, Eq o, Monoid o)

mkExplorer :: PureLanguage p c o => Bool -> (c -> c -> Bool) -> (p -> c -> (Maybe c, o)) -> c -> Explorer p c o
mkExplorer :: Bool
-> (c -> c -> Bool)
-> (p -> c -> (Maybe c, o))
-> c
-> Explorer p c o
mkExplorer Bool
shadowing c -> c -> Bool
eqfunc p -> c -> (Maybe c, o)
definterp c
initialConf = Bool
-> (c -> c -> Bool)
-> (p -> c -> Identity (Maybe c, o))
-> c
-> Explorer p c o
forall p (m :: * -> *) c o.
Language p m c o =>
Bool
-> (c -> c -> Bool)
-> (p -> c -> m (Maybe c, o))
-> c
-> Explorer p m c o
ExplorerM.mkExplorer Bool
shadowing c -> c -> Bool
eqfunc ((p -> c -> (Maybe c, o)) -> p -> c -> Identity (Maybe c, o)
forall (m :: * -> *) o a b.
(Monad m, Monoid o) =>
(a -> b -> (Maybe b, o)) -> a -> b -> m (Maybe b, o)
wrap p -> c -> (Maybe c, o)
definterp) c
initialConf

mkExplorerNoSharing :: PureLanguage p c o => (p -> c -> (Maybe c, o)) -> c -> Explorer p c o
mkExplorerNoSharing :: (p -> c -> (Maybe c, o)) -> c -> Explorer p c o
mkExplorerNoSharing = Bool
-> (c -> c -> Bool)
-> (p -> c -> (Maybe c, o))
-> c
-> Explorer p c o
forall p c o.
PureLanguage p c o =>
Bool
-> (c -> c -> Bool)
-> (p -> c -> (Maybe c, o))
-> c
-> Explorer p c o
mkExplorer Bool
False ((c -> Bool) -> c -> c -> Bool
forall a b. a -> b -> a
const ((c -> Bool) -> c -> c -> Bool)
-> (Bool -> c -> Bool) -> Bool -> c -> c -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> c -> Bool
forall a b. a -> b -> a
const (Bool -> c -> c -> Bool) -> Bool -> c -> c -> Bool
forall a b. (a -> b) -> a -> b
$ Bool
False)

currRef :: Explorer a b o -> Ref
currRef :: Explorer a b o -> Ref
currRef = Explorer a b o -> Ref
forall programs (m :: * -> *) configs output.
Explorer programs m configs output -> Ref
ExplorerM.currRef

config :: Explorer a b o -> b
config :: Explorer a b o -> b
config = Explorer a b o -> b
forall programs (m :: * -> *) configs output.
Explorer programs m configs output -> configs
ExplorerM.config

deref :: Explorer p c o -> Ref -> Maybe c
deref :: Explorer p c o -> Ref -> Maybe c
deref = Explorer p c o -> Ref -> Maybe c
forall p (m :: * -> *) c o. Explorer p m c o -> Ref -> Maybe c
ExplorerM.deref

wrap :: (Monad m, Monoid o) => (a -> b -> (Maybe b, o)) -> a -> b -> m (Maybe b, o)
wrap :: (a -> b -> (Maybe b, o)) -> a -> b -> m (Maybe b, o)
wrap a -> b -> (Maybe b, o)
def a
p b
e = (Maybe b, o) -> m (Maybe b, o)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Maybe b, o) -> m (Maybe b, o)) -> (Maybe b, o) -> m (Maybe b, o)
forall a b. (a -> b) -> a -> b
$ a -> b -> (Maybe b, o)
def a
p b
e

execute :: PureLanguage p c o =>  p -> Explorer p c o -> (Explorer p c o, o)
execute :: p -> Explorer p c o -> (Explorer p c o, o)
execute p
p Explorer p c o
e = Identity (Explorer p c o, o) -> (Explorer p c o, o)
forall a. Identity a -> a
runIdentity (Identity (Explorer p c o, o) -> (Explorer p c o, o))
-> Identity (Explorer p c o, o) -> (Explorer p c o, o)
forall a b. (a -> b) -> a -> b
$ p -> Explorer p c o -> Identity (Explorer p c o, o)
forall p (m :: * -> *) c o.
Language p m c o =>
p -> Explorer p m c o -> m (Explorer p m c o, o)
ExplorerM.execute p
p Explorer p c o
e

executeAll :: PureLanguage p c o => [p] -> Explorer p c o -> (Explorer p c o, o)
executeAll :: [p] -> Explorer p c o -> (Explorer p c o, o)
executeAll [p]
p Explorer p c o
e = Identity (Explorer p c o, o) -> (Explorer p c o, o)
forall a. Identity a -> a
runIdentity (Identity (Explorer p c o, o) -> (Explorer p c o, o))
-> Identity (Explorer p c o, o) -> (Explorer p c o, o)
forall a b. (a -> b) -> a -> b
$ [p] -> Explorer p c o -> Identity (Explorer p c o, o)
forall p (m :: * -> *) c o.
Language p m c o =>
[p] -> Explorer p m c o -> m (Explorer p m c o, o)
ExplorerM.executeAll [p]
p Explorer p c o
e

revert :: ExplorerM.Ref -> Explorer p c o -> Maybe (Explorer p c o)
revert :: Ref -> Explorer p c o -> Maybe (Explorer p c o)
revert = Ref -> Explorer p c o -> Maybe (Explorer p c o)
forall p (m :: * -> *) c o.
Ref -> Explorer p m c o -> Maybe (Explorer p m c o)
ExplorerM.revert

incomingEdges :: Ref -> Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
incomingEdges :: Ref -> Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
incomingEdges = Ref -> Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
forall p (m :: * -> *) c o.
Ref -> Explorer p m c o -> [((Ref, c), (p, o), (Ref, c))]
ExplorerM.incomingEdges

getTrace :: Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
getTrace :: Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
getTrace = Explorer p c o -> [((Ref, c), (p, o), (Ref, c))]
forall p (m :: * -> *) c o.
Explorer p m c o -> [((Ref, c), (p, o), (Ref, c))]
ExplorerM.getTrace

getTraces :: Explorer p c o -> [[((Ref, c), (p, o), (Ref, c))]]
getTraces :: Explorer p c o -> [[((Ref, c), (p, o), (Ref, c))]]
getTraces = Explorer p c o -> [[((Ref, c), (p, o), (Ref, c))]]
forall p (m :: * -> *) c o.
Explorer p m c o -> [[((Ref, c), (p, o), (Ref, c))]]
ExplorerM.getTraces

getPathsFromTo :: Explorer p c o -> Ref -> Ref -> [[((Ref, c), (p, o), (Ref, c))]]
getPathsFromTo :: Explorer p c o -> Ref -> Ref -> [[((Ref, c), (p, o), (Ref, c))]]
getPathsFromTo = Explorer p c o -> Ref -> Ref -> [[((Ref, c), (p, o), (Ref, c))]]
forall p (m :: * -> *) c o.
Explorer p m c o -> Ref -> Ref -> [[((Ref, c), (p, o), (Ref, c))]]
ExplorerM.getPathsFromTo

getPathFromTo :: Explorer p c o -> Ref -> Ref -> [((Ref, c), (p, o), (Ref, c))]
getPathFromTo :: Explorer p c o -> Ref -> Ref -> [((Ref, c), (p, o), (Ref, c))]
getPathFromTo = Explorer p c o -> Ref -> Ref -> [((Ref, c), (p, o), (Ref, c))]
forall p (m :: * -> *) c o.
Explorer p m c o -> Ref -> Ref -> [((Ref, c), (p, o), (Ref, c))]
ExplorerM.getPathFromTo

executionGraph :: Explorer p c o -> ((Ref, c), [(Ref, c)], [((Ref, c), (p, o), (Ref, c))])
executionGraph :: Explorer p c o
-> ((Ref, c), [(Ref, c)], [((Ref, c), (p, o), (Ref, c))])
executionGraph = Explorer p c o
-> ((Ref, c), [(Ref, c)], [((Ref, c), (p, o), (Ref, c))])
forall p (m :: * -> *) c o.
Explorer p m c o
-> ((Ref, c), [(Ref, c)], [((Ref, c), (p, o), (Ref, c))])
ExplorerM.executionGraph

leaves :: Explorer p c o -> [(Ref, c)]
leaves :: Explorer p c o -> [(Ref, c)]
leaves = Explorer p c o -> [(Ref, c)]
forall p (m :: * -> *) c o. Explorer p m c o -> [(Ref, c)]
ExplorerM.leaves

toExport :: Explorer p c o -> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))])
toExport :: Explorer p c o -> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))])
toExport = Explorer p c o -> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))])
forall p (m :: * -> *) c o.
Explorer p m c o -> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))])
ExplorerM.toExport

fromExport :: Explorer p c o -> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))]) -> Explorer p c o
fromExport :: Explorer p c o
-> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))]) -> Explorer p c o
fromExport = Explorer p c o
-> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))]) -> Explorer p c o
forall p (m :: * -> *) c o.
Explorer p m c o
-> (Ref, [(Ref, c)], [(Ref, Ref, (p, o))]) -> Explorer p m c o
ExplorerM.fromExport