(* Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file * for details. All rights reserved. Use of this source code is governed by a * BSD-style license that can be found in the LICENSE file. *) Require Import Coq.Lists.SetoidList. Require Import Coq.Init.Wf. Require Import Omega. Require Import Common. Require Import Syntax. Require Import ObjectModel. Require Import OperationalSemantics. Import Common.NatMapFacts. Import Common.MoreNatMapFacts. Import ObjectModel.Subtyping. Section OperationalSemanticsSpec. (** The well-formedness hypothesis is that the environments are built via [lib_to_env] function from the object model module. [program_wf] theorem defined there provides the rest of the well-formedness properties. *) Variable L : library. Variable CE : class_env. Variable ME : member_env. Hypothesis program_wf_hyp: lib_to_env L = (CE, ME). (** Auxiliary well-formedness hypothesis that should be a corollary of [program_wf_hyp], but requires additional facts about the object model to be proven. *) Inductive ref_in_intf : nat -> interface -> Prop := | RI_Method : forall ref proc_desc intf, List.In proc_desc (procedures intf) -> ref_in_dart_type ref (DT_Function_Type (pr_type proc_desc)) -> ref_in_intf ref intf | RI_Getter : forall ref get_desc intf, List.In get_desc (getters intf) -> ref_in_dart_type ref (gt_type get_desc) -> ref_in_intf ref intf. Hypothesis intf_refs_wf: forall class_id intf ref, NatMap.MapsTo class_id intf CE -> ref_in_intf ref intf -> NatMap.In ref CE. (** Yet another hypothesis about well-formedness of getters. *) Hypothesis program_getters_wf: forall class_id intf get_desc, NatMap.MapsTo class_id intf CE -> List.In get_desc (getters intf) -> NatMap.In (gt_ref get_desc) ME. Lemma runtime_value_interface_procedures_wf : forall val intf type_opt proc_desc, value_of_type CE ME val intf type_opt -> List.In proc_desc (procedures intf) -> NatMap.In (pr_ref proc_desc) ME. Proof. intros. destruct H. (* Case 1. Value of Interface Type. *) pose proof (program_wf L CE ME class_id intf proc_desc program_wf_hyp). apply H3. apply NatMapFacts.find_mapsto_iff. auto. auto. (* Case 2. Value of Function Type. *) rewrite H in H0. pose proof (List.in_inv H0). destruct H4. rewrite <- H4. simpl. apply MoreNatMapFacts.maps_in_mapsto. apply MoreNatMapFacts.maps_mapsto_in. exists (M_Procedure proc). auto. pose proof (List.in_nil H4). contradiction. (* Case 3. Null Value. *) rewrite H in H0. pose proof (List.in_nil H0). contradiction. Qed. Lemma method_exists_desc : forall type name, method_exists CE ME type name -> (* TODO(dmitryas): Replace `value_of_type` here with a relation that binds together the interface and the type, avoiding the construction of the value. *) exists intf desc, (value_of_type CE ME (mk_runtime_value type) intf type /\ List.In desc (procedures intf) /\ ((pr_name desc) = name)%string). Proof. intros. destruct H; ( (* Cases of Interface Type and Function Type are analogous. *) exists intf, desc; split; auto ). Qed. Lemma subtype_means_equals : forall type_pair, subtype type_pair = true -> fst type_pair = snd type_pair. Proof. intro. apply well_founded_ind with (R := pair_size_order) (a := type_pair). apply pair_size_order_wf. intros. assert ((fst x) <: (snd x)). destruct x. simpl. auto. destruct (fst x) eqn:?. destruct (snd x) eqn:?. (* t1 : Interface Type, t2 : Interface Type. *) simplify_subtypes. apply N.eqb_eq in H1. rewrite H1. reflexivity. (* t1 : Interface Type, t2 : Function Type. *) simplify_subtypes. destruct (snd x) eqn :?. (* t1 : Function Type, t2 : Interface Type. *) simplify_subtypes. (* t1 : Function Type, t2 : Function Type. *) simplify_subtypes. apply andb_true_iff in H1. destruct H1. assert (d = d1). apply H with (y := (d, d1)). unfold pair_size_order. destruct x. simpl in Heqd. simpl in Heqd0. rewrite Heqd, Heqd0. unfold pair_size. simpl. omega. auto. assert (d2 = d0). apply H with (y := (d2, d0)). unfold pair_size_order. destruct x. simpl in Heqd. simpl in Heqd0. rewrite Heqd, Heqd0. unfold pair_size. simpl. omega. auto. rewrite H3, H4. reflexivity. Qed. Lemma structural_subtype_methods : forall type1 type2 name, method_exists CE ME (Some type1) name -> type2 <: type1 -> method_exists CE ME (Some type2) name. Proof. intros. apply subtype_means_equals in H0. simpl in H0. rewrite H0. auto. Qed. Lemma structural_subtype_getters : forall type1 type2 name, getter_exists CE ME (Some type1) name -> type2 <: type1 -> getter_exists CE ME (Some type2) name. Proof. intros. apply subtype_means_equals in H0. simpl in H0. rewrite H0. auto. Qed. Theorem step_configuration_wf : forall conf1, configuration_wf CE ME conf1 -> exists conf2, step CE ME conf1 conf2. Proof. intros. (* Construct the second configuration from the preconditions of well-formedness of the first configuration. *) destruct H. (* Case 1. Eval Variable Get. *) unfold env_in in H. destruct ( List.find (fun entry : env_entry => Nat.eqb var (var_ref entry)) env ) eqn:?; try contradiction. exists (Value_Passing_Configuration ret_cont (value e)). constructor. unfold env_get. auto. (* Case 2. Eval Method Invocation. *) exists (Eval_Configuration rcvr_expr env (Expression_Continuation (Method_Invocation_Ek name arg_expr env ret_cont) rcvr_type)). constructor. auto. (* Case 3. Eval Property Get. *) exists (Eval_Configuration rcvr_expr env (Expression_Continuation (Property_Get_Ek name ret_cont) rcvr_type)). constructor. auto. (* Case 4. Eval Constructor Invocation. *) pose proof (MoreNatMapFacts.maps_in_mapsto interface CE class_id H). destruct H0 as (intf & H1). set (type := DT_Interface_Type (Interface_Type class_id)). set (new_val := mk_runtime_value (Some type)). exists (Value_Passing_Configuration ret_cont new_val). constructor 14 with (intf := intf) (type_opt := Some type); try auto. constructor 1 with (class_id := class_id); try (simpl; auto). apply NatMapFacts.find_mapsto_iff. auto. (* Case 6. Exec Variable Declaration with Initializer. *) exists (Eval_Configuration init_expr env (Expression_Continuation (Var_Declaration_Ek var var_type env next_cont) init_type)). constructor. auto. (* Case 7. Exec Variable Declaration without Initializer. *) set (null_val := mk_runtime_value None). set (env' := env_extend var var_type null_val env). exists (Forward_Configuration next_cont env'). constructor 15 with (null_val := null_val). constructor 3. simpl. congruence. simpl. congruence. trivial. trivial. (* Case 8. Exec Return Statement. *) exists (Eval_Configuration expr env ret_cont). constructor. (* Case 9. Exec Expression Statement. *) exists (Eval_Configuration expr env (Expression_Continuation (Expression_Ek env ret_cont next_cont) expr_type)). constructor. auto. (* Case 10. Exec Block. *) destruct stmts eqn:?. (* Case 10.1. Exec Empty Block. *) exists (Forward_Configuration next_cont env). constructor. (* Case 10.2. Exec Non-Empty Block. *) exists (Exec_Configuration s env ret_cont (Block_Sk l env ret_cont next_cont)). constructor. (* Case 11. Pass Value to MethodInvocationEK. *) exists (Eval_Configuration arg_expr env (Expression_Continuation (Invocation_Ek rcvr_val name env ret_cont) arg_type)). constructor 9 with (rcvr_type := rcvr_type). auto. auto. (* Case 12. Pass Value to InvocationEK. *) pose proof (method_exists_desc (runtime_type rcvr_val) name H). destruct H0 as (intf & desc & H1). destruct H1. destruct H1. pose proof (runtime_value_interface_procedures_wf (mk_runtime_value (runtime_type rcvr_val)) intf (runtime_type rcvr_val) desc H0). pose proof (H3 H1). apply MoreNatMapFacts.maps_in_mapsto in H4. destruct H4 as (mbr & H5). destruct mbr eqn:?. destruct p eqn:?. destruct f eqn:?. destruct v eqn:?. set (env' := env_extend n0 d0 arg_val empty_env). set (null_val := mk_runtime_value None). set (next_cont := Exit_Sk ret_cont null_val). exists (Exec_Configuration s env' ret_cont next_cont). constructor 10 with (rcvr_intf := intf) (rcvr_type_opt := (runtime_type rcvr_val)) (proc_desc := desc) (func_node := f) (var_id := n0) (var_type := d0) (var_init := o) (ret_type := d) (null_val := null_val) (memb_data := m) (named_data := n). destruct rcvr_val. simpl. simpl in H0. auto. auto. rewrite Heqf0; auto. auto. trivial. trivial. constructor; simpl; congruence. (* Case 13. Pass Value to PropertyGetEK. *) set (type := runtime_type rcvr_val). assert (mk_runtime_value type = rcvr_val). destruct rcvr_val. subst type. simpl. congruence. destruct H0. destruct (gt_type desc) eqn:?. (* Case 13.1. Getting a Value of Interface Type from a Value of Interface Type. *) assert (runtime_type rcvr_val = type). rewrite <- H1. simpl. auto. subst type. rewrite H1 in H2. rewrite H0 in H2. destruct H2 eqn:?; try (rewrite e1 in H5; rewrite H0 in H5; discriminate H5). assert (type0 = type). rewrite e1 in H5. injection H5. intros. auto. destruct i eqn:?. assert (NatMap.In n CE). apply intf_refs_wf with (class_id := class_id0) (intf := intf) (ref := n). apply NatMapFacts.find_mapsto_iff. auto. constructor 2 with (get_desc := desc). auto. rewrite Heqd. constructor. pose proof (MoreNatMapFacts.maps_in_mapsto interface CE n H7). destruct H8 as (el & H9). set (ret_type := DT_Interface_Type (Interface_Type n)). set (ret_intf := el). set (ret_val := mk_runtime_value (Some ret_type)). exists (Value_Passing_Configuration ret_cont ret_val). constructor 12 with (rcvr_intf := intf) (rcvr_type_opt := Some type) (memb_id := gt_ref desc) (ret_intf := ret_intf) (ret_type := ret_type). auto. set (get_desc_alt := mk_getter_desc name (gt_ref desc) ret_type). assert (desc = get_desc_alt). destruct desc. subst get_desc_alt. simpl. simpl in H4. rewrite H4. simpl in Heqd. rewrite Heqd. subst ret_type. congruence. rewrite <- H8. auto. constructor 1 with (class_id := n). auto. apply NatMapFacts.find_mapsto_iff. subst ret_intf. auto. simpl. congruence. (* Case 13.2. Getting a Value of Function Type from a Value of Interface Type. *) set (ret_type := DT_Function_Type f). set (ret_intf := mk_interface ((mk_procedure_desc "call" (gt_ref desc) f) :: nil) ((mk_getter_desc "call" (gt_ref desc) (DT_Function_Type f)) :: nil)). set (ret_val := mk_runtime_value (Some ret_type)). assert (runtime_type rcvr_val = Some type0). subst type. rewrite <- H1. simpl. auto. subst type. rewrite H1 in H2. rewrite H0 in H2. destruct H2 eqn:?; try (rewrite e1 in H5; rewrite H0 in H5; discriminate H5). assert (type0 = type). rewrite e1 in H5. injection H5. intros. auto. assert (class_id0 = class_id). rewrite e in H6. rewrite H0 in H6. injection H6. intros. auto. exists (Value_Passing_Configuration ret_cont ret_val). constructor 12 with (rcvr_intf := intf) (rcvr_type_opt := Some type) (memb_id := gt_ref desc) (ret_intf := ret_intf) (ret_type := ret_type). constructor 1 with (class_id := class_id0); auto. set (get_desc_alt := mk_getter_desc name (gt_ref desc) ret_type). assert (desc = get_desc_alt). destruct desc. subst get_desc_alt. simpl. simpl in H4. rewrite H4. simpl in Heqd. rewrite Heqd. subst ret_type. congruence. rewrite <- H8. auto. clear Heqv. destruct H2; try (rewrite e1 in H5; rewrite H0 in H5; discriminate H5). apply NatMapFacts.find_mapsto_iff in e0. pose proof (program_getters_wf class_id0 intf desc e0). pose proof (H10 H3). apply MoreNatMapFacts.maps_in_mapsto in H11. destruct H11 as (mbr & H12). destruct mbr. constructor 2 with (memb_id := gt_ref desc) (proc := p). simpl. congruence. simpl. congruence. auto. simpl. subst ret_type. congruence. (* Case 13.3. Getting a Value from a Value of Function Type. *) subst type. rewrite H1 in H2. rewrite H in H2. destruct H2 eqn:?; try ( clear Heqv; rewrite <- H1 in e1; simpl in e1; rewrite H0 in e1; rewrite e in e1; discriminate e1 ). assert (ftype0 = ftype). rewrite H0 in H. injection H. intros. auto. exists (Value_Passing_Configuration ret_cont val). constructor 12 with (rcvr_intf := intf) (rcvr_type_opt := Some type0) (memb_id := gt_ref desc) (ret_intf := intf) (ret_type := type0). rewrite H. auto. pose proof H2. rewrite e0 in H3. pose proof (List.in_inv H3). destruct H7. clear Heqv. rewrite H7 in H3. rewrite H7 in e0. rewrite <- H7. simpl. rewrite <- e0 in H3. rewrite H5 in H7. rewrite <- H0 in H7. rewrite H7. auto. pose proof (List.in_nil H7). contradiction. rewrite H0; rewrite <- H5; auto. (* Case 13.4. Getting a Value from Null. *) rewrite e0 in H3. pose proof (List.in_nil H3). contradiction. (* Case 9. Forward. *) destruct next_cont. (* Case 9.1. Forward to Exit. *) exists (Value_Passing_Configuration e r). constructor. (* Case 9.2. Forward to the Next Statement in Block. *) destruct l. (* Case 9.2.1. Block is Empty. *) exists (Forward_Configuration next_cont e). constructor. (* Case 9.2.2. Block is Non-Empty. *) exists (Exec_Configuration s env e0 (Block_Sk l e e0 next_cont)). constructor. (* Case 10. Pass Value to ExpressionEk. *) exists (Forward_Configuration next_cont env). constructor. (* Case 11. Pass Value to VarDeclarationEk. *) set (env' := env_extend var var_type val env). exists (Forward_Configuration next_cont env'). constructor. auto. (* Case 12. Pass Value to MethodInvocationEK: No Such Method. *) exists (Value_Passing_Configuration (Expression_Continuation Halt_Ek rcvr_type) (mk_runtime_value None)). assert (rcvr_val = mk_runtime_value None). destruct rcvr_val. simpl in H. rewrite H. reflexivity. rewrite H0. constructor 19. (* Case 13. Pass Value to PropertyGetEK: No Such Getter. *) exists (Value_Passing_Configuration (Expression_Continuation Halt_Ek rcvr_type) (mk_runtime_value None)). assert (rcvr_val = mk_runtime_value None). destruct rcvr_val. simpl in H. rewrite H. reflexivity. rewrite H0. constructor 20. Qed. Lemma configuration_valid_wf : forall conf, configuration_valid CE ME conf -> configuration_wf CE ME conf. Proof. intros. destruct H. (* Case 1. Eval Configuration. *) destruct H2. (* Case 1.1. Eval Variable Get. *) constructor. auto. (* Case 1.2. Eval Property Get. *) remember (E_Property_Get (Property_Get expr name)) as expr0. destruct H3. assert ( exists rcvr_type, expression_type CE (env_to_type_env env) expr = Some rcvr_type ). rewrite Heqexpr0 in H3. simpl in H3. destruct (expression_type CE (env_to_type_env env) expr) eqn:?; try discriminate H3. exists d. reflexivity. destruct H5 as (rcvr_type & H6). rewrite Heqexpr0. destruct name. constructor 3 with (rcvr_type := rcvr_type). auto. (* Case 1.3. Eval Constructor Invocation. *) constructor. remember (E_Invocation_Expression (IE_Constructor_Invocation (Constructor_Invocation class_id))) as expr. destruct H; try discriminate Heqexpr. assert (ref = class_id). injection Heqexpr. intros. auto. rewrite <- H2. auto. (* Case 1.4. Eval Method Invocation. *) remember (E_Invocation_Expression (IE_Method_Invocation (Method_Invocation rcvr_expr name (Arguments arg_expr) ref))) as expr. destruct H3. assert ( exists rcvr_type, expression_type CE (env_to_type_env env) rcvr_expr = Some rcvr_type ). rewrite Heqexpr in H2. simpl in H2. destruct (expression_type CE (env_to_type_env env) rcvr_expr) eqn:?; try discriminate H2. exists d. reflexivity. destruct H4 as (rcvr_type & H5). rewrite Heqexpr. destruct name. constructor 2 with (rcvr_type := rcvr_type). auto. (* Case 2. Exec Configuration. *) destruct H3. (* Case 2.1. Exec Expression Statement. *) remember (S_Expression_Statement (Expression_Statement expr)) as stmt. destruct H4. assert ( exists expr_type, expression_type CE (env_to_type_env env) expr = Some expr_type ). rewrite Heqstmt in H4. simpl in H4. destruct (expression_type CE (env_to_type_env env) expr) eqn:?; try discriminate H4. exists d. auto. destruct H6 as (expr_type & H7). rewrite Heqstmt. constructor 8 with (expr_type := expr_type). auto. (* Case 2.2. Exec Empty Block. *) constructor. (* Case 2.3. Exec Non-Empty Block. *) constructor. (* Case 2.4. Exec Return Statement. *) constructor. (* Case 2.5. Exec Variable Declaration without Initializer. *) constructor. (* Case 2.6. Exec Variable Declaration with Initializer. *) remember (S_Variable_Declaration (Variable_Declaration var type (Some init_expr))) as stmt. destruct H4. assert ( exists init_type, expression_type CE (env_to_type_env env) init_expr = Some init_type ). rewrite Heqstmt in H4. simpl in H4. destruct (expression_type CE (env_to_type_env env) init_expr) eqn:?; try discriminate H4. exists d. auto. destruct H6 as (init_type & H7). rewrite Heqstmt. constructor 5 with (init_type := init_type). auto. (* Case 3. Value Passing Configuration *) destruct cont. destruct u. (* Case 3.1. Pass Value to ExpressionEK. *) constructor. (* Case 3.2. Pass Value to MethodInvocationEK. *) destruct (runtime_type val) eqn:?. (* Case 3.2.1. Non Null Value. Actual Invocation. *) remember (Expression_Continuation (Method_Invocation_Ek s e e0 e1) d) as econt. destruct H; try discriminate Heqecont. constructor 10 with (arg_type := arg_type) (rcvr_type := d0). auto. auto. (* Case 3.2.2. Null Value. No Such Method. *) assert (val = mk_runtime_value None). destruct val. simpl in Heqo. rewrite Heqo. reflexivity. rewrite H2. constructor. rewrite <- H2. auto. (* Case 3.3. Pass Value to InvocationEK. *) remember (Expression_Continuation (Invocation_Ek r s e e0) d) as econt. destruct H; try discriminate Heqecont. remember (runtime_type rcvr_val) as rcvr_val_type. destruct H3; constructor; rewrite <- Heqrcvr_val_type; auto. (* Case 3.4. Pass Value to PropertyGetEK. *) destruct (runtime_type val) eqn:?. assert (val = mk_runtime_value (Some d0)). destruct val. rewrite <- Heqo. simpl. reflexivity. (* Case 3.4.1. Non Null Value. Actual Invocation. *) constructor 12 with (rcvr_type := d0). auto. rewrite H2. simpl. remember (Expression_Continuation (Property_Get_Ek s e) d) as econt. destruct H1; try discriminate Heqo. assert (type = d0). injection Heqo. intros. auto. rewrite H3 in *. remember (Expression_Continuation cont expected_type) as econt. destruct H; try discriminate Heqecont. remember (Some rcvr_type) as rt. destruct H4. assert (rcvr_type0 = rcvr_type). injection Heqrt. intros. auto. rewrite H11 in *. assert (rcvr_type = expected_type). injection Heqecont0. intros. auto. rewrite H12 in *. apply structural_subtype_getters with (type1 := expected_type) (type2 := d0). auto. assert (name = s). injection Heqecont. intros. auto. rewrite <- H13. auto. auto. (* Case 3.4.2. Null Value. No Such Getter. *) constructor. auto. (* Case 3.5. Pass Value to Var Declaration. *) constructor. (* Case 3.6. Pass Value to Halt. *) remember (Expression_Continuation Halt_Ek d) as econt. destruct H; discriminate Heqecont. (* Case 4. Forward Configuration. *) constructor. Qed. Lemma configuration_valid_step : forall conf1 conf2, configuration_valid CE ME conf1 -> step CE ME conf1 conf2 -> configuration_valid CE ME conf2 \/ configuration_final conf2. Proof. admit. Admitted. Theorem progress: forall conf1, configuration_valid CE ME conf1 -> exists conf2, step CE ME conf1 conf2 /\ (configuration_valid CE ME conf2 \/ configuration_final conf2). Proof. intros. admit. Admitted. Lemma preservation_eval: forall conf1 conf2 exp val env cont val_type exp_type, configuration_valid CE ME conf1 -> conf1 = Eval_Configuration exp env cont -> conf2 = Value_Passing_Configuration cont val -> steps CE ME conf1 conf2 -> expression_type CE (env_to_type_env env) exp = Some exp_type -> (runtime_type val) = Some val_type -> subtype (val_type, exp_type) = true. Proof. admit. Admitted. End OperationalSemanticsSpec.