Variable subst_default : variable -> value.
Definition rule_subst_of_cbv_function (proof_tree : cbv) : nat * (variable -> value) :=
match proof_tree with
| cbv_function i s _ _ _ => (i, s)
| _ => (0, subst_default) (* impossible case *)
end.
Definition proj_left (proof_tree : cbv) : term :=
match proof_tree with
| cbv_constr _ t _ => t
| cbv_split _ _ t _ => t
| cbv_function _ _ _ t _ => t
end.
Definition proj_right (proof_tree : cbv) : value :=
match proof_tree with
| cbv_constr _ _ v => v
| cbv_split _ _ _ v => v
| cbv_function _ _ _ _ v => v
end.
Variable prog : list rule.
Variable rule_default : rule.
Fixpoint wf (proof_tree : cbv) : Prop :=
match proof_tree with
| cbv_constr l (capply c lt) (c_capply c' lv) =>
c = c' /\
lt = map proj_left l /\ lv = map proj_right l /\ (* Permutations would also be acceptable *)
andl (map wf l)
| cbv_split l ((cbv_function _ _ _ (fapply f lv) v) as p) (fapply f' lt) v' =>
lt = map proj_left l /\ lv = map (@term_from_value _ _ _)(map proj_right l) /\
andl (map wf l) /\
f = f' /\ v = v' /\
wf p
| cbv_function i s p (fapply f lv) v =>
exists lp t,
i < length prog /\
nth i prog rule_default = rule_intro f lp t /\
lv = map (@term_from_value _ _ _) (map (psubst s) lp) /\
proj_left p = subst s t /\ proj_right p = v /\
wf p
| _ => False
end.

Lemma wf_InCBV_wf p proof_tree: wf proof_tree -> InCBV p proof_tree -> wf p.
Fixpoint size (proof_tree : cbv) : nat :=
match proof_tree with
| cbv_constr l t v => term_size t + value_size v + suml (map size l)
| cbv_split l p t v => term_size t + value_size v + size p + suml (map size l)
| cbv_function _ _ p t v => size p + term_size t + value_size v
end.