Require Import Streams.
Require Import Equality.
Require Import List.
Require Import Syntax.
Require Import Alphabet.
Require Grammar.
Require Automaton.
Require Validator_safe.
Require Interpreter.
Module Make(
Import A:
Automaton.T) (
Import Inter:
Interpreter.T A).
Module Import Valid :=
Validator_safe.Make A.
A correct automaton does not crash *
Section Safety_proof.
Hypothesis safe:
safe.
Proposition shift_head_symbs:
shift_head_symbs.
Proof.
Proposition goto_head_symbs:
goto_head_symbs.
Proof.
Proposition shift_past_state:
shift_past_state.
Proof.
Proposition goto_past_state:
goto_past_state.
Proof.
Proposition reduce_ok:
reduce_ok.
Proof.
We prove that a correct automaton won't crash : the interpreter will
not return Err *
Variable init :
initstate.
The stack of states of an automaton stack *
Definition state_stack_of_stack (
stack:
stack) :=
(
List.map
(
fun cell:
sigT noninitstate_type =>
singleton_state_pred (
projT1 cell))
stack ++ [
singleton_state_pred init])%
list.
The stack of symbols of an automaton stack *
Definition symb_stack_of_stack (
stack:
stack) :=
List.map
(
fun cell:
sigT noninitstate_type =>
last_symb_of_non_init_state (
projT1 cell))
stack.
The stack invariant : it basically states that the assumptions on the
states are true. *
Inductive stack_invariant:
stack ->
Prop :=
|
stack_invariant_constr:
forall stack,
prefix (
head_symbs_of_state (
state_of_stack init stack))
(
symb_stack_of_stack stack) ->
prefix_pred (
head_states_of_state (
state_of_stack init stack))
(
state_stack_of_stack stack) ->
stack_invariant_next stack ->
stack_invariant stack
with stack_invariant_next:
stack ->
Prop :=
|
stack_invariant_next_nil:
stack_invariant_next []
|
stack_invariant_next_cons:
forall state_cur st stack_rec,
stack_invariant stack_rec ->
stack_invariant_next (
existT _ state_cur st::
stack_rec).
pop conserves the stack invariant and does not crash
under the assumption that we can pop at this place.
Moreover, after a pop, the top state of the stack is allowed. *
Lemma pop_stack_invariant_conserved
(
symbols_to_pop:
list symbol) (
stack_cur:
stack)
A action:
stack_invariant stack_cur ->
prefix symbols_to_pop (
head_symbs_of_state (
state_of_stack init stack_cur)) ->
match pop symbols_to_pop stack_cur (
A:=
A)
action with
|
OK (
stack_new,
_) =>
stack_invariant stack_new /\
state_valid_after_pop
(
state_of_stack init stack_new)
symbols_to_pop
(
head_states_of_state (
state_of_stack init stack_cur))
|
Err =>
False
end.
Proof with
prefix is associative *
Lemma prefix_ass:
forall (
l1 l2 l3:
list symbol),
prefix l1 l2 ->
prefix l2 l3 ->
prefix l1 l3.
Proof.
induction l1; intros.
constructor.
inversion H; subst.
inversion H0; subst.
constructor; eauto.
Qed.
prefix_pred is associative *
Lemma prefix_pred_ass:
forall (
l1 l2 l3:
list (
state->
bool)),
prefix_pred l1 l2 ->
prefix_pred l2 l3 ->
prefix_pred l1 l3.
Proof.
induction l1; intros.
constructor.
inversion H; subst.
inversion H0; subst.
constructor; eauto.
intro.
specialize (H3 x).
specialize (H4 x).
destruct (f0 x); simpl in *; intuition.
rewrite H4 in H3; intuition.
Qed.
If we have the right to reduce at this state, then the stack invariant
is conserved by reduce_step and reduce_step does not crash. *
Lemma reduce_step_stack_invariant_conserved stack prod buff:
stack_invariant stack ->
valid_for_reduce (
state_of_stack init stack)
prod ->
match reduce_step init stack prod buff with
|
OK (
Fail_sr |
Accept_sr _ _) =>
True
|
OK (
Progress_sr stack_new _) =>
stack_invariant stack_new
|
Err =>
False
end.
Proof with
If the automaton is safe, then the stack invariant is conserved by
step and step does not crash. *
Lemma step_stack_invariant_conserved (
stack:
stack)
buffer:
stack_invariant stack ->
match step init stack buffer with
|
OK (
Fail_sr |
Accept_sr _ _) =>
True
|
OK (
Progress_sr stack_new _) =>
stack_invariant stack_new
|
Err =>
False
end.
Proof with
If the automaton is safe, then it does not crash *
Theorem parse_no_err buffer n_steps:
parse init buffer n_steps <>
Err.
Proof with
A version of parse that uses safeness in order to return a
parse_result, and not a result parse_result : we have proven that
parsing does not return Err. *
Definition parse_with_safe (
buffer:
Stream token) (
n_steps:
nat):
parse_result init.
Proof with
eauto.
pose proof (
parse_no_err buffer n_steps).
destruct (
parse init buffer n_steps)...
congruence.
Defined.
End Safety_proof.
End Make.