Fixpoint compute_nested_efield_rec {cs:compspecs} e lr_default :=
  match e with
  | Efield e' id t =>
    match typeof e' with
    | Tstruct id_str _ =>
      if eqb_type (field_type id (co_members (get_co id_str))) t
      then match compute_nested_efield_rec e' LLLL with
           | (e'', efs, lr) => (e'', eStructField id :: efs, lr)
           end
      else (e, nil, lr_default)
    | Tunion id_uni _ =>
      if eqb_type (field_type id (co_members (get_co id_uni))) t
      then match compute_nested_efield_rec e' LLLL with
           | (e'', efs, lr) => (e'', eUnionField id :: efs, lr)
           end
      else (e, nil, lr_default)
    | _ => (e, nil, lr_default)
    end
  | Ederef (Ebinop Cop.Oadd e' ei (Tpointer t a)) t' =>
    match typeof e' with
    | Tarray t'' _ _ =>
      match eqb_type t t'', eqb_type t t', eqb_attr a noattr with
      | true, true, true =>
        match compute_nested_efield_rec e' RRRR with
        | (e'', efs, lr) => (e'', eArraySubsc ei :: efs, lr)
        end
      | _, _, _ => (e, nil, lr_default)
      end
    | Tpointer t'' _ =>
      match eqb_type t t'', eqb_type t t', eqb_attr a noattr, eqb_type (typeof e') int_or_ptr_type with
      | true, true, true, false => (e', eArraySubsc ei :: nil, RRRR)
      | _, _, _, _ => (e, nil, lr_default)
      end
    | _ => (e, nil, lr_default)
    end
  | _ => (e, nil, lr_default)
  end.Definition compute_nested_efield {cs: compspecs} (e: expr): expr * list efield * LLRR := compute_nested_efield_rec e LLLL.Inductive compute_root_type: forall (t_from_e: type) (lr: LLRR) (t_root: type), Prop :=
  | compute_root_type_lvalue: forall t, compute_root_type t LLLL t
  | compute_root_type_Tpointer_expr: forall t a1 n a2, compute_root_type (Tpointer t a1) RRRR (Tarray t n a2)
  | compute_root_type_Tarray_expr: forall t n1 a1 n2 a2, compute_root_type (Tarray t n1 a1) RRRR (Tarray t n2 a2).Inductive compute_root_type: forall (t_from_e: type) (lr: LLRR) (t_root: type), Prop :=
  | compute_root_type_lvalue: forall t, compute_root_type t LLLL t
  | compute_root_type_Tpointer_expr: forall t a1 n a2, compute_root_type (Tpointer t a1) RRRR (Tarray t n a2)
  | compute_root_type_Tarray_expr: forall t n1 a1 n2 a2, compute_root_type (Tarray t n1 a1) RRRR (Tarray t n2 a2).Inductive compute_root_type: forall (t_from_e: type) (lr: LLRR) (t_root: type), Prop :=
  | compute_root_type_lvalue: forall t, compute_root_type t LLLL t
  | compute_root_type_Tpointer_expr: forall t a1 n a2, compute_root_type (Tpointer t a1) RRRR (Tarray t n a2)
  | compute_root_type_Tarray_expr: forall t n1 a1 n2 a2, compute_root_type (Tarray t n1 a1) RRRR (Tarray t n2 a2).Inductive compute_root_type: forall (t_from_e: type) (lr: LLRR) (t_root: type), Prop :=
  | compute_root_type_lvalue: forall t, compute_root_type t LLLL t
  | compute_root_type_Tpointer_expr: forall t a1 n a2, compute_root_type (Tpointer t a1) RRRR (Tarray t n a2)
  | compute_root_type_Tarray_expr: forall t n1 a1 n2 a2, compute_root_type (Tarray t n1 a1) RRRR (Tarray t n2 a2).(* which means (e, lr) is possible to be called by compute_nested_efield_rec *)
Definition LR_possible (e: expr) (lr: LLRR) : bool :=
  match lr with
  | LLLL => match (typeof e) with
                              | Tarray _ _ _ => false
                              | _ => true
            end
  | RRRR => match (typeof e) with
            | Tarray _ _ _ => true
            | _ => false
            end
  end.Definition array_relexed_type_eq (t1 t2: type): Prop :=
  match t1, t2 with
  | Tarray t1' _ _, Tarray t2' _ _ => t1' = t2'
  | _, _ => t1 = t2
  end.

Lemma compute_nested_efield_lemma: forall e rho, type_is_by_value (typeof e) = true -> match compute_nested_efield e with | (e_root, efs, lr) => forall t_root gfs, exists tts, compute_root_type (typeof e_root) lr t_root -> efield_denote efs gfs rho -> nested_efield e_root efs tts = e /\ LR_of_type t_root = lr /\ legal_nested_efield t_root e_root gfs tts lr = true /\ nested_field_type t_root gfs = typeof e end.