I understand how to prove equivalence of two programs when they're represented in the same datatype, from the first chapter of PL Foundations. We want to show that they step to the same value.
How does this work when programs are represented as different types, with separate step relations, e.g. when a compiler translates an AST into an SSA IR which conceptually behaves the same but executes differently? Another example is a program and transition system, where there is a correspondence between program reductions and transitions.
Here's what I've tried. There are two languages, imp1 and imp2, with e.g. just a single Skip command. I figured a good "evaluation result" would be a (finite, for now) trace of actions, to allow for concurrency. There are (multi-)step relations defined for both which allow a finite number of skips.
The problem is that in the final equivalence theorem, the behaviour of imp1 tells me nothing about the behaviour of imp2: given that the imp1 program takes a Skip step, I don't know anything about the next step of imp2.
This feels really silly but what am I missing? Does there need to be some additional relation mapping single steps of imp1 to those of imp2? This feels too restrictive: what if one step of imp1 corresponds to many steps of imp2 or vice versa? Any other resources would be welcome!
From Coq Require Import Strings.String.
From Coq Require Import Lists.List. Import ListNotations.
Inductive imp1 : Type :=
| Skip1 : imp1.
Inductive imp2 : Type :=
| Skip2 : imp2.
Inductive action :=
| A.
Inductive step1 : imp1 -> imp1 -> action -> Prop :=
| SkipStep1 :
step1 Skip1 Skip1 A.
Inductive step2 : imp2 -> imp2 -> action -> Prop :=
| SkipStep2 :
step2 Skip2 Skip2 A.
Definition trace := list action.
Inductive multi_step1 : imp1 -> imp1 -> trace -> Prop :=
| step1_end : forall l, multi_step1 l l []
| step1_step : forall i1 i2 i3 a1 a2,
step1 i1 i2 a1 ->
multi_step1 i2 i3 a2 ->
multi_step1 i1 i3 (a1 :: a2).
Inductive multi_step2 : imp2 -> imp2 -> trace -> Prop :=
| step2_end : forall l, multi_step2 l l []
| step2_step : forall i1 i2 i3 a1 a2,
step2 i1 i2 a1 ->
multi_step2 i2 i3 a2 ->
multi_step2 i1 i3 (a1 :: a2).
Definition compile (i : imp1) : imp2 :=
match i with
| Skip1 => Skip2
end.
Theorem equiv :
forall t i1 i2 j1 j2,
multi_step1 i1 i2 t
-> compile i1 = j1
-> multi_step2 j1 j2 t.
Proof.
intros t i1 i2 j1 j2 Hstep1 Hcomp.
inversion Hstep1; subst.
- destruct i2.
simpl.
Admitted.