Section Evaluates.
Variables variable function constructor : Type.
Notation value := (Syntax.value constructor).
Notation term := (Syntax.term variable function constructor).
Notation pattern := (Syntax.pattern variable constructor).
Notation rule := (Syntax.rule variable function constructor).
Notation cbv := (CBV_cache.cbv variable function constructor).
Notation cache := (CBV_cache.cache variable function constructor).
Variable variable_eq_dec : forall (x1 x2 : variable), {x1=x2}+{x1<>x2}.
Variable function_eq_dec : forall (x1 x2 : function), {x1=x2}+{x1<>x2}.
Variable constructor_eq_dec : forall (x1 x2 : constructor), {x1=x2}+{x1<>x2}.
Variable term_default : term.
Variable value_default : value.
Variable function_default : function.
Variable rule_default : rule.
Variable prog : list rule.
Variable max_arity : nat.
Notation wf :=
(CBV_cache.wf variable_eq_dec function_eq_dec constructor_eq_dec rule_default prog max_arity).
Notation assoc_cache := (assoc (term_beq variable_eq_dec function_eq_dec constructor_eq_dec)).
(* Function ranks and compatibility *)
Variable rank: function -> nat.
Hypothesis prog_is_ppo : PPO_prog prog rank.
Hypothesis prog_is_wf : wf_prog max_arity prog.
Definition term_order (t1 t2: term): Prop :=
In t1 (sub_terms_strict _ _ _ t2).
Set Implicit Arguments.
Definition active_term := prod function (list value).
Definition term_from_active_term (t: active_term) : term :=
let (f, lv) := t in
fapply f (map (@term_from_value _ _ _) lv).
Definition value_list_order (lv lv' : list value) : Prop :=
suml (map (@value_size _) lv) < suml (map (@value_size _) lv').
Definition unify_list
(s : list (variable * value)) (lv : list value) (lp : list pattern) :
option (variable -> value) :=
option_map (assoc_default (variable_beq variable_eq_dec) value_default) (unify_list_aux s lv lp).

Lemma psubst_app p v (s s' : list (variable * value)) :
(forall x : variable, assoc (variable_beq variable_eq_dec) x s <> None -> assoc (variable_beq variable_eq_dec) x s' = None) ->
(forall x, In x (vars_of_pattern p) -> assoc (variable_beq variable_eq_dec) x s <> None) ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default s        ) p = v ->
psubst (assoc_default (variable_beq variable_eq_dec) value_default (s' ++ s)) p = v.