(*** Machine specification ***)
(** Abstract syntax of machine code **)
Definition var: Set := positive.
Definition var_eq: forall (v1 v2: var), {v1=v2} + {v1<>v2} := positive_eq_dec.
Definition V (n: nat) : var := P_of_succ_nat n.
Definition label: Set := positive.
Definition label_eq: forall (l1 l2: label), {l1=l2} + {l1<>l2} := positive_eq_dec.
Definition L (n: nat) : label := P_of_succ_nat n.
Section instr_def.
Variable X:Type.
Inductive instr : Type :=
| instr_assert : X -> instr
| instr_getlabel: label -> var -> instr
| instr_fetch_field: var -> nat -> var -> instr
| instr_cons: var -> var -> var -> instr
| instr_seq: instr -> instr -> instr
| instr_if_nil : var -> instr -> instr -> instr
| instr_call: var -> instr
| instr_return: instr
| instr_nil : instr.
End instr_def.
Implicit Arguments instr_assert [X].
Implicit Arguments instr_getlabel [X].
Implicit Arguments instr_fetch_field [X].
Implicit Arguments instr_cons [X].
Implicit Arguments instr_seq [X].
Implicit Arguments instr_if_nil [X].
Implicit Arguments instr_call [X].
Implicit Arguments instr_return [X].
Fixpoint fmap_instr {A B} (f:A->B) (x:instr A) : instr B :=
match x with
| instr_assert a => instr_assert (f a)
| instr_getlabel l v => instr_getlabel l v
| instr_fetch_field v1 n v2 => instr_fetch_field v1 n v2
| instr_cons v1 v2 v3 => instr_cons v1 v2 v3
| instr_seq i1 i2 => instr_seq (fmap_instr f i1) (fmap_instr f i2)
| instr_if_nil v i1 i2 => instr_if_nil v (fmap_instr f i1) (fmap_instr f i2)
| instr_call v => instr_call v
| instr_return => instr_return
| instr_nil => instr_nil _
end.
(** Run-time values and environments **)
Inductive value: Set :=
| value_label: label -> value
| value_cons: value -> value -> value.
Definition store := map value.
Definition store_empty : store := empty value.
Definition program X := map (instr X).
Definition terminationMeasure : Type :=
label -> store -> option nat.
Definition store_incr (r1 r2:store) :=
forall l x,
r1#l = Some x ->
r2#l = Some x.
Definition termMeasure_incr (s1 s2:terminationMeasure) :=
forall l r, s1 l r = None \/ s1 l r = s2 l r.
Module KnotInput <: KNOT_INPUT__HERED_PROP_OTH_REL.
Definition F := program.
Definition fmap A B (f:A->B) := map_fmap _ _ (fmap_instr f).
Implicit Arguments fmap [A B].

(* Specifications: *)
Lemma fmap_id : forall A, fmap (id A) = id (F A).
Lemma fmap_comp : forall A B C (f:B -> C) (g:A -> B),
fmap f oo fmap g = fmap (f oo g).