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).
(* 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_aux: forall e rho lr_default,
(LR_possible e lr_default = true ->
match compute_nested_efield_rec e lr_default 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 /\
type_almost_match e_root t_root lr = true /\
legal_nested_efield_rec t_root gfs tts = true /\
match gfs with
| nil => array_relexed_type_eq t_root (typeof e)
| _ => nested_field_type t_root gfs = typeof e
end
end) /\
forall t,
(LR_possible (Ederef e t) lr_default = true ->
match compute_nested_efield_rec (Ederef e t) lr_default 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 = Ederef e t /\
LR_of_type t_root = lr /\
type_almost_match e_root t_root lr = true /\
legal_nested_efield_rec t_root gfs tts = true /\
match gfs with
| nil => array_relexed_type_eq t_root (typeof (Ederef e t))
| _ => nested_field_type t_root gfs = typeof (Ederef e t)
end
end).