{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE FlexibleInstances #-}

module Language.REST.Path where

import qualified Data.HashSet as S
import GHC.Generics (Generic)
import Data.Hashable

-- | @Step@ represents an intermediate step in a 'Path' explored by REST
data Step rule term a = Step {
    forall rule term a. Step rule term a -> PathTerm rule term
term     :: PathTerm rule term -- ^ The "from" term in this path
  , forall rule term a. Step rule term a -> rule
rule     :: rule               -- ^ The rule generating the next term
  , forall rule term a. Step rule term a -> a
ordering :: a                  -- ^ The generated constraints from applying the rule
  , forall rule term a. Step rule term a -> Bool
fromPLE  :: Bool               -- ^ Whether the term was derived from a provably terminating eval function
} deriving (Step rule term a -> Step rule term a -> Bool
(Step rule term a -> Step rule term a -> Bool)
-> (Step rule term a -> Step rule term a -> Bool)
-> Eq (Step rule term a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall rule term a.
(Eq term, Eq rule, Eq a) =>
Step rule term a -> Step rule term a -> Bool
$c== :: forall rule term a.
(Eq term, Eq rule, Eq a) =>
Step rule term a -> Step rule term a -> Bool
== :: Step rule term a -> Step rule term a -> Bool
$c/= :: forall rule term a.
(Eq term, Eq rule, Eq a) =>
Step rule term a -> Step rule term a -> Bool
/= :: Step rule term a -> Step rule term a -> Bool
Eq, Eq (Step rule term a)
Eq (Step rule term a) =>
(Step rule term a -> Step rule term a -> Ordering)
-> (Step rule term a -> Step rule term a -> Bool)
-> (Step rule term a -> Step rule term a -> Bool)
-> (Step rule term a -> Step rule term a -> Bool)
-> (Step rule term a -> Step rule term a -> Bool)
-> (Step rule term a -> Step rule term a -> Step rule term a)
-> (Step rule term a -> Step rule term a -> Step rule term a)
-> Ord (Step rule term a)
Step rule term a -> Step rule term a -> Bool
Step rule term a -> Step rule term a -> Ordering
Step rule term a -> Step rule term a -> Step rule term a
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall rule term a.
(Ord term, Ord rule, Ord a) =>
Eq (Step rule term a)
forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Ordering
forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Step rule term a
$ccompare :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Ordering
compare :: Step rule term a -> Step rule term a -> Ordering
$c< :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
< :: Step rule term a -> Step rule term a -> Bool
$c<= :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
<= :: Step rule term a -> Step rule term a -> Bool
$c> :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
> :: Step rule term a -> Step rule term a -> Bool
$c>= :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
>= :: Step rule term a -> Step rule term a -> Bool
$cmax :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Step rule term a
max :: Step rule term a -> Step rule term a -> Step rule term a
$cmin :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Step rule term a
min :: Step rule term a -> Step rule term a -> Step rule term a
Ord, (forall x. Step rule term a -> Rep (Step rule term a) x)
-> (forall x. Rep (Step rule term a) x -> Step rule term a)
-> Generic (Step rule term a)
forall x. Rep (Step rule term a) x -> Step rule term a
forall x. Step rule term a -> Rep (Step rule term a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall rule term a x. Rep (Step rule term a) x -> Step rule term a
forall rule term a x. Step rule term a -> Rep (Step rule term a) x
$cfrom :: forall rule term a x. Step rule term a -> Rep (Step rule term a) x
from :: forall x. Step rule term a -> Rep (Step rule term a) x
$cto :: forall rule term a x. Rep (Step rule term a) x -> Step rule term a
to :: forall x. Rep (Step rule term a) x -> Step rule term a
Generic, Eq (Step rule term a)
Eq (Step rule term a) =>
(Int -> Step rule term a -> Int)
-> (Step rule term a -> Int) -> Hashable (Step rule term a)
Int -> Step rule term a -> Int
Step rule term a -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Eq (Step rule term a)
forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Int -> Step rule term a -> Int
forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Step rule term a -> Int
$chashWithSalt :: forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Int -> Step rule term a -> Int
hashWithSalt :: Int -> Step rule term a -> Int
$chash :: forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Step rule term a -> Int
hash :: Step rule term a -> Int
Hashable)


-- | @PathTerm@ is the term explored at a path
data PathTerm rule term = PathTerm
    {  forall rule term. PathTerm rule term -> term
pathTerm :: term
    ,  forall rule term. PathTerm rule term -> HashSet (term, rule)
rejected :: S.HashSet (term, rule) -- ^ The orderings FROM pathTerm that were rejected.
                                          -- TODO: This should be removed, as it's really only used
                                          --       in the visualization

    } deriving (PathTerm rule term -> PathTerm rule term -> Bool
(PathTerm rule term -> PathTerm rule term -> Bool)
-> (PathTerm rule term -> PathTerm rule term -> Bool)
-> Eq (PathTerm rule term)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall rule term.
(Eq term, Eq rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
$c== :: forall rule term.
(Eq term, Eq rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
== :: PathTerm rule term -> PathTerm rule term -> Bool
$c/= :: forall rule term.
(Eq term, Eq rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
/= :: PathTerm rule term -> PathTerm rule term -> Bool
Eq, Eq (PathTerm rule term)
Eq (PathTerm rule term) =>
(PathTerm rule term -> PathTerm rule term -> Ordering)
-> (PathTerm rule term -> PathTerm rule term -> Bool)
-> (PathTerm rule term -> PathTerm rule term -> Bool)
-> (PathTerm rule term -> PathTerm rule term -> Bool)
-> (PathTerm rule term -> PathTerm rule term -> Bool)
-> (PathTerm rule term -> PathTerm rule term -> PathTerm rule term)
-> (PathTerm rule term -> PathTerm rule term -> PathTerm rule term)
-> Ord (PathTerm rule term)
PathTerm rule term -> PathTerm rule term -> Bool
PathTerm rule term -> PathTerm rule term -> Ordering
PathTerm rule term -> PathTerm rule term -> PathTerm rule term
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall rule term. (Ord term, Ord rule) => Eq (PathTerm rule term)
forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Ordering
forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> PathTerm rule term
$ccompare :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Ordering
compare :: PathTerm rule term -> PathTerm rule term -> Ordering
$c< :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
< :: PathTerm rule term -> PathTerm rule term -> Bool
$c<= :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
<= :: PathTerm rule term -> PathTerm rule term -> Bool
$c> :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
> :: PathTerm rule term -> PathTerm rule term -> Bool
$c>= :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
>= :: PathTerm rule term -> PathTerm rule term -> Bool
$cmax :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> PathTerm rule term
max :: PathTerm rule term -> PathTerm rule term -> PathTerm rule term
$cmin :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> PathTerm rule term
min :: PathTerm rule term -> PathTerm rule term -> PathTerm rule term
Ord, (forall x. PathTerm rule term -> Rep (PathTerm rule term) x)
-> (forall x. Rep (PathTerm rule term) x -> PathTerm rule term)
-> Generic (PathTerm rule term)
forall x. Rep (PathTerm rule term) x -> PathTerm rule term
forall x. PathTerm rule term -> Rep (PathTerm rule term) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall rule term x.
Rep (PathTerm rule term) x -> PathTerm rule term
forall rule term x.
PathTerm rule term -> Rep (PathTerm rule term) x
$cfrom :: forall rule term x.
PathTerm rule term -> Rep (PathTerm rule term) x
from :: forall x. PathTerm rule term -> Rep (PathTerm rule term) x
$cto :: forall rule term x.
Rep (PathTerm rule term) x -> PathTerm rule term
to :: forall x. Rep (PathTerm rule term) x -> PathTerm rule term
Generic, Eq (PathTerm rule term)
Eq (PathTerm rule term) =>
(Int -> PathTerm rule term -> Int)
-> (PathTerm rule term -> Int) -> Hashable (PathTerm rule term)
Int -> PathTerm rule term -> Int
PathTerm rule term -> Int
forall a. Eq a => (Int -> a -> Int) -> (a -> Int) -> Hashable a
forall rule term.
(Hashable term, Hashable rule) =>
Eq (PathTerm rule term)
forall rule term.
(Hashable term, Hashable rule) =>
Int -> PathTerm rule term -> Int
forall rule term.
(Hashable term, Hashable rule) =>
PathTerm rule term -> Int
$chashWithSalt :: forall rule term.
(Hashable term, Hashable rule) =>
Int -> PathTerm rule term -> Int
hashWithSalt :: Int -> PathTerm rule term -> Int
$chash :: forall rule term.
(Hashable term, Hashable rule) =>
PathTerm rule term -> Int
hash :: PathTerm rule term -> Int
Hashable)

-- | A path explored by REST.
-- The head of the 1st part of the tuple is the initial term.
-- The 2nd part of the tuple is the last term.
type Path rule term a = ([Step rule term a], PathTerm rule term)

-- | Extracts the list of terms from the path
pathTerms :: Path rule term a -> [term]
pathTerms :: forall rule term a. Path rule term a -> [term]
pathTerms ([Step rule term a]
xs, PathTerm rule term
x) = (PathTerm rule term -> term) -> [PathTerm rule term] -> [term]
forall a b. (a -> b) -> [a] -> [b]
map PathTerm rule term -> term
forall rule term. PathTerm rule term -> term
pathTerm ([PathTerm rule term] -> [term]) -> [PathTerm rule term] -> [term]
forall a b. (a -> b) -> a -> b
$ (Step rule term a -> PathTerm rule term)
-> [Step rule term a] -> [PathTerm rule term]
forall a b. (a -> b) -> [a] -> [b]
map Step rule term a -> PathTerm rule term
forall rule term a. Step rule term a -> PathTerm rule term
term [Step rule term a]
xs [PathTerm rule term]
-> [PathTerm rule term] -> [PathTerm rule term]
forall a. [a] -> [a] -> [a]
++ [PathTerm rule term
x]

-- | Extracts the last (most recently generated) term
runtimeTerm :: Path rule term a -> term
runtimeTerm :: forall rule term a. Path rule term a -> term
runtimeTerm ([Step rule term a]
_, PathTerm rule term
pt) = PathTerm rule term -> term
forall rule term. PathTerm rule term -> term
pathTerm PathTerm rule term
pt