From Undecidability.H10 Require Import H10 dio_single dio_logic.
From Undecidability.Synthetic Require Export DecidabilityFacts EnumerabilityFacts ListEnumerabilityFacts ReducibilityFacts.
From Undecidability.L.Datatypes Require Import LNat Lists LProd.
From Undecidability.L Require Import Tactics.LTactics Computability.MuRec Computability.Synthetic Tactics.GenEncode.
From Undecidability.Shared.Libs.DLW.Vec Require Import pos.
(* * Diophantine Equations *)
Inductive poly : Set :=
poly_cnst : nat -> poly
| poly_var : nat -> poly
| poly_add : poly -> poly -> poly
| poly_mul : poly -> poly -> poly.
MetaCoq Run (tmGenEncode "enc_poly" poly).
Hint Resolve enc_poly_correct : Lrewrite.
Instance term_poly_cnst: computable poly_cnst. extract constructor. Qed.
Instance term_poly_var : computable poly_var.  extract constructor. Qed.
Instance term_poly_add : computable poly_add.  extract constructor. Qed.
Instance term_poly_mul : computable poly_mul.  extract constructor. Qed.
Fixpoint eval (p : poly) (L : list nat) :=
match p with
| poly_cnst n => n
| poly_var n => nth n L 0
| poly_add p1 p2 => eval p1 L + eval p2 L
| poly_mul p1 p2 => eval p1 L * eval p2 L
end.
Instance term_eval : computable eval. extract. Qed.
Definition poly_add' '(x,y) : poly  := poly_add x y.
Instance term_poly_add' : computable poly_add'. extract. Qed.
Definition poly_mul' '(x,y) : poly := poly_mul x y.
Instance term_poly_mul' : computable poly_mul'. extract. Qed.
Fixpoint L_poly n : list (poly) :=
match n with
| 0 => []
| S n => L_poly n ++  map poly_cnst (L_nat n)
++ map poly_var (L_nat n)
++ map poly_add' (list_prod (L_poly n) (L_poly n))
++ map poly_mul' (list_prod (L_poly n) (L_poly n))
end.
Instance term_L_poly : computable L_poly. extract. Qed.
Instance enum_poly :
list_enumerator__T L_poly poly.

Lemma eval_L_from n p L :
eval (@conv n p) (L_from (fun p : pos n => nth (pos2nat p) L 0)) = eval (conv p) L.