packages feed

g2-0.2.0.0: src/G2/Equiv/Types.hs

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveDataTypeable #-}

module G2.Equiv.Types ( module G2.Equiv.Config
                      , module G2.Equiv.Types
                      , module G2.Equiv.G2Calls) where

import G2.Equiv.Config
import G2.Equiv.G2Calls
import G2.Language

import GHC.Generics (Generic)
import Data.Data (Typeable)
import qualified Data.HashMap.Lazy as HM
import qualified Data.HashSet as HS
import qualified Data.Sequence as DS


-- States

data StateH = StateH {
      latest :: StateET
    , history :: [StateET]
    , discharge :: Maybe StateET
  }
  deriving (Eq, Generic)

instance Named StateH where
  names (StateH s h d) =
    names s DS.>< names h DS.>< names d
  rename old new (StateH s h d) =
    StateH (rename old new s) (rename old new h) (rename old new d)

newStateH :: StateET -> StateH
newStateH s = StateH {
    latest = s
  , history = []
  , discharge = Nothing
  }

-- The container field is only relevant for induction.  When the expression for
-- one past state is actually an inner scrutinee of an expression that really
-- was encountered in the past, the container holds the full expression.
data PrevMatch t = PrevMatch {
    present :: (State t, State t)
  , past :: (State t, State t)
  , conditions :: (HM.HashMap Id Expr, HS.HashSet (Expr, Expr))
  , container :: State t
}

data ActMarker = Coinduction CoMarker
               | Equality EqualMarker
               | NoObligations (StateET, StateET)
               | NotEquivalent (StateET, StateET)
               | SolverFail (StateET, StateET)
               | CycleFound CycleMarker
               | Unresolved (StateET, StateET)

instance Named ActMarker where
  names (Coinduction cm) = names cm
  names (Equality em) = names em
  names (NoObligations s_pair) = names s_pair
  names (NotEquivalent s_pair) = names s_pair
  names (SolverFail s_pair) = names s_pair
  names (CycleFound cm) = names cm
  names (Unresolved s_pair) = names s_pair
  rename old new m = case m of
    Coinduction cm -> Coinduction $ rename old new cm
    Equality em -> Equality $ rename old new em
    NoObligations s_pair -> NoObligations $ rename old new s_pair
    NotEquivalent s_pair -> NotEquivalent $ rename old new s_pair
    SolverFail s_pair -> SolverFail $ rename old new s_pair
    CycleFound cm -> CycleFound $ rename old new cm
    Unresolved s_pair -> Unresolved $ rename old new s_pair

data LemmaMarker = LemmaProposed Lemma
                 | LemmaProven Lemma
                 | LemmaRejected Lemma
                 | LemmaProvenEarly (Lemma, Lemma)
                 | LemmaRejectedEarly (Lemma, Lemma)
                 | LemmaUnresolved Lemma

instance Named LemmaMarker where
  names (LemmaProposed l) = names l
  names (LemmaProven l) = names l
  names (LemmaRejected l) = names l
  names (LemmaProvenEarly l_pair) = names l_pair
  names (LemmaRejectedEarly l_pair) = names l_pair
  names (LemmaUnresolved l) = names l
  rename old new lm = case lm of
    LemmaProposed l -> LemmaProposed $ rename old new l
    LemmaProven l -> LemmaProven $ rename old new l
    LemmaRejected l -> LemmaRejected $ rename old new l
    LemmaProvenEarly lp -> LemmaProvenEarly $ rename old new lp
    LemmaRejectedEarly lp -> LemmaRejectedEarly $ rename old new lp
    LemmaUnresolved l -> LemmaUnresolved $ rename old new l

data Marker = Marker (StateH, StateH) ActMarker
            | LMarker LemmaMarker

instance Named Marker where
  names (Marker (sh1, sh2) m) =
    names sh1 DS.>< names sh2 DS.>< names m
  names (LMarker lm) = names lm
  rename old new (Marker (sh1, sh2) m) =
    Marker (rename old new sh1, rename old new sh2) $ rename old new m
  rename old new (LMarker lm) =
    LMarker $ rename old new lm

data Side = ILeft | IRight deriving (Eq, Show, Typeable, Generic)

data IndMarker = IndMarker {
      ind_real_present :: (StateET, StateET)
    , ind_used_present :: (StateET, StateET)
    , ind_past :: (StateET, StateET)
    , ind_result :: (StateET, StateET)
    , ind_present_scrutinees :: (Expr, Expr)
    , ind_past_scrutinees :: (StateET, StateET)
    , ind_side :: Side
    , ind_fresh_name :: Name
  }
  deriving (Eq, Generic)

-- states paired with lemmas show what the state was before lemma usage
data CoMarker = CoMarker {
    co_real_present :: (StateET, StateET)
  , co_used_present :: (StateET, StateET)
  , co_past :: (StateET, StateET)
  , lemma_used_left :: [(StateET, Lemma)]
  , lemma_used_right :: [(StateET, Lemma)]
}

instance Named CoMarker where
  names (CoMarker (s1, s2) (q1, q2) (p1, p2) lemma_l lemma_r) =
    (DS.><) (names [s1, s2, q1, q2, p1, p2]) ((names lemma_l) DS.>< (names lemma_r))
  rename old new (CoMarker (s1, s2) (q1, q2) (p1, p2) lemma_l lemma_r) =
    let r = rename old new
        s1' = r s1
        s2' = r s2
        q1' = r q1
        q2' = r q2
        p1' = r p1
        p2' = r p2
        lemma_l' = rename old new lemma_l
        lemma_r' = rename old new lemma_r
    in CoMarker (s1', s2') (q1', q2') (p1', p2') lemma_l' lemma_r'

reverseCoMarker :: CoMarker -> CoMarker
reverseCoMarker (CoMarker (s1, s2) (q1, q2) (p1, p2) lemma_l lemma_r) =
  CoMarker (s2, s1) (q2, q1) (p2, p1) lemma_r lemma_l

data EqualMarker = EqualMarker {
    eq_real_present :: (StateET, StateET)
  , eq_used_present :: (StateET, StateET)
}

instance Named EqualMarker where
  names (EqualMarker (s1, s2) (q1, q2)) =
    foldr (DS.><) DS.empty $ map names [s1, s2, q1, q2]
  rename old new (EqualMarker (s1, s2) (q1, q2)) =
    let r = rename old new
        s1' = r s1
        s2' = r s2
        q1' = r q1
        q2' = r q2
    in EqualMarker (s1', s2') (q1', q2')

-- the indicated side is the one with the cycle
-- cycle_past is the past state that matches the present
data CycleMarker = CycleMarker {
    cycle_real_present :: (StateET, StateET)
  , cycle_past :: StateET
  , cycle_mapping :: HM.HashMap Id Expr
  , cycle_side :: Side
}

instance Named CycleMarker where
  names (CycleMarker (s1, s2) p _ _) =
    names s1 DS.>< names s2 DS.>< names p
  rename old new (CycleMarker (s1, s2) p hm sd) =
    let r = rename old new
        s1' = r s1
        s2' = r s2
        p' = r p
    in CycleMarker (s1', s2') p' hm sd

data Lemma = Lemma { lemma_name :: String
                   , lemma_lhs :: StateET
                   , lemma_rhs :: StateET
                   , lemma_lhs_origin :: String
                   , lemma_rhs_origin :: String
                   , lemma_to_be_proven :: [(StateH, StateH)] }
                   deriving (Eq, Generic)

instance Named Lemma where
  names (Lemma _ s1 s2 _ _ sh) = names s1 DS.>< names s2 DS.>< names sh
  rename old new (Lemma lnm s1 s2 f1 f2 sh) =
    Lemma lnm (rename old new s1) (rename old new s2) f1 f2 (rename old new sh)

type ProposedLemma = Lemma
type ProvenLemma = Lemma
type DisprovenLemma = Lemma