Local Open Scope kripke_model.
Class Action: Type := {
action: Type;
trace := list action;
traces := trace -> Prop
}.
Definition singleton_trace {Ac: Action} (a: action): trace := cons a nil.
Definition singleton_traces {Ac: Action} (tr: trace): traces := eq tr.
Definition trace_app {Ac: Action}: trace -> trace -> trace := @app _.
Inductive traces_app {Ac: Action}: traces -> traces -> traces :=
traces_app_intro: forall tr1 tr2 (Tr1 Tr2: traces), Tr1 tr1 -> Tr2 tr2 -> traces_app Tr1 Tr2 (trace_app tr1 tr2).
Class Command2Traces (P: ProgrammingLanguage) (Ac: Action): Type := {
cmd_denote: cmd -> traces
}.
Class ActionInterpret (state: Type) (Ac: Action): Type := {
state_enable: action -> state -> MetaState state -> Prop (*;
state_enable_pf: forall a s ms1 ms2, state_enable a s ms1 -> state_enable a s ms2 -> ms1 = ms2*)
}.
Class TraceSemantics (P: ProgrammingLanguage) (state: Type) (Ac: Action): Type := {
c2t :> Command2Traces P Ac;
ac_sem :> ActionInterpret state Ac
}.
Class Action_resource (Ac: Action) (Res: Resource) : Type := {
Aacquire_res: resource -> action;
Arelease_res: resource -> action;
}.
Class NormalAction_resource (Ac: Action) (Res: Resource) {Acr: Action_resource Ac Res}: Type := {
Aacquire_res_inv: forall r1 r2, Aacquire_res r1 = Aacquire_res r2 -> r1 = r2;
Arelease_res_inv: forall r1 r2, Arelease_res r1 = Arelease_res r2 -> r1 = r2;
Aacquire_Arelease_res: forall r1 r2, Aacquire_res r1 <> Arelease_res r2;
}.
Definition is_resource_action {Ac: Action} {Res: Resource} {Acr: Action_resource Ac Res} (r: resource) (a: action) := Aacquire_res r = a \/ Arelease_res r = a.
Definition is_resources_action {Ac: Action} {Res: Resource} {Acr: Action_resource Ac Res} (a: action) := exists r, is_resource_action r a.
Ltac solve_resource_action :=
repeat
match goal with
| H: Aacquire_res ?r1 = Aacquire_res ?r2 |- _ => apply Aacquire_res_inv in H; subst
| H: Arelease_res ?r1 = Arelease_res ?r2 |- _ => apply Arelease_res_inv in H; subst
| H: Aacquire_res ?r1 = Arelease_res ?r2 |- _ => exfalso; apply Aacquire_Arelease_res in H; apply H
| H: Arelease_res ?r1 = Aacquire_res ?r2 |- _ => exfalso; symmetry in H; apply Aacquire_Arelease_res in H; apply H
| H: ~ is_resource_action ?r (Aacquire_res ?r) |- _ => exfalso; apply H; left; auto
| H: ~ is_resource_action ?r (Arelease_res ?r) |- _ => exfalso; apply H; right; auto
| H: ~ is_resources_action (Aacquire_res ?r) |- _ => exfalso; apply H; exists r; left; auto
| H: ~ is_resources_action (Arelease_res ?r) |- _ => exfalso; apply H; exists r; right; auto
end;
repeat
let HH := fresh "H" in
match goal with
| H: ~ is_resource_action ?r1 (Aacquire_res ?r2) |- _ =>
specialize (fun (HH: r2 = r1) => H (or_introl (f_equal Aacquire_res (eq_sym HH))))
| H: ~ is_resource_action ?r1 (Arelease_res ?r2) |- _ =>
specialize (fun (HH: r2 = r1) => H (or_intror (f_equal Arelease_res (eq_sym HH))))
end.
Instance Res_Join (Res: Resource): Join resources := Pred_Join resource.
Instance Res_SA (Res: Resource): SeparationAlgebra resources := Pred_SA resource.
(* res_enable A1 A1' A2 := A1 ==> A1' while A2 is the environ *)
Inductive res_enable {Ac: Action} {Res: Resource} {Acr: Action_resource Ac Res}: action -> resources -> resources -> resources -> Prop :=
| res_enable_acq: forall r A1 A1' A2, join A1 (eq r) A1' -> ~ A2 r -> res_enable (Aacquire_res r) A1 A1' A2
| res_enable_rel: forall r A1 A1' A2, join A1' (eq r) A1 -> res_enable (Arelease_res r) A1 A1' A2
| res_enable_other: forall a A1 A2, ~ is_resources_action a -> res_enable a A1 A1 A2.

Lemma res_enable_acq_inv {Ac: Action} {Res: Resource} {Acr: Action_resource Ac Res} {nAcr: NormalAction_resource Ac Res}:
forall r A1 A1' A2, res_enable (Aacquire_res r) A1 A1' A2 -> join A1 (eq r) A1' /\ ~ A2 r.