{-# 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
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
/= :: 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
Eq, Step rule term a -> Step rule term a -> Bool
Step rule term a -> Step rule term a -> Ordering
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
min :: 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
max :: Step rule term a -> Step rule term a -> Step rule term a
$cmax :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Step rule term a
>= :: 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
$c< :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Bool
compare :: Step rule term a -> Step rule term a -> Ordering
$ccompare :: forall rule term a.
(Ord term, Ord rule, Ord a) =>
Step rule term a -> Step rule term a -> Ordering
Ord, 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
$cto :: forall rule term a x. Rep (Step rule term a) x -> Step rule term a
$cfrom :: forall rule term a x. Step rule term a -> Rep (Step rule term a) x
Generic, 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
hash :: Step rule term a -> Int
$chash :: forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Step rule term a -> Int
hashWithSalt :: Int -> Step rule term a -> Int
$chashWithSalt :: forall rule term a.
(Hashable term, Hashable rule, Hashable a) =>
Int -> 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
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
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
$c== :: forall rule term.
(Eq term, Eq rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
Eq, PathTerm rule term -> PathTerm rule term -> Bool
PathTerm rule term -> PathTerm rule term -> Ordering
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
min :: 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
max :: PathTerm rule term -> PathTerm rule term -> PathTerm rule term
$cmax :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> PathTerm rule term
>= :: 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
$c< :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Bool
compare :: PathTerm rule term -> PathTerm rule term -> Ordering
$ccompare :: forall rule term.
(Ord term, Ord rule) =>
PathTerm rule term -> PathTerm rule term -> Ordering
Ord, 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
$cto :: forall rule term x.
Rep (PathTerm rule term) x -> PathTerm rule term
$cfrom :: forall rule term x.
PathTerm rule term -> Rep (PathTerm rule term) x
Generic, 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
hash :: PathTerm rule term -> Int
$chash :: forall rule term.
(Hashable term, Hashable rule) =>
PathTerm rule term -> Int
hashWithSalt :: Int -> PathTerm rule term -> Int
$chashWithSalt :: forall rule term.
(Hashable term, Hashable rule) =>
Int -> 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) = forall a b. (a -> b) -> [a] -> [b]
map forall rule term. PathTerm rule term -> term
pathTerm forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map forall rule term a. Step rule term a -> PathTerm rule term
term [Step rule term a]
xs 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) = forall rule term. PathTerm rule term -> term
pathTerm PathTerm rule term
pt