cap_machine.linking

From iris Require Import base.
From iris.program_logic Require Import language ectx_language ectxi_language.
From stdpp Require Import gmap fin_maps fin_sets.
From cap_machine Require Import addr_reg.

Section Linking.

  Variable Symbols: Type.
  Variable Symbols_eq_dec: EqDecision Symbols.
  Variable Symbols_countable: Countable Symbols.

  Variable Word: Type.
  Variable can_address_only: Word (gset Addr) Prop.
  Variable is_main: Word Prop.

  Definition imports: Type := gset (Symbols * Addr).
  Definition exports: Type := gmap Symbols Word.
  Definition segment: Type := gmap Addr Word.

  Definition pre_component: Type := (segment * imports * exports).
  Inductive component: Type :=
  | Lib: pre_component component
  | Main: pre_component Word component.

  Inductive well_formed_pre_comp: pre_component Prop :=
  | wf_pre_intro:
       (ms : gmap Addr Word) imp (exp : gmap Symbols Word)
        (Hdisj: s, is_Some (exp !! s) a, (s, a) imp)
        (Hexp: (s : Symbols) (w : Word), exp !! s = Some w can_address_only w (dom ms))
        (Himp: s a, (s, a) imp is_Some (ms !! a))
        (Himpdisj: s1 s2 a, (, a) imp (, a) imp = )
        (Hnpwl: (a : Addr) (w : Word), ms !! a = Some w can_address_only w (dom ms)),
        well_formed_pre_comp (ms, imp, exp).

  Inductive well_formed_comp: component Prop :=
  | wf_lib:
       comp
        (Hwf_pre: well_formed_pre_comp comp),
        well_formed_comp (Lib comp)
  | wf_main:
       comp w_main
        (Hwf_pre: well_formed_pre_comp comp)
        (Hw_main_addr: can_address_only w_main (dom (comp.1.1)))
        (Hw_main: is_main w_main),
        well_formed_comp (Main comp w_main).

  Inductive is_program: component Prop :=
  | is_program_intro:
       ms imp exp w_main
        (Hnoimports: imp = )
        (Hwfcomp: well_formed_comp (Main (ms, imp, exp) w_main)),
        is_program (Main (ms,imp, exp) w_main).

  Definition resolve_imports (imp: imports) (exp: exports) (ms: segment) :=
    set_fold (fun '(s, a) m match exp !! s with Some w <[a:=w]> m | None m end) ms imp.

  Lemma resolve_imports_spec:
     imp exp ms a
      (Himpdisj: s1 s2 a, (, a) imp (, a) imp = ),
      (( s, (s, a) imp)
       (resolve_imports imp exp ms) !! a = ms !! a)
      ( s, (s, a) imp
       (exp !! s = None (resolve_imports imp exp ms) !! a = ms !! a) ( wexp, exp !! s = Some wexp (resolve_imports imp exp ms) !! a = Some wexp)).
  Proof.
    intros imp exp ms a. eapply (set_fold_ind_L (fun m imp ( s1 s2 a, (, a) imp (, a) imp = ) (( s, (s, a) imp) m !! a = ms !! a) ( s, (s, a) imp (exp !! s = None m !! a = ms !! a) ( wexp, exp !! s = Some wexp m !! a = Some wexp))) (fun '(s, a) m match exp !! s with Some w <[a:=w]> m | None m end)); eauto.
    { intros. split; auto. intros.
      eapply elem_of_empty in ; elim ; auto. }
    intros. destruct x. split.
    { intros. destruct (exp !! s).
      - rewrite lookup_insert_ne; auto.
        + apply .
          * intros. eapply ; eapply elem_of_union; right; eauto.
          * intro Y. destruct Y as [sy Hiny].
            eapply . exists sy. eapply elem_of_union. right; eauto.
        + intro; subst a. eapply . exists s.
          eapply elem_of_union. left. eapply elem_of_singleton. reflexivity.
      - apply .
        + intros. eapply ; eapply elem_of_union; right; eauto.
        + intro Y. destruct Y as [sy Hiny].
          eapply . exists sy. eapply elem_of_union. right; auto. }
    { intros; destruct (exp !! s) eqn:Hexp.
      - destruct (decide (f = a)).
        + subst f; rewrite lookup_insert.
          right. assert ( = s) as ; eauto.
          eapply elem_of_union in . destruct .
          * generalize (proj1 (elem_of_singleton _ _) ). inversion 1; subst; auto.
          * eapply ( s a); [eapply elem_of_union_r; auto|eapply elem_of_union_l; eapply elem_of_singleton; eauto].
        + rewrite lookup_insert_ne; auto.
          eapply elem_of_union in ; destruct .
          * erewrite elem_of_singleton in . inversion ; congruence.
          * eapply ; auto.
            intros; eapply ; eapply elem_of_union; right; eauto.
      - eapply elem_of_union in . destruct .
        + erewrite elem_of_singleton in . inversion ; subst; clear .
          left; split; auto. eapply (proj1 ( ltac:(intros; eapply ; eapply elem_of_union; right; eauto))).
          intro Y. destruct Y as [sy Hsy].
          eapply H. replace s with sy; auto.
          eapply ; [eapply elem_of_union_r; eauto| eapply elem_of_union_l; eapply elem_of_singleton; eauto].
        + eapply ; auto.
          intros; eapply ; eapply elem_of_union_r; eauto. }
  Unshelve. Fail idtac. Admitted.


  Lemma resolve_imports_spec_in:
     imp exp ms a s
      (Himpdisj: s1 s2 a, (, a) imp (, a) imp = ),
      (s, a) imp
      (exp !! s = None (resolve_imports imp exp ms) !! a = ms !! a) ( wexp, exp !! s = Some wexp (resolve_imports imp exp ms) !! a = Some wexp).
  Proof.
    intros. eapply resolve_imports_spec; eauto.
  Unshelve. Fail idtac. Admitted.


  Lemma resolve_imports_spec_not_in:
     imp exp ms a
      (Himpdisj: s1 s2 a, (, a) imp (, a) imp = ),
      (( s, (s, a) imp)
       (resolve_imports imp exp ms) !! a = ms !! a).
  Proof.
    intros. eapply resolve_imports_spec; eauto.
  Unshelve. Fail idtac. Admitted.


  Inductive link_pre_comp: pre_component pre_component pre_component Prop :=
  | link_pre_comp_intro:
       ms1 ms2 ms imp1 imp2 imp exp1 exp2 exp
        (Hms_disj: a, is_Some ( !! a) is_Some ( !! a) False)
        (Hexp: exp = merge (fun o1 o2 match with | Some _ | None end) )
        (Himp: s a, (s, a) imp (((s, a) (s, a) ) exp !! s = None))
        (Hms: ms = resolve_imports exp (resolve_imports exp (map_union ))),
        link_pre_comp (, , ) (, , ) (ms, imp, exp).

  Inductive link: component component component Prop :=
  | link_lib_lib:
       comp1 comp2 comp
        (Hlink: link_pre_comp comp)
        (Hwf_l: well_formed_comp (Lib ))
        (Hwf_r: well_formed_comp (Lib )),
        link (Lib ) (Lib ) (Lib comp)
  | link_lib_main:
       comp1 comp2 comp w_main
        (Hlink: link_pre_comp comp)
        (Hwf_l: well_formed_comp (Lib ))
        (Hwf_r: well_formed_comp (Main w_main)),
        link (Lib ) (Main w_main) (Main comp w_main)
  | link_main_lib:
       comp1 comp2 comp w_main
        (Hlink: link_pre_comp comp)
        (Hwf_l: well_formed_comp (Main w_main))
        (Hwf_r: well_formed_comp (Lib )),
        link (Main w_main) (Lib ) (Main comp w_main).

  Inductive is_context (c comp p: component): Prop :=
  | is_context_intro:
       (His_program: link c comp p is_program p),
      is_context c comp p.

End Linking.