Section RegSpec.
Variable sig : Type.
(* Notation without EqType stuff *)
Local Notation "sig '^+'" := ((boundary + sig) % type) (at level 0) : type_scope.
Inductive RegSpec : Type :=
| Contains {sigX X : Type} {cX : codable sigX X} (r : Retract sigX sig) : X -> RegSpec
| Contains_size {sigX X : Type} {cX : codable sigX X} (r : Retract sigX sig) : X -> nat -> RegSpec
| Void : RegSpec
| Void_size : nat -> RegSpec
| Custom : (tape sig^+ -> Prop) -> RegSpec. (* Allows the user to specify the tape manually *)
(* Semantics *)
Definition tspec_single (spec : RegSpec) (t : tape sig^+) : Prop :=
match spec with
| Contains r x => t ≃(r) x
| Contains_size r x s => t ≃(r; s) x
| Void => isVoid t
| Void_size s => isVoid_size t s
| Custom p => p t
end.
(* (* Remove the space annotations *)
Definition removeSpace_reg (P : RegSpec) :=
match P with
| Contains_size r x size => Contains r x
| Void_size size => Void
| _ => P
end.
*)
End RegSpec.
Arguments Custom {sig}.
Arguments Void {sig}.
Arguments Void_size {sig}.
Arguments dummy_sizes : simpl never.
Hint Resolve tspec_single_Contains_size_Contains : core.
Declare Scope spec_scope.
Delimit Scope spec_scope with spec.
Bind Scope spec_scope with Spec.
Notation "'≃≃(' S ')'" := (tspec S%spec) (at level 0, S at level 200, no associativity, format "'≃≃(' S ')'").
Notation "'≃≃(' P ',' S ')'" := (tspec (P%list,S%vector)) (at level 0, P at level 200, S at level 200, no associativity, format "'≃≃(' P ','  S ')'").
Notation "t ≃≃ S" := (tspec S%spec t) (at level 70, no associativity).
Notation "≃( I ) x" := (Contains I x) (at level 70, I at level 200, no associativity, format "'≃(' I ')'  x").
Notation "≃( I ';' s ) x" := (Contains_size I s x) (at level 70, I at level 200, s at level 200, no associativity, format "'≃(' I ';' s ')'  x").
Arguments tspec _%spec _.
Fixpoint implList (Ps : list Prop) (Q : Prop) :=
match Ps with
[] => Q
| P::Ps => P -> implList Ps Q
end.
Arguments implList !_ _.
Instance fold_right_impl' : Proper (Forall2 Basics.impl --> Basics.impl ==> Basics.impl) (implList).

Lemma Triple_introPure (F sig: finType) (n : nat) P (Ps : SpecV sig n) Q (pM : pTM sig^+ F n) :
implList P (Triple (≃≃([],Ps)) pM Q)
-> Triple (tspec (P,Ps)) pM Q.