------------------------------------------------------------------------
-- This approach appears to be both awkward to use and non-trivial to
-- understand
------------------------------------------------------------------------

module NonDeterministic.LongestPrefix where

open import Data.Nat
open import Data.List
open import Data.Colist hiding ([_]; _⊑_)
open import Coinduction
open import Data.Maybe
open import Data.Product
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality

open import NonDeterministic.Expr

------------------------------------------------------------------------
-- Partial lists

-- A partial list can end in ⊥.

infixr 5 _∷_

data PartialList (A : Set) : Set where
     : PartialList A
  []  : PartialList A
  _∷_ : (x : A) (xs : PartialList A)  PartialList A

-- xs ⊑ ys means that xs is an approximation of ys.

infix 4 _⊑_

data _⊑_ {A} : PartialList A  Colist A  Set where
     :  {ys}                                  ys
  []  :                                   []      []
  _∷_ :  x {xs ys} (xs⊑ys : xs   ys)  x  xs  x  ys

------------------------------------------------------------------------
-- Semantics

-- []⊑Trace[ e ] means that [] is an approximation of the trace of e.
--
-- The use of coinduction here is unsatisfactory to me. It would
-- perhaps be more natural to use ⊥ as the semantics/trace of a
-- non-terminating, non-productive computation (an infinite sequence
-- of nops which does not emit any messages). In that case I believe
-- that it would be correct to say that ms (a partial stream) is one
-- of the traces of e if
--   ⑴ all /finite/ approximations of ms are approximations of the
--     trace of e, and also
--   ⑵ ms is not an approximation of some other partial stream ms′
--     satisfying ⑴, ignoring streams ms′ that differ from ms just by
--     the addition of trailing external messages.
-- However, the second part of ⑵ (ignoring…) seems a bit ugly, so I
-- have not pursued this definition.

data []⊑Trace[_] : Expr  Set where
  nop :  {e} (x :  []⊑Trace[  e ])  []⊑Trace[ nop e ]

-- ms ⊑Trace[ e ] means that ms is an approximation of the trace of e.

infix 4 _⊑Trace[_]

data _⊑Trace[_] : PartialList Msg  Expr  Set where
      :  {e}                                         ⊑Trace[        e ]
  []   :  {e}      (x :  []⊑Trace[   e ])  []          ⊑Trace[        e ]
  nop  :  {e ms}   (x : ms ⊑Trace[  e ])  ms          ⊑Trace[ nop    e ]
  tick :  {e m ms} (x : ms ⊑Trace[  e ])  user m  ms ⊑Trace[ tick m e ]
  tock :  {e m ms} (x : ms ⊑Trace[   e ])  ext  m  ms ⊑Trace[        e ]

-- A colist of messages is a trace of e if all its approximations are
-- approximations of /some/ trace of e.

infix 4 _HasTrace_

_HasTrace_ : Semantics
e HasTrace ms =  {p}  p  ms  p ⊑Trace[ e ]

------------------------------------------------------------------------
-- Examples

[]⊑Trace[nops] : []⊑Trace[ nops ]
[]⊑Trace[nops] = nop ( []⊑Trace[nops])

possible : nops HasTrace []
possible   = 
possible [] = [] []⊑Trace[nops]

no-msgs :  {m p}  ¬ user m  p ⊑Trace[ nops ]
no-msgs (nop x) = no-msgs x

impossible :  {m ms}  ¬ nops HasTrace (user m  ms)
impossible {m} ht = no-msgs (ht (user m  ))

ok : ticks HasTrace scissors
ok                    = 
ok (.(user )  xs⊑ys) = tick (ok xs⊑ys)