Files
linguist/samples/Coq/JsCorrectness.v
Alhadis 4f1e5c34b1 Add permissive-licensed Coq samples
BSD-2-Clause: https://github.com/jscert/jscert

  * JSCorrectness.v
  * JSInterpreterExtraction.v
  * JSNumber.v
  * JSPrettyInterm.v

MIT/Expat: https://github.com/clarus/coq-atm

  * Computation.v
  * Main.v
  * Spec.v
2016-11-03 02:50:54 +11:00

5945 lines
237 KiB
Coq

Set Implicit Arguments.
Require Import Shared.
Require Import LibFix LibList.
Require Import JsSyntax JsSyntaxAux JsCommon JsCommonAux JsPreliminary.
Require Import JsInterpreterMonads JsInterpreter JsPrettyInterm JsPrettyRules.
Ltac tryfalse_nothing :=
try match goal with x: nothing |- _ => destruct x end;
tryfalse.
(**************************************************************)
(** ** Implicit Types -- copied from JsPreliminary *)
Implicit Type b : bool.
Implicit Type n : number.
Implicit Type k : int.
Implicit Type s : string.
Implicit Type i : literal.
Implicit Type l : object_loc.
Implicit Type w : prim.
Implicit Type v : value.
Implicit Type r : ref.
Implicit Type ty : type.
Implicit Type rt : restype.
Implicit Type rv : resvalue.
Implicit Type lab : label.
Implicit Type labs : label_set.
Implicit Type R : res.
Implicit Type o : out.
Implicit Type ct : codetype.
Implicit Type x : prop_name.
Implicit Type str : strictness_flag.
Implicit Type m : mutability.
Implicit Type Ad : attributes_data.
Implicit Type Aa : attributes_accessor.
Implicit Type A : attributes.
Implicit Type Desc : descriptor.
Implicit Type D : full_descriptor.
Implicit Type L : env_loc.
Implicit Type E : env_record.
Implicit Type Ed : decl_env_record.
Implicit Type X : lexical_env.
Implicit Type O : object.
Implicit Type S : state.
Implicit Type C : execution_ctx.
Implicit Type P : object_properties_type.
Implicit Type W : result.
Implicit Type e : expr.
Implicit Type p : prog.
Implicit Type t : stat.
Implicit Type T : Type.
(**************************************************************)
(** Correctness Properties *)
Record runs_type_correct runs :=
make_runs_type_correct {
runs_type_correct_expr : forall S C e o,
runs_type_expr runs S C e = o ->
red_expr S C (expr_basic e) o;
runs_type_correct_stat : forall S C t o,
runs_type_stat runs S C t = o ->
red_stat S C (stat_basic t) o;
runs_type_correct_prog : forall S C p o,
runs_type_prog runs S C p = o ->
red_prog S C (prog_basic p) o;
runs_type_correct_call : forall S C l v vs o,
runs_type_call runs S C l v vs = o ->
red_expr S C (spec_call l v vs) o;
runs_type_correct_call_prealloc : forall S C l B args o,
runs_type_call_prealloc runs S C B l args = result_some (specret_out o) ->
red_expr S C (spec_call_prealloc B l args) o;
runs_type_correct_construct : forall S C co l args o,
runs_type_construct runs S C co l args = o ->
red_expr S C (spec_construct_1 co l args) o;
runs_type_correct_function_has_instance : forall S C (lo lv : object_loc) o,
runs_type_function_has_instance runs S lo lv = o ->
red_expr S C (spec_function_has_instance_2 lv lo) o;
runs_type_correct_get_args_for_apply : forall S C array (index n : int) y,
runs_type_get_args_for_apply runs S C array index n = result_some y ->
red_spec S C (spec_function_proto_apply_get_args array index n) y;
runs_type_correct_object_has_instance : forall S C B l v o,
runs_type_object_has_instance runs S C B l v = result_some (specret_out o) ->
red_expr S C (spec_object_has_instance_1 B l v) o;
runs_type_correct_stat_while : forall S C rv ls e t o,
runs_type_stat_while runs S C rv ls e t = o ->
red_stat S C (stat_while_1 ls e t rv) o;
runs_type_correct_stat_do_while : forall S C rv ls e t o,
runs_type_stat_do_while runs S C rv ls e t = o ->
red_stat S C (stat_do_while_1 ls t e rv) o;
runs_type_correct_stat_for_loop : forall S C labs rv eo2 eo3 t o,
runs_type_stat_for_loop runs S C labs rv eo2 eo3 t = o ->
red_stat S C (stat_for_2 labs rv eo2 eo3 t) o;
runs_type_correct_object_delete : forall S C l x str o,
runs_type_object_delete runs S C l x str = o ->
red_expr S C (spec_object_delete l x str) o;
runs_type_correct_object_get_own_prop : forall S C l x sp,
runs_type_object_get_own_prop runs S C l x = result_some sp ->
red_spec S C (spec_object_get_own_prop l x) sp;
runs_type_correct_object_get_prop : forall S C l x sp,
runs_type_object_get_prop runs S C l x = result_some sp ->
red_spec S C (spec_object_get_prop l x) sp;
runs_type_correct_object_get : forall S C l x o,
runs_type_object_get runs S C l x = o ->
red_expr S C (spec_object_get l x) o;
runs_type_correct_object_proto_is_prototype_of : forall S C lthis l o,
runs_type_object_proto_is_prototype_of runs S lthis l = o ->
red_expr S C (spec_call_object_proto_is_prototype_of_2_3 lthis l) o;
runs_type_correct_object_put : forall S C l x v str o,
runs_type_object_put runs S C l x v str = o ->
red_expr S C (spec_object_put l x v str) o;
runs_type_correct_equal : forall S C v1 v2 o,
runs_type_equal runs S C v1 v2 = o ->
red_expr S C (spec_equal v1 v2) o;
runs_type_correct_to_integer : forall S C v o,
runs_type_to_integer runs S C v = o ->
red_expr S C (spec_to_integer v) o;
runs_type_correct_to_string : forall S C v o,
runs_type_to_string runs S C v = o ->
red_expr S C (spec_to_string v) o;
(* ARRAYS *)
runs_type_correct_array_element_list : forall S C l oes o k,
runs_type_array_element_list runs S C l oes k = o ->
red_expr S C (expr_array_3 l oes k) o;
runs_type_correct_object_define_own_prop_array_loop :
forall S C l newLen oldLen newLenDesc newWritable throw o
(def : state -> prop_name -> descriptor -> strictness_flag -> specres nothing)
(def_correct : forall S str o x Desc,
def S x Desc str = res_out o ->
red_expr S C (spec_object_define_own_prop_1 builtin_define_own_prop_default l x Desc str) o),
runs_type_object_define_own_prop_array_loop runs S C l newLen oldLen newLenDesc newWritable throw def = o ->
red_expr S C (spec_object_define_own_prop_array_3l l newLen oldLen newLenDesc newWritable throw) o;
runs_type_correct_array_join_elements : forall S C l k length sep s o,
runs_type_array_join_elements runs S C l k length sep s = result_some (specret_out o) ->
red_expr S C (spec_call_array_proto_join_elements l k length sep s) o
}.
(**************************************************************)
(** Useful Tactics *)
Ltac absurd_neg :=
let H := fresh in
introv H; inverts H; tryfalse.
Hint Constructors abort.
(**************************************************************)
(** General Lemmas *)
Lemma arguments_from_spec_1 : forall args,
exists v, arguments_from args (v::nil)
/\ get_arg 0 args = v.
Proof.
Hint Constructors arguments_from.
intros. destruct args as [|v vs].
exists undef. splits*.
exists v. splits*.
Qed.
Lemma res_overwrite_value_if_empty_empty : forall R,
res_overwrite_value_if_empty resvalue_empty R = R.
Proof. introv. unfolds. cases_if~. destruct R; simpls; inverts~ e. Qed.
Lemma res_type_res_overwrite_value_if_empty : forall rv R,
res_type R = res_type (res_overwrite_value_if_empty rv R).
Proof.
introv. destruct R. unfold res_overwrite_value_if_empty. simpl.
cases_if; reflexivity.
Qed.
Lemma res_label_res_overwrite_value_if_empty : forall rv R,
res_label R = res_label (res_overwrite_value_if_empty rv R).
Proof.
introv. destruct R. unfold res_overwrite_value_if_empty. simpl.
cases_if; reflexivity.
Qed.
Lemma res_overwrite_value_if_empty_resvalue : forall rv1 rv2, exists rv3,
res_normal rv3 = res_overwrite_value_if_empty rv1 rv2 /\ (rv3 = rv1 \/ rv3 = rv2).
Proof. introv. unfolds res_overwrite_value_if_empty. cases_if*. Qed.
Lemma get_arg_correct : forall args vs,
arguments_from args vs ->
forall num,
num < length vs ->
get_arg num args = LibList.nth num vs.
Proof.
introv A. induction~ A.
introv I. false I. lets (I'&_): (rm I). inverts~ I'.
introv I. destruct* num. rewrite nth_succ. rewrite <- IHA.
unfolds. repeat rewrite~ nth_def_nil.
rewrite length_cons in I. nat_math.
introv I. destruct* num. rewrite nth_succ. rewrite <- IHA.
unfolds. rewrite~ nth_def_succ.
rewrite length_cons in I. nat_math.
Qed.
Lemma get_arg_correct_0 : forall args,
arguments_from args (get_arg 0 args :: nil).
Proof. introv. destruct args; do 2 constructors. Qed.
Lemma get_arg_correct_1 : forall args,
arguments_from args (get_arg 0 args :: get_arg 1 args :: nil).
Proof. introv. destruct args as [|? [|? ?]]; do 3 constructors. Qed.
Lemma get_arg_correct_2 : forall args,
arguments_from args (get_arg 0 args :: get_arg 1 args :: get_arg 2 args :: nil).
Proof. introv. destruct args as [|? [|? [|? ?]]]; do 4 constructors. Qed.
Lemma get_arg_first_and_rest_correct : forall args v lv,
(v, lv) = get_arg_first_and_rest args <->
arguments_first_and_rest args (v, lv).
Proof.
induction args; introv; splits; introv Hyp;
unfolds get_arg_first_and_rest; unfolds get_arg;
simpls; inverts~ Hyp.
Qed.
Lemma and_impl_left : forall P1 P2 P3 : Prop,
(P1 -> P2) ->
P1 /\ P3 ->
P2 /\ P3.
Proof. auto*. Qed.
Ltac applys_and_base L :=
applys~ and_impl_left; [applys~ L|]; try reflexivity.
Tactic Notation "applys_and" constr(E) :=
applys_and_base (>> E).
Tactic Notation "applys_and" constr(E) constr(A1) :=
applys_and_base (>> E A1).
Tactic Notation "applys_and" constr(E) constr(A1) constr(A2) :=
applys_and_base (>> E A1 A2).
Tactic Notation "applys_and" constr(E) constr(A1) constr(A2) constr(A3) :=
applys_and_base (>> E A1 A2 A3).
Ltac constructors_and :=
let H := fresh in
eapply and_impl_left; [ intro H; constructors; exact H |].
Lemma run_callable_correct : forall S v co,
run_callable S v = Some co ->
callable S v co.
Proof.
introv E. destruct v; simpls~.
inverts~ E.
sets_eq <- B: (pick_option (object_binds S o)). destruct B; simpls; tryfalse.
exists o0. splits~. forwards~: @pick_option_correct EQB. inverts~ E.
Qed.
(**************************************************************)
(** Monadic Constructors, Lemmas *)
(* Shared defs *)
(** [eqabort o1 o] assert that [o1] and [o] are equal
and satisfy the [abort] predicate. *)
Definition eqabort o1 o :=
o = o1 /\ abort o.
Ltac prove_abort :=
solve [ assumption | (constructor; absurd_neg) ].
(** [isout W Pred] asserts that [W] is in fact
an outcome that satisfies [Pred]. *)
Definition isout W (Pred:out->Prop) :=
exists o1, W = res_out o1 /\ Pred o1.
Hint Unfold isout.
Hint Unfold eqabort.
(* Generic *)
Lemma if_empty_label_out : forall T K S R (o : T),
if_empty_label S R K = result_some o ->
res_label R = label_empty /\ K tt = result_some o.
Proof. introv H. unfolds in H. cases_if; tryfalse. eexists; auto*. Qed.
Lemma if_some_out : forall (A B : Type) (oa : option A) K (b : B),
if_some oa K = result_some b ->
exists (a:A), oa = Some a /\ K a = result_some b.
Proof. introv E. destruct* oa; tryfalse. Qed.
Lemma if_result_some_out : forall (A B : Type) (W : resultof A) K (b : B),
if_result_some W K = result_some b ->
exists (y : A), W = result_some y /\ K y = result_some b.
Proof. introv H. destruct* W; tryfalse. Qed.
Lemma if_some_or_default_out : forall (A B : Type) (oa : option A) d K (b : B),
if_some_or_default oa d K = b ->
(oa = None /\ d = b)
\/ (exists a, oa = Some a /\ K a = b).
Proof. introv E. destruct* oa; tryfalse. Qed.
(* Results *)
Definition if_ter_post (K : _ -> _ -> result) o o1 :=
(o1 = out_div /\ o = o1)
\/ (exists S R, o1 = out_ter S R /\ K S R = o).
Lemma if_ter_out : forall W K o,
if_ter W K = res_out o ->
isout W (if_ter_post K o).
Proof.
introv H. destruct W as [[|o1]| | | ]; simpls; tryfalse_nothing.
exists o1. splits~. unfolds. destruct o1 as [|S R].
inverts* H.
jauto.
Qed.
Definition if_success_state_post rv0 (K : _ -> _ -> result) o o1 :=
(o1 = out_div /\ o = o1) \/
(exists S R, o1 = out_ter S R /\ res_type R = restype_throw /\ o = out_ter S R) \/
(exists S R, o1 = out_ter S R /\ res_type R <> restype_throw /\
res_type R <> restype_normal /\ o = out_ter S (res_overwrite_value_if_empty rv0 R)) \/
exists S rv, o1 = out_ter S (res_normal rv) /\
K S (ifb rv = resvalue_empty then rv0 else rv) = res_out o.
Lemma if_success_state_out : forall rv W K o,
if_success_state rv W K = o ->
isout W (if_success_state_post rv K o).
Proof.
introv E. forwards~ (o1&WE&P): if_ter_out (rm E). subst W. eexists. splits*.
inversion_clear P as [?|(S&R&?&H)]. branch~ 1.
substs. destruct R as [rt rv' rl]. destruct~ rt; simpls;
try solve [branch 3; repeat eexists; [discriminate | discriminate | inverts~ H]].
forwards~ (?&?): if_empty_label_out (rm H). simpls. substs.
branch 4. repeat eexists. auto*.
inverts H. branch 2. repeat eexists.
Qed.
Definition if_success_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S rv, o1 = out_ter S (res_normal rv) /\ K S rv = o.
Lemma if_success_out : forall W K o,
if_success W K = res_out o ->
isout W (if_success_post K o).
Proof.
introv E. forwards~ (o1&WE&P): if_ter_out (rm E). subst W. eexists. splits*.
inversion_clear P as [[? ?]|(S&R&?&H)]. substs. branch~ 1.
substs. destruct R as [rt rv' rl]. destruct~ rt; simpls;
try solve [inverts H; branch 1; splits~; prove_abort].
forwards~ (?&?): if_empty_label_out (rm H). simpls. substs.
branch 2. repeat eexists. auto*.
Qed.
(* Documentation: same with unfolding:
Lemma if_success_out : forall W K o,
if_success W K = o ->
exists o1, W = res_out o1 /\
( (o = o1 /\ abort o)
\/ (exists S rv, o1 = out_ter S rv /\ K S rv = o)).
*)
Definition if_void_post (K : _ -> result) o o1 :=
eqabort o1 o \/
exists S, o1 = out_void S /\ K S = o.
Lemma if_void_out : forall W K o,
if_void W K = o ->
isout W (if_void_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_success_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&?&?)]; subst; [ left* | right ].
exists S. destruct R; tryfalse. auto.
Admitted. (*faster*)
(* if_not_throw *)
Definition if_not_throw_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
(exists S R, o1 = out_ter S R /\
((res_type R <> restype_throw /\ K S R = o) \/
(res_type R = restype_throw /\ o = o1))).
Hint Extern 1 (_ <> _ :> restype) => congruence.
Lemma if_not_throw_out : forall W K o,
if_not_throw W K = o ->
isout W (if_not_throw_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1 & WE & P): if_ter_out (rm E).
exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?] | (S & R & ? & ?)]. branch~ 1.
splits~. substs~.
right. exists S R; splits~.
destruct (res_type R); try solve [left; splits~; discriminate].
right; splits~. subst. inverts~ H0.
Qed.
Definition if_any_or_throw_post (K1 K2 : _ -> _ -> result) o o1 :=
(o1 = out_div /\ o = o1) \/
(exists S R, o1 = out_ter S R /\
( (res_type R <> restype_throw /\ K1 S R = o)
\/ (res_type R = restype_throw /\ exists (v : value), res_value R = v
/\ res_label R = label_empty /\ K2 S v = o))). (* Didn't worked when writing [exists (v : value), R = res_throw v]. *)
Lemma if_any_or_throw_out : forall W K1 K2 o,
if_any_or_throw W K1 K2 = res_out o ->
isout W (if_any_or_throw_post K1 K2 o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_ter_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&?&?)]; subst; [ left* | right ].
exists S R. split~. destruct (res_type R); tryfalse; simple*.
right. destruct (res_value R); tryfalse; simple*. split*.
forwards*: if_empty_label_out.
Admitted. (*faster*)
Definition if_success_or_return_post (K1 : state -> result) (K2 : state -> resvalue -> result) o o1 :=
(o1 = out_div /\ o = o1)
\/ exists S R, o1 = out_ter S R /\
( (res_type R = restype_normal /\ res_label R = label_empty /\ K1 S = o)
\/ (res_type R = restype_return /\ res_label R = label_empty /\ K2 S (res_value R) = o)
\/ (res_type R <> restype_normal /\ res_type R <> restype_return /\ o1 = o)).
Lemma if_success_or_return_out : forall W (K1 : state -> result) (K2 : state -> resvalue -> result) o,
if_success_or_return W K1 K2 = o ->
isout W (if_success_or_return_post K1 K2 o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_ter_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
exists S R. split~. destruct (res_type R); tryfalse; simple*.
branch 1. forwards*: if_empty_label_out.
branch 3. inverts* E.
branch 3. inverts* E.
branch 2. forwards*: if_empty_label_out.
branch 3. inverts* E.
Admitted. (*faster*)
(* TODO: misssing
if_normal_continue_or_break *)
Definition if_break_post (K : _ -> _ -> result) o o1 :=
(o1 = out_div /\ o = o1)
\/ (exists S R, o1 = out_ter S R /\
( (res_type R <> restype_break /\ o1 = o)
\/ (res_type R = restype_break /\ K S R = o))).
Lemma if_break_out : forall W K o,
if_break W K = o ->
isout W (if_break_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_ter_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
exists S R. split~. destruct (res_type R); try inverts E; simple*.
Admitted. (*faster*)
Definition if_value_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S v, o1 = out_ter S (res_val v) /\ K S v = o.
Lemma if_value_out : forall W K o,
if_value W K = res_out o ->
isout W (if_value_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_success_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_bool_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S z, o1 = out_ter S (res_val (prim_bool z)) /\ K S z = o.
Lemma if_bool_out : forall W K o,
if_bool W K = res_out o ->
isout W (if_bool_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_object_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S l, o1 = out_ter S (res_val (value_object l)) /\ K S l = o.
Lemma if_object_out : forall W K o,
if_object W K = res_out o ->
isout W (if_object_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_string_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S s, o1 = out_ter S (res_val (prim_string s)) /\ K S s = o.
Lemma if_string_out : forall W K o,
if_string W K = res_out o ->
isout W (if_string_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_number_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S n, o1 = out_ter S (res_val (prim_number n)) /\ K S n = o.
Lemma if_number_out : forall W K o,
if_number W K = res_out o ->
isout W (if_number_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1 & WE & P): if_value_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_prim_post (K : _ -> _ -> result) o o1 :=
eqabort o1 o \/
exists S w, o1 = out_ter S (res_val (value_prim w)) /\ K S w = o.
Lemma if_prim_out : forall W K o,
if_prim W K = res_out o ->
isout W (if_prim_post K o).
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_out (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Admitted. (*faster*)
Lemma if_abort_out : forall T o K (t : T),
if_abort o K = result_some t ->
abort o /\ K tt = result_some t.
Proof. introv H. destruct* o. simpls. cases_if*. Qed.
Definition if_spec_post (A B:Type) K (b:specret B) y :=
(exists o, y = specret_out o /\ b = specret_out o /\ abort o)
\/ (exists (S:state) (a:A), y = specret_val S a /\ K S a = result_some b).
Lemma if_spec_out : forall (A B : Type) (W : specres A) K (b : specret B),
if_spec W K = result_some b ->
exists y, W = result_some y /\ if_spec_post K b y.
Proof.
introv E. unfolds in E. unfolds in E.
destruct W; tryfalse. exists s. split~.
unfolds. destruct s; [ right | left ].
exists___*.
lets (?&H): if_abort_out E. inverts H. exists___*.
Admitted. (* faster *)
Definition if_ter_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (R : res), o = out_ter S R /\ K S R = result_some y).
Lemma if_ter_spec : forall T W K (y : specret T),
if_ter W K = result_some y ->
isout W (if_ter_spec_post K y).
Proof.
introv H. destruct W as [[|o1]| | | ]; simpls; tryfalse_nothing.
exists o1. splits~. unfolds. destruct o1 as [|S R].
inverts* H.
jauto.
Qed.
Definition if_success_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (rv : resvalue), o = out_ter S rv /\ K S rv = result_some y).
Lemma if_success_spec : forall T W K (y : specret T),
if_success W K = result_some y ->
exists (o : out), W = o /\ if_success_spec_post K y o. (* LATER: Change to [isout] *)
Proof.
introv E. forwards~ (o1&WE&P): if_ter_spec (rm E). subst W. eexists. splits*.
inversion_clear P as [[? ?]|(S&R&?&H)]. substs. branch~ 1.
substs. destruct R as [rt rv' rl]. destruct~ rt; simpls;
try solve [inverts H; branch 1; splits~; prove_abort].
forwards~ (?&?): if_empty_label_out (rm H). simpls. substs.
branch 2. repeat eexists. auto*.
Qed.
Definition if_value_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (v : value), o = out_ter S v /\ K S v = result_some y).
Lemma if_value_spec : forall T W K (y : specret T),
if_value W K = result_some y ->
exists (o : out), W = o /\ if_value_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_success_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_prim_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (w : prim), o = out_ter S w /\ K S w = result_some y).
Lemma if_prim_spec : forall T W K (y : specret T),
if_prim W K = result_some y ->
exists (o : out), W = o /\ if_prim_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_bool_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (b : bool), o = out_ter S b /\ K S b = result_some y).
Lemma if_bool_spec : forall T W K (y : specret T),
if_bool W K = result_some y ->
exists (o : out), W = o /\ if_bool_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_number_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (n : number), o = out_ter S n /\ K S n = result_some y).
Lemma if_number_spec : forall T W K (y : specret T),
if_number W K = result_some y ->
exists (o : out), W = o /\ if_number_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_string_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (s : string), o = out_ter S s /\ K S s = result_some y).
Lemma if_string_spec : forall T W K (y : specret T),
if_string W K = result_some y ->
exists (o : out), W = o /\ if_string_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. destruct p; tryfalse. exists___*.
Admitted. (*faster*)
Definition if_object_spec_post T K (y:specret T) o :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (l : object_loc), o = out_ter S l /\ K S l = result_some y).
Lemma if_object_spec : forall T W K (y : specret T),
if_object W K = result_some y ->
exists (o : out), W = o /\ if_object_spec_post K y o.
Proof.
introv E. unfolds in E.
forwards~ (o1&WE&P): if_value_spec (rm E). exists o1. split~.
unfolds. unfolds in P.
inversion_clear P as [[? ?]|(S&R&H&E)]; subst; [ left* | right ].
destruct R; tryfalse. exists___*.
Qed.
(************************************************************)
(* ** Correctness Tactics *)
(** [prove_not_intercept] proves a goal of
the form "~ abort_intercepted_* _" *)
Ltac prove_not_intercept :=
let H := fresh in intros H; try solve [ inversion H; false~ ].
Hint Extern 1 (~ abort_intercepted_expr _) => prove_not_intercept.
Hint Extern 1 (~ abort_intercepted_stat _) => prove_not_intercept.
Hint Extern 1 (~ abort_intercepted_prog _) => prove_not_intercept.
Ltac abort_tactic L :=
try subst; apply L;
[ simpl; congruence
| try prove_abort
| try prove_not_intercept ].
Tactic Notation "abort_expr" :=
abort_tactic red_expr_abort.
Tactic Notation "abort_stat" :=
abort_tactic red_stat_abort.
Tactic Notation "abort_prog" :=
abort_tactic red_prog_abort.
Tactic Notation "abort_spec" :=
abort_tactic red_spec_abort.
Tactic Notation "abort" :=
match goal with
| |- red_expr _ _ _ _ => abort_expr
| |- red_stat _ _ _ _ => abort_stat
| |- red_prog _ _ _ _ => abort_prog
| |- red_spec _ _ _ _ => abort_spec
end.
(** [run_select_ifres] selects the appropriate "out" lemma *)
Ltac run_select_extra T := fail.
Ltac run_select_ifres H :=
match type of H with ?T = _ => match T with
| @if_ter nothing _ _ => constr:(if_ter_out)
| @if_success nothing _ _ => constr:(if_success_out)
| @if_value nothing _ _ => constr:(if_value_out)
| @if_void nothing _ _ => constr:(if_void_out)
| if_break _ _ => constr:(if_break_out)
| @if_object nothing _ _ => constr:(if_object_out)
| @if_bool nothing _ _ => constr:(if_bool_out)
| @if_string nothing _ _ => constr:(if_string_out)
| @if_number nothing _ _ => constr:(if_number_out)
| @if_prim nothing _ _ => constr:(if_prim_out)
| if_ter _ _ => constr:(if_ter_spec)
| if_success _ _ => constr:(if_success_spec)
| if_value _ _ => constr:(if_value_spec)
| if_bool _ _ => constr:(if_bool_spec)
| if_string _ _ => constr:(if_string_spec)
| if_object _ _ => constr:(if_object_spec)
| if_number _ _ => constr:(if_number_spec)
| if_prim _ _ => constr:(if_prim_spec)
| if_spec _ _ => constr:(if_spec_out)
| if_void _ _ => constr:(if_void_out)
| if_not_throw _ _ => constr:(if_not_throw_out)
| if_any_or_throw _ _ _ => constr:(if_any_or_throw_out)
| if_success_or_return _ _ _ => constr:(if_success_or_return_out)
| if_success_state _ _ _ => constr:(if_success_state_out)
| ?x => run_select_extra T
end end.
(* template:
Ltac run_select_extra T ::=
match T with
| if_any_or_throw _ _ _ => constr:(if_any_or_throw_out)
end.
*)
(** [run_select_proj] is used to obtain automatically
the right correctness lemma out of the correctness record *)
Ltac run_select_proj_extra_error HT := fail.
Ltac run_select_proj_extra_ref HT := fail.
Ltac run_select_proj_extra_conversions HT := fail.
Ltac run_select_proj_extra_construct HT := fail.
Ltac run_select_proj_extra_get_value HT := fail.
Ltac run_select_proj H :=
match type of H with ?T = _ => let HT := get_head T in
match HT with
| runs_type_expr => constr:(runs_type_correct_expr)
| runs_type_stat => constr:(runs_type_correct_stat)
| runs_type_prog => constr:(runs_type_correct_prog)
| runs_type_call => constr:(runs_type_correct_call)
| runs_type_construct => constr:(runs_type_correct_construct)
| runs_type_function_has_instance => constr:(runs_type_correct_function_has_instance)
| runs_type_object_has_instance => constr:(runs_type_correct_object_has_instance)
| runs_type_stat_while => constr:(runs_type_correct_stat_while)
| runs_type_stat_do_while => constr:(runs_type_correct_stat_do_while)
| runs_type_stat_for_loop => constr:(runs_type_correct_stat_for_loop)
| runs_type_object_delete => constr:(runs_type_correct_object_delete)
| runs_type_object_get_own_prop => constr:(runs_type_correct_object_get_own_prop)
| runs_type_object_get_prop => constr:(runs_type_correct_object_get_prop)
| runs_type_object_get => constr:(runs_type_correct_object_get)
| runs_type_object_proto_is_prototype_of => constr:(runs_type_correct_object_proto_is_prototype_of)
| runs_type_object_put => constr:(runs_type_correct_object_put)
| runs_type_equal => constr:(runs_type_correct_equal)
| runs_type_to_integer => constr:(runs_type_correct_to_integer)
| runs_type_to_string => constr:(runs_type_correct_to_string)
| runs_type_array_element_list => constr:(runs_type_correct_array_element_list)
| runs_type_object_define_own_prop_array_loop => constr:(runs_type_correct_object_define_own_prop_array_loop)
| ?x => run_select_proj_extra_error HT
| ?x => run_select_proj_extra_ref HT
| ?x => run_select_proj_extra_conversions HT
| ?x => run_select_proj_extra_construct HT
| ?x => run_select_proj_extra_get_value HT
end end.
(** [prove_runs_type_correct] discharges the trivial goal
that consists in invoking the induction hypothesis*)
Ltac prove_runs_type_correct :=
match goal with |- runs_type_correct _ => assumption end.
(* [run_hyp H] exploits the induction hypothesis
on [runs_type_correct] to the hypothesis [H] *)
Ltac run_hyp_core H R :=
let H' := fresh in rename H into H';
let Proj := run_select_proj H' in
lets R: Proj (rm H');
try prove_runs_type_correct.
(** [select_ind_hyp] returns the induction hypothesis
on [runs_type_correct] *)
Ltac select_ind_hyp tt :=
match goal with IH: runs_type_correct _ |- _ => constr:(IH) end.
(* old run_hyp H:
Ltac run_hyp_core H R :=
let H' := fresh in rename H into H';
let IH := select_ind_hyp tt in
let Proj := run_select_proj H' in
lets R: Proj IH (rm H').
*)
Tactic Notation "run_hyp" hyp(H) "as" simple_intropattern(R) :=
run_hyp_core H R.
Tactic Notation "run_hyp" hyp(H) :=
let T := fresh in rename H into T;
run_hyp T as H.
Tactic Notation "run_hyp" :=
match goal with H: _ = result_some _ |- _ => run_hyp H end.
Tactic Notation "run_hyp" "*" hyp(H) :=
run_hyp H; auto*.
Tactic Notation "run_hyp" "*" :=
run_hyp; auto*.
(* [run_pre] exploits the appropriate "out" lemma, whether it comes
from the correctness record or it is an auxiliary lemma. *)
Ltac run_pre_ifres H o1 R1 K :=
let L := run_select_ifres H in
lets (o1&R1&K): L (rm H). (* deconstruction of the "isout" *)
Ltac run_pre_core H o1 R1 K :=
run_pre_ifres H o1 R1 K;
let O1 := fresh "O1" in
try (rename R1 into O1; run_hyp O1 as R1).
Tactic Notation "run_pre" hyp(H) "as" ident(o1) ident(R1) ident(K) :=
let T := fresh in rename H into T;
run_pre_core T o1 R1 K.
Tactic Notation "run_pre_ifres" "as" ident(o1) ident(R1) :=
unfold result_some_out in *; unfold res_to_res_void in * ; unfold result_out in *; unfold res_out in *;
(* LATER: improve unfolds *)
match goal with H: _ = result_some _ |- _ =>
let T := fresh in rename H into T;
run_pre_ifres T o1 R1 H end.
Tactic Notation "run_pre" "as" ident(o1) ident(R1) :=
unfold result_some_out in *; unfold res_to_res_void in * ; unfold result_out in *; unfold res_out in *;
(* LATER: improve unfolds *)
match goal with H: _ = result_some _ |- _ =>
let T := fresh in rename H into T;
run_pre_core T o1 R1 H end.
Tactic Notation "run_pre" "as" ident(o1) :=
let R1 := fresh "R1" o1 in
run_pre as o1 R1.
Tactic Notation "run_pre" :=
let o1 := fresh "o1" in let R1 := fresh "R1" in
run_pre as o1 R1.
(** [run_apply Red o1 R1] applys a reduction rule on a given
[o1] or reduction reaching [o1]. *)
Tactic Notation "run_apply" constr(Red) constr(o1orR1) :=
applys Red o1orR1.
Tactic Notation "run_apply" constr(Red) constr(o1) constr(R1) :=
first [ applys Red (rm R1)
| applys Red o1 ].
(** [run_post] decomposes the conclusion of the "out"
lemma *)
Ltac run_post_run_expr_get_value := fail.
Ltac run_post_extra := fail.
Ltac run_post_core :=
let Er := fresh "Er" in
let Ab := fresh "Ab" in
let S := fresh "S" in
let O1 := fresh "O1" in
let go H X :=
destruct H as [(Er&Ab)|(S&X&O1&H)];
[ try abort | try subst_hyp O1 ] in
match goal with
| H: if_ter_post _ _ _ |- _ =>
let R := fresh "R" in go H R
| H: if_success_post _ _ _ |- _ =>
let rv := fresh "rv" in go H rv
| H: if_value_post _ _ _ |- _ =>
let v := fresh "v" in go H v
| H: if_void_post _ _ _ |- _ =>
destruct H as [(Er&Ab)|(S&O1&H)];
[ try abort | try subst_hyp O1 ]
| H: if_not_throw_post _ _ _ |- _ =>
let R := fresh "R" in
let N := fresh "N" in let v := fresh "v" in
let E := fresh "E" in let L := fresh "L" in
destruct H as [(Er & Ab) | (S & R & O1 & [(N & H) | (N & H)])];
[try abort | try subst_hyp O1 | try abort]
| H: if_break_post _ _ _ |- _ =>
let R := fresh "R" in let E := fresh "E" in
let HT := fresh "HT" in
destruct H as [(Er&E)|(S&R&O1&[(HT&E)|(HT&H)])];
[ try abort | try subst_hyp O1 | try subst_hyp O1 ]
| H: if_object_post _ _ _ |- _ =>
let l := fresh "l" in go H l
| H: if_bool_post _ _ _ |- _ =>
let b := fresh "b" in go H b
| H: if_string_post _ _ _ |- _ =>
let s := fresh "s" in go H s
| H: if_number_post _ _ _ |- _ =>
let m := fresh "m" in go H m
| H: if_prim_post _ _ _ |- _ =>
let w := fresh "w" in go H w
| H: if_ter_spec_post _ _ _ |- _ =>
let R := fresh "R" in go H R
| H: if_success_spec_post _ _ _ |- _ =>
let rv := fresh "rv" in go H rv
| H: if_value_spec_post _ _ _ |- _ =>
let v := fresh "v" in go H v
| H: if_bool_spec_post _ _ _ |- _ =>
let b := fresh "b" in go H b
| H: if_string_spec_post _ _ _ |- _ =>
let s := fresh "s" in go H s
| H: if_object_spec_post _ _ _ |- _ =>
let l := fresh "l" in go H l
| H: if_number_spec_post _ _ _ |- _ =>
let m := fresh "m" in go H m
| H: if_prim_spec_post _ _ _ |- _ =>
let w := fresh "w" in go H w
| H: if_spec_post _ _ _ |- _ =>
let o := fresh "o" in let Er' := fresh "Er" in
let S := fresh "S" in let a := fresh "a" in
destruct H as [(o&Er&Er'&Ab)|(S&a&O1&H)];
[ try abort | try subst_hyp O1 ]
| H: if_any_or_throw_post _ _ _ _ |- _ =>
let R := fresh "R" in
let N := fresh "N" in let v := fresh "v" in
let E := fresh "E" in let L := fresh "L" in
destruct H as [(Er&Ab)|(S&R&O1&[(N&H)|(N&v&E&L&H)])];
[ try subst_hyp Er; try subst_hyp Ab | try subst_hyp O1 | try subst_hyp O1 ]
| H: if_success_or_return_post _ _ _ _ |- _ =>
let S := fresh "S" in let R := fresh "R" in
let o1 := fresh "o1" in let W1 := fresh "W1" in let O1 := fresh "O1" in
let E1 := fresh "E" in let E2 := fresh "E" in
destruct H as [(Er&Ab)|(S&R&O1&[(E1&E2&K)|[(E1&E2&K)|(E1&E2&K)]])];
[ try subst_hyp Er; try subst_hyp Ab; try abort
| try subst_hyp O1 | try subst_hyp O1 | try subst_hyp O1 ]
| H: if_success_state_post _ _ _ _ |- _ =>
(* LATER: improve the statement of the lemma *)
let S := fresh "S" in let R := fresh "R" in
let O1 := fresh "O1" in
let E1 := fresh "E" in let E2 := fresh "E" in let rv := fresh "rv" in
destruct H as [(Er&Ab)|[(S&R&O1&E1&H)|[(S&R&O1&E1&E2&H)|(S&rv&O1&H)]]];
[ try subst_hyp Er; try subst_hyp Ab; try abort
| try subst_hyp O1 | try subst_hyp O1 | try subst_hyp O1 ]
| |- _ => run_post_run_expr_get_value
| |- _ => run_post_extra
end.
(* template
Ltac run_post_extra ::=
let Er := fresh "Er" in let Ab := fresh "Ab" in
let O1 := fresh "O1" in let S := fresh "S" in
match goal with
| H: if_any_or_throw_post _ _ _ _ |- _ => ...
end.
*)
Tactic Notation "run_post" :=
run_post_core.
(** [run_inv] simplifies equalities in goals
by performing inversions on equalities. *)
Ltac run_inv :=
unfold result_some_out in *; unfold res_to_res_void in * ; unfold out_retn in *; unfold result_out in *;
repeat
match goal with
| H: resvalue_value ?v = resvalue_value ?v |- _ => clear H
| H: resvalue_value _ = resvalue_value _ |- _ => inverts H
| H: res_spec _ _ = _ |- _ => unfold res_spec in H
| H: _ = res_spec _ _ |- _ => unfold res_spec in H
| H: res_out _ = _ |- _ => unfold res_out in H
| H: _ = res_out _ |- _ => unfold res_out in H
| H: res_ter _ _ = _ |- _ => unfold res_ter in H
| H: _ = res_ter _ _ |- _ => unfold res_ter in H
| H: result_some ?o = result_some ?o |- _ => clear H
| H: result_some _ = result_some _ |- _ => inverts H
| H: out_ter ?S ?R = out_ter ?S ?R |- _ => clear H
| H: out_ter _ _ = out_ter _ _ |- _ => inverts H
| H: res_intro ?t ?v ?l = res_intro ?t ?v ?l |- _ => clear H
| H: res_intro _ _ _ = res_intro _ _ _ |- _ => inverts H
| H: ret _ _ = _ |- _ => unfold ret in H
| H: _ = ret _ _ |- _ => unfold ret in H
| H: ret_void _ = _ |- _ => unfold ret_void in H
| H: _ = ret_void _ |- _ => unfold ret_void in H
| H: res_void _ = _ |- _ => unfold res_void in H
| H: _ = res_void _ |- _ => unfold res_void in H
| H: specret_val ?S ?R = specret_val ?S ?R |- _ => clear H
| H: specret_val _ _ = specret_val _ _ |- _ => inverts H
| H: specret_out ?o = specret_out ?o |- _ => clear H
| H: specret_out _ = _ |- _ => inverts H
| H: _ = specret_out _ |- _ => inverts H
| H: out_from_retn ?sp = out_from_retn ?sp |- _ => clear H
| H: out_from_retn _ = out_from_retn _ |- _ => inverts H
end.
(** [runs_inv] is the same as [run_inv] followed by subst. *)
Ltac runs_inv :=
run_inv; subst.
(** Auxiliary tactics to select/check the current "out" *)
Ltac run_get_current_out tt :=
match goal with
| |- red_expr _ _ _ ?o => o
| |- red_stat _ _ _ ?o => o
| |- red_prog _ _ _ ?o => o
| |- red_spec _ _ _ ?o => o
| |- red_javascript _ ?o => o
end.
Ltac run_check_current_out o :=
match goal with
| |- red_expr _ _ _ o => idtac
| |- red_stat _ _ _ o => idtac
| |- red_prog _ _ _ o => idtac
| |- red_spec _ _ _ o => idtac
| |- red_javascript _ o => idtac
end.
(** [run_step Red] combines [run_pre], [run_apply Red] and calls
[run_post] on the main reduction subgoal, followed
with a cleanup using [run_inv] *)
Ltac run_step Red :=
let o1 := fresh "o1" in let R1 := fresh "R1" in
run_pre as o1 R1;
match Red with ltac_wild => idtac | _ =>
let o := run_get_current_out tt in
run_apply Red o1 R1;
try (run_check_current_out o; run_post; run_inv; try assumption)
end.
(** [run_step_using Red Lem] combines [run_pre],
a forward to exploit the correctness lemma [Lem],
[run_apply Red] and calls
[run_post] on the main reduction subgoal, followed
with a cleanup using [run_inv] *)
Ltac run_step_using Red Lem :=
let o1 := fresh "o1" in let O1 := fresh "O1" in
let R1 := fresh "R1" in
run_pre_ifres as o1 O1;
lets R1: Lem (rm O1);
try prove_runs_type_correct;
match Red with ltac_wild => idtac | _ =>
let o := run_get_current_out tt in
run_apply Red o1 R1;
try (run_check_current_out o; run_post; run_inv; try assumption)
end.
(** [run_simpl] is intended for simplyfing simple monads
that do not match over a result, then run
[run_inv] to clean up the goal. *)
Ltac run_simpl_run_error H T K := fail.
Ltac run_simpl_base H K :=
let E := fresh "E" in
match type of H with ?T = _ => match T with
| if_some _ _ =>
let x := fresh "x" in
lets (x&E&K): if_some_out (rm H)
| if_some_or_default _ _ _ =>
let x := fresh "x" in
let E1 := fresh "E" in let E2 := fresh "E" in
lets [(E1&E2)|(n&E&K)]: if_some_or_default_out (rm H)
| if_empty_label _ _ _ =>
lets (E&K): if_empty_label_out (rm H)
| ?x => run_simpl_run_error H T K
| ?x => run_hyp_core H K
end end.
Ltac run_simpl_core H K :=
run_simpl_base H K; run_inv.
Tactic Notation "run_simpl" ident(H) "as" ident(K) :=
let T := fresh in rename H into T;
run_simpl_core T K.
Tactic Notation "run_simpl" :=
unfold result_some_out in *; unfold res_to_res_void in * ; unfold result_out in *; unfold res_out in *;
(* LATER: handle unfold *)
match goal with H: _ = result_some _ |- _ =>
let H' := fresh in rename H into H';
run_simpl_core H' H
end.
(** [run Red] is the same as [run_step Red].
[run] without arguments is the same as [run_simpl].
[runs] is same as [run] followed with [subst]. *)
Tactic Notation "run" constr(Red) :=
run_step Red.
Tactic Notation "run" "~" constr(Red) :=
run Red; auto~.
Tactic Notation "run" "*" constr(Red) :=
run Red; auto*.
Tactic Notation "run" constr(Red) "using" constr(Lem) :=
run_step_using Red Lem.
Tactic Notation "run" "~" constr(Red) "using" constr(Lem) :=
run Red using Lem; auto~.
Tactic Notation "run" "*" constr(Red) "using" constr(Lem) :=
run Red using Lem; auto*.
Tactic Notation "runs" constr(Red) :=
run Red; subst.
Tactic Notation "runs" "~" constr(Red) :=
run Red; subst; auto~.
Tactic Notation "runs" "*" constr(Red) :=
run Red; subst; auto*.
Tactic Notation "run" :=
run_simpl.
Tactic Notation "run" "~" :=
run; auto~.
Tactic Notation "run" "*" :=
run; auto*.
Tactic Notation "runs" :=
run; subst.
Tactic Notation "runs" "~" :=
runs; auto~.
Tactic Notation "runs" "*" :=
runs; auto*.
(* debugging of [run Red]:
run_pre as o1 R1.
or: run_pre H as o1 R1 K. (* where H is the hypothesis *)
or: run_pre_core H o1 R1 K. (* where H is the hypothesis *)
or: run_pre_lemma H o1 R1 K. (* where H is the hypothesis *)
run_apply __my_red_lemma__ R1. (* where R1 is the red hypothesis *)
run_post.
run_inv.
*)
(************************************************************)
(* ** Correctness Lemmas *)
Lemma type_of_prim_not_object : forall w,
type_of w <> type_object.
Proof. destruct w; simpl; try congruence. Qed.
Hint Resolve type_of_prim_not_object.
Lemma is_lazy_op_correct : forall op,
match is_lazy_op op with
| None => regular_binary_op op
| Some b => lazy_op op b
end.
Proof.
Hint Constructors lazy_op.
unfold regular_binary_op.
intros. destruct op; simple*.
Admitted. (* faster *)
Lemma run_object_method_correct : forall Z (Proj : _ -> Z) S l (z : Z),
run_object_method Proj S l = Some z ->
object_method Proj S l z.
Proof.
introv B. unfolds. forwards (O&Bi&E): LibOption.map_on_inv B.
forwards: @pick_option_correct Bi. exists* O.
Qed.
Lemma run_object_heap_set_extensible_correct : forall b S l S',
run_object_heap_set_extensible b S l = Some S' ->
object_heap_set_extensible b S l S'.
Proof.
introv R. unfolds in R. forwards (O&H&E): LibOption.map_on_inv (rm R).
forwards: @pick_option_correct (rm H). exists O. splits~.
Qed.
Lemma build_error_correct : forall S C vproto vmsg o,
build_error S vproto vmsg = o ->
red_expr S C (spec_build_error vproto vmsg) o.
Proof.
introv R. unfolds in R.
match goal with H: context [object_alloc ?s ?o] |- _ => sets_eq X: (object_alloc s o) end.
destruct X as (l&S'). cases_if.
applys~ red_spec_build_error EQX. run_inv.
applys~ red_spec_build_error_1_no_msg.
Qed.
Lemma run_error_correct' : forall T S ne o C,
run_error S ne = (res_out o : specres T) ->
red_expr S C (spec_error ne) o /\ abort o.
Proof.
introv R. unfolds in R. run_pre as o1 R1. forwards R0: build_error_correct (rm R1).
applys_and red_spec_error R0. run_post.
run_inv. splits~. abort.
run_inv. splits; [|prove_abort]. apply~ red_spec_error_1.
Qed.
Lemma run_error_correct : forall T S ne o C,
run_error S ne = (res_out o : specres T) ->
red_expr S C (spec_error ne) o.
Proof. intros. applys* run_error_correct'. Qed.
Lemma run_error_correct_2 : forall T S (ne : native_error) o C,
run_error S ne = (res_out o : specres T) -> red_expr S C (spec_error ne) o.
Proof. intros. apply* run_error_correct. Qed.
Hint Resolve run_error_correct run_error_correct_2.
Ltac run_simpl_run_error H T K ::=
match T with run_error _ _ =>
let N := fresh "N" in
let C := match goal with |- _ _ ?C _ _ => constr:(C) end in
lets (K&N): run_error_correct C (rm H)
end.
Lemma run_error_not_some_out_res : forall S v T,
~ (run_error S native_error_type = result_some (@specret_out T (out_ter S (res_val v)))).
Proof.
set (C := execution_ctx_intro nil nil (value_prim (prim_bool true)) false). introv Hyp.
apply run_error_correct' with (C := C) in Hyp.
destruct Hyp as (Hred & Habort).
inverts Hred. simpls. inverts H.
inverts H3. simpls. inverts H.
inverts H0. simpls. inverts H.
inverts H9. simpls. inverts H.
inverts Habort. unfolds abrupt_res.
false~ H0. false~ H3.
Admitted. (*faster*)
Lemma out_error_or_void_correct : forall S C str (ne : native_error) o,
out_error_or_void S str ne = o ->
red_expr S C (spec_error_or_void str ne) o /\
(~ abort o -> o = out_void S).
Proof.
introv E. unfolds in E. cases_if.
applys_and red_spec_error_or_void_true.
forwards~ (RC&Cr): run_error_correct' E. splits*.
inverts E. splits~. apply~ red_spec_error_or_void_false.
Qed.
Lemma out_error_or_cst_correct' : forall S C str (ne : native_error) v o,
out_error_or_cst S str ne v = o ->
red_expr S C (spec_error_or_cst str ne v) o /\
(~ abort o -> o = out_ter S v).
Proof.
introv E. unfolds in E. cases_if.
applys_and red_spec_error_or_cst_true. forwards~ (RC&Cr): run_error_correct' E. splits*.
inverts E. splits~. apply~ red_spec_error_or_cst_false.
Qed.
(* LATER: clean up redundant proof for the direct case *)
Lemma out_error_or_cst_correct : forall S C str ne v o,
out_error_or_cst S str ne v = o ->
red_expr S C (spec_error_or_cst str ne v) o.
Proof.
introv HR. unfolds in HR. case_if.
applys* red_spec_error_or_cst_true.
run_inv. applys* red_spec_error_or_cst_false.
Qed.
Ltac run_select_proj_extra_error HT ::=
match HT with
| run_error => constr:(run_error_correct)
| run_object_method => constr:(run_object_method_correct)
end.
(**************************************************************)
(** ** Object Get *)
Lemma object_has_prop_correct : forall runs S C l x o,
runs_type_correct runs ->
object_has_prop runs S C l x = o ->
red_expr S C (spec_object_has_prop l x) o.
Proof.
introv IH HR. unfolds in HR. run_simpl. run_hyp E as M.
applys~ red_spec_object_has_prop M. destruct x0.
run red_spec_object_has_prop_1_default using runs_type_correct_object_get_prop.
apply~ red_spec_object_has_prop_2. rewrite decide_def. repeat cases_if~.
Qed.
Lemma run_object_get_prop_correct : forall runs S C l x y,
runs_type_correct runs ->
run_object_get_prop runs S C l x = result_some y ->
red_spec S C (spec_object_get_prop l x) y.
Proof.
introv IH HR. unfolds in HR.
run. applys* red_spec_object_get_prop.
applys* run_object_method_correct. clear E.
destruct x0; tryfalse.
run red_spec_object_get_prop_1_default. case_if.
subst. run. applys red_spec_object_get_prop_2_undef.
applys* run_object_method_correct.
destruct x0; tryfalse.
destruct p; tryfalse. run_inv. applys red_spec_object_get_prop_3_null.
applys red_spec_object_get_prop_3_not_null. run_hyp*.
run_inv. destruct a; tryfalse.
applys* red_spec_object_get_prop_2_not_undef.
Admitted. (*faster*)
Lemma object_get_builtin_correct : forall runs S C B (vthis:value) l x o,
runs_type_correct runs ->
object_get_builtin runs S C B vthis l x = o ->
red_expr S C (spec_object_get_1 B vthis l x) o.
Proof.
introv IH HR. unfolds in HR.
let_name as Mdefault.
asserts Mdefault_correct: (forall S l o,
Mdefault S l = res_out o ->
red_expr S C (spec_object_get_1 builtin_get_default vthis l x) o).
clear HR o. subst. introv HR.
run red_spec_object_get_1_default. destruct a as [|[Ad|Aa]].
run_inv. applys* red_spec_object_get_2_undef.
run_inv. applys* red_spec_object_get_2_data.
applys red_spec_object_get_2_accessor.
destruct (attributes_accessor_get Aa); tryfalse.
destruct p; tryfalse. run_inv.
applys* red_spec_object_get_3_accessor_undef.
applys* red_spec_object_get_3_accessor_object. run_hyp*.
clear EQMdefault.
let_name as Mfunction.
asserts Mfunction_correct: (forall S o,
Mfunction S = res_out o ->
red_expr S C (spec_object_get_1 builtin_get_function vthis l x) o).
clear HR o. subst. introv HR.
run* red_spec_object_get_1_function. clear R1.
case_if.
applys* red_spec_function_get_1_error.
run_inv. applys* red_spec_function_get_1_normal.
clear EQMfunction. destruct B; tryfalse.
applys~ Mdefault_correct.
applys~ Mfunction_correct.
(* argument object *)
run. forwards* obpm: run_object_method_correct.
run. substs. run~ red_spec_object_get_args_obj.
destruct a. (* LTAC ARTHUR: This [a] wasn't properly named. *)
apply* red_spec_object_get_args_obj_1_undef.
run_hyp. apply~ red_spec_object_get_args_obj_1_attrs.
Admitted. (* faster *)
Lemma run_object_get_correct : forall runs S C l x o,
runs_type_correct runs ->
run_object_get runs S C l x = o ->
red_expr S C (spec_object_get l x) o.
Proof.
introv IH HR. unfolds in HR. run.
applys* red_spec_object_get.
applys* run_object_method_correct. clear E.
applys* object_get_builtin_correct.
Qed.
Lemma object_can_put_correct : forall runs S C l x o,
runs_type_correct runs ->
object_can_put runs S C l x = o ->
red_expr S C (spec_object_can_put l x) o.
Proof.
introv IH HR. unfolds in HR. run. run_hyp E as CP.
applys~ red_spec_object_can_put CP. destruct x0.
run red_spec_object_can_put_1_default. destruct a.
run. run_hyp E as P. applys~ red_spec_object_can_put_2_undef P.
destruct x0 as [()|lproto]; tryfalse.
run. run_hyp E as E. apply~ red_spec_object_can_put_4_null.
run red_spec_object_can_put_4_not_null using run_object_get_prop_correct.
destruct a as [|[Ad|Aa]].
run. run_hyp E as E. apply~ red_spec_object_can_put_5_undef.
run. run_hyp E as E. applys~ red_spec_object_can_put_5_data E. destruct x0.
applys~ red_spec_object_can_put_6_extens_true.
applys~ red_spec_object_can_put_6_extens_false.
run_inv. apply~ red_spec_object_can_put_5_accessor. rewrite decide_def.
repeat cases_if~.
destruct a; run_inv.
apply~ red_spec_object_can_put_2_data.
apply~ red_spec_object_can_put_2_accessor. rewrite decide_def. repeat cases_if~.
Qed.
Lemma object_default_value_correct : forall runs S C l pref o,
runs_type_correct runs ->
object_default_value runs S C l pref = o ->
red_expr S C (spec_object_default_value l pref) o.
Proof.
introv IH HR. unfolds in HR.
run. lets H: run_object_method_correct (rm E).
applys* red_spec_object_default_value (rm H).
destruct x.
let_name as M.
asserts M_correct: (forall S x (F:state->result) K (o:out),
(M S x F = res_out o) ->
(forall S' o', (F S' = o') -> red_expr S' C K o') ->
red_expr S C (spec_object_default_value_sub_1 l x K) o).
clears HR S o. introv HR HK. subst M.
run red_spec_object_default_value_sub_1
using run_object_get_correct.
run. forwards R1: run_callable_correct (rm E).
destruct x0.
simpls. run. destruct v; tryfalse.
run* red_spec_object_default_value_sub_2_callable.
destruct v; run_inv.
applys* red_spec_object_default_value_sub_3_prim.
applys* red_spec_object_default_value_sub_3_object.
applys* red_spec_object_default_value_sub_2_not_callable.
clear EQM.
let_name.
applys* red_spec_object_default_value_1_default.
applys* red_spec_object_default_value_2.
subst. applys* M_correct.
clears S o. intros S o HR. simpls.
applys* red_spec_object_default_value_3.
subst. applys* M_correct.
clears S o. intros S o HR. simpls.
applys* red_spec_object_default_value_4.
Admitted. (* faster *)
(** Conversions *)
Lemma to_primitive_correct : forall runs S C v o prefo,
runs_type_correct runs ->
to_primitive runs S C v prefo = o ->
red_expr S C (spec_to_primitive v prefo) o.
Proof.
introv IH HR. unfolds in HR. destruct v.
run_inv. applys* red_spec_to_primitive_pref_prim.
applys* red_spec_to_primitive_pref_object.
applys* object_default_value_correct.
run_pre. rewrite R1. run_post; substs~.
Qed.
Lemma to_number_correct : forall runs S C v o,
runs_type_correct runs ->
to_number runs S C v = o ->
red_expr S C (spec_to_number v) o.
Proof.
introv IH HR. unfolds in HR. destruct v.
run_inv. applys* red_spec_to_number_prim.
run red_spec_to_number_object using to_primitive_correct.
applys* red_spec_to_number_1.
Qed.
Lemma to_string_correct : forall runs S C v o,
runs_type_correct runs ->
to_string runs S C v = o ->
red_expr S C (spec_to_string v) o.
Proof.
introv IH HR. unfolds in HR. destruct v.
run_inv. applys* red_spec_to_string_prim.
run red_spec_to_string_object using to_primitive_correct.
applys* red_spec_to_string_1.
Qed.
Lemma to_integer_correct : forall runs S C v o,
runs_type_correct runs ->
to_integer runs S C v = o ->
red_expr S C (spec_to_integer v) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_to_integer using to_number_correct.
applys* red_spec_to_integer_1.
Qed.
Lemma to_int32_correct : forall runs S C v (y:specret int),
runs_type_correct runs ->
to_int32 runs S C v = result_some y ->
red_spec S C (spec_to_int32 v) y.
Proof.
introv IH HR. unfolds in HR.
run red_spec_to_int32 using to_number_correct.
applys* red_spec_to_int32_1.
Qed.
Lemma to_uint32_correct : forall runs S C v (y:specret int),
runs_type_correct runs ->
to_uint32 runs S C v = result_some y ->
red_spec S C (spec_to_uint32 v) y.
Proof.
introv IH HR. unfolds in HR.
run red_spec_to_uint32 using to_number_correct.
applys* red_spec_to_uint32_1.
Qed.
Ltac run_select_proj_extra_conversions HT ::=
match HT with
| to_primitive => constr:(to_primitive_correct)
| to_number => constr:(to_number_correct)
| to_string => constr:(to_string_correct)
| to_int32 => constr:(to_int32_correct)
| to_uint32 => constr:(to_uint32_correct)
end.
Lemma run_object_define_own_prop_array_loop_correct :
forall runs S C l newLen oldLen newLenDesc newWritable throw o
(def : state -> prop_name -> descriptor -> strictness_flag -> specres nothing)
(def_correct : forall S str o x Desc,
def S x Desc str = res_out o ->
red_expr S C (spec_object_define_own_prop_1 builtin_define_own_prop_default l x Desc str) o),
runs_type_correct runs ->
run_object_define_own_prop_array_loop runs S C l newLen oldLen newLenDesc newWritable throw def = o ->
red_expr S C (spec_object_define_own_prop_array_3l l newLen oldLen newLenDesc newWritable throw) o.
Proof.
introv Hyp HR IH.
unfolds run_object_define_own_prop_array_loop.
cases_if*. let_name.
applys~ red_spec_object_define_own_prop_array_3l_condition_true.
rewrite <- EQoldLen'.
run~ red_spec_object_define_own_prop_array_3l_ii.
run~ red_spec_object_define_own_prop_array_3l_ii_1.
destruct b; cases_if*; clear n.
applys* red_spec_object_define_own_prop_array_3l_ii_2.
eapply runs_type_correct_object_define_own_prop_array_loop; eassumption.
applys* red_spec_object_define_own_prop_array_3l_ii_2_3.
eapply red_spec_object_define_own_prop_array_3l_iii_1. reflexivity.
destruct newWritable; try solve [false].
let_name as newLenDesc''. rewrite <- EQnewLenDesc''.
apply red_spec_object_define_own_prop_array_3l_iii_2_true.
let_name. cases_if*. subst newLenDesc0.
run~ red_spec_object_define_own_prop_array_3l_iii_3.
applys* red_spec_object_define_own_prop_array_3l_iii_4.
applys* red_spec_object_define_own_prop_reject.
applys* out_error_or_cst_correct.
let_name as newLenDesc''. rewrite <- EQnewLenDesc''.
apply red_spec_object_define_own_prop_array_3l_iii_2_false.
let_name. cases_if*. subst newLenDesc0.
run~ red_spec_object_define_own_prop_array_3l_iii_3.
applys* red_spec_object_define_own_prop_array_3l_iii_4.
applys* red_spec_object_define_own_prop_reject.
applys* out_error_or_cst_correct.
applys~ red_spec_object_define_own_prop_array_3l_condition_false.
destruct newWritable; cases_if*; clear n.
inverts IH. applys* red_spec_object_define_own_prop_array_3n.
applys* red_spec_object_define_own_prop_array_3m.
Qed.
Lemma object_define_own_prop_correct : forall runs S C l x Desc str o,
runs_type_correct runs ->
object_define_own_prop runs S C l x Desc str = o ->
red_expr S C (spec_object_define_own_prop l x Desc str) o.
Proof.
introv IH HR. unfolds in HR.
let_name as rej. asserts Rej: (forall S str o,
rej S str = o ->
red_expr S C (spec_object_define_own_prop_reject str) o).
clear HR S str o. introv HR. subst.
applys* red_spec_object_define_own_prop_reject.
applys* out_error_or_cst_correct.
let_name as def. asserts Def: (forall S str o x Desc,
def S x Desc str = res_out o ->
red_expr S C (spec_object_define_own_prop_1 builtin_define_own_prop_default l x Desc str) o).
clear HR S str o Desc x. introv HR. subst.
run red_spec_object_define_own_prop_1_default.
run. applys* red_spec_object_define_own_prop_2.
applys* run_object_method_correct. clear E.
destruct a.
case_if.
let_name. run. forwards B: @pick_option_correct (rm E).
applys* red_spec_object_define_own_prop_3_undef_true A.
case_if; case_if*.
subst. applys* red_spec_object_define_own_prop_3_undef_false.
let_name as wri. asserts Wri: (forall S A o,
wri S A = res_out o ->
red_expr S C (spec_object_define_own_prop_write l x A Desc str) o).
clear HR o. introv HR. subst.
run. forwards B: @pick_option_correct (rm E).
applys* red_spec_object_define_own_prop_write.
clear EQwri.
case_if.
run_inv. applys* red_spec_object_define_own_prop_3_includes.
applys* red_spec_object_define_own_prop_3_not_include.
case_if.
run_inv. applys* red_spec_object_define_own_prop_4_reject.
applys* red_spec_object_define_own_prop_4_not_reject. case_if.
applys* red_spec_object_define_own_prop_5_generic. case_if.
applys* red_spec_object_define_own_prop_5_a. case_if;
[ | applys* red_spec_object_define_own_prop_6a_reject].
let_name. run. forwards B: @pick_option_correct (rm E).
applys* red_spec_object_define_own_prop_6a_accept A'.
case_if as HC1.
destruct a; inverts n2; tryfalse.
applys* red_spec_object_define_own_prop_5_b. case_if.
applys* red_spec_object_define_own_prop_6b_false_reject.
applys* red_spec_object_define_own_prop_6b_false_accept.
case_if. destruct a; tryfalse.
applys* red_spec_object_define_own_prop_5_c. case_if.
applys* red_spec_object_define_own_prop_6c_1.
applys* red_spec_object_define_own_prop_6c_2.
clear EQdef.
run.
applys* red_spec_object_define_own_prop.
applys* run_object_method_correct.
clear E. destruct x0. (* LTAC ARTHUR: This [x0] wasn't properly named. *)
(* default *)
applys* Def.
(* Array object *)
run red_spec_object_define_own_prop_array_1.
destruct a; [inverts HR | ]. destruct a; [ | inverts HR].
let_name. subst oldLen.
eapply red_spec_object_define_own_prop_array_2. reflexivity.
destruct (attributes_data_value a); [ | inverts HR].
let_name. let_name. subst descValueOpt.
eapply red_spec_object_define_own_prop_array_2_1. reflexivity.
eapply red_spec_to_uint32. apply red_spec_to_number_prim. reflexivity.
apply red_spec_to_uint32_1. rewrite <- EQoldLen.
case_if. subst x.
apply red_spec_object_define_own_prop_array_branch_3_4_3.
assert (Hyp : {v | descriptor_value Desc = Some v} + {descriptor_value Desc = None}).
{
destruct (descriptor_value Desc); [left | right]; auto. exists~ v.
} inverts Hyp as Hyp.
(* Step 3b *)
destruct Hyp as (v & EQv); rewrite EQv in *.
run~ red_spec_object_define_own_prop_array_3_3c; rename a0 into newLen.
run~ red_spec_object_define_own_prop_array_3c; rename m into newLenN.
case_if*. applys~ red_spec_object_define_own_prop_array_3d.
applys* run_error_correct. let_name.
applys~ red_spec_object_define_own_prop_array_3e.
clear dependent newLenN. case_if*.
subst; applys* red_spec_object_define_own_prop_array_3f.
case_if*. applys* red_spec_object_define_own_prop_array_3g.
applys~ red_spec_object_define_own_prop_array_3g_to_h.
rewrite <- EQnewLenDesc. let_name. let_name as newLenDesc'.
cases_if*; lets HnW : n1; rewrite EQnewWritable in n1.
apply red_spec_object_define_own_prop_array_3i.
destruct (descriptor_writable newLenDesc); jauto.
cases_if*. false~. clear n1 EQnewWritable. rewrite <- EQnewLenDesc'.
replace false with newWritable by (destruct newWritable; auto; false).
run* red_spec_object_define_own_prop_array_3j. destruct b; case_if*; clear n1.
apply red_spec_object_define_own_prop_array_to_3l.
applys* run_object_define_own_prop_array_loop_correct.
inverts HR. apply red_spec_object_define_own_prop_array_3k.
apply red_spec_object_define_own_prop_array_3h.
destruct (descriptor_writable newLenDesc); jauto.
cases_if*. clear n1 EQnewWritable. subst newLenDesc'.
replace true with newWritable by (destruct newWritable; auto; false).
run* red_spec_object_define_own_prop_array_3j. destruct b; case_if*; clear n1.
apply red_spec_object_define_own_prop_array_to_3l.
applys* run_object_define_own_prop_array_loop_correct.
inverts HR. applys* red_spec_object_define_own_prop_array_3k.
(* Step 3a *)
rewrite Hyp in HR. applys~ red_spec_object_define_own_prop_array_3_3a.
(* Branching between Step 4 and Step 5 *)
applys~ red_spec_object_define_own_prop_array_branch_3_4_4.
run red_spec_object_define_own_prop_array_branch_4_5.
run red_spec_object_define_own_prop_array_branch_4_5_a.
case_if. rename a0 into ilen, s into slen.
applys~ red_spec_object_define_own_prop_array_branch_4_5_b_4.
run red_spec_object_define_own_prop_array_4a.
case_if; rename a0 into index.
applys~ red_spec_object_define_own_prop_array_4b.
run~ red_spec_object_define_own_prop_array_4c.
destruct b; case_if*. case_if.
eapply red_spec_object_define_own_prop_array_4c_e. auto. reflexivity. auto.
run_inv. applys~ red_spec_object_define_own_prop_array_4f.
applys~ red_spec_object_define_own_prop_array_4c_d.
applys~ red_spec_object_define_own_prop_array_branch_4_5_b_5.
applys~ red_spec_object_define_own_prop_array_5.
(* arguments object *)
run. forwards~ obpm: run_object_method_correct (rm E).
run. subst. run~ red_spec_object_define_own_prop_args_obj.
run~ red_spec_object_define_own_prop_args_obj_1. cases_if; substs.
let_name. asserts Follow: (forall S o,
follow S = result_some (specret_out o) ->
red_expr S C spec_args_obj_define_own_prop_6 o).
introv RES. rewrite EQfollow in RES. inverts RES.
apply* red_spec_object_define_own_prop_args_obj_6.
clear EQfollow. destruct a as [|A]. (* LTAC ARTHUR: this [a] has been defined by tactics. *)
apply~ red_spec_object_define_own_prop_args_obj_2_true_undef.
cases_if.
run~ red_spec_object_define_own_prop_args_obj_2_true_acc.
apply* red_spec_object_define_own_prop_args_obj_5.
let_name as next. asserts Next: (forall S o,
next S = result_some (specret_out o) ->
red_expr S C (spec_args_obj_define_own_prop_4 l x Desc str x1) o).
introv RES. rewrite EQnext in RES. cases_if.
run~ red_spec_object_define_own_prop_args_obj_4_false.
apply~ red_spec_object_define_own_prop_args_obj_5.
apply~ red_spec_object_define_own_prop_args_obj_4_not_false.
clear EQnext. sets_eq <- dvDesc: (descriptor_value Desc). destruct dvDesc.
run~ red_spec_object_define_own_prop_args_obj_2_true_not_acc_some.
apply~ red_spec_object_define_own_prop_args_obj_3.
apply~ red_spec_object_define_own_prop_args_obj_2_true_not_acc_none.
apply~ red_spec_object_define_own_prop_args_obj_2_false.
Admitted. (* faster *)
Lemma prim_new_object_correct : forall S C w o,
prim_new_object S w = o ->
red_expr S C (spec_prim_new_object w) o.
Proof.
introv H. destruct w; tryfalse;
unfolds in H; repeat let_simpl;
match goal with H: context [object_alloc ?s ?o] |- _ => sets_eq X: (object_alloc s o) end;
destruct X as (l&S').
inversion H. applys* red_spec_prim_new_object_bool.
inversion H. applys* red_spec_prim_new_object_number.
run. applys* red_spec_prim_new_object_string.
apply pick_option_correct in E. auto.
Qed.
(* todo: move to the right place above here *)
Lemma to_object_correct : forall S C v o,
to_object S v = o ->
red_expr S C (spec_to_object v) o.
Proof.
hint run_error_correct_2, prim_new_object_correct.
introv HR. unfolds in HR. destruct v as [w|l].
destruct w.
applys* red_spec_to_object_undef_or_null.
applys* red_spec_to_object_undef_or_null.
applys* red_spec_to_object_prim. rew_logic*. splits; congruence.
applys* red_spec_to_object_prim. rew_logic*. splits; congruence.
applys* red_spec_to_object_prim. rew_logic*. splits; congruence.
run_inv. applys* red_spec_to_object_object.
Qed.
Lemma run_object_prim_value_correct : forall S l o,
run_object_prim_value S l = o ->
exists (v : value), o = out_ter S v /\
object_prim_value S l v.
Proof.
introv HR. unfolds in HR. do 2 runs. eexists. splits*.
forwards~: run_object_method_correct E.
Qed.
Lemma prim_value_get_correct : forall runs S C v x o,
runs_type_correct runs ->
prim_value_get runs S C v x = o ->
red_expr S C (spec_prim_value_get v x) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_prim_value_get using to_object_correct.
applys* red_spec_prim_value_get_1.
applys* object_get_builtin_correct.
Admitted. (*faster*)
Lemma object_put_complete_correct : forall runs S C B vthis l x v str o,
runs_type_correct runs ->
object_put_complete runs B S C vthis l x v str = o ->
red_expr S C (spec_object_put_1 B vthis l x v str) o.
Proof.
introv IH HR. unfolds in HR. destruct B.
run red_spec_object_put_1_default using object_can_put_correct. cases_if.
run red_spec_object_put_2_true. let_name.
asserts follows_correct: (forall Aa o,
a = full_descriptor_undef \/ (a = attributes_accessor_of Aa) ->
follow tt = res_out o ->
red_expr S0 C (spec_object_put_3 vthis l x v str (specret_val S2 a)) o).
clear HR. introv N E. substs.
run red_spec_object_put_3_not_data using run_object_get_prop_correct. apply* N.
clear N. tests Acc: (exists Aa', a0 = attributes_accessor_of Aa').
lets (Aa'&?): (rm Acc). let_simpl. substs.
sets_eq va': (attributes_accessor_set Aa'). destruct va' as [|la']; tryfalse.
run* red_spec_object_put_4_accessor. rewrite <- EQva'. discriminate.
apply~ red_spec_object_put_5_return.
let_name. asserts E': (follow' tt = o0).
destruct a0 as [|()]; try solve [false~ Acc]; exact E.
asserts (?&H'): (exists (Ad : attributes_data),
a0 = full_descriptor_undef \/ a0 = Ad).
destruct a0 as [|()]. exists* (arbitrary : attributes_data). exists* a0. false~ Acc.
clear E. substs. destruct vthis.
forwards (H&_): out_error_or_void_correct C (rm E').
applys* red_spec_object_put_4_not_accessor_prim H.
let_simpl. run* red_spec_object_put_4_not_accessor_object using
object_define_own_prop_correct. apply~ red_spec_object_put_5_return.
destruct a as [|[Ad|Aa]]. applys~ follows_correct (arbitrary : attributes_accessor).
clear EQfollow follow follows_correct.
destruct vthis as [wthis|lthis].
apply~ red_spec_object_put_3_data_prim. apply~ out_error_or_void_correct.
let_simpl. run* red_spec_object_put_3_data_object
using object_define_own_prop_correct. apply~ red_spec_object_put_5_return.
apply~ follows_correct.
apply~ red_spec_object_put_2_false. apply~ out_error_or_void_correct.
Qed.
Lemma prim_value_put_correct : forall runs S C w x v str o,
runs_type_correct runs ->
prim_value_put runs S C w x v str = o ->
red_expr S C (spec_prim_value_put w x v str) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_prim_value_put using to_object_correct.
applys* red_spec_prim_value_put_1.
applys* object_put_complete_correct.
Qed.
(*************************************************************)
Lemma env_record_get_binding_value_correct : forall runs S C L rn rs o,
runs_type_correct runs ->
env_record_get_binding_value runs S C L rn rs = o ->
red_expr S C (spec_env_record_get_binding_value L rn rs) o.
Proof.
introv IH HR. unfolds in HR.
run_simpl. forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_get_binding_value B. destruct x.
run_simpl. rewrite <- Heap.binds_equiv_read_option in E. destruct x as [mu v].
cases_if.
applys~ red_spec_env_record_get_binding_value_1_decl_uninitialized E.
apply~ out_error_or_cst_correct.
applys~ red_spec_env_record_get_binding_value_1_decl_initialized E.
run_inv. apply~ red_spec_returns.
run red_spec_env_record_get_binding_value_1_object using object_has_prop_correct.
cases_if; run_inv.
apply~ red_spec_env_record_get_binding_value_obj_2_true.
applys~ run_object_get_correct HR.
apply~ red_spec_env_record_get_binding_value_obj_2_false.
applys~ out_error_or_cst_correct HR.
Qed.
Lemma throw_result_run_error_correct : forall runs S C ne T (y:specret T),
runs_type_correct runs ->
throw_result (run_error S ne) = result_some y ->
red_spec S C (spec_error_spec ne) y.
Proof.
introv IH HR. unfolds throw_result.
lets ([|y1]&E&K): if_result_some_out (rm HR); tryfalse_nothing. run_inv.
lets (E2&Ab): run_error_correct' (rm E).
applys* red_spec_error_spec.
abort.
Qed.
Lemma ref_kind_env_record_inv : forall r,
ref_kind_of r = ref_kind_env_record ->
exists L, ref_base r = ref_base_type_env_loc L.
Proof.
introv E. unfolds ref_kind_of.
destruct (ref_base r).
destruct v; tryfalse. destruct p; tryfalse.
exists___*.
Qed.
Lemma ref_kind_base_object_inv : forall r,
(ref_kind_of r = ref_kind_primitive_base \/
ref_kind_of r = ref_kind_object) ->
exists v, ref_base r = ref_base_type_value v.
Proof.
introv E. unfolds ref_kind_of.
destruct E; destruct (ref_base r); tryfalse;
destruct v; tryfalse; try solve [exists___*].
Qed.
Lemma ref_get_value_correct : forall runs S C rv y,
runs_type_correct runs ->
ref_get_value runs S C rv = result_some y ->
red_spec S C (spec_get_value rv) y.
Proof.
introv IH HR. unfolds in HR. destruct rv; tryfalse.
run_inv. applys* red_spec_ref_get_value_value.
let_name as M.
asserts M_correct: (
( ref_kind_of r = ref_kind_primitive_base
\/ ref_kind_of r = ref_kind_object) ->
M tt = result_some y ->
red_spec S C (spec_get_value r) y).
clear HR. introv EQ HR. subst M.
asserts: (ref_is_property r). unfolds. destruct* EQ.
lets (v&Ev): ref_kind_base_object_inv EQ. rewrite Ev in HR.
unfolds ref_has_primitive_base. case_if.
run* red_spec_ref_get_value_ref_b_has_primitive_base using prim_value_get_correct.
applys* red_spec_ref_get_value_ref_b_1.
destruct EQ; tryfalse. destruct v as [|l]; tryfalse.
run* red_spec_ref_get_value_ref_b_has_not_primitive_base using run_object_get_correct.
applys* red_spec_ref_get_value_ref_b_1.
clear EQM.
sets_eq k: (ref_kind_of r). destruct k; tryfalse.
(* case undef *)
applys* red_spec_ref_get_value_ref_a. unfolds*.
applys* throw_result_run_error_correct.
(* case prim *)
applys* M_correct.
(* case object *)
applys* M_correct.
(* case env_record *)
lets (L&EQL): ref_kind_env_record_inv (sym_eq EQk).
rewrite EQL in HR.
run* red_spec_ref_get_value_ref_c using env_record_get_binding_value_correct.
applys* red_spec_ref_get_value_ref_c_1.
Admitted. (*faster*)
Lemma object_put_correct : forall runs S C l x v str o,
runs_type_correct runs ->
object_put runs S C l x v str = o ->
red_expr S C (spec_object_put l x v str) o.
Proof.
introv IH HR. unfolds in HR.
run. applys red_spec_object_put. apply* run_object_method_correct.
applys* object_put_complete_correct.
Admitted. (*faster*)
Lemma env_record_set_mutable_binding_correct : forall runs S C L x v str o,
runs_type_correct runs ->
env_record_set_mutable_binding runs S C L x v str = o ->
red_expr S C (spec_env_record_set_mutable_binding L x v str) o.
Proof.
introv IH HR. unfolds in HR.
run_simpl. forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_set_mutable_binding B. destruct x0.
run_simpl. rewrite <- Heap.binds_equiv_read_option in E. destruct x0 as [mu ?].
cases_if; run_inv.
applys~ red_spec_env_record_set_mutable_binding_1_decl_mutable E.
apply~ red_spec_returns.
applys~ red_spec_env_record_set_mutable_binding_1_decl_non_mutable E.
apply~ out_error_or_void_correct.
apply~ red_spec_env_record_set_mutable_binding_1_object.
applys~ object_put_correct HR.
Qed.
Lemma ref_is_property_from_not_unresolvable_value : forall r v,
~ ref_is_unresolvable r ->
ref_base r = ref_base_type_value v ->
ref_is_property r.
Proof.
introv N E. unfolds ref_is_property, ref_is_unresolvable, ref_kind_of.
destruct (ref_base r); tryfalse. destruct* v0. destruct* p.
Admitted. (* faster *)
Lemma ref_put_value_correct : forall runs S C rv v o,
runs_type_correct runs ->
ref_put_value runs S C rv v = o ->
red_expr S C (spec_put_value rv v) o.
Proof.
introv IH HR. unfolds in HR.
destruct rv; tryfalse.
applys* red_spec_ref_put_value_value.
case_if.
case_if.
applys~ red_spec_ref_put_value_ref_a_1.
applys* run_error_correct.
applys~ red_spec_ref_put_value_ref_a_2.
applys* object_put_correct.
case_if.
cases (ref_base r); tryfalse.
case_if; destruct v0; tryfalse.
applys* red_spec_ref_put_value_ref_b_has_primitive_base.
applys* prim_value_put_correct.
applys* red_spec_ref_put_value_ref_b_has_not_primitive_base.
applys* object_put_correct.
cases (ref_base r); tryfalse.
applys* red_spec_ref_put_value_ref_c.
applys* env_record_set_mutable_binding_correct.
Admitted. (* faster *)
Lemma run_expr_get_value_correct : forall runs S C e y,
runs_type_correct runs ->
run_expr_get_value runs S C e = result_some y ->
red_spec S C (spec_expr_get_value e) y.
Proof.
introv IH HR. unfolds in HR.
run red_spec_expr_get_value.
applys* red_spec_expr_get_value_1.
applys* ref_get_value_correct.
Admitted. (* faster *)
Ltac run_select_proj_extra_ref HT ::=
match HT with
| object_put => constr:(object_put_correct)
| ref_put_value => constr:(ref_put_value_correct)
| run_expr_get_value => constr:(run_expr_get_value_correct)
| object_define_own_prop => constr:(object_define_own_prop_correct)
end.
Lemma env_record_create_mutable_binding_correct : forall runs S C L x deletable_opt o,
runs_type_correct runs ->
env_record_create_mutable_binding runs S C L x deletable_opt = o ->
red_expr S C (spec_env_record_create_mutable_binding L x deletable_opt) o.
Proof.
introv IH HR. unfolds in HR. let_simpl.
run_simpl. forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_create_mutable_binding B.
destruct x0.
cases_if; run_inv. let_simpl. run_inv.
apply~ red_spec_env_record_create_mutable_binding_1_decl_indom.
run red_spec_env_record_create_mutable_binding_1_object
using object_has_prop_correct. cases_if. let_simpl.
run* red_spec_env_record_create_mutable_binding_obj_2.
apply~ red_spec_env_record_create_mutable_binding_obj_3.
Qed.
Lemma env_record_create_set_mutable_binding_correct : forall runs S C L x deletable_opt v str o,
runs_type_correct runs ->
env_record_create_set_mutable_binding runs S C L x deletable_opt v str = o ->
red_expr S C (spec_env_record_create_set_mutable_binding L x deletable_opt v str) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_env_record_create_set_mutable_binding
using env_record_create_mutable_binding_correct.
forwards: env_record_set_mutable_binding_correct IH (rm HR).
apply~ red_spec_env_record_create_set_mutable_binding_1.
Qed.
Lemma env_record_create_immutable_binding_correct : forall S C L x o,
env_record_create_immutable_binding S L x = o ->
red_expr S C (spec_env_record_create_immutable_binding L x) o.
Proof.
introv HR. unfolds in HR.
run_simpl. forwards B: @pick_option_correct (rm E).
destruct x0; tryfalse. cases_if. run_inv.
applys~ red_spec_env_record_create_immutable_binding B.
Qed.
Lemma env_record_initialize_immutable_binding_correct : forall S C L x v o,
env_record_initialize_immutable_binding S L x v = o ->
red_expr S C (spec_env_record_initialize_immutable_binding L x v) o.
Proof.
introv HR. unfolds in HR.
run. forwards B: @pick_option_correct (rm E). destruct x0; tryfalse.
run. forwards B': @pick_option_correct (rm E). cases_if. let_simpl. run_inv. substs.
applys~ red_spec_env_record_initialize_immutable_binding B B'.
Qed.
(************************************************************)
(* Treatement of [spec_expr_get_value_conv] *)
Definition if_spec_ter_post_bool (K:state->bool->result) o (y:specret value) :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (b:bool), y = specret_val S (value_prim b)
/\ K S b = o).
Ltac run_post_if_spec_ter_post_bool H := (* todo: integrate into run_post *)
let Ab := fresh "Ab" in
let Eq := fresh "Eq" in
let S1 := fresh "S" in
let b := fresh "b" in
let O1 := fresh "O1" in
destruct H as [(Er&Ab)|(S1&b&O1&H)];
[ try abort | try subst_hyp O1 ].
Lemma if_spec_post_to_bool : forall (K:state->bool->result) S C e o y1,
red_spec S C (spec_expr_get_value e) y1 ->
if_spec_post
(fun S v => 'let b := convert_value_to_boolean v in K S b) (specret_out o) y1 ->
exists y2,
red_spec S C (spec_expr_get_value_conv spec_to_boolean e) y2
/\ if_spec_ter_post_bool K o y2.
Proof.
introv HR HP. run_post.
exists y1. splits.
subst. apply* red_spec_expr_get_value_conv. abort.
subst. left. splits; run_inv; auto~.
exists (specret_val S1 (value_prim (convert_value_to_boolean a))). splits.
applys* red_spec_expr_get_value_conv.
applys* red_spec_expr_get_value_conv_1.
applys* red_spec_to_boolean.
applys* red_spec_expr_get_value_conv_2.
right. exists S1 __. split. reflexivity. auto.
Qed.
(* LATER: avoid the copy-paste, and rename the tactic *)
Definition if_spec_ter_post_object (K:state->object_loc->result) o (y:specret value) :=
(y = specret_out o /\ abort o)
\/ (exists S, exists (l:object_loc), y = specret_val S (value_object l)
/\ K S l = o).
Lemma if_spec_post_to_object : forall (K:state->object_loc->result) S C e o y1,
red_spec S C (spec_expr_get_value e) y1 ->
if_spec_post
(fun S v => if_object (to_object S v) K) (specret_out o) y1 ->
exists y2,
red_spec S C (spec_expr_get_value_conv spec_to_object e) y2
/\ if_spec_ter_post_object K o y2.
Proof.
introv HR HP. run_post.
exists y1. splits.
subst. apply* red_spec_expr_get_value_conv. abort.
subst. left. splits; run_inv; auto~.
run_pre. lets*: to_object_correct C (rm R1). run_post.
subst. exists (specret_out (T:=value) o1). split.
applys* red_spec_expr_get_value_conv.
applys* red_spec_expr_get_value_conv_1. abort.
left. splits~.
exists (specret_val S0 (value_object l)). split.
applys* red_spec_expr_get_value_conv.
applys* red_spec_expr_get_value_conv_1.
applys* red_spec_expr_get_value_conv_2.
right. exists___*.
Qed.
Definition lift2 T (C:T->value) y :=
match y with
| specret_val S' (x1,x2) => specret_val S' (C x1, C x2)
| specret_out o => specret_out o
end.
Lemma convert_twice_primitive_correct : forall runs S C v1 v2 y,
runs_type_correct runs ->
convert_twice_primitive runs S C v1 v2 = result_some y ->
red_spec S C (spec_convert_twice (spec_to_primitive_auto v1) (spec_to_primitive_auto v2)) (lift2 value_prim y).
Proof.
introv IH HR. unfolds in HR. unfolds in HR.
run red_spec_convert_twice.
run red_spec_convert_twice_1.
unfolds lift2. applys red_spec_convert_twice_2.
Admitted. (*faster*)
Lemma convert_twice_number_correct : forall runs S C v1 v2 y,
runs_type_correct runs ->
convert_twice_number runs S C v1 v2 = result_some y ->
red_spec S C (spec_convert_twice (spec_to_number v1) (spec_to_number v2)) (lift2 (fun n=>n:value) y).
Proof.
introv IH HR. unfolds in HR. unfolds in HR.
run red_spec_convert_twice.
run red_spec_convert_twice_1.
unfolds lift2. applys red_spec_convert_twice_2.
Admitted. (*faster*)
Lemma convert_twice_string_correct : forall runs S C v1 v2 y,
runs_type_correct runs ->
convert_twice_string runs S C v1 v2 = result_some y ->
red_spec S C (spec_convert_twice (spec_to_string v1) (spec_to_string v2)) (lift2 (fun s=>s:value) y).
Proof.
introv IH HR. unfolds in HR. unfolds in HR.
run red_spec_convert_twice.
run red_spec_convert_twice_1.
unfolds lift2. applys red_spec_convert_twice_2.
Admitted. (*faster*)
Lemma get_puremath_op_correct : forall op F,
get_puremath_op op = Some F ->
puremath_op op F.
Proof.
Hint Constructors puremath_op.
introv HR. destruct op; simpls; inverts* HR.
Admitted. (*faster*)
Lemma get_inequality_op_correct : forall op b1 b2,
get_inequality_op op = Some (b1,b2) ->
inequality_op op b1 b2.
Proof.
Hint Constructors inequality_op.
introv HR. destruct op; simpls; inverts* HR.
Admitted. (*faster*)
Lemma get_shift_op_correct : forall op F b,
get_shift_op op = Some (b,F) ->
shift_op op b F.
Proof.
Hint Constructors shift_op.
introv HR. destruct op; simpls; inverts* HR.
Admitted. (*faster*)
Lemma get_bitwise_op_correct : forall op F,
get_bitwise_op op = Some F ->
bitwise_op op F.
Proof.
Hint Constructors bitwise_op.
introv HR. destruct op; simpls; inverts* HR.
Admitted. (*faster*)
(**************************************************************)
Lemma run_object_get_own_prop_correct : forall runs S C l x y,
runs_type_correct runs ->
run_object_get_own_prop runs S C l x = result_some y ->
red_spec S C (spec_object_get_own_prop l x) y.
Proof.
introv IH HR. unfolds in HR. run.
applys* red_spec_object_get_own_prop.
applys* run_object_method_correct. clear E.
let_name as M. asserts M_correct: (forall S y,
M S = result_some y ->
red_spec S C (spec_object_get_own_prop_1 builtin_get_own_prop_default l x) y).
clears HR S. subst. introv HR. run.
sets_eq <- Ao: (Heap.read_option x1 x).
applys~ red_spec_object_get_own_prop_1_default. eexists. splits.
applys run_object_method_correct E.
rewrite~ EQAo.
clear E. destruct Ao.
applys* red_spec_object_get_own_prop_2_some_data.
applys* red_spec_object_get_own_prop_2_none.
clear EQM.
destruct x0.
(* default *)
subst*.
(* argument object *)
run~ red_spec_object_get_own_prop_args_obj. destruct a as [|A]. (* LTAC ARTHUR: this [a] has been defined by tactics. *)
inverts HR. applys~ red_spec_object_get_own_prop_args_obj_1_undef.
run. forwards~ obpm: run_object_method_correct (rm E).
run. subst. run~ red_spec_object_get_own_prop_args_obj_1_attrs.
let_name. asserts Follow: (forall S A y,
follow S A = result_some y ->
red_spec S C (spec_args_obj_get_own_prop_4 A) y).
introv RES. rewrite EQfollow in RES. inverts RES.
apply~ red_spec_object_get_own_prop_args_obj_4.
clear EQfollow. destruct a. (* LTAC ARTHUR: idem. *)
apply* red_spec_object_get_own_prop_args_obj_2_undef.
run~ red_spec_object_get_own_prop_args_obj_2_attrs using run_object_get_correct.
destruct A as [Ad|]; tryfalse.
apply~ red_spec_object_get_own_prop_args_obj_3.
(* string *)
run~ red_spec_object_get_own_prop_string. destruct a as [|A]. (* LTAC ARTHUR: this [a] has been defined by tactics. *)
run red_spec_object_get_own_prop_string_1_undef using to_int32_correct.
run red_spec_object_get_own_prop_string_2.
cases_if.
inverts HR. apply~ red_spec_object_get_own_prop_string_3_different.
subst x. run_pre. forwards* (v&EQo&Opv): run_object_prim_value_correct. run_post.
inverts Ab as Ab'; false. inverts H0. false Ab'. reflexivity.
inverts EQo. applys~ red_spec_object_get_own_prop_string_3_same Opv.
run~ red_spec_object_get_own_prop_string_4.
let_name. apply~ red_spec_object_get_own_prop_string_5. cases_if.
inverts HR. apply~ red_spec_object_get_own_prop_string_6_outofbounds. math.
inverts HR. apply~ red_spec_object_get_own_prop_string_6_inbounds. math.
inverts HR. apply~ red_spec_object_get_own_prop_string_1_attrs.
Admitted. (*faster*)
Lemma run_function_has_instance_correct : forall runs S C (lo lv : object_loc) o,
runs_type_correct runs ->
run_function_has_instance runs S lo lv = o ->
red_expr S C (spec_function_has_instance_2 lv lo) o.
Proof.
intros runs IH lo S C lv o HR. unfolds in HR. run_simpl.
forwards~ M: run_object_method_correct (rm E).
applys~ red_spec_function_has_instance_2 M.
destruct x as [()|lproto]; tryfalse; run_inv.
apply~ red_spec_function_has_instance_3_null.
cases_if; run_inv.
apply~ red_spec_function_has_instance_3_eq.
apply~ red_spec_function_has_instance_3_neq.
applys~ runs_type_correct_function_has_instance HR.
Qed.
Lemma run_object_has_instance_correct : forall runs S C B l v o,
runs_type_correct runs ->
run_object_has_instance runs S C B l v = result_some (specret_out o) ->
red_expr S C (spec_object_has_instance_1 B l v) o.
Proof.
introv IH HR. unfolds in HR. destruct B.
destruct v.
run_inv. applys* red_spec_object_has_instance_1_function_prim.
run red_spec_object_has_instance_1_function_object
using run_object_get_correct.
destruct v.
applys* red_spec_function_has_instance_1_prim.
applys red_spec_function_has_instance_1_object.
applys* runs_type_correct_function_has_instance.
repeat run; apply run_object_method_correct in E;
apply run_object_method_correct in E1; subst.
apply red_spec_object_has_instance_after_bind.
applys~ red_spec_function_has_instance_after_bind_1. eassumption.
destruct x1. applys* red_spec_function_has_instance_after_bind_2_some.
applys* runs_type_correct_object_has_instance.
applys* red_spec_function_has_instance_after_bind_2_none.
Admitted. (* faster*)
Lemma run_binary_op_correct : forall runs S C (op : binary_op) v1 v2 o,
runs_type_correct runs ->
run_binary_op runs S C op v1 v2 = o ->
red_expr S C (expr_binary_op_3 op v1 v2) o.
Proof.
introv IH HR. unfolds in HR.
(* Add *)
case_if. subst.
run red_expr_binary_op_add using convert_twice_primitive_correct.
destruct a as [w1 w2]. case_if.
run* red_expr_binary_op_add_1_string using convert_twice_string_correct.
destruct a as [s1 s2]. run_inv.
applys* red_expr_binary_op_add_string_1.
run* red_expr_binary_op_add_1_number using convert_twice_number_correct.
destruct a as [n1 n2]. run_inv.
applys* red_expr_puremath_op_1.
(* Puremath *)
case_if. run.
run red_expr_puremath_op using convert_twice_number_correct.
applys* get_puremath_op_correct.
destruct a as [n1 n2]. run_inv.
applys* red_expr_puremath_op_1.
(* Shiftop *)
case_if. run. destruct x as [b F].
lets M: red_expr_shift_op b. case_if; subst.
run* M. applys* get_shift_op_correct.
run red_expr_shift_op_1. applys* red_expr_shift_op_2.
run* M. applys* get_shift_op_correct.
run red_expr_shift_op_1. applys* red_expr_shift_op_2.
(* bitwise *)
case_if. run.
run red_expr_bitwise_op. applys* get_bitwise_op_correct.
run red_expr_bitwise_op_1. applys* red_expr_bitwise_op_2.
(* inequality *)
clear n H H0 H1.
case_if. run. destruct x as [b1 b2].
applys red_expr_inequality_op. applys* get_inequality_op_correct.
run red_expr_inequality_op_1 using convert_twice_primitive_correct.
destruct a as [w1 w2]. let_name. destruct p as [wa wb]. simpls.
sets_eq wr: (inequality_test_primitive wa wb).
run_inv. applys_eq* (>> red_expr_inequality_op_2 EQp EQwr) 1.
fequals. case_if; case_if; case_if*; case_if*; case_if*; case_if*; case_if*; case_if*.
(* instanceof *)
case_if. subst.
destruct v2.
applys* red_expr_binary_op_instanceof_non_object.
run. lets M: run_object_method_correct (rm E).
destruct x.
applys* red_expr_binary_op_instanceof_normal.
simpls.
applys* red_spec_object_has_instance.
applys* run_object_has_instance_correct.
applys* red_expr_binary_op_instanceof_non_instance.
(* in *)
case_if. subst. destruct v2.
applys* red_expr_binary_op_in_non_object.
run red_expr_binary_op_in_object.
applys* red_expr_binary_op_in_1.
applys* object_has_prop_correct.
(* equal *)
clear n n0 H. case_if. subst.
applys* red_expr_binary_op_equal.
applys* runs_type_correct_equal.
(* disequal *)
case_if. subst.
run red_expr_binary_op_disequal.
applys* red_expr_binary_op_disequal_1.
(* strict equality *)
case_if. subst.
run_inv. applys* red_expr_binary_op_strict_equal.
(* strict disequality *)
case_if. subst.
run_inv. applys* red_expr_binary_op_strict_disequal.
(* coma *)
case_if. subst.
run_inv. applys* red_expr_binary_op_coma.
Admitted. (*faster*)
(**************************************************************)
(* Auxiliary results for [array_args_map_loop] *)
Lemma array_args_map_loop_no_abort : forall oes runs S o l C k,
array_args_map_loop runs S C l oes k = o -> exists S', o = out_ter S' res_empty.
Proof.
inductions oes; introv Hyp.
+ simpls. exists S. inverts~ Hyp.
+ simpls. run. eapply IHoes; eassumption.
Qed.
Lemma array_args_map_loop_correct : forall oes runs S S' l C k,
array_args_map_loop runs S C l oes k = res_void S' ->
red_expr S C (spec_call_array_new_3 l oes k) (out_ter S' l).
Proof.
induction oes; introv Hyp.
+ simpls. inverts Hyp. apply red_spec_call_array_new_3_empty.
+ simpls. unfolds res_void. run. rename x into S''.
apply pick_option_correct in E.
applys~ red_spec_call_array_new_3_nonempty. exact E.
jauto.
Qed.
(**************************************************************)
(* Auxiliary results for [spec_expr_get_value_conv] *)
Lemma run_construct_prealloc_correct : forall runs S C B args o,
runs_type_correct runs ->
run_construct_prealloc runs S C B args = o ->
red_expr S C (spec_construct_prealloc B args) o.
Proof.
introv IH HR. unfolds in HR.
destruct B.
(* prealloc_global *)
discriminate.
(* prealloc_global_eval *)
discriminate.
(* prealloc_global_parse_int *)
discriminate.
(* prealloc_global_parse_float *)
discriminate.
(* prealloc_global_is_finite *)
discriminate.
(* prealloc_global_is_nan *)
discriminate.
(* prealloc_global_decode_uri *)
discriminate.
(* prealloc_global_decode_uri_component *)
discriminate.
(* prealloc_global_encode_uri *)
discriminate.
(* prealloc_global_encode_uri_component *)
discriminate.
(* prealloc_object *)
let_name. subst.
applys* red_spec_call_object_new.
applys* get_arg_correct_0.
destruct (get_arg 0 args) as [p | l]; unfolds call_object_new; [destruct p | ]; simpls; repeat let_name; try destruct p as (l & S'); substs.
inverts HR. applys* red_spec_call_object_new_1_null_or_undef.
inverts HR. applys* red_spec_call_object_new_1_null_or_undef.
applys* red_spec_call_object_new_1_prim.
applys* to_object_correct.
applys* red_spec_call_object_new_1_prim.
applys* to_object_correct.
applys* red_spec_call_object_new_1_prim.
applys* to_object_correct.
inverts HR. applys* red_spec_call_object_new_1_object.
(* prealloc_object_get_proto_of *)
discriminate.
(* prealloc_object_get_own_prop_descriptor *)
discriminate.
(* prealloc_object_get_own_prop_name *)
discriminate.
(* prealloc_object_create *)
discriminate.
(* prealloc_object_define_prop *)
discriminate.
(* prealloc_object_define_props *)
discriminate.
(* prealloc_object_seal *)
discriminate.
(* prealloc_object_freeze *)
discriminate.
(* prealloc_object_prevent_extensions *)
discriminate.
(* prealloc_object_is_sealed *)
discriminate.
(* prealloc_object_is_frozen *)
discriminate.
(* prealloc_object_is_extensible *)
discriminate.
(* prealloc_object_keys *)
discriminate.
(* prealloc_object_keys_call *)
discriminate.
(* prealloc_object_proto *)
discriminate.
(* prealloc_object_proto_to_string *)
discriminate.
(* prealloc_object_proto_value_of *)
discriminate.
(* prealloc_object_proto_has_own_prop *)
discriminate.
(* prealloc_object_proto_is_prototype_of *)
discriminate.
(* prealloc_object_proto_prop_is_enumerable *)
discriminate.
(* prealloc_function *)
discriminate. (* LATER *)
(* prealloc_function_proto *)
discriminate.
(* prealloc_function_proto_to_string *)
discriminate.
(* prealloc_function_proto_apply *)
discriminate.
(* prealloc_function_proto_call *)
discriminate.
(* prealloc_function_proto_bind *)
discriminate.
(* prealloc_bool *)
repeat let_name.
applys* red_spec_construct_bool.
apply get_arg_correct_0.
applys* red_spec_to_boolean.
destruct p as (l & S').
inverts HR.
applys* red_spec_construct_bool_1.
substs~.
(* prealloc_bool_proto *)
discriminate.
(* prealloc_bool_proto_to_string *)
discriminate.
(* prealloc_bool_proto_value_of *)
discriminate.
(* prealloc_number *)
let_name. cases_if*.
subst. repeat let_name.
remember (object_alloc S O) as p.
destruct p as (l & S1).
inverts HR.
applys* red_spec_construct_number_nil.
applys* red_spec_construct_number_1. substs~.
let_name. subst.
run~ red_spec_construct_number_not_nil.
applys~ get_arg_correct_0.
repeat let_name.
remember (object_alloc S0 O) as p.
destruct p as (l & S1).
inverts HR.
applys* red_spec_construct_number_1.
substs~.
(* prealloc_number_proto *)
discriminate.
(* prealloc_number_proto_to_string *)
discriminate.
(* prealloc_number_proto_value_of *)
discriminate.
(* prealloc_number_proto_to_fixed *)
discriminate.
(* prealloc_number_proto_to_exponential *)
discriminate.
(* prealloc_number_proto_to_precision *)
discriminate.
(* prealloc_array *)
repeat let_name. destruct p as (l & S'). repeat let_name.
subst arg_len. destruct args. case_if*.
applys~ red_spec_call_array_new_no_args.
eapply red_spec_call_array_new_1; try eassumption.
run. apply pick_option_correct in E.
applys* red_spec_call_array_new_2.
simpls. run. apply red_spec_call_array_new_3_empty.
destruct args. case_if*. clear e.
unfolds get_arg. unfolds nth_def. subst v.
applys~ red_spec_call_array_new_single_arg.
applys~ red_spec_call_array_new_single_allocate; try (subst; eassumption).
destruct v0; [destruct p | ]; subst;
try solve [run; rename x into S''; run; rename x into S'''; apply pick_option_correct in E; apply pick_option_correct in E0;
apply (red_spec_call_array_new_single_not_prim_number S' S'') with (n := JsNumber.of_int 0); jauto;
introv Heq; inverts Heq].
run~ red_spec_call_array_new_single_prim_number. cases_if*.
run; rename x into S''; apply pick_option_correct in E.
applys~ red_spec_call_array_new_single_number_correct.
applys~ red_spec_call_array_new_single_set_length.
applys~ red_spec_call_array_new_single_number_incorrect.
applys run_error_correct HR.
cases_if*. eapply red_spec_call_array_new_multiple_args. reflexivity.
eapply red_spec_call_array_new_1; try eassumption.
run. apply pick_option_correct in E.
applys* red_spec_call_array_new_2.
remember (v1 :: args) as args'; clear dependent v1.
run_pre. run_post; subst.
apply array_args_map_loop_no_abort in R1.
destruct R1 as (S'' & Heq_o'). subst. inverts Ab.
false~ H0. inverts HR.
eapply array_args_map_loop_correct. eassumption.
(* prealloc_array_is_array *)
discriminate.
(* prealloc_array_proto *)
discriminate.
(* prealloc_array_proto_to_string *)
discriminate.
(* prealloc_array_proto_join *)
discriminate.
(* prealloc_array_proto_pop *)
discriminate.
(* prealloc_array_proto_push *)
discriminate.
(* prealloc_string *)
repeat let_name.
cases_if*. subst.
symmetry in EQarg_len. apply length_zero_inv in EQarg_len. subst.
apply red_spec_construct_string_empty.
let_name.
match goal with H: context [object_alloc ?s ?o] |- _ => sets_eq X: (object_alloc s o) end.
destruct X as (l & S'). let_name. subst.
run. rename x into S''. apply pick_option_correct in E.
remember (object_with_primitive_value
(object_with_get_own_property
(object_new prealloc_string_proto "String")
builtin_get_own_prop_string) "") as O.
applys* red_spec_construct_string_2; substs~.
applys* red_spec_construct_string_non_empty.
subst. destruct args; jauto; discriminate.
apply get_arg_correct_0. subst.
run red_spec_construct_string_1 using to_string_correct.
let_name.
match goal with H: context [object_alloc ?s ?o] |- _ => sets_eq X: (object_alloc s o) end.
destruct X as (l & S'). let_name. subst.
run. rename x into S''. apply pick_option_correct in E.
remember (object_with_primitive_value
(object_with_get_own_property
(object_new prealloc_string_proto "String")
builtin_get_own_prop_string) "") as O.
applys* red_spec_construct_string_2; substs~.
(* prealloc_string_proto *)
discriminate.
(* prealloc_string_proto_to_string *)
discriminate.
(* prealloc_string_proto_value_of *)
discriminate.
(* prealloc_string_proto_char_at *)
discriminate.
(* prealloc_string_proto_char_code_at *)
discriminate.
(* prealloc_math *)
discriminate.
(* prealloc_mathop *)
discriminate.
(* prealloc_date *)
discriminate.
(* prealloc_regexp *)
discriminate.
(* prealloc_error *)
let_name. apply~ red_spec_construct_error.
apply~ get_arg_correct_0.
substs. apply* build_error_correct.
(* prealloc_error_proto *)
discriminate.
(* prealloc_native_error *)
let_name. apply~ red_spec_construct_native_error.
apply~ get_arg_correct_0.
substs. apply* build_error_correct.
(* prealloc_native_error_proto *)
discriminate. (* TODO *)
(* prealloc_error_proto_to_string *)
discriminate.
(* prealloc_throw_type_error *)
discriminate.
(* prealloc_json *)
discriminate.
Admitted. (*faster*)
Lemma run_construct_default_correct : forall runs S C l args o,
runs_type_correct runs ->
run_construct_default runs S C l args = res_out o ->
red_expr S C (spec_construct_default l args) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_construct_default using run_object_get_correct.
let_simpl. let_simpl. let_name. destruct p as [l' S2].
run* red_spec_construct_default_1. rewrite* EQp. case_if; case_if*.
let_simpl. run_inv.
applys* red_spec_function_construct_2. case_if; case_if*.
Admitted. (*faster*)
Lemma run_construct_correct : forall runs S C co l args o,
runs_type_correct runs ->
run_construct runs S C co l args = o ->
red_expr S C (spec_construct_1 co l args) o.
Proof.
introv IH HR. unfolds in HR.
destruct co.
applys* red_spec_construct_1_default. applys* run_construct_default_correct.
repeat run. apply run_object_method_correct in E.
apply run_object_method_correct in E1; subst.
applys* red_spec_construct_1_after_bind.
destruct x1. repeat run. let_name.
apply run_object_method_correct in E0; subst.
applys* red_spec_construct_1_after_bind_1_some.
applys* runs_type_correct_construct.
applys* red_spec_construct_1_after_bind_1_none.
applys* red_spec_construct_1_prealloc. applys* run_construct_prealloc_correct.
Admitted. (* faster *)
Lemma creating_function_object_proto_correct : forall runs S C l o,
runs_type_correct runs ->
creating_function_object_proto runs S C l = o ->
red_expr S C (spec_creating_function_object_proto l) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_creating_function_object_proto
using run_construct_prealloc_correct.
let_simpl. run red_spec_creating_function_object_proto_1.
let_simpl. applys* red_spec_creating_function_object_proto_2. run_hyp*.
Admitted. (* faster *)
Lemma creating_function_object_correct : forall runs S C names bd X str o,
runs_type_correct runs ->
creating_function_object runs S C names bd X str = o ->
red_expr S C (spec_creating_function_object names bd X str) o.
Proof.
introv IH HR. unfolds in HR.
let_simpl. let_simpl. let_simpl. let_simpl. let_name. destruct p as [l S1].
let_simpl. run* red_spec_creating_function_object.
run red_spec_creating_function_object_1
using creating_function_object_proto_correct.
case_if; destruct str; tryfalse.
run_inv. applys* red_spec_creating_function_object_2_not_strict.
let_simpl. let_simpl.
run* red_spec_creating_function_object_2_strict. clear EQp.
run* red_spec_creating_function_object_3.
applys* red_spec_creating_function_object_4.
Admitted. (* faster*)
Lemma env_record_has_binding_correct : forall runs S C L x o,
runs_type_correct runs ->
env_record_has_binding runs S C L x = o ->
red_expr S C (spec_env_record_has_binding L x) o.
Proof.
introv IH HR. unfolds in HR. run_simpl.
forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_has_binding B. destruct x0; run_inv.
apply~ red_spec_env_record_has_binding_1_decl.
rewrite decide_def; auto.
apply~ red_spec_env_record_has_binding_1_object.
apply* object_has_prop_correct.
Qed.
Lemma binding_inst_function_decls_correct : forall runs S C args L fds str bconfig o,
runs_type_correct runs ->
binding_inst_function_decls runs S C L fds str bconfig = o ->
red_expr S C (spec_binding_inst_function_decls args L fds str bconfig) o.
Proof.
introv IH HR. gen S o. induction fds; introv HR.
simpls. run_inv. applys* red_spec_binding_inst_function_decls_nil.
simpls. let_name. let_name. let_name. let_name.
run (@red_spec_binding_inst_function_decls_cons str_fd)
using creating_function_object_correct. subst*. subst*. clear R1.
let_name as M. rename a into fd. rename l into fo.
asserts M_correct: (forall S o,
M S = o ->
red_expr S C (spec_binding_inst_function_decls_5 args L fd fds str fo bconfig) o).
clears HR S o. introv HR. subst M.
subst fname. run red_spec_binding_inst_function_decls_5
using env_record_set_mutable_binding_correct.
applys* red_spec_binding_inst_function_decls_6.
clear EQM.
subst fname. run red_spec_binding_inst_function_decls_1
using env_record_has_binding_correct.
case_if; subst.
case_if; try subst L.
run red_spec_binding_inst_function_decls_2_true_global
using run_object_get_prop_correct.
destruct a; tryfalse. case_if.
let_name. run* red_spec_binding_inst_function_decls_3_true.
applys* red_spec_binding_inst_function_decls_4.
applys red_spec_binding_inst_function_decls_3_false.
destruct (attributes_configurable a); tryfalse; auto. (* LATER: cleanup *)
case_if.
applys* red_spec_binding_inst_function_decls_3a_type_error.
applys* red_spec_binding_inst_function_decls_3a_no_error.
applys* red_spec_binding_inst_function_decls_2_true.
run red_spec_binding_inst_function_decls_2_false
using env_record_create_mutable_binding_correct.
applys* red_spec_binding_inst_function_decls_4.
Admitted. (* faster *)
Lemma binding_inst_var_decls_correct : forall runs S C L vds bconfig str o,
runs_type_correct runs ->
binding_inst_var_decls runs S C L vds bconfig str = o ->
red_expr S C (spec_binding_inst_var_decls L vds bconfig str) o.
Proof.
introv IH HR. gen S o. induction vds; introv HR.
simpls. run_inv. applys* red_spec_binding_inst_var_decls_nil.
simpls. let_simpl.
run red_spec_binding_inst_var_decls_cons
using env_record_has_binding_correct.
case_if; subst.
applys* red_spec_binding_inst_var_decls_1_true.
run red_spec_binding_inst_var_decls_1_false
using env_record_create_set_mutable_binding_correct.
applys* red_spec_binding_inst_var_decls_2.
Admitted. (* faster *)
Lemma binding_inst_formal_params_correct : forall runs S C L args names str o,
runs_type_correct runs ->
binding_inst_formal_params runs S C L args names str = o ->
red_expr S C (spec_binding_inst_formal_params args L names str) o.
Proof.
introv IH HR. gen S args o. induction names; introv HR.
simpls. run_inv. applys* red_spec_binding_inst_formal_params_empty.
simpls.
let_name. let_name.
run (@red_spec_binding_inst_formal_params_non_empty v args')
using env_record_has_binding_correct.
subst v args'. destruct* args.
let_name as M. asserts M_correct: (forall S o,
M S = o ->
red_expr S C (spec_binding_inst_formal_params_3 args' L a names str v) o).
clears HR S o. introv HR. subst M.
run red_spec_binding_inst_formal_params_3
using env_record_set_mutable_binding_correct.
applys* red_spec_binding_inst_formal_params_4.
clear EQM.
case_if; subst.
applys* red_spec_binding_inst_formal_params_1_declared.
run red_spec_binding_inst_formal_params_1_not_declared
using env_record_create_mutable_binding_correct.
applys* red_spec_binding_inst_formal_params_2.
Admitted. (* faster *)
Lemma make_arg_getter_correct : forall runs S C x X o,
runs_type_correct runs ->
make_arg_getter runs S C x X = o ->
red_expr S C (spec_make_arg_getter x X) o.
Proof.
introv IH HR. unfolds in HR.
apply~ red_spec_make_arg_getter. applys~ creating_function_object_correct HR.
Qed.
Lemma make_arg_setter_correct : forall runs S C x X o,
runs_type_correct runs ->
make_arg_setter runs S C x X = o ->
red_expr S C (spec_make_arg_setter x X) o.
Proof.
introv IH HR. unfolds in HR.
apply~ red_spec_make_arg_setter. applys~ creating_function_object_correct HR.
Qed.
Lemma arguments_object_map_loop_correct : forall runs S C l xs len args args' X str lmap xsmap o,
runs_type_correct runs ->
len = length args ->
arguments_object_map_loop runs S C l xs len args X str lmap xsmap = o ->
red_expr S C (spec_arguments_object_map_2 l xs (args ++ args') X str lmap xsmap (len - 1)) o.
Proof.
introv IH EQlen HR. gen o args args' S xsmap. induction len; introv EQlen HR.
simpls. apply~ red_spec_arguments_object_map_2_negative. math. cases_if.
substs. inverts HR. apply~ red_spec_arguments_object_map_8_nil.
run. let_name. inverts HR. forwards~ B: @pick_option_correct E.
applys~ red_spec_arguments_object_map_8_cons B. substs*.
unfolds in HR. fold arguments_object_map_loop in HR.
let_name. destruct tdl as (rmlargs&largs).
forwards EQargs: take_drop_last_spec EQtdl; [destruct args; tryfalse; discriminate|].
forwards EQlargs: take_drop_last_length EQtdl; [destruct args; tryfalse; discriminate|].
clear EQtdl. simpl in HR.
let_name. let_name. asserts Loop: (forall S xsmap o,
arguments_object_map_loop' S xsmap = o ->
red_expr S C (spec_arguments_object_map_2 l xs (rmlargs ++ largs :: args') X str lmap xsmap (len - 1)) o).
clear HR. introv RES. subst arguments_object_map_loop'. apply* IHlen. math.
clear EQarguments_object_map_loop'.
asserts_rewrite (Datatypes.S len - 1 = len). math.
run~ red_spec_arguments_object_map_2_positive using object_define_own_prop_correct.
clear HR. subst args. rew_app. applys~ ZNth_app_r ZNth_here. math.
subst A. auto*.
clear R1 EQA. cases_if.
apply~ red_spec_arguments_object_map_3_next.
apply~ nat_int_ge.
rewrite EQargs. rew_app. apply~ Loop.
let_name. asserts ZN: (ZNth len xs x).
apply Nth_to_ZNth. forwards (x'&N): length_Nth_lt len xs. math.
forwards EQx': Nth_to_nth_def "" N. subst x'. rewrite~ <- EQx in N.
cases_if.
applys~ red_spec_arguments_object_map_3_cont_next ZN.
rewrite EQargs. rew_app. apply~ Loop.
applys~ red_spec_arguments_object_map_3_cont_cont ZN.
rew_logic in n0. destruct n0 as [? NI]. splits.
destruct~ str; false.
auto*.
run red_spec_arguments_object_map_4 using make_arg_getter_correct.
run red_spec_arguments_object_map_5 using make_arg_setter_correct.
let_name. run~ red_spec_arguments_object_map_6.
rewrite EQA' in R1. simpl in R1.
simpl. auto*.
apply~ red_spec_arguments_object_map_7.
rewrite EQargs. rew_app. apply~ Loop.
Admitted. (* faster *)
Lemma arguments_object_map_correct : forall runs S C l xs args X str o,
runs_type_correct runs ->
arguments_object_map runs S C l xs args X str = o ->
red_expr S C (spec_arguments_object_map l xs args X str) o.
Proof.
introv IH HR. unfolds in HR.
run red_spec_arguments_object_map using run_construct_prealloc_correct.
apply~ red_spec_arguments_object_map_1.
rewrite <- (app_nil_r args).
apply* arguments_object_map_loop_correct; rew_app~.
Qed.
Lemma create_arguments_object_correct : forall runs S C lf xs args X str o,
runs_type_correct runs ->
create_arguments_object runs S C lf xs args X str = o ->
red_expr S C (spec_create_arguments_object lf xs args X str) o.
Proof.
introv IH HR. unfolds in HR. let_name. let_name. destruct p as [l S'].
let_name. run* red_spec_create_arguments_object; try solve [ substs* ].
clear EQA EQO EQp A. run red_spec_create_arguments_object_1
using arguments_object_map_correct. cases_if.
let_name. let_name.
run* red_spec_create_arguments_object_2_strict; try solve [ substs* ].
clear EQA. run red_spec_create_arguments_object_3.
apply~ red_spec_create_arguments_object_4.
let_name.
run* red_spec_create_arguments_object_2_non_strict; try solve [ substs* ].
clear EQA. apply~ red_spec_create_arguments_object_4.
Qed.
Lemma binding_inst_arg_obj_correct : forall runs S C lf p xs args L o,
runs_type_correct runs ->
binding_inst_arg_obj runs S C lf p xs args L = o ->
red_expr S C (spec_binding_inst_arg_obj lf p xs args L) o.
Proof.
introv IH HR. unfolds in HR. let_name.
run~ red_spec_binding_inst_arg_obj using create_arguments_object_correct.
cases_if.
run red_spec_binding_inst_arg_obj_1_strict
using env_record_create_immutable_binding_correct.
apply~ red_spec_binding_inst_arg_obj_2.
apply~ env_record_initialize_immutable_binding_correct.
apply~ red_spec_binding_inst_arg_obj_1_not_strict.
applys~ env_record_create_set_mutable_binding_correct HR.
Qed.
Lemma execution_ctx_binding_inst_correct : forall runs S C ct funco (p:prog) args o,
runs_type_correct runs ->
execution_ctx_binding_inst runs S C ct funco p args = o ->
red_expr S C (spec_binding_inst ct funco p args) o.
Proof.
introv IH HR. unfolds in HR.
cases (execution_ctx_variable_env C); tryfalse. rename e into L.
applys* red_spec_binding_inst. clears TEMP. let_simpl.
let_name as M. asserts M_correct: (forall S xs o,
M S xs = o ->
red_expr S C (spec_binding_inst_3 ct funco p xs args L) o).
clear HR S o. introv HR. subst M.
let_name. let_name.
run red_spec_binding_inst_3
using binding_inst_function_decls_correct.
subst bconfig. rewrite decide_def. auto.
auto.
applys red_spec_binding_inst_4.
run red_spec_binding_inst_5 using env_record_has_binding_correct.
let_name as N. asserts N_correct: (forall S o,
N S = o ->
red_expr S C (spec_binding_inst_8 p bconfig L) o).
clear HR S o. introv HR. subst N.
applys red_spec_binding_inst_8.
applys* binding_inst_var_decls_correct.
clear EQN.
destruct ct.
destruct funco.
destruct b; tryfalse.
applys* red_spec_binding_inst_6_no_arguments. rew_logic*.
run red_spec_binding_inst_6_arguments
using binding_inst_arg_obj_correct.
applys* red_spec_binding_inst_7.
destruct b; tryfalse.
applys* red_spec_binding_inst_6_no_arguments. rew_logic*.
applys* red_spec_binding_inst_6_no_arguments.
rew_logic*. left. congruence.
applys* red_spec_binding_inst_6_no_arguments.
rew_logic*. left; congruence.
destruct ct; destruct funco; tryfalse.
run. lets H: run_object_method_correct (rm E).
run. subst. run* red_spec_binding_inst_1_function
using binding_inst_formal_params_correct.
applys* red_spec_binding_inst_2.
applys* red_spec_binding_inst_1_not_function. congruence.
applys* red_spec_binding_inst_1_not_function. congruence.
Admitted. (* faster *)
Lemma entering_eval_code_correct : forall runs S C bdirect bd F K o,
runs_type_correct runs ->
entering_eval_code runs S C bdirect bd F = o ->
(forall S' C' o', F S' C' = o' -> red_expr S' C' K o') ->
red_expr S C (spec_entering_eval_code bdirect bd K) o.
Proof.
introv IH HR HK. unfolds in HR.
let_name. let_name.
applys* red_spec_entering_eval_code str C'. case_if; case_if*.
let_name. destruct p as [lex S'].
let_name. let_name.
run_pre. applys* red_spec_entering_eval_code_1 str lex S' C1 o1.
rewrite EQp. case_if; case_if*.
subst C1. case_if; case_if*.
subst p. applys* execution_ctx_binding_inst_correct R1.
run_post. clear R1.
applys* red_spec_entering_eval_code_2.
Admitted. (* faster *)
Lemma run_eval_correct : forall runs S C (is_direct_call : bool) vs o,
runs_type_correct runs ->
run_eval runs S C is_direct_call vs = o ->
red_expr S C (spec_call_global_eval is_direct_call vs) o.
Proof.
introv IH HR. unfolds in HR.
lets (v&H&E): arguments_from_spec_1 vs. rewrites (rm E) in *.
applys* red_spec_call_global_eval (rm H).
destruct v;
[| run_inv; applys* red_spec_call_global_eval_1_not_string; simpl; congruence].
destruct p; run_inv;
try (applys* red_spec_call_global_eval_1_not_string; simpl; congruence).
let_name. destruct (pick_option (parse s str)) eqn:P.
forwards B: @pick_option_correct (rm P).
applys* red_spec_call_global_eval_1_string_parse.
applys* entering_eval_code_correct (rm HR).
clear - IH. introv HR. run red_spec_call_global_eval_2.
sets_eq RT: (res_type R). destruct RT; tryfalse.
run. cases (res_value R); tryfalse; run_inv.
applys* red_spec_call_global_eval_3_normal_empty.
destruct R. simpls. subst.
applys* red_spec_call_global_eval_3_normal_value.
run_inv. applys* red_spec_call_global_eval_3_throw.
applys red_spec_call_global_eval_1_string_not_parse.
introv Pa. forwards (?&Par): @pick_option_defined (ex_intro _ p Pa).
rewrite Par in P. false.
applys run_error_correct HR.
Admitted. (*faster*)
Lemma run_list_expr_correct : forall runs S C es y,
runs_type_correct runs ->
run_list_expr runs S C nil es = result_some y ->
red_spec S C (spec_list_expr es) y.
Proof.
introv IH. cuts M: (forall es S C vs y,
run_list_expr runs S C vs es = result_some y ->
red_spec S C (spec_list_expr_1 (rev vs) es) y).
intros HR. apply red_spec_list_expr. applys* M (@nil value).
clears S C es y. intros es. induction es; introv HR.
simpls. run_inv. applys* red_spec_list_expr_1_nil.
simpls. run red_spec_list_expr_1_cons.
applys red_spec_list_expr_2. forwards M: IHes HR.
rew_list in M. auto.
Admitted. (*faster*)
Lemma run_call_default_correct : forall runs S C lf o,
runs_type_correct runs ->
run_call_default runs S C lf = o ->
red_expr S C (spec_call_default_1 lf) o.
Proof.
introv IH HR. unfolds in HR. let_simpl.
run. applys* red_spec_call_default_1.
applys* run_object_method_correct. clear E.
destruct x.
case_if.
applys* red_spec_call_default_2_empty_body.
run_inv. applys* red_spec_call_default_3_normal.
run* red_spec_call_default_2_body.
destruct R as [RT RV RL]; simpls. subst.
applys red_spec_call_default_3_normal.
destruct R as [RT RV RL]; simpls. subst.
applys red_spec_call_default_3_return.
subst. abort.
applys* red_spec_call_default_2_empty_body.
run_inv. applys* red_spec_call_default_3_normal.
Admitted. (* faster *)
Lemma env_record_implicit_this_value_correct : forall S C L v,
env_record_implicit_this_value S L = Some v ->
red_expr S C (spec_env_record_implicit_this_value L) (out_ter S v).
Proof.
introv HR. unfolds in HR.
run_simpl HR as H; tryfalse. inverts H. forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_implicit_this_value B. destruct n.
applys~ red_spec_env_record_implicit_this_value_1_decl.
applys~ red_spec_env_record_implicit_this_value_1_object.
Qed.
Lemma run_expr_call_correct : forall runs S C e1 e2s o,
runs_type_correct runs ->
run_expr_call runs S C e1 e2s = o ->
red_expr S C (expr_call e1 e2s) o.
Proof.
introv IH HR. unfolds in HR.
let_name. run red_expr_call.
run red_expr_call_1 using ref_get_value_correct.
run red_expr_call_2 using run_list_expr_correct.
destruct a.
applys* red_expr_call_3.
case_if.
applys* red_expr_call_3_callable.
rename o0 into l. rename a0 into vs.
let_name as M. asserts M_correct: (forall S0 vthis o,
M vthis = o ->
red_expr S0 C (expr_call_5 l is_eval_direct vs (out_ter S3 vthis)) o).
clear HR S o. introv HR. subst M.
case_if.
subst. applys red_expr_call_5_eval. applys* run_eval_correct.
applys* red_expr_call_5_not_eval. apply* IH.
clear EQM.
subst. destruct rv; tryfalse.
applys* red_expr_call_4_not_ref.
cases (ref_base r).
case_if. applys* red_expr_call_4_prop.
run. applys* red_expr_call_4_env.
applys* env_record_implicit_this_value_correct.
(* other branch *)
applys* red_expr_call_3.
Admitted. (*faster*)
Ltac run_select_proj_extra_construct HT ::=
match HT with
| run_construct_prealloc => constr:(run_construct_prealloc_correct)
| run_construct => constr:(run_construct_correct)
| run_call_default => constr:(run_call_default_correct)
| creating_function_object_proto => constr:(creating_function_object_proto_correct)
| creating_function_object => constr:(creating_function_object_correct)
| run_list_expr => constr:(run_list_expr_correct)
| execution_ctx_binding_inst => constr:(execution_ctx_binding_inst_correct)
end.
(**************************************************************)
(** ** Property descriptors *)
Lemma from_prop_descriptor_correct : forall runs S0 S C D o,
runs_type_correct runs ->
from_prop_descriptor runs S C D = o ->
red_expr S0 C (spec_from_descriptor (ret S D)) o.
Proof.
introv IH HR. unfolds in HR. destruct D.
run_inv. applys* red_spec_from_descriptor_undef.
run* red_spec_from_descriptor_some.
rename a into A.
let_name as M. asserts M_correct: (forall S0 S b o,
M S b = res_out o ->
red_expr S0 C (spec_from_descriptor_4 l A (out_ter S b)) o).
clear HR S o. introv HR. subst M.
let_name. run* red_spec_from_descriptor_4. congruence.
let_name. run* red_spec_from_descriptor_5. congruence.
applys* red_spec_from_descriptor_6.
clear EQM.
destruct A.
let_name. run* red_spec_from_descriptor_1_data. congruence.
let_name. run red_spec_from_descriptor_2_data. congruence.
applys* M_correct.
let_name. run red_spec_from_descriptor_1_accessor. congruence.
let_name. run red_spec_from_descriptor_3_accessor. congruence.
applys* M_correct.
Admitted. (*faster*)
(**************************************************************)
(** ** Object Initialisation *)
Lemma create_new_function_in_correct : forall runs S C args bd o,
runs_type_correct runs ->
create_new_function_in runs S C args bd = o ->
red_expr S C (spec_create_new_function_in C args bd) o.
Proof.
introv IH HR. unfolds in HR. applys red_spec_create_new_function_in.
applys* creating_function_object_correct.
Qed.
Lemma init_object_correct : forall runs S C l (pds : propdefs) o,
runs_type_correct runs ->
init_object runs S C l pds = o ->
red_expr S C (expr_object_1 l pds) o.
Proof.
introv IH. gen S. induction pds as [|(pn&pb) pds]; introv HR.
simpls. run_inv. applys red_expr_object_1_nil.
simpls. let_name. let_name.
asserts follows_correct: (forall S Desc, follows S Desc = res_out o ->
red_expr S C (expr_object_4 l x Desc pds) o).
subst follows. clear HR. introv HR.
run red_expr_object_4 using object_define_own_prop_correct.
applys* red_expr_object_5.
clear EQfollows.
applys* red_expr_object_1_cons x.
destruct pb.
run red_expr_object_2_val.
applys* red_expr_object_3_val.
run red_expr_object_2_get using create_new_function_in_correct.
applys* red_expr_object_3_get.
run red_expr_object_2_set using create_new_function_in_correct.
applys* red_expr_object_3_set.
Qed.
Lemma red_expr_array_3_object_loc_eq : forall ElementList S S' C l l' k,
red_expr S C (expr_array_3 l ElementList k) (out_ter S' l') -> l = l'.
Proof.
induction ElementList using (measure_induction length).
destruct ElementList; introv Hyp.
+ inverts~ Hyp. inverts~ H0.
+ destruct o.
- inverts Hyp. inverts H0.
inverts H8. inverts H1. unfolds abrupt_res. false~ H4.
inverts H10. inverts H1. unfolds abrupt_res. false~ H4.
inverts H12. inverts H1. unfolds abrupt_res. false~ H4.
inverts H13. inverts H1. unfolds abrupt_res. false~ H4.
inverts H14. inverts H1. unfolds abrupt_res. false~ H4.
specializes~ H H6. rew_length; nat_math.
- inverts Hyp. inverts H0.
specializes~ H H10.
inverts H4.
* rew_length; nat_math.
* destruct H as (e & oes' & Heq). subst.
rewrite H3. rew_length.
destruct Elision. rewrite app_nil_l in H3.
inverts H3. rew_length; nat_math.
Admitted. (*faster*)
Lemma run_array_element_list_correct : forall runs S C l oes o k,
runs_type_correct runs ->
run_array_element_list runs S C l oes k = o ->
red_expr S C (expr_array_3 l oes k) o.
Proof.
introv IH HR. gen runs S C l o.
destruct oes; intros.
+ inverts HR. apply red_expr_array_3_nil.
+ destruct o.
- unfolds run_array_element_list.
let_name. subst.
run~ red_expr_array_3_some_val; rename a into v.
run~ red_expr_array_3_get_len using run_object_get_correct.
run~ red_expr_array_3_convert_len.
run~ red_expr_array_3_add_len.
let_name. subst. run~ red_expr_array_3_def_own_prop.
run red_expr_array_3_next. substs~.
- simpls. let_name.
eapply red_expr_array_3_none.
* apply elision_head_decomposition.
* jauto. * jauto. * jauto.
* substs. applys* runs_type_correct_array_element_list.
Qed.
Lemma init_array_correct : forall runs S C l oes o,
runs_type_correct runs ->
init_array runs S C l oes = o ->
red_expr S C (expr_array_1 l oes) o.
Proof.
introv IH HR. unfolds in HR. let_name. let_name.
apply red_expr_array_1 with (ElementList := ElementList)
(Elision := list_repeat None ElisionLength)
(ElisionLength := ElisionLength);
try solve [try rewrite my_Z_of_nat_def; substs~].
run red_expr_array_2.
eapply run_array_element_list_correct; eassumption.
apply run_array_element_list_correct in R1; auto.
apply red_expr_array_3_object_loc_eq in R1. subst l0.
apply red_expr_array_add_length.
run red_expr_array_add_length_0 using run_object_get_correct.
run red_expr_array_add_length_1. run red_expr_array_add_length_2.
run red_expr_array_add_length_3. apply red_expr_array_add_length_4.
Qed.
Lemma lexical_env_get_identifier_ref_correct : forall runs S C lexs x str y,
runs_type_correct runs ->
lexical_env_get_identifier_ref runs S C lexs x str = result_some y ->
red_spec S C (spec_lexical_env_get_identifier_ref lexs x str) y.
Proof.
introv IH. gen S C. induction lexs; introv HR.
simpls. run_inv.
applys* red_spec_lexical_env_get_identifier_ref_nil.
simpls.
applys red_spec_lexical_env_get_identifier_ref_cons.
run red_spec_lexical_env_get_identifier_ref_cons_1 using env_record_has_binding_correct.
cases_if; run_inv.
apply~ red_spec_lexical_env_get_identifier_ref_cons_2_true.
apply~ red_spec_lexical_env_get_identifier_ref_cons_2_false.
Qed.
Lemma run_typeof_value_correct : forall S v,
run_typeof_value S v = typeof_value S v.
Proof. intros. destruct v; simpl. auto. case_if; case_if*. Qed.
Ltac run_select_proj_extra_get_value HT ::=
match HT with
| ref_get_value => constr:(ref_get_value_correct)
end.
(**************************************************************)
(** ** Main theorem *)
Hint Extern 1 (regular_unary_op _) =>
intros ?; false_invert.
Lemma prepost_op_correct : forall u F ispre,
run_prepost_op u = Some (F,ispre) ->
prepost_op u F ispre.
Proof.
Hint Constructors prepost_op.
introv HR. destruct u; simpls; inverts* HR.
Qed.
Lemma object_delete_default_correct : forall runs S C l x str o,
runs_type_correct runs ->
object_delete_default runs S C l x str = o ->
red_expr S C (spec_object_delete_1 builtin_delete_default l x str) o.
Proof.
introv IH HR. unfolds in HR. run red_spec_object_delete_1_default. destruct a.
run_inv. applys red_spec_object_delete_2_undef. (* This rule is erroneous, the conclusion should contains [S0] instead [S]. *)
case_if.
run. forwards B: @pick_option_correct (rm E).
applys_eq* red_spec_object_delete_2_some_configurable 1.
applys* red_spec_object_delete_3_some_non_configurable.
applys* out_error_or_cst_correct.
Qed.
Lemma object_delete_correct : forall runs S C l x str o,
runs_type_correct runs ->
object_delete runs S C l x str = o ->
red_expr S C (spec_object_delete l x str) o.
Proof.
introv IH HR. unfolds in HR. run. rename x0 into B. (* LTAC ARTHUR *)
applys* red_spec_object_delete.
applys* run_object_method_correct. clear E.
destruct B.
(* default *)
applys~ object_delete_default_correct HR.
(* argument object *)
run. forwards* obpm: run_object_method_correct.
run. substs. run~ red_spec_object_delete_args_obj.
run red_spec_object_delete_args_obj_1 using object_delete_default_correct.
cases_if. destruct a. (* LTAC ARTHUR *)
apply~ red_spec_object_delete_args_obj_2_else.
inverts HR. apply~ red_spec_object_delete_args_obj_4.
run red_spec_object_delete_args_obj_2_if.
apply~ red_spec_object_delete_args_obj_3.
apply~ red_spec_object_delete_args_obj_4.
apply~ red_spec_object_delete_args_obj_2_else.
inverts HR. apply~ red_spec_object_delete_args_obj_4.
Qed.
Lemma env_record_delete_binding_correct : forall runs S C L x o,
runs_type_correct runs ->
env_record_delete_binding runs S C L x = o ->
red_expr S C (spec_env_record_delete_binding L x) o.
Proof.
introv IH HR. unfolds in HR.
run_simpl. forwards B: @pick_option_correct (rm E).
applys~ red_spec_env_record_delete_binding B. destruct x0.
sets_eq <- ero E: (Heap.read_option d x). destruct ero as [[mu ?]|].
rewrite <- Heap.binds_equiv_read_option in E. destruct mu; run_inv;
applys~ red_spec_env_record_delete_binding_1_decl_indom E; case_if*.
rewrite <- Heap.not_indom_equiv_read_option in E. run_inv.
applys~ red_spec_env_record_delete_binding_1_decl_not_indom E.
run. apply~ red_spec_env_record_delete_binding_1_object.
Qed.
Lemma identifier_resolution_correct : forall runs S C x y,
runs_type_correct runs ->
identifier_resolution runs S C x = result_some y ->
red_spec S C (spec_identifier_resolution C x) y.
Proof.
introv IH HR.
unfolds spec_identifier_resolution, identifier_resolution.
applys* lexical_env_get_identifier_ref_correct.
Qed.
Lemma run_expr_correct : forall runs S C e o,
runs_type_correct runs ->
run_expr runs S C e = o ->
red_expr S C (expr_basic e) o.
Proof.
introv IH R. unfolds in R.
destruct e as [ | | | pds | oes | | | | | | | | | ].
(* this *)
run_inv. apply~ red_expr_this.
(* identifier *)
run_inv. run red_expr_identifier using identifier_resolution_correct.
applys* red_expr_identifier_1.
(* literal *)
run_inv. apply~ red_expr_literal.
(* object *)
run red_expr_object using run_construct_prealloc_correct.
applys red_expr_object_0.
applys* init_object_correct.
(* _ARRAYS_ *)
run red_expr_array using run_construct_prealloc_correct.
applys red_expr_array_0.
applys* init_array_correct.
(* function *)
unfolds in R. destruct o0.
let_name. destruct p as (lex'&S').
destruct lex' as [|L lex']; simpls; tryfalse.
run_simpl. forwards: @pick_option_correct (rm E).
run* red_expr_function_named using env_record_create_immutable_binding_correct.
run red_expr_function_named_1 using creating_function_object_correct.
run red_expr_function_named_2 using env_record_initialize_immutable_binding_correct.
apply~ red_expr_function_named_3.
apply~ red_expr_function_unnamed. applys~ creating_function_object_correct IH.
(* Access *)
unfolds in R. run red_expr_access.
run red_expr_access_1. cases_if.
forwards [R1 N]: run_error_correct' C (rm R). applys red_expr_access_2.
applys* red_spec_check_object_coercible_undef_or_null.
abort.
applys red_expr_access_2.
applys* red_spec_check_object_coercible_return.
run red_expr_access_3.
applys* red_expr_access_4.
(* member *)
run_hyp R. apply~ red_expr_member.
(* new *)
unfolds in R. run red_expr_new.
run red_expr_new_1.
destruct a; tryfalse.
applys* red_expr_new_2_type_error_not_object.
run. lets M: run_object_method_correct (rm E).
destruct x; tryfalse.
applys red_expr_new_2_construct.
applys* red_spec_constructor.
applys* run_construct_correct.
applys* red_expr_new_2_type_error_no_construct.
(* call *)
applys* run_expr_call_correct.
(* unary operators *)
unfolds in R. case_if as N.
run* red_expr_prepost. run red_expr_prepost_1_valid.
run red_expr_prepost_2. run. destruct x as [F ispre].
let_simpl. let_name. lets: prepost_op_correct (rm E).
run* red_expr_prepost_3. subst. applys* red_expr_prepost_4.
destruct u; try solve [ false n; unfolds; do 2 eexists; constructors ].
(* delete *)
run red_expr_delete. destruct rv; run_inv.
apply~ red_expr_delete_1_not_ref. intro; false_invert.
apply~ red_expr_delete_1_not_ref. intro; false_invert.
case_if; run_inv.
apply~ red_expr_delete_1_ref_unresolvable. cases_if.
apply~ red_expr_delete_2_strict. apply* run_error_correct.
run_inv. apply~ red_expr_delete_2_not_strict.
cases (ref_base r).
run* red_expr_delete_1_ref_property using to_object_correct.
apply* ref_is_property_from_not_unresolvable_value.
apply~ red_expr_delete_3. runs~.
rename e0 into L. apply* red_expr_delete_1_ref_env_record. cases_if.
apply~ red_expr_delete_4_strict. apply* run_error_correct.
apply~ red_expr_delete_4_not_strict. applys* env_record_delete_binding_correct.
(* void *)
run* red_expr_unary_op. applys red_expr_unary_op_1.
applys* red_expr_unary_op_void.
(* typeof *)
run red_expr_typeof. destruct rv; tryfalse.
applys* red_expr_typeof_1_value. run_inv. applys* red_expr_typeof_2.
applys run_typeof_value_correct.
case_if.
run_inv. applys* red_expr_typeof_1_ref_unresolvable.
run* red_expr_typeof_1_ref_resolvable.
applys* red_expr_typeof_2.
applys* run_typeof_value_correct.
(* add *)
run* red_expr_unary_op. applys red_expr_unary_op_1.
applys red_expr_unary_op_add. run_hyp*.
(* neg *)
run* red_expr_unary_op. applys red_expr_unary_op_1.
run red_expr_unary_op_neg. applys* red_expr_unary_op_neg_1.
(* bitwise not *)
run* red_expr_unary_op. applys red_expr_unary_op_1.
run red_expr_unary_op_bitwise_not.
applys* red_expr_unary_op_bitwise_not_1.
(* not *)
run* red_expr_unary_op. applys red_expr_unary_op_1.
forwards* M: red_spec_to_boolean a.
applys* red_expr_unary_op_not. applys* red_expr_unary_op_not_1.
(* binary operators *)
unfolds in R. rename b into op.
lets: (is_lazy_op_correct op). cases (is_lazy_op op).
run* red_expr_binary_op_lazy.
let_name. applys* red_expr_lazy_op_1. applys* red_spec_to_boolean.
case_if; subst; run_inv.
applys* red_expr_lazy_op_2_first.
run* red_expr_lazy_op_2_second.
applys* red_expr_lazy_op_2_second_1.
run* red_expr_binary_op.
run red_expr_binary_op_1.
applys* red_expr_binary_op_2.
inverts R as M. applys* run_binary_op_correct M.
(* conditionnal *)
unfolds in R.
run_pre. lets (y1&R2&K): if_spec_post_to_bool (rm R1) (rm R).
applys* red_expr_conditional (rm R2). run_post_if_spec_ter_post_bool K.
let_name. run red_expr_conditional_1. case_if in EQe; case_if*.
applys* red_expr_conditional_2.
(* assign *)
unfolds in R. run red_expr_assign. let_name. rename rv into rv1.
asserts follow_correct: (forall S0 S rv o, follow S rv = o ->
exists v, rv = resvalue_value v /\ red_expr S0 C (expr_assign_4 rv1 (ret S v)) o).
subst follow. clear R. introv HR.
destruct rv; tryfalse. exists v. split~.
run red_expr_assign_4_put_value.
applys* red_expr_assign_5_return.
clear EQfollow.
destruct o0.
run red_expr_assign_1_compound using ref_get_value_correct.
run red_expr_assign_2_compound_get_value.
run red_expr_assign_3_compound_op using run_binary_op_correct.
forwards (v&?&?): follow_correct (rm R). subst.
applys* red_expr_assign_3'.
run red_expr_assign_1_simple.
forwards (v&?&?): follow_correct (rm R). run_inv. auto*.
Admitted. (*faster*)
(* Hints for automatically applying "run_hyp" in obvious cases *)
Hint Extern 1 (red_stat ?S ?C ?s ?o) =>
match goal with H: _ = result_some o |- _ => run_hyp H end.
Hint Extern 1 (red_expr ?S ?C ?s ?o) =>
match goal with H: _ = result_some o |- _ => run_hyp H end.
Lemma run_var_decl_item_correct : forall runs S C x eo o,
runs_type_correct runs ->
run_var_decl_item runs S C x eo = o ->
red_stat S C (stat_var_decl_item (x,eo)) o.
Proof.
introv IH HR. unfolds in HR. destruct eo.
run red_stat_var_decl_item_some using identifier_resolution_correct.
run red_stat_var_decl_item_1. run red_stat_var_decl_item_2.
applys* red_stat_var_decl_item_3.
run_inv. applys* red_stat_var_decl_item_none.
Admitted. (* faster *)
Lemma run_var_decl_correct : forall runs S C ls o,
runs_type_correct runs ->
run_var_decl runs S C ls = o ->
red_stat S C (stat_var_decl ls) o.
Proof.
introv IH. gen S. induction ls as [|[x eo]]; introv HR.
simpls. run_inv. applys* red_stat_var_decl_nil.
simpls. run red_stat_var_decl_cons using run_var_decl_item_correct.
applys* red_stat_var_decl_1.
Admitted. (* faster *)
Lemma run_elements_correct : forall runs S C str ls o,
runs_type_correct runs ->
run_elements runs S C ls = o ->
red_prog S C (prog_intro str (rev ls)) o.
Proof.
introv IH HR. gen S C str o.
induction ls; introv HR; unfolds in HR; rew_list.
run_inv. applys* red_prog_nil.
run_pre. eauto. applys* red_prog_cons. run_post. clear R1.
(* run* red_prog_cons. ==> LATER: should work*)
destruct a.
run red_prog_1_stat. applys* red_prog_2.
run_inv. applys red_prog_1_funcdecl.
Admitted. (*faster*)
Lemma run_block_correct : forall runs S C ls o,
runs_type_correct runs ->
run_block runs S C ls = o ->
red_stat S C (stat_block (rev ls)) o.
Proof.
introv IH HR. gen S C o.
induction ls; introv HR; unfolds in HR; rew_list.
run_inv. applys* red_stat_block_nil.
run_pre. eauto. applys* red_stat_block_cons.
run_post. clear R1.
(* run* red_stat_block_cons. ==> LATER: should work*)
run red_stat_block_1.
subst. applys* red_stat_block_2_throw.
subst. applys* red_stat_block_2_not_throw.
applys* red_stat_block_2_not_throw. simple*.
unfolds res_overwrite_value_if_empty. case_if; case_if*.
Admitted. (*faster*)
Lemma run_stat_switch_no_default_end_correct : forall runs S C rv scs o,
runs_type_correct runs ->
run_stat_switch_end runs S C rv scs = o ->
red_stat S C (stat_switch_nodefault_5 rv scs) o.
Proof.
introv IH HR. gen S C rv o. induction scs; introv HR; unfolds in HR.
run_inv. apply~ red_stat_switch_nodefault_5_nil.
destruct a as [e ts]. run red_stat_switch_nodefault_5_cons.
forwards~ H: run_block_correct R1. rew_list~ in H.
substs. abort.
substs. tests: (res_is_normal R).
apply~ red_stat_switch_nodefault_6_abrupt.
apply~ red_stat_switch_nodefault_6_normal. apply* IHscs. repeat case_if*.
Qed.
Lemma run_stat_switch_no_default_correct : forall runs S C vi rv scs o,
runs_type_correct runs ->
run_stat_switch_no_default runs S C vi rv scs = o ->
red_stat S C (stat_switch_nodefault_1 vi rv scs) o.
Proof.
introv IH HR. gen S C vi rv o. induction scs; introv HR; unfolds in HR.
run_inv. apply~ red_stat_switch_nodefault_1_nil.
apply~ red_stat_switch_nodefault_5_nil.
destruct a. run red_stat_switch_nodefault_1_cons. let_simpl.
apply~ red_stat_switch_nodefault_2. case_if.
run red_stat_switch_nodefault_3_true using run_block_correct. rew_list~ in R1.
apply~ red_stat_switch_nodefault_4.
applys~ run_stat_switch_no_default_end_correct HR.
apply~ red_stat_switch_nodefault_3_false.
Qed.
Lemma run_stat_switch_with_default_end_correct : forall runs S C rv scs o,
runs_type_correct runs ->
run_stat_switch_end runs S C rv scs = o ->
red_stat S C (stat_switch_default_7 rv scs) o.
Proof.
introv IH HR. gen S C rv o. induction scs; introv HR; unfolds in HR.
run_inv. apply~ red_stat_switch_default_7_nil.
destruct a as [e ts]. run red_stat_switch_default_7_cons.
forwards~ H: run_block_correct R1. rew_list~ in H.
substs. abort.
substs. tests: (res_is_normal R).
apply~ red_stat_switch_default_8_abrupt.
apply~ red_stat_switch_default_8_normal. apply* IHscs. repeat case_if*.
Qed.
Lemma run_stat_switch_with_default_default_correct : forall runs S C vi rv ts scs o,
runs_type_correct runs ->
run_stat_switch_with_default_default runs S C ts scs = o ->
red_stat S C (stat_switch_default_5 vi rv ts scs) o.
Proof.
introv IH HR. unfolds in HR. run red_stat_switch_default_5
using run_block_correct. rew_list~ in R1.
apply~ red_stat_switch_default_6.
applys~ run_stat_switch_with_default_end_correct HR.
Qed.
Lemma run_stat_switch_with_default_B_correct : forall runs S C vi rv ts scs o,
runs_type_correct runs ->
run_stat_switch_with_default_B runs S C vi rv ts scs = o ->
red_stat S C (stat_switch_default_B_1 vi rv ts scs) o.
Proof.
introv IH HR. gen S C vi rv ts o. induction scs; introv HR; unfolds in HR.
apply~ red_stat_switch_default_B_1_nil.
applys~ run_stat_switch_with_default_default_correct HR.
destruct a. run red_stat_switch_default_B_1_cons. let_simpl.
apply~ red_stat_switch_default_B_2. case_if.
run red_stat_switch_default_B_3_true using run_block_correct. rew_list~ in R1.
apply~ red_stat_switch_default_B_4.
applys~ run_stat_switch_with_default_end_correct HR.
apply~ red_stat_switch_default_B_3_false.
Qed.
Lemma run_stat_switch_with_default_A_correct : forall runs S C found vi rv scs1 ts scs2 o,
runs_type_correct runs ->
run_stat_switch_with_default_A runs S C found vi rv scs1 ts scs2 = o ->
red_stat S C (stat_switch_default_A_1 found vi rv scs1 ts scs2) o.
Proof.
introv IH HR. gen S C found vi rv ts scs2 o. induction scs1; introv HR; unfolds in HR.
case_if.
apply~ red_stat_switch_default_A_1_nil_true.
applys~ run_stat_switch_with_default_default_correct HR.
apply~ red_stat_switch_default_A_1_nil_false.
applys~ run_stat_switch_with_default_B_correct HR.
destruct a. let_name. asserts follow_correct: (forall S o,
follow S = res_out o ->
red_stat S C (stat_switch_default_A_4 rv vi l scs1 ts scs2) o).
clear HR. introv E. substs. run red_stat_switch_default_A_4
using run_block_correct. rew_list~ in R1. abort.
substs. applys~ red_stat_switch_default_A_5_abrupt.
apply~ red_stat_switch_default_A_5. apply~ IHscs1. repeat case_if~.
clear EQfollow. case_if.
apply~ red_stat_switch_default_A_1_cons_true.
run red_stat_switch_default_A_1_cons_false.
apply~ red_stat_switch_default_A_2. let_simpl. cases_if.
apply~ red_stat_switch_default_A_3_true.
apply~ red_stat_switch_default_A_3_false.
Qed.
Lemma run_stat_switch_correct : forall runs S C labs e sb o,
runs_type_correct runs ->
run_stat_switch runs S C labs e sb = o ->
red_stat S C (stat_switch labs e sb) o.
Proof.
introv IH HR. unfolds in HR.
run red_stat_switch. let_name. asserts follow_correct: (forall S C o1 o,
follow o1 = res_out o -> red_stat S C (stat_switch_2 o1 labs) o).
clear HR. introv HR. substs.
do 2 (run_pre; run_post; run_inv; substs); try solve [abort].
case_if; run_inv.
destruct R. simpls. substs. apply* red_stat_switch_2_break.
abort.
apply~ red_stat_switch_2_normal.
case_if; run_inv; tryfalse.
destruct R. simpls. substs. apply* red_stat_switch_2_break.
asserts follow_arg: (forall W o,
follow W = res_out o -> exists (o1 : out), W = o1).
clear HR follow_correct. introv R. substs.
do 2 (run_pre; run_post; run_inv; substs); tryfalse; auto*.
clear EQfollow. destruct sb.
forwards~ (o1&E): follow_arg HR.
applys~ red_stat_switch_1_nodefault o1.
applys~ run_stat_switch_no_default_correct E.
apply~ follow_correct. rewrite~ <- E.
forwards~ (o1&E): follow_arg HR.
applys~ red_stat_switch_1_default o1.
applys~ run_stat_switch_with_default_A_correct E.
apply~ follow_correct. rewrite~ <- E.
Qed.
Lemma run_stat_for_correct : forall runs S C labs eo1 eo2 eo3 t o,
runs_type_correct runs ->
run_stat_for runs S C labs eo1 eo2 eo3 t = o ->
red_stat S C (stat_for labs eo1 eo2 eo3 t) o.
Proof.
introv IH R. unfolds in R. destruct eo1.
run red_stat_for_some. run_hyp.
apply~ red_stat_for_1.
run_hyp R. apply~ red_stat_for_none.
Qed.
Lemma run_stat_for_var_correct : forall runs S C labs ds eo2 eo3 t o,
runs_type_correct runs ->
run_stat_for_var runs S C labs ds eo2 eo3 t = o ->
red_stat S C (stat_for_var labs ds eo2 eo3 t) o.
Proof.
introv IH R. unfolds in R.
run red_stat_for_var. run_hyp. apply~ red_stat_for_var_1.
Qed.
Lemma run_stat_correct : forall runs S C t o,
runs_type_correct runs ->
run_stat runs S C t = o ->
red_stat S C (stat_basic t) o.
Proof.
introv RC R. unfolds in R.
destruct t as [ | | ls | ls | e t1 t2o | labs t e | labs e t | e t
| e | eo | labo | labo | t co fo | labs e1 e2 e3 t
| labs xeo1s e2 e3 t | labs e1 e2 e3 t | labs str eo e t | eo | ].
(* Expression *)
run red_stat_expr. apply red_stat_expr_1.
(* Label *)
unfolds in R. run red_stat_label.
tests HC: (res_is_normal R0).
inverts HC. run_inv. subst. applys* red_stat_label_1_normal.
subst. applys* red_stat_abort. intro M. inverts M. simpls. false.
case_if.
applys* red_stat_label_1_break_eq. destruct R0; simpls. fequal*.
applys* red_stat_abort. constructors. intro N. inverts N. false.
intro M. inverts M. simpls. false.
(* LATER: change interpreter to make it more faithful *)
(* Block *)
forwards* E: run_block_correct (rev ls). rew_list* in E.
(* Variable declaration *)
applys* run_var_decl_correct.
(* If *)
unfolds in R.
run_pre. lets (y1&R2&K): if_spec_post_to_bool (rm R1) (rm R).
applys* red_stat_if (rm R2). run_post_if_spec_ter_post_bool K.
case_if.
applys~ red_stat_if_1_true. apply~ RC.
destruct t2o.
applys~ red_stat_if_1_false. apply~ RC.
run_inv. applys* red_stat_if_1_false_implicit.
(* Do-while *)
applys* red_stat_do_while. applys* runs_type_correct_stat_do_while.
(* While *)
apply~ red_stat_while. applys* runs_type_correct_stat_while.
(* With *)
unfolds in R.
run_pre. lets (y1&R2&K): if_spec_post_to_object (rm R1) (rm R).
applys* red_stat_with (rm R2). run_post_if_spec_ter_post_bool K.
let_name. let_name. destruct p as [lex' S3]. let_name.
subst lex. applys* red_stat_with_1. subst C'. run_inv. run_hyp*.
(* Throw *)
unfolds in R.
run red_stat_throw. applys* red_stat_throw_1.
(* Return *)
unfolds in R. destruct eo.
run red_stat_return_some. apply* red_stat_return_1.
inverts* R. applys red_stat_return_none.
(* Break *)
run_inv. applys* red_stat_break.
(* Continue *)
run_inv. applys* red_stat_continue.
(* Try *)
unfolds in R. let_name.
asserts finally_correct: (forall S (R:res),
finally S R = res_out o ->
red_stat S C (stat_try_4 R fo) o).
subst finally. clear R. introv HR.
destruct fo.
simpls. run red_stat_try_4_finally.
applys* red_stat_try_5_finally_result.
run_inv. applys* red_stat_try_4_no_finally.
clear EQfinally.
run red_stat_try. abort.
applys* red_stat_try_1_no_throw.
destruct co as [c|].
destruct c as [x t2]. let_name. let_name.
destruct p as [lex' S']. destruct lex'; tryfalse.
subst lex. run* red_stat_try_1_throw_catch
using env_record_create_set_mutable_binding_correct.
run red_stat_try_2_catch.
applys~ red_stat_try_3_catch_result finally_correct.
applys~ red_stat_try_1_throw_no_catch. applys~ finally_correct.
rewrite <- R. fequal. destruct R0; simpls; substs~.
(* For *)
apply* run_stat_for_correct.
(* For-var *)
apply* run_stat_for_var_correct.
(* For-in *)
discriminate.
(* For-in-var *)
discriminate.
(* Debugger *)
run_inv. apply red_stat_debugger.
(* switch *)
applys~ run_stat_switch_correct R.
Admitted. (*faster*)
Lemma run_prog_correct : forall runs S C p o,
runs_type_correct runs ->
run_prog runs S C p = o ->
red_prog S C (prog_basic p) o.
Proof.
introv RC R. unfolds in R. destruct p.
forwards*: run_elements_correct (rev l). rew_list* in H.
Admitted. (*faster*)
(* LATER: generalize statement to handle continuations *)
Lemma entering_func_code_correct : forall runs S C lf vthis args o,
runs_type_correct runs ->
entering_func_code runs S C lf vthis args = result_some (specret_out o) ->
red_expr S C (spec_entering_func_code lf vthis args (spec_call_default_1 lf)) o.
Proof.
introv IH HR. unfolds in HR. sets_eq K: (spec_call_default_1 lf).
run. run. subst x. lets H: run_object_method_correct (rm E).
let_name. let_name as M. rename x0 into bd.
asserts M_correct: (forall S v o,
M S v = res_out o ->
red_expr S C (spec_entering_func_code_3 lf args str bd v K) o).
clears HR S o. introv HR. subst M.
run. run. subst x. lets H: run_object_method_correct (rm E).
let_name. destruct p as [lex' S1]. let_name.
run* (@red_spec_entering_func_code_3 lex' S1 C').
applys* red_spec_entering_func_code_4.
subst K. applys* run_call_default_correct.
clear EQM.
applys* red_spec_entering_func_code str.
case_if; subst str.
applys* red_spec_entering_func_code_1_strict.
destruct vthis.
destruct p. (* LATER: improve *)
applys* red_spec_entering_func_code_1_null_or_undef.
applys* red_spec_entering_func_code_1_null_or_undef.
run red_spec_entering_func_code_1_not_object.
simpls. splits; congruence.
applys* to_object_correct.
applys* red_spec_entering_func_code_2.
run red_spec_entering_func_code_1_not_object.
simpls. splits; congruence.
applys* to_object_correct.
applys* red_spec_entering_func_code_2.
run red_spec_entering_func_code_1_not_object.
simpls. splits; congruence.
applys* to_object_correct.
applys* red_spec_entering_func_code_2.
applys* red_spec_entering_func_code_1_object.
Admitted. (* faster *)
Lemma if_spec_throw_result : forall S K, if_spec (@throw_result descriptor (run_error S native_error_type)) K = @throw_result descriptor (run_error S native_error_type).
Proof.
intros. repeat unfolds.
remember (run_error S native_error_type) as Error.
unfolds run_error. unfolds if_object.
unfolds if_value. unfolds if_success. unfolds if_ter.
unfolds if_out_some. unfolds if_result_some. unfolds build_error.
cases_if*; rewrite decide_def in H; cases_if*; clear H.
remember (object_alloc S (object_new (prealloc_native_error_proto native_error_type) "Error")) as O.
destruct O as (l & S'). simpls.
unfolds if_empty_label.
cases_if*. subst. simpls. cases_if*.
Qed.
Lemma run_to_descriptor_correct : forall runs S C v y,
runs_type_correct runs ->
run_to_descriptor runs S C v = result_some y ->
red_spec S C (spec_to_descriptor v) y.
Proof.
introv IH HR. unfold run_to_descriptor in HR.
destruct v as [p | l].
apply~ red_spec_to_descriptor_not_object.
applys* throw_result_run_error_correct.
applys* red_spec_to_descriptor_object.
run red_spec_to_descriptor_1a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_1b_false.
run red_spec_to_descriptor_2a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_2b_false.
run red_spec_to_descriptor_3a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_3b_false.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
* run red_spec_to_descriptor_3b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_3c.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
- run red_spec_to_descriptor_2b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_2c.
run red_spec_to_descriptor_3a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_3b_false.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
* run red_spec_to_descriptor_3b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_3c.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
+ run red_spec_to_descriptor_1b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_1c.
run red_spec_to_descriptor_2a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_2b_false.
run red_spec_to_descriptor_3a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_3b_false.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
* run red_spec_to_descriptor_3b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_3c.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
- run red_spec_to_descriptor_2b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_2c.
run red_spec_to_descriptor_3a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_3b_false.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
* run red_spec_to_descriptor_3b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_3c.
run red_spec_to_descriptor_4a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_4b_false.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
+ run red_spec_to_descriptor_4b_true using run_object_get_correct.
simpls. applys* red_spec_to_descriptor_4c.
run red_spec_to_descriptor_5a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
- apply red_spec_to_descriptor_5b_false.
run red_spec_to_descriptor_6a using object_has_prop_correct.
cases_if*; destruct b; inverts H.
* apply red_spec_to_descriptor_6b_false.
{
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
* run red_spec_to_descriptor_6b_true using run_object_get_correct.
{
cases_if*.
rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
+ applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
+ unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
- run red_spec_to_descriptor_5b_true using run_object_get_correct.
cases_if*.
* rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_5c_error.
applys* throw_result_run_error_correct.
* simpls. applys* red_spec_to_descriptor_5c_ok.
run red_spec_to_descriptor_6a using object_has_prop_correct.
{
cases_if*; destruct b; inverts H.
+ apply red_spec_to_descriptor_6b_false.
cases_if*.
- applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
- unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
+ run red_spec_to_descriptor_6b_true using run_object_get_correct.
cases_if*.
- rewrite if_spec_throw_result in *.
applys* red_spec_to_descriptor_6c_error.
applys* throw_result_run_error_correct.
- simpls. applys* red_spec_to_descriptor_6c_ok.
cases_if*.
* applys~ red_spec_to_descriptor_7_error.
applys* throw_result_run_error_correct.
* unfolds in HR. inverts HR. applys~ red_spec_to_descriptor_7_ok.
}
}
Admitted. (* Faster *)
Lemma run_object_freeze_correct : forall runs S C l xs o,
runs_type_correct runs ->
run_object_freeze runs S C l xs = result_some (specret_out o) ->
red_expr S C (spec_call_object_freeze_2 l xs) o.
Proof.
introv IH HR. gen S. induction xs; introv HR; unfolds in HR.
run. apply~ red_spec_call_object_freeze_2_nil.
apply~ run_object_heap_set_extensible_correct.
run red_spec_call_object_freeze_2_cons.
destruct a0 as [|A]; tryfalse.
applys~ red_spec_call_object_freeze_3.
run red_spec_call_object_freeze_4.
clear. rew_refl. destruct A as [()|()]; simpls; repeat cases_if;
simpls; fold_bool; rew_refl in *; intuit; tryfalse; repeat (fequals); tryfalse*.
applys~ red_spec_call_object_freeze_5.
Qed.
Lemma run_object_is_sealed_correct : forall runs S C l xs o,
runs_type_correct runs ->
run_object_is_sealed runs S C l xs = result_some (specret_out o) ->
red_expr S C (spec_call_object_is_sealed_2 l xs) o.
Proof.
introv IH HR. gen S. induction xs; introv HR; unfolds in HR.
run. apply~ red_spec_call_object_is_sealed_2_nil.
apply~ run_object_method_correct.
run red_spec_call_object_is_sealed_2_cons.
destruct a0 as [|A]; tryfalse. cases_if as CF.
inverts HR. applys~ red_spec_call_object_is_sealed_3_prop_configurable.
applys~ red_spec_call_object_is_sealed_3_prop_not_configurable.
Qed.
Lemma run_object_is_frozen_correct : forall runs S C l xs o,
runs_type_correct runs ->
run_object_is_frozen runs S C l xs = result_some (specret_out o) ->
red_expr S C (spec_call_object_is_frozen_2 l xs) o.
Proof.
introv IH HR. gen S o. induction xs; introv HR; unfolds in HR.
run. apply~ red_spec_call_object_is_frozen_2_nil.
apply~ run_object_method_correct.
run red_spec_call_object_is_frozen_2_cons. let_name.
asserts CC: (forall A o, check_configurable A = result_some (specret_out o) ->
red_expr S1 C (spec_call_object_is_frozen_5 l xs A) o).
rewrite EQcheck_configurable. clear - IHxs. introv HR. cases_if as AC.
inverts HR. apply~ red_spec_call_object_is_frozen_5_prop_configurable.
apply~ red_spec_call_object_is_frozen_5_prop_not_configurable.
clear EQcheck_configurable. destruct a0 as [|[Ad|Aa]].
discriminate.
apply red_spec_call_object_is_frozen_3_desc_is_data; simpls~. cases_if as W.
inverts HR. applys~ red_spec_call_object_is_frozen_4_prop_is_writable.
apply~ red_spec_call_object_is_frozen_4_prop_is_not_writable.
apply~ red_spec_call_object_is_frozen_3_desc_is_not_data.
Qed.
Lemma run_object_seal_correct : forall runs S C l xs o,
runs_type_correct runs ->
run_object_seal runs S C l xs = result_some (specret_out o) ->
red_expr S C (spec_call_object_seal_2 l xs) o.
Proof.
introv IH HR. gen o S. induction xs; introv HR; unfolds in HR.
run. apply~ red_spec_call_object_seal_2_nil.
apply~ run_object_heap_set_extensible_correct.
run red_spec_call_object_seal_2_cons.
destruct a0 as [|A]; tryfalse.
run red_spec_call_object_seal_3.
clear. repeat cases_if~. destruct~ A as [()|()].
applys~ red_spec_call_object_seal_4.
Qed.
Lemma run_function_proto_apply_get_args_correct : forall runs S C array (index n : int) y,
runs_type_correct runs ->
run_get_args_for_apply runs S C array index n = result_some y ->
red_spec S C (spec_function_proto_apply_get_args array index n) y.
Proof.
introv IH HR; unfolds run_get_args_for_apply. cases_if*.
+ run~ red_spec_function_apply_get_args_true.
run red_spec_function_apply_get_args_1 using run_object_get_correct.
let_name; subst.
run red_spec_function_apply_get_args_2 using runs_type_correct_get_args_for_apply.
apply red_spec_function_apply_get_args_3.
+ inverts HR. applys~ red_spec_function_apply_get_args_false.
Qed.
Lemma push_correct : forall S S' C l args a o runs,
runs_type_correct runs ->
push runs S' C l args a = result_some (specret_out o) ->
red_expr S C (spec_call_array_proto_push_3 l args (specret_val S' a)) o.
Proof.
introv IH HR.
apply red_spec_call_array_proto_push_3.
gen a o S S' C l runs. inductions args; intros.
+ simpls; let_name; subst.
apply red_spec_call_array_proto_push_4_empty.
run red_spec_call_array_proto_push_5.
apply red_spec_call_array_proto_push_6.
+ unfold push in HR. unfolds let_binding. (* Why doesn't let_name work here? *)
apply red_spec_call_array_proto_push_4_nonempty.
run red_spec_call_array_proto_push_4_nonempty_1.
run red_spec_call_array_proto_push_4_nonempty_2.
apply red_spec_call_array_proto_push_4_nonempty_3.
applys* IHargs.
Qed.
Lemma vtsfj_correct : forall runs S C l index sR,
runs_type_correct runs ->
valueToStringForJoin runs S C l index = result_some sR ->
red_spec S C (spec_call_array_proto_join_vtsfj l index) sR.
Proof.
introv IH HR. unfolds in HR.
run red_spec_call_array_proto_join_vtsfj.
run red_spec_call_array_proto_join_vtsfj_1 using run_object_get_correct.
destruct v as [p | loc].
+ destruct p; try solve [inverts HR; applys* red_spec_call_array_proto_join_vtsfj_2_undef_null];
run* red_spec_call_array_proto_join_vtsfj_2_other; try solve [intuition; inverts H0];
applys* red_spec_call_array_proto_join_vtsfj_3.
+ run* red_spec_call_array_proto_join_vtsfj_2_other; try solve [intuition; inverts H0];
applys* red_spec_call_array_proto_join_vtsfj_3.
Qed.
Lemma run_array_join_elements_correct : forall runs S C l k length sep sR o,
runs_type_correct runs ->
run_array_join_elements runs S C l k length sep sR = o ->
red_expr S C (spec_call_array_proto_join_elements l k length sep sR) o.
Proof.
introv IH HR. unfolds in HR. cases_if*.
+ repeat let_name; subst.
applys* red_spec_call_array_proto_join_elements_continue.
run* red_spec_call_array_proto_join_elements_1 using vtsfj_correct.
let_name; subst.
apply red_spec_call_array_proto_join_elements_2.
applys* runs_type_correct_array_join_elements.
+ inverts HR. applys* red_spec_call_array_proto_join_elements_exit.
Qed.
Lemma run_call_prealloc_correct : forall runs S C B vthis args o,
runs_type_correct runs ->
run_call_prealloc runs S C B vthis args = o ->
red_expr S C (spec_call_prealloc B vthis args) o.
Proof.
introv IH HR. unfolds in HR.
destruct B.
(* prealloc_global *)
discriminate.
(* prealloc_global_eval *)
discriminate.
(* prealloc_global_parse_int *)
discriminate.
(* prealloc_global_parse_float *)
discriminate.
(* prealloc_global_is_finite *)
let_name. run red_spec_call_global_is_finite.
substs. apply~ get_arg_correct_0.
applys red_spec_call_global_is_finite_1.
cases_if; fold_bool; rew_refl~.
(* prealloc_global_is_nan *)
let_name. run red_spec_call_global_is_nan.
substs. apply~ get_arg_correct_0.
applys red_spec_call_global_is_nan_1.
cases_if; fold_bool; rew_refl~.
(* prealloc_global_decode_uri *)
discriminate.
(* prealloc_global_decode_uri_component *)
discriminate.
(* prealloc_global_encode_uri *)
discriminate.
(* prealloc_global_encode_uri_component *)
discriminate.
(* prealloc_object *)
let_name. subst.
applys* red_spec_call_object_call.
applys* get_arg_correct_0.
destruct (get_arg 0 args) as [p | l].
destruct p.
applys* red_spec_call_object_call_1_null_or_undef.
apply run_construct_prealloc_correct in HR; auto.
applys* red_spec_call_object_call_1_null_or_undef.
apply run_construct_prealloc_correct in HR; auto.
applys* red_spec_call_object_call_1_other.
splits; discriminate.
applys~ to_object_correct.
applys* red_spec_call_object_call_1_other.
splits; discriminate.
applys~ to_object_correct.
applys* red_spec_call_object_call_1_other.
splits; discriminate.
applys~ to_object_correct.
applys* red_spec_call_object_call_1_other.
splits; discriminate.
applys~ to_object_correct.
(* prealloc_object_get_proto_of *)
let_name. apply~ red_spec_call_object_get_proto_of.
substs. apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_get_proto_of_1_not_object.
apply* run_error_correct.
run. apply~ red_spec_call_object_get_proto_of_1_object.
apply* run_object_method_correct.
(* prealloc_object_get_own_prop_descriptor *)
let_name. apply~ red_spec_call_object_get_own_prop_descriptor.
apply* get_arg_correct_1.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_get_own_prop_descriptor_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run red_spec_call_object_get_own_prop_descriptor_1_object.
run red_spec_call_object_get_own_prop_descriptor_2.
apply* from_prop_descriptor_correct.
(* prealloc_object_get_own_prop_name *)
discriminate.
(* prealloc_object_create *)
discriminate.
(* prealloc_object_define_prop *)
let_name. let_name. let_name.
apply~ red_spec_call_object_object_define_prop.
apply* get_arg_correct_2.
rewrite <- EQo0 in *. rewrite <- EQp in *. rewrite <- EQattr in *.
destruct o0.
apply red_spec_call_object_object_define_prop_1_not_object.
destruct p0; discriminate.
apply* run_error_correct.
run red_spec_call_object_object_define_prop_1_object.
run red_spec_call_object_object_define_prop_2.
apply* run_to_descriptor_correct.
run red_spec_call_object_object_define_prop_3.
apply* red_spec_call_object_object_define_prop_4.
(* prealloc_object_define_props *)
discriminate.
(* prealloc_object_seal *)
let_name. apply~ red_spec_call_object_seal.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_seal_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. forwards~ B: @pick_option_correct E.
applys~ red_spec_call_object_seal_1_object B.
applys~ run_object_seal_correct HR.
(* prealloc_object_freeze *)
let_name. apply~ red_spec_call_object_freeze.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_freeze_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. forwards~ B: @pick_option_correct E.
applys~ red_spec_call_object_freeze_1_object B.
applys~ run_object_freeze_correct HR.
(* prealloc_object_prevent_extensions *)
let_name. apply~ red_spec_call_object_prevent_extensions.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_prevent_extensions_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. forwards~ B: @pick_option_correct E.
applys~ red_spec_call_object_prevent_extensions_object B.
(* prealloc_object_is_sealed *)
let_name. apply~ red_spec_call_object_is_sealed.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_is_sealed_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. forwards~ B: @pick_option_correct E.
applys~ red_spec_call_object_is_sealed_1_object B.
applys~ run_object_is_sealed_correct HR.
(* prealloc_object_is_frozen *)
let_name. apply~ red_spec_call_object_is_frozen.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_is_frozen_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. forwards~ B: @pick_option_correct E.
applys~ red_spec_call_object_is_frozen_1_object B.
applys~ run_object_is_frozen_correct HR.
(* prealloc_object_is_extensible *)
let_name. apply~ red_spec_call_object_is_extensible.
apply* get_arg_correct_0.
rewrite <- EQv in *. destruct v.
apply red_spec_call_object_is_extensible_1_not_object.
destruct p; discriminate.
apply* run_error_correct.
run. apply~ red_spec_call_object_is_extensible_1_object.
apply~ run_object_method_correct.
(* prealloc_object_keys *)
discriminate.
(* prealloc_object_keys_call *)
discriminate.
(* prealloc_object_proto *)
discriminate.
(* prealloc_object_proto_to_string *)
apply red_spec_call_object_proto_to_string.
destruct vthis as [p | l]; [destruct p | ].
inverts HR. apply red_spec_call_object_proto_to_string_1_undef.
inverts HR. apply red_spec_call_object_proto_to_string_1_null.
run red_spec_call_object_proto_to_string_1_other using to_object_correct. rew_logic; splits; discriminate.
run. apply run_object_method_correct in E.
applys* red_spec_call_object_proto_to_string_2.
run red_spec_call_object_proto_to_string_1_other using to_object_correct. rew_logic; splits; discriminate.
run. apply run_object_method_correct in E.
applys* red_spec_call_object_proto_to_string_2.
run red_spec_call_object_proto_to_string_1_other using to_object_correct. rew_logic; splits; discriminate.
run. apply run_object_method_correct in E.
applys* red_spec_call_object_proto_to_string_2.
run red_spec_call_object_proto_to_string_1_other using to_object_correct. rew_logic. splits; discriminate.
run. apply run_object_method_correct in E.
applys* red_spec_call_object_proto_to_string_2.
(* prealloc_object_proto_value_of *)
apply~ red_spec_call_object_proto_value_of.
apply~ to_object_correct.
(* prealloc_object_proto_has_own_prop *)
let_name. run red_spec_call_object_proto_has_own_prop.
substs. apply~ get_arg_correct_0.
run red_spec_call_object_proto_has_own_prop_1 using to_object_correct.
run red_spec_call_object_proto_has_own_prop_2.
destruct a. (* LTAC ARTHUR *)
inverts HR. apply~ red_spec_call_object_proto_has_own_prop_3_undef.
inverts HR. apply~ red_spec_call_object_proto_has_own_prop_3_not_undef.
(* prealloc_object_proto_is_prototype_of *)
let_name. destruct v as [p | l].
inverts HR. applys* red_spec_call_object_proto_is_prototype_of_not_object.
applys* get_arg_correct_0.
applys* red_spec_call_object_proto_is_prototype_of_1_not_object.
rewrite~ <- EQv.
applys* red_spec_call_object_proto_is_prototype_of_not_object.
apply get_arg_correct_0.
rewrite <- EQv. run red_spec_call_object_proto_is_prototype_of_1_object using to_object_correct.
apply red_spec_call_object_proto_is_prototype_of_2.
applys* runs_type_correct_object_proto_is_prototype_of.
(* prealloc_object_proto_prop_is_enumerable *)
let_name.
applys* red_spec_call_object_proto_prop_is_enumerable.
apply get_arg_correct_0. subst.
run red_spec_call_object_proto_prop_is_enumerable_1.
run red_spec_call_object_proto_prop_is_enumerable_2 using to_object_correct.
run red_spec_call_object_proto_prop_is_enumerable_3.
destruct a; inverts HR.
apply red_spec_call_object_proto_prop_is_enumerable_4_undef.
applys* red_spec_call_object_proto_prop_is_enumerable_4_not_undef.
(* prealloc_function *)
discriminate. (* LATER *)
(* prealloc_function_proto *)
inverts HR. apply red_spec_call_function_proto_invoked.
(* prealloc_function_proto_to_string *)
cases_if*. applys* red_spec_function_proto_to_string_not_callable.
(* prealloc_function_proto_apply *)
repeat let_name.
cases_if*; [ | applys* red_spec_function_apply_1].
destruct vthis as [p | func]; [inverts i; inverts H | ].
applys* red_spec_function_apply_1_2; [apply get_arg_correct_1 | substs].
destruct (get_arg 1 args) as [p | array].
destruct p;
try solve [apply runs_type_correct_call in HR; auto;
applys* red_spec_function_apply_2];
try solve [apply red_spec_function_apply_3 with (array := func); [splits; discriminate | applys* run_error_correct]].
run~ red_spec_function_apply_4 using run_object_get_correct.
run red_spec_function_apply_5.
run red_spec_function_apply_6 using run_function_proto_apply_get_args_correct.
apply red_spec_function_apply_7. applys* runs_type_correct_call.
(* prealloc_function_proto_call *)
cases_if*; [ | applys* red_spec_call_function_not_callable].
destruct vthis as [p | l]; [inverts i; inverts H |].
remember (get_arg_first_and_rest args) as gargs; destruct gargs.
applys* red_spec_call_function_callable.
rewrite* <- get_arg_first_and_rest_correct.
applys* runs_type_correct_call.
(* prealloc_function_proto_bind *)
cases_if*; [ | applys* red_spec_function_bind_1].
destruct vthis as [p | this]; [inverts HR | ].
remember (get_arg_first_and_rest args) as gargs; destruct gargs as (thisArg & A).
applys* red_spec_function_bind_2.
rewrite* <- get_arg_first_and_rest_correct.
repeat let_simpl;
match goal with H: context [object_alloc ?s ?o] |- _ => sets_eq X: (object_alloc s o) end;
destruct X as (l & S').
applys* red_spec_function_bind_3.
let_name. subst. run red_spec_function_bind_4.
run. cases_if*; subst; apply run_object_method_correct in E.
applys* red_spec_function_bind_length_true.
run red_spec_function_bind_length_1 using run_object_get_correct.
run red_spec_function_bind_length_2. cases_if*; inverts R1.
applys* red_spec_function_bind_length_3_zero.
applys* red_spec_function_bind_length_3_L.
inverts R1. applys* red_spec_function_bind_length_false.
repeat let_name.
run; rename x into S''. run. repeat let_name.
forwards B: @pick_option_correct (rm E0).
applys* red_spec_function_bind_5.
applys* red_spec_function_bind_6. rewrite* <- EQA0. substs.
run* red_spec_function_bind_7.
run* red_spec_function_bind_8.
apply red_spec_function_bind_9.
(* prealloc_bool *)
inverts HR. apply~ red_spec_call_bool.
apply~ get_arg_correct_0.
apply~ red_spec_to_boolean.
(* prealloc_bool_proto *)
discriminate.
(* prealloc_bool_proto_to_string *)
destruct vthis as [p | l].
destruct p; try solve [
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct]].
inverts HR. applys* red_spec_call_bool_proto_to_string_bool. constructor.
remember (run_object_method object_class_ S l). destruct o0.
simpls. cases_if*.
remember (run_object_method object_prim_value_ S l). destruct o0.
simpls. destruct o0. destruct v.
destruct p.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
inverts HR. subst.
symmetry in Heqo1, Heqo0.
apply run_object_method_correct in Heqo0.
apply run_object_method_correct in Heqo1.
applys* red_spec_call_bool_proto_to_string_bool.
constructor*.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
simpls. apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H3 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
eexists; jauto.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo1.
simpls. inverts Heqo1.
apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. assert (a = O).
{
apply pick_option_correct in Heq.
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. rewrite Hv in Heqo0. false*.
simpls. apply red_spec_call_bool_proto_to_string_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. inverts Heqo0.
(* prealloc_bool_proto_value_of *)
destruct vthis as [p | l].
destruct p; try solve [
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct]].
inverts HR. apply red_spec_call_bool_proto_value_of_bool. constructor.
remember (run_object_method object_class_ S l). destruct o0.
simpls. cases_if*.
remember (run_object_method object_prim_value_ S l). destruct o0.
simpls. destruct o0. destruct v.
destruct p.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
inverts HR. subst. apply red_spec_call_bool_proto_value_of_bool.
symmetry in Heqo1, Heqo0.
apply run_object_method_correct in Heqo0.
apply run_object_method_correct in Heqo1.
constructor*.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
simpls. apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H3 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
eexists; jauto.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo1.
simpls. inverts Heqo1.
apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. assert (a = O).
{
apply pick_option_correct in Heq.
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. rewrite Hv in Heqo0. false*.
simpls. apply red_spec_call_bool_proto_value_of_not_bool;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. inverts Heqo0.
(* prealloc_number *)
cases_if.
substs. inverts HR. apply~ red_spec_call_number_nil.
inverts HR. apply~ red_spec_call_number_not_nil.
apply~ get_arg_correct_0.
apply* to_number_correct.
(* prealloc_number_proto *)
discriminate.
(* prealloc_number_proto_to_string *)
discriminate.
(* prealloc_number_proto_value_of *)
destruct vthis as [p | l].
destruct p; try solve [
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct]].
inverts HR. apply red_spec_call_number_proto_value_of_number. constructor.
remember (run_object_method object_class_ S l). destruct o0.
simpls. cases_if*.
remember (run_object_method object_prim_value_ S l). destruct o0.
simpls. destruct o0. destruct v.
destruct p.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
inverts HR. subst. apply red_spec_call_number_proto_value_of_number.
symmetry in Heqo1, Heqo0.
apply run_object_method_correct in Heqo0.
apply run_object_method_correct in Heqo1.
constructor*.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
symmetry in Heqo1. apply run_object_method_correct in Heqo1.
destruct Heqo1 as (O1 & Hb1 & Hv1).
destruct H3 as (O2 & Hb2 & Hv2).
assert (O1 = O2).
{
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. false~.
simpls. apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H3 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
eexists; jauto.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo1.
simpls. inverts Heqo1.
apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. assert (a = O).
{
apply pick_option_correct in Heq.
applys* Heap_binds_func.
apply object_loc_comparable.
} subst. rewrite Hv in Heqo0. false*.
simpls. apply red_spec_call_number_proto_value_of_not_number;
[introv Hv; inverts Hv | applys* run_error_correct].
destruct H0 as (O & Hb & Hv).
unfolds run_object_method.
assert (exists a, object_binds S l a).
exists~ O.
lets Hyp : (@pick_option_defined _ (object_binds S l) (object_binds_pickable_option S l) H).
destruct Hyp as (a & Heq).
rewrite Heq in Heqo0.
simpls. inverts Heqo0.
(* prealloc_number_proto_to_fixed *)
discriminate.
(* prealloc_number_proto_to_exponential *)
discriminate.
(* prealloc_number_proto_to_precision *)
discriminate.
(* prealloc_array *)
apply run_construct_prealloc_correct in HR; auto.
applys* red_spec_call_to_construct_array. auto.
(* prealloc_array_is_array *)
let_name; subst.
applys* red_spec_call_array_is_array_fetch_arg.
applys* get_arg_correct_0.
destruct (get_arg 0 args).
inverts HR. applys* red_spec_call_array_is_array_1.
run. apply run_object_method_correct in E.
applys* red_spec_call_array_is_array_2_branch.
cases_if*; inverts HR.
applys* red_spec_call_array_is_array_2.
applys* red_spec_call_array_is_array_3.
(* prealloc_array_proto *)
discriminate.
(* prealloc_array_proto_to_string *)
run red_spec_call_array_proto_to_string using to_object_correct.
run red_spec_call_array_proto_to_string_1 using run_object_get_correct.
cases_if*.
destruct v as [p | array]; inverts HR.
applys* red_spec_call_array_proto_to_string_2_true.
applys* runs_type_correct_call.
applys* red_spec_call_array_proto_to_string_2_false.
applys* runs_type_correct_call_prealloc.
(* prealloc_array_proto_join *)
let_name; subst.
run red_spec_call_array_proto_join using to_object_correct.
run red_spec_call_array_proto_join_1 using run_object_get_correct.
run red_spec_call_array_proto_join_2. let_name; subst.
applys* red_spec_call_array_proto_join_3.
apply get_arg_correct_0. cases_if*.
run~ red_spec_call_array_proto_join_3_other.
cases_if*. inverts HR. applys* red_spec_call_array_proto_join_4.
let_name; subst.
run~ red_spec_call_array_proto_join_5 using vtsfj_correct.
apply red_spec_call_array_proto_join_6. applys* run_array_join_elements_correct.
run~ red_spec_call_array_proto_join_3_undef.
cases_if*. inverts HR. applys* red_spec_call_array_proto_join_4.
let_name; subst.
run~ red_spec_call_array_proto_join_5 using vtsfj_correct.
apply red_spec_call_array_proto_join_6. applys* run_array_join_elements_correct.
(* prealloc_array_proto_pop *)
run red_spec_call_array_proto_pop using to_object_correct.
run red_spec_call_array_proto_pop_1 using run_object_get_correct.
run red_spec_call_array_proto_pop_2. cases_if*. subst.
apply red_spec_call_array_proto_pop_3_empty.
run red_spec_call_array_proto_pop_3_empty_1.
apply red_spec_call_array_proto_pop_3_empty_2.
applys~ red_spec_call_array_proto_pop_3_nonempty.
run red_spec_call_array_proto_pop_3_nonempty_1.
run red_spec_call_array_proto_pop_3_nonempty_2 using run_object_get_correct.
run red_spec_call_array_proto_pop_3_nonempty_3 using object_delete_default_correct.
run red_spec_call_array_proto_pop_3_nonempty_4.
applys~ red_spec_call_array_proto_pop_3_nonempty_5.
(* prealloc_array_proto_push *)
run red_spec_call_array_proto_push using to_object_correct.
run red_spec_call_array_proto_push_1 using run_object_get_correct.
run red_spec_call_array_proto_push_2.
applys* push_correct.
(* prealloc_string *)
cases_if; substs.
inverts HR. apply red_spec_call_string_empty.
let_name; substs. run red_spec_call_string_non_empty.
apply get_arg_correct_0.
apply red_spec_call_string_non_empty_1.
(* prealloc_string_proto *)
discriminate. (* LATER *)
(* prealloc_string_proto_to_string *)
applys* red_spec_call_string_proto_to_string.
destruct vthis as [p | l]. cases_if*.
inverts HR. applys* red_spec_call_string_proto_value_of_prim_string.
applys* red_spec_call_string_proto_value_of_bad_type.
run. apply run_object_method_correct in E.
cases_if*. subst.
apply run_object_prim_value_correct in HR.
destruct HR as (v & Heq & Hprim). subst.
applys* red_spec_call_string_proto_value_of_obj_string.
applys* red_spec_call_string_proto_value_of_obj_other.
destruct E as (y & Hbind & Hclass).
introv (y' & Hbind' & Hclass').
assert (y = y'). applys* Heap_binds_func.
apply object_loc_comparable. subst. false~.
(* prealloc_string_proto_value_of *)
destruct vthis as [p | l]. cases_if*. inverts HR.
applys* red_spec_call_string_proto_value_of_prim_string.
applys* red_spec_call_string_proto_value_of_bad_type.
run. apply run_object_method_correct in E.
cases_if*. subst.
apply run_object_prim_value_correct in HR.
destruct HR as (v & Heq & Hprim). subst.
applys* red_spec_call_string_proto_value_of_obj_string.
applys* red_spec_call_string_proto_value_of_obj_other.
destruct E as (y & Hbind & Hclass).
introv (y' & Hbind' & Hclass').
assert (y = y'). applys* Heap_binds_func.
apply object_loc_comparable. subst. false~.
(* prealloc_string_proto_char_at *)
discriminate.
(* prealloc_string_proto_char_code_at *)
discriminate.
(* prealloc_math *)
discriminate.
(* prealloc_mathop *)
discriminate.
(* prealloc_date *)
discriminate.
(* prealloc_regexp *)
discriminate.
(* prealloc_error *)
let_name. apply~ red_spec_call_error.
apply~ get_arg_correct_0.
substs. apply* build_error_correct.
(* prealloc_error_proto *)
discriminate.
(* prealloc_native_error *)
let_name. applys* red_spec_call_native_error.
apply~ get_arg_correct_0.
substs; applys* build_error_correct.
(* prealloc_native_error_proto *)
discriminate.
(* prealloc_error_proto_to_string *)
discriminate.
(* prealloc_throw_type_error *)
apply~ red_spec_call_throw_type_error.
apply* run_error_correct.
(* prealloc_json *)
discriminate.
Admitted. (* faster *)
Lemma run_call_correct : forall runs S C l v vs o,
runs_type_correct runs ->
run_call runs S C l v vs = o ->
red_expr S C (spec_call l v vs) o.
Proof.
introv IH HR. simpls. unfolds in HR.
run. run. subst. lets H: run_object_method_correct (rm E).
applys* red_spec_call. clear H.
destruct x0.
applys* red_spec_call_1_default. applys* red_spec_call_default.
applys* entering_func_code_correct.
repeat run. let_name. subst.
apply run_object_method_correct in E; apply run_object_method_correct in E1;
apply run_object_method_correct in E3.
applys* red_spec_call_1_after_bind_full.
applys* runs_type_correct_call.
applys* red_spec_call_1_prealloc. applys* run_call_prealloc_correct.
Admitted. (* faster *)
Lemma run_stat_while_correct : forall runs S C rv ls e t o,
runs_type_correct runs ->
run_stat_while runs S C rv ls e t = o ->
red_stat S C (stat_while_1 ls e t rv) o.
Proof.
intros runs IH ls e t S C rv o R. unfolds in R.
run_pre. lets (y1&R2&K): if_spec_post_to_bool (rm R1) (rm R).
applys~ red_stat_while_1 (rm R2). run_post_if_spec_ter_post_bool K.
case_if.
run red_stat_while_2_true.
let_name. let_simpl. applys red_stat_while_3 rv'. case_if; case_if*.
case_if in K.
applys red_stat_while_4_not_continue. rew_logic*. case_if in K.
run_inv. applys* red_stat_while_5_break.
applys* red_stat_while_5_not_break. case_if in K; run_inv.
applys* red_stat_while_6_abort.
applys* red_stat_while_6_normal. run_hyp*.
rew_logic in *. applys* red_stat_while_4_continue. run_hyp*.
run_inv. applys red_stat_while_2_false.
Admitted. (*faster*)
Lemma run_stat_do_while_correct : forall runs S C rv ls e t o,
runs_type_correct runs ->
run_stat_do_while runs S C rv ls e t = o ->
red_stat S C (stat_do_while_1 ls t e rv) o.
Proof.
introv IH R. unfolds in R.
run red_stat_do_while_1. do 2 let_name.
applys~ red_stat_do_while_2 rv'.
repeat cases_if~. clear EQrv'.
asserts loop_correct: (forall o, loop tt = res_out o ->
red_stat S0 C (stat_do_while_6 ls t e rv') o).
clear R. introv H. subst loop.
run_pre. lets (y1&R2&K): if_spec_post_to_bool (rm R1) (rm H).
applys~ red_stat_do_while_6 (rm R2). run_post_if_spec_ter_post_bool K.
cases_if.
apply~ red_stat_do_while_7_true. apply* IH.
run_inv. apply* red_stat_do_while_7_false.
clear EQloop. cases_if in R.
apply~ red_stat_do_while_3_continue. rewrite decide_def in H. cases_if~ in H.
apply~ red_stat_do_while_3_not_continue.
rewrite decide_def in H. cases_if~ in H. clear H. cases_if.
run_inv. apply~ red_stat_do_while_4_break.
apply~ red_stat_do_while_4_not_break. cases_if; run_inv.
apply~ red_stat_do_while_5_abort.
apply~ red_stat_do_while_5_normal.
Admitted. (*faster*)
Lemma run_stat_for_loop_correct : forall runs S C labs rv eo2 eo3 t o,
runs_type_correct runs ->
run_stat_for_loop runs S C labs rv eo2 eo3 t = o ->
red_stat S C (stat_for_2 labs rv eo2 eo3 t) o.
Proof.
introv IH R. unfolds in R. let_name.
asserts follows_correct: (forall S o, follows S = res_out o ->
red_stat S C (stat_for_4 labs rv eo2 eo3 t) o).
clear R. introv R. rewrite EQfollows in R. clear EQfollows.
run red_stat_for_4. do 2 let_name. applys~ red_stat_for_5 rv'.
repeat cases_if*.
clear EQrv'. cases_if.
run_inv. apply~ red_stat_for_6_break.
apply~ red_stat_for_6_not_break. rew_logic~ in *. cases_if.
apply red_stat_for_7_continue. rew_logic~ in *. destruct eo3.
run red_stat_for_8_some. subst loop. run_hyp.
apply~ red_stat_for_9.
subst loop. run_hyp. apply~ red_stat_for_8_none.
run_inv. apply~ red_stat_for_7_abort. rew_logic* in *.
clear EQfollows. destruct eo2.
run_pre. lets (y1&R2&K): if_spec_post_to_bool (rm R1) (rm R).
applys~ red_stat_for_2_some (rm R2). run_post_if_spec_ter_post_bool K.
cases_if; run_inv.
apply~ red_stat_for_3_not_false. discriminate.
apply~ red_stat_for_3_false.
apply~ red_stat_for_2_none.
Admitted. (*faster*)
Lemma object_proto_is_prototype_of_correct : forall runs S C lthis l o,
runs_type_correct runs ->
object_proto_is_prototype_of runs S lthis l = o ->
red_expr S C (spec_call_object_proto_is_prototype_of_2_3 lthis l) o.
Proof.
introv IH HR. unfolds in HR.
run. forwards* Omp: run_object_method_correct.
applys~ red_spec_call_object_proto_is_prototype_of_3 Omp.
destruct x as [p|]. (* LTAC ARTHUR *)
destruct p; inverts HR.
apply~ red_spec_call_object_proto_is_prototype_of_4_null.
cases_if; substs; inverts HR.
apply~ red_spec_call_object_proto_is_prototype_of_4_equal.
run_hyp. apply* red_spec_call_object_proto_is_prototype_of_4_not_equal.
Admitted. (*faster*)
Lemma run_equal_correct : forall runs S C v1 v2 o,
runs_type_correct runs ->
run_equal runs S C v1 v2 = o ->
red_expr S C (spec_equal v1 v2) o.
Proof.
introv IH R. unfolds in R. let_simpl.
apply~ red_spec_equal. cases_if.
run_inv. rewrite e. apply~ red_spec_equal_1_same_type.
apply~ red_spec_equal_1_diff_type. let_name.
asserts dc_conv_correct: (forall v1 F Ext v2 o,
dc_conv v1 F v2 = res_out o ->
(forall S v o, F S v = o -> red_expr S C (Ext v) o) ->
red_expr S C (spec_equal_3 v1 Ext v2) o).
clear R. introv E Cor. substs. run red_spec_equal_3_convert_and_recurse.
run_inv. apply* Cor.
run_hyp. apply~ red_spec_equal_4_recurse.
clear EQdc_conv.
Ltac eqcas R :=
match type of R with context [ ifb ?P then _ else _ ] =>
let x := fresh "x" in set (x := P) in * end;
case_if in R as C; [ rewrite If_l; try assumption
| rewrite If_r; try assumption ].
eqcas R. run_inv. applys red_spec_equal_2_return.
eqcas R. run_inv. applys red_spec_equal_2_return.
eqcas R. applys dc_conv_correct R. introv E. applys* to_number_correct E.
eqcas R. applys dc_conv_correct R. introv E. applys* to_number_correct E.
eqcas R. applys dc_conv_correct R. introv E. applys* to_number_correct E.
eqcas R. applys dc_conv_correct R. introv E. applys* to_number_correct E.
eqcas R. applys dc_conv_correct R. introv E. applys* to_primitive_correct E.
eqcas R. applys dc_conv_correct R. introv E. applys* to_primitive_correct E.
run_inv. applys red_spec_equal_2_return.
Admitted. (* faster *)
Theorem runs_correct : forall num,
runs_type_correct (runs num).
Proof.
induction num.
constructors;
try (introv M; inverts M; introv P; inverts P).
introv Hyp M; inverts M.
constructors.
introv. apply~ run_expr_correct.
introv. apply~ run_stat_correct.
introv. apply~ run_prog_correct.
introv. apply~ run_call_correct.
introv. apply~ run_call_prealloc_correct.
introv. apply~ run_construct_correct.
introv. apply~ run_function_has_instance_correct.
introv. apply~ run_function_proto_apply_get_args_correct.
introv. apply~ run_object_has_instance_correct.
introv. apply~ run_stat_while_correct.
introv. apply~ run_stat_do_while_correct.
introv. apply~ run_stat_for_loop_correct.
introv. apply~ object_delete_correct.
introv. apply~ run_object_get_own_prop_correct.
introv. apply~ run_object_get_prop_correct.
introv. apply~ run_object_get_correct.
introv. apply~ object_proto_is_prototype_of_correct.
introv. apply~ object_put_correct.
introv. apply~ run_equal_correct.
introv. apply~ to_integer_correct.
introv. apply~ to_string_correct.
introv. apply~ run_array_element_list_correct.
introv Hyp. apply~ run_object_define_own_prop_array_loop_correct.
introv. apply~ run_array_join_elements_correct.
Qed.
Theorem run_javascript_correct : forall runs p o,
runs_type_correct runs ->
run_javascript runs p = o ->
red_javascript p o.
Proof.
introv IH HR. unfolds in HR. run_pre as o1 R1.
applys* red_javascript_intro R1. run_post. run_inv. run_hyp.
apply~ red_javascript_intro_1.
Qed.
Corollary run_javascript_correct_num : forall num p o,
run_javascript (runs num) p = result_out o ->
red_javascript p o.
Proof.
introv IH. applys~ run_javascript_correct IH.
apply~ runs_correct.
Qed.