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_SpecFalse {sig : finType} {n : nat} {F : Type} P (pM : pTM sig^+ F n) Q : Triple (≃≃([False],P)) pM Q.  Lemma Triple_RemoveSpace (n : nat) (sig : finType) (F : Type) (P : SpecV sig n) P' (M : pTM sig^+ F n) (Q : F -> SpecV sig n) Q' (fs : Vector.t (nat->nat) n) : (forall s, Triple (tspec (P',withSpace P s)) M (fun y => tspec (Q' y,withSpace (Q y) (appSize fs s)))) -> (* Specifications with size will always have this form *)
Triple (tspec (P',P)) M (fun y => tspec (Q' y ,Q y)).
Instance fold_right_and : Proper (iff ==> Forall2 iff ==> iff) (fold_right and).

Lemma tspec_space_ext (sig : finType) (n : nat) (t : tapes (boundary+sig) n) (P P':list Prop) (R R' : SpecV sig n)
(ss ss' : Vector.t nat n) :
tspec (P',withSpace R' ss') t ->
implList P' (List.fold_right and True P) ->
(forall i, tspec_single (withSpace_single R'[@i] ss'[@i]) t[@i] -> tspec_single (withSpace_single R[@i] ss[@i]) t[@i]) ->
tspec (P,withSpace R ss) t.