Library Io.Evaluate

Require Import FunctionNinjas.All.
Require Import Io.All.

Import C.Notations.

Evaluate the commands of a computation.
Fixpoint command {E1 E2 : Effect.t} {A : Type}
  (run : (c : Effect.command E1), C.t E2 (Effect.answer E1 c))
  (x : C.t E1 A) : C.t E2 A :=
  match x with
  | C.Ret _ xC.Ret _ x
  | C.Call crun c
  | C.Let _ _ x fC.Let _ _ (command run x) (fun xcommand run (f x))
  | C.Join _ _ x yC.Join _ _ (command run x) (command run y)
  | C.Choose _ x yC.Choose _ (command run x) (command run y)
  end.

Fixpoint exception {E1 E2 : Effect.t} {Exc A : Type}
  (run : (c : Effect.command E1), C.t E2 (Effect.answer E1 c + Exc))
  (run_join : ExcExcExc) (x : C.t E1 A) : C.t E2 (A + Exc) :=
  match x with
  | C.Ret _ xret @@ inl x
  | C.Call crun c
  | C.Let _ _ x f
    let! x := exception run run_join x in
    match x with
    | inl xexception run run_join (f x)
    | inr excret @@ inr exc
    end
  | C.Join _ _ x y
    let! xy := join (exception run run_join x) (exception run run_join y) in
    match xy with
    | (inl x, inl y)ret @@ inl (x, y)
    | (inr exc, inl _) | (inl _, inr exc)ret @@ inr exc
    | (inr exc_x, inr exc_y)ret @@ inr (run_join exc_x exc_y)
    end
  | C.Choose _ x y
    choose (exception run run_join x) (exception run run_join y)
  end.