aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jason Gross <jgross@mit.edu>2017-12-01 23:13:14 -0500
committerGravatar Jason Gross <jasongross9@gmail.com>2018-01-29 18:04:58 -0500
commit18592a2abbd63e7b19b5ac554f3578fc5cde6ca7 (patch)
tree59ee56068bde020fa25213be38afee3698dc2c0d /src
parent1ad2515d3f3d955f9ff9747cc8aec5975fb6b4c5 (diff)
Finish first working version of partial reduction
The names are terrible and the code organization isn't great, and I don't like the long list of [Let] statements which are morally doing very similar things, but, it works.
Diffstat (limited to 'src')
-rw-r--r--src/Experiments/SimplyTypedArithmetic.v1586
1 files changed, 1224 insertions, 362 deletions
diff --git a/src/Experiments/SimplyTypedArithmetic.v b/src/Experiments/SimplyTypedArithmetic.v
index 3fd269fe7..4d765bdc8 100644
--- a/src/Experiments/SimplyTypedArithmetic.v
+++ b/src/Experiments/SimplyTypedArithmetic.v
@@ -316,79 +316,78 @@ Module Compilers.
End type.
Export type.Notations.
- Module op.
+ Module ident.
Import type.
- Inductive op : type -> type -> Set :=
- | Const {t} (v : interp t) : op unit t
- | Let_In {tx tC} : op (tx * (tx -> tC)) tC
- | App {s d} : op ((s -> d) * s) d
- | S : op nat nat
- | nil {t} : op unit (list t)
- | cons {t} : op (t * list t) (list t)
- | fst {A B} : op (A * B) A
- | snd {A B} : op (A * B) B
- | bool_rect {T} : op (T * T * bool) T
- | nat_rect {P} : op (P * (nat -> P -> P) * nat) P
- | pred : op nat nat
- | List_seq : op (nat * nat) (list nat)
- | List_repeat {A} : op (A * nat) (list A)
- | List_combine {A B} : op (list A * list B) (list (A * B))
- | List_map {A B} : op ((A -> B) * list A) (list B)
- | List_flat_map {A B} : op ((A -> list B) * list A) (list B)
- | List_partition {A} : op ((A -> bool) * list A) (list A * list A)
- | List_app {A} : op (list A * list A) (list A)
- | List_fold_right {A B} : op ((B -> A -> A) * A * list B) A
- | List_update_nth {T} : op (nat * (T -> T) * list T) (list T)
- | Z_runtime_mul : op (Z * Z) Z
- | Z_runtime_add : op (Z * Z) Z
- | Z_add : op (Z * Z) Z
- | Z_mul : op (Z * Z) Z
- | Z_pow : op (Z * Z) Z
- | Z_opp : op Z Z
- | Z_div : op (Z * Z) Z
- | Z_modulo : op (Z * Z) Z
- | Z_eqb : op (Z * Z) bool
- | Z_of_nat : op nat Z.
-
- Notation curry2 f
- := (fun '(a, b) => f a b).
- Notation curry3 f
- := (fun '(a, b, c) => f a b c).
-
- Definition interp {s d} (opc : op s d) : type.interp s -> type.interp d
- := match opc in op s d return type.interp s -> type.interp d with
- | Const t v => fun _ => v
- | Let_In tx tC => curry2 (@LetIn.Let_In (type.interp tx) (fun _ => type.interp tC))
- | App s d
- => fun '((f, x) : (type.interp s -> type.interp d) * type.interp s)
- => f x
+ Inductive ident : type -> Set :=
+ | Const {t} (v : interp t) : ident t
+ | Let_In {tx tC} : ident (tx -> (tx -> tC) -> tC)
+ | S : ident (nat -> nat)
+ | nil {t} : ident (list t)
+ | cons {t} : ident (t -> list t -> list t)
+ | pair {A B} : ident (A -> B -> A * B)
+ | fst {A B} : ident (A * B -> A)
+ | snd {A B} : ident (A * B -> B)
+ | bool_rect {T} : ident (T -> T -> bool -> T)
+ | nat_rect {P} : ident (P -> (nat -> P -> P) -> nat -> P)
+ | pred : ident (nat -> nat)
+ | List_seq : ident (nat -> nat -> list nat)
+ | List_repeat {A} : ident (A -> nat -> list A)
+ | List_combine {A B} : ident (list A -> list B -> list (A * B))
+ | List_map {A B} : ident ((A -> B) -> list A -> list B)
+ | List_flat_map {A B} : ident ((A -> list B) -> list A -> list B)
+ | List_partition {A} : ident ((A -> bool) -> list A -> list A * list A)
+ | List_app {A} : ident (list A -> list A -> list A)
+ | List_rev {A} : ident (list A -> list A)
+ | List_fold_right {A B} : ident ((B -> A -> A) -> A -> list B -> A)
+ | List_update_nth {T} : ident (nat -> (T -> T) -> list T -> list T)
+ | List_nth_default {T} : ident (T -> list T -> nat -> T)
+ | Z_runtime_mul : ident (Z -> Z -> Z)
+ | Z_runtime_add : ident (Z -> Z -> Z)
+ | Z_add : ident (Z -> Z -> Z)
+ | Z_mul : ident (Z -> Z -> Z)
+ | Z_pow : ident (Z -> Z -> Z)
+ | Z_opp : ident (Z -> Z)
+ | Z_div : ident (Z -> Z -> Z)
+ | Z_modulo : ident (Z -> Z -> Z)
+ | Z_eqb : ident (Z -> Z -> bool)
+ | Z_of_nat : ident (nat -> Z)
+ | Nat_sub : ident (nat -> nat -> nat).
+
+ Definition interp {t} (idc : ident t) : type.interp t
+ := match idc in ident t return type.interp t with
+ | Const t v => v
+ | Let_In tx tC => @LetIn.Let_In (type.interp tx) (fun _ => type.interp tC)
| S => Datatypes.S
- | nil t => fun _ => @Datatypes.nil (type.interp t)
- | cons t => curry2 (@Datatypes.cons (type.interp t))
+ | nil t => @Datatypes.nil (type.interp t)
+ | cons t => @Datatypes.cons (type.interp t)
+ | pair A B => @Datatypes.pair (type.interp A) (type.interp B)
| fst A B => @Datatypes.fst (type.interp A) (type.interp B)
| snd A B => @Datatypes.snd (type.interp A) (type.interp B)
- | bool_rect T => curry3 (@Datatypes.bool_rect (fun _ => type.interp T))
- | nat_rect P => curry3 (@Datatypes.nat_rect (fun _ => type.interp P))
+ | bool_rect T => @Datatypes.bool_rect (fun _ => type.interp T)
+ | nat_rect P => @Datatypes.nat_rect (fun _ => type.interp P)
| pred => Nat.pred
- | List_seq => curry2 List.seq
- | List_combine A B => curry2 (@List.combine (type.interp A) (type.interp B))
- | List_map A B => curry2 (@List.map (type.interp A) (type.interp B))
- | List_repeat A => curry2 (@List.repeat (type.interp A))
- | List_flat_map A B => curry2 (@List.flat_map (type.interp A) (type.interp B))
- | List_partition A => curry2 (@List.partition (type.interp A))
- | List_app A => curry2 (@List.app (type.interp A))
- | List_fold_right A B => curry3 (@List.fold_right (type.interp A) (type.interp B))
- | List_update_nth T => curry3 (@update_nth (type.interp T))
- | Z_runtime_mul => curry2 runtime_mul
- | Z_runtime_add => curry2 runtime_add
- | Z_add => curry2 Z.add
- | Z_mul => curry2 Z.mul
- | Z_pow => curry2 Z.pow
- | Z_modulo => curry2 Z.modulo
+ | List_seq => List.seq
+ | List_combine A B => @List.combine (type.interp A) (type.interp B)
+ | List_map A B => @List.map (type.interp A) (type.interp B)
+ | List_repeat A => @List.repeat (type.interp A)
+ | List_flat_map A B => @List.flat_map (type.interp A) (type.interp B)
+ | List_partition A => @List.partition (type.interp A)
+ | List_app A => @List.app (type.interp A)
+ | List_rev A => @List.rev (type.interp A)
+ | List_fold_right A B => @List.fold_right (type.interp A) (type.interp B)
+ | List_update_nth T => @update_nth (type.interp T)
+ | List_nth_default T => @List.nth_default (type.interp T)
+ | Z_runtime_mul => runtime_mul
+ | Z_runtime_add => runtime_add
+ | Z_add => Z.add
+ | Z_mul => Z.mul
+ | Z_pow => Z.pow
+ | Z_modulo => Z.modulo
| Z_opp => Z.opp
- | Z_div => curry2 Z.div
- | Z_eqb => curry2 Z.eqb
+ | Z_div => Z.div
+ | Z_eqb => Z.eqb
| Z_of_nat => Z.of_nat
+ | Nat_sub => Nat.sub
end.
Module List.
@@ -399,8 +398,10 @@ Module Compilers.
Notation flat_map := List_flat_map.
Notation partition := List_partition.
Notation app := List_app.
+ Notation rev := List_rev.
Notation fold_right := List_fold_right.
Notation update_nth := List_update_nth.
+ Notation nth_default := List_nth_default.
End List.
Module Z.
@@ -416,43 +417,50 @@ Module Compilers.
Notation of_nat := Z_of_nat.
End Z.
+ Module Nat.
+ Notation sub := Nat_sub.
+ End Nat.
+
Module Export Notations.
- Notation op := op.
+ Notation ident := ident.
End Notations.
- End op.
- Export op.Notations.
+ End ident.
+ Export ident.Notations.
Inductive expr {var : type -> Type} : type -> Type :=
- | TT : expr ()
- | Pair {A B} (a : expr A) (b : expr B) : expr (A * B)
| Var {t} (v : var t) : expr t
- | Op {s d} (opc : op s d) (args : expr s) : expr d
+ | Ident {t} (idc : ident t) : expr t
+ | App {s d} (f : expr (s -> d)) (x : expr s) : expr d
| Abs {s d} (f : var s -> expr d) : expr (s -> d).
+ Notation TT := (Ident (@ident.Const type.unit tt)).
+ Notation Pair x y := (App (App (Ident ident.pair) x) y).
+
Bind Scope expr_scope with expr.
Delimit Scope expr_scope with expr.
+ Notation "f x" := (App f x) (only printing) : expr_scope.
Notation "'λ' x .. y , t" := (Abs (fun x => .. (Abs (fun y => t%expr)) ..)) : expr_scope.
Notation "( x , y , .. , z )" := (Pair .. (Pair x%expr y%expr) .. z%expr) : expr_scope.
Notation "( )" := TT : expr_scope.
Notation "()" := TT : expr_scope.
- Notation "'expr_let' x := A 'in' b" := (Op op.Let_In (Pair A%expr (Abs (fun x => b%expr)))) : expr_scope.
- Notation "f x" := (Op op.App (f, x)%expr) (only printing) : expr_scope.
+ Notation "'expr_let' x := A 'in' b" := (App (App (Ident ident.Let_In) A%expr) (Abs (fun x => b%expr))) : expr_scope.
+ Notation "[ ]" := (Ident ident.nil) : expr_scope.
+ Notation "x :: xs" := (App (App (Ident ident.cons) x%expr) xs%expr) : expr_scope.
Definition Expr t := forall var, @expr var t.
Fixpoint interp {t} (e : @expr type.interp t) : type.interp t
:= match e with
- | TT => tt
- | Pair A B a b => (interp a, interp b)
| Var t v => v
- | Op s d opc args => op.interp opc (interp args)
+ | Ident t idc => ident.interp idc
+ | App s d f x => interp f (interp x)
| Abs s d f => fun v => interp (f v)
end.
Definition Interp {t} (e : Expr t) := interp (e _).
Definition const {var t} (v : type.interp t) : @expr var t
- := Op (op.Const v) TT.
+ := Ident (ident.Const v).
Section option_partition.
Context {A : Type} (f : A -> option Datatypes.bool).
@@ -509,48 +517,102 @@ Module Compilers.
| _ => None
end.
- Definition invert_Pair {A B} (e : @expr var (type.prod A B)) : option (@expr var A * @expr var B)
- := match e in expr t return option match t with
- | type.prod _ _ => _
- | _ => True
- end with
- | Pair _ _ a b => Some (a, b)
+ Definition invert_App {d} (e : @expr var d) : option { s : _ & @expr var (s -> d) * @expr var s }%type
+ := match e with
+ | App s d f x => Some (existT _ s (f, x))
| _ => None
end.
- Definition invert_Op {t} (e : @expr var t) : option { s : _ & op s t * @expr var s }%type
+ Definition invert_Ident {t} (e : @expr var t) : option (ident t)
:= match e with
- | Op s d opc args => Some (existT _ s (opc, args))
+ | Ident t idc => Some idc
| _ => None
end.
- Definition invert_OpConst {t} (e : @expr var t) : option (type.interp t)
- := match invert_Op e with
- | Some (existT s (opc, args))
- => match opc with
- | op.Const t v => Some v
+ Definition invert_Const {t} (e : @expr var t) : option (type.interp t)
+ := match invert_Ident e with
+ | Some idc
+ => match idc with
+ | ident.Const t v => Some v
| _ => None
end
| None => None
end.
- Definition invert_op_S (e : @expr var type.nat) : option (@expr var type.nat)
- := match invert_Op e with
- | Some (existT s (opc, args))
- => match opc in op s d return expr s -> option (expr type.nat) with
- | op.S => fun args => Some args
+ Definition invert_AppIdent {d} (e : @expr var d) : option { s : _ & @ident (s -> d) * @expr var s }%type
+ := match invert_App e with
+ | Some (existT s (f, x))
+ => match invert_Ident f with
+ | Some f' => Some (existT _ s (f', x))
+ | None => None
+ end
+ | None => None
+ end.
+
+ Definition invert_App2 {d} (e : @expr var d) : option { s1s2 : _ * _ & @expr var (fst s1s2 -> snd s1s2 -> d) * @expr var (fst s1s2) * @expr var (snd s1s2) }%type
+ := match invert_App e with
+ | Some (existT s (f, y))
+ => match invert_App f with
+ | Some (existT s' (f', x))
+ => Some (existT _ (s', s) (f', x, y))
+ | None => None
+ end
+ | None => None
+ end.
+
+ Definition invert_Pair {A B} (e : @expr var (type.prod A B)) : option (@expr var A * @expr var B)
+ := match invert_App2 e with
+ | Some (existT (s1, s2) (f, x, y))
+ => match invert_Ident f with
+ | Some idc
+ => match idc in ident t
+ return match t return Type with
+ | (A -> B -> _)%ctype
+ => expr A
+ | _ => True
+ end
+ -> match t return Type with
+ | (A -> B -> _)%ctype
+ => expr B
+ | _ => True
+ end
+ -> option match t with
+ | (_ -> _ -> A * B)%ctype
+ => expr A * expr B
+ | _ => True
+ end
+ with
+ | ident.pair A B => fun x y => Some (x, y)
+ | _ => fun _ _ => None
+ end x y
+ | None => None
+ end
+ | None => None
+ end.
+
+ Definition invert_S (e : @expr var type.nat) : option (@expr var type.nat)
+ := match invert_AppIdent e with
+ | Some (existT s (idc, x))
+ => match idc in ident t
+ return match t return Type with
+ | (s -> d)%ctype => expr s
+ | _ => True
+ end
+ -> option (expr type.nat)
+ with
+ | ident.S => fun args => Some args
| _ => fun _ => None
- end args
+ end x
| None => None
end.
- Definition invert_Z (e : @expr var type.Z) : option Z := invert_OpConst e.
- Definition invert_bool (e : @expr var type.bool) : option bool := invert_OpConst e.
+ Definition invert_Z (e : @expr var type.Z) : option Z := invert_Const e.
+ Definition invert_bool (e : @expr var type.bool) : option bool := invert_Const e.
Fixpoint invert_nat_full (e : @expr var type.nat) : option nat
- := match e with
- | Op _ _ op.S args
+ := match e return option nat with
+ | App type.nat _ (Ident _ ident.S) args
=> option_map S (invert_nat_full args)
- | Op _ _ (op.Const type.nat v) _
+ | Ident _ (ident.Const type.nat v)
=> Some v
| _ => None
end.
@@ -562,37 +624,69 @@ Module Compilers.
| _ => True
end
with
- | Op s d opc args
- => match opc in op s d
- return option match s with
- | type.prod A (type.list B) => expr A * list (expr B)
+ | Ident t idc
+ => match idc in ident t
+ return option match t return Type with
+ | type.list A => list (expr A)
| _ => True
end
- -> option match d with
- | type.list t => list (expr t)
- | _ => True
- end
with
- | op.Const (type.list _) v => fun _ => Some (List.map const v)
- | op.cons _ => option_map (fun '(x, xs) => cons x xs)
- | op.nil _ => fun _ => Some nil
- | _ => fun _ => None
+ | ident.Const (type.list _) v => Some (List.map const v)
+ | ident.nil _ => Some nil
+ | _ => None
end
- (match args in expr t
- return option match t with
- | type.prod A (type.list B) => expr A * list (expr B)
+ | App (type.list s) d f xs
+ => match @invert_list_full s xs return _ with
+ | Some xs
+ => match invert_AppIdent f
+ return option match d return Type with
+ | type.list t => list (expr t)
+ | _ => True
+ end
+ with
+ | Some (existT s' (idc, x))
+ => match idc in ident t
+ return match t return Type with
+ | (s' -> d')%ctype => expr s'
| _ => True
end
- with
- | Pair _ (type.list _) x xs
- => match @invert_list_full _ xs with
- | Some xs => Some (x, xs)
- | None => None
- end
- | _ => None
- end)
+ -> match t return Type with
+ | (s' -> type.list s -> _)%ctype => list (expr s)
+ | _ => list (@expr var s)
+ end
+ -> option match t return Type with
+ | (_ -> _ -> type.list d)%ctype => list (expr d)
+ | _ => True
+ end
+ with
+ | ident.cons A => fun x xs => Some (cons x xs)
+ | _ => fun _ _ => None
+ end x xs
+ | _ => None
+ end
+ | None => None
+ end
| _ => None
end.
+
+ (** TODO: figure out a better name for this *)
+ Definition Smart_invert_Pair {A B} (e : @expr var (type.prod A B)) : option (@expr var A * @expr var B)
+ := match invert_Pair e, invert_Var e, invert_Const e with
+ | Some ab, _, _ => Some ab
+ | _, Some v, _ => Some (App (Ident ident.fst) (Var v), App (Ident ident.snd) (Var v))
+ | _, _, Some v => Some (@const var A (fst v), @const var B (snd v))
+ | None, None, None => None
+ end.
+
+ (** TODO: figure out a better name for this *)
+ Definition Smart_invert_list_full {A} (e : @expr var (type.list A)) : option (list (@expr var A))
+ := match invert_Const e, invert_list_full e with
+ | Some ls, _ => Some (List.map (@const var A) ls)
+ | _, Some ls => Some ls
+ | None, None => None
+ end.
+
+
(*Section with_map.
(* oh, the horrors of not being able to use non-linear deep
pattern matches. Luckily Coq's guard checker unfolds things,
@@ -634,17 +728,17 @@ Module Compilers.
: forall d : extra_dataT t, option (list (U t d))
:= match e in expr t return list_to_forall_data_option_list t
with
- | Op s d opc args
- => match opc in op s d
+ | Op s d idc args
+ => match idc in op s d
return (prod_list_to_forall_data_option_list s
-> list_to_forall_data_option_list d)
with
- | op.Const (type.list _) v
+ | ident.Const (type.list _) v
=> fun _ data => Some (List.map (f _ data) (List.map const v))
- | op.cons _
+ | ident.cons _
=> fun xs data
=> option_map (fun '(x, xs) => cons (f _ data x) xs) (xs data)
- | op.nil _
+ | ident.nil _
=> fun _ _ => Some nil
| _ => fun _ _ => None
end
@@ -669,23 +763,260 @@ Module Compilers.
Definition reify_list {t} (ls : list (@expr var t)) : @expr var (type.list t)
:= list_rect
(fun _ => _)
- (Op op.nil TT)
- (fun x _ xs => Op op.cons (x, xs))
+ (Ident ident.nil)
+ (fun x _ xs => App (App (Ident ident.cons) x) xs)
ls.
- End gallina_reify.
+ Definition reify_list_by_app {t} (ls : list (@expr var (type.list t))) : @expr var (type.list t)
+ := list_rect
+ (fun _ => _)
+ (Ident ident.nil)
+ (fun ls1 _ ls2 => App (App (Ident ident.List.app) ls1) ls2)
+ ls.
+ End gallina_reify.
+ (** TODO: should this even be named [arguments]? *)
Module arguments.
- Inductive arguments : type -> Set :=
- | generic {T} : arguments T
- (*| cps {T} (aT : arguments T) : arguments T*)
- | arrow {A B} (aB : arguments B) : arguments (A -> B)
- | unit : arguments type.unit
- | prod {A B} (aA : arguments A) (aB : arguments B) : arguments (A * B)
- | list {T} (aT : arguments T) : arguments (type.list T)
- | nat : arguments type.nat
- | Z : arguments type.Z
- | bool : arguments type.bool.
+ (*Module rec.*)
+ (** TODO: pick a better name for this (partial_expr?) *)
+ Section interp.
+ Context (var : type -> Type).
+ Definition interp_prestep (interp : type -> Type) (t : type)
+ := match t return Type with
+ | type.prod A B as t => interp A * interp B
+ | type.arrow s d => interp s -> interp d
+ | type.list A => list (interp A)
+ | type.unit as t
+ | type.Z as t
+ | type.nat as t
+ | type.bool as t
+ => type.interp t
+ end%type.
+ Definition interp_step (interp : type -> Type) (t : type)
+ := match t return Type with
+ | type.unit as t
+ | type.arrow _ _ as t
+ => interp_prestep interp t
+ | type.prod _ _ as t
+ | type.list _ as t
+ | type.Z as t
+ | type.nat as t
+ | type.bool as t
+ => @expr var t + interp_prestep interp t
+ end%type.
+ Fixpoint interp (t : type)
+ := interp_step interp t.
+
+ Definition unprestep {t : type} : interp_prestep interp t -> interp t
+ := match t return interp_prestep interp t -> interp t with
+ | type.unit as t
+ | type.arrow _ _ as t
+ => id
+ | type.prod _ _ as t
+ | type.list _ as t
+ | type.Z as t
+ | type.nat as t
+ | type.bool as t
+ => @inr _ (interp_prestep interp t)
+ end%type.
+
+ Definition unprestep2 {t : type}
+ : interp_prestep (interp_prestep interp) t
+ -> match t with
+ | type.arrow _ _ => interp_prestep (interp_prestep interp) t
+ | t => interp_prestep interp t
+ end
+ := match t
+ return (interp_prestep (interp_prestep interp) t
+ -> match t with
+ | type.arrow _ _ => interp_prestep (interp_prestep interp) t
+ | t => interp_prestep interp t
+ end)
+ with
+ | type.prod A B
+ => fun '((a, b) : interp_prestep interp A * interp_prestep interp B)
+ => (@unprestep A a, @unprestep B b)
+ | type.list A as t
+ => List.map (@unprestep A)
+ | type.arrow _ _ as t
+ | type.unit as t
+ | type.Z as t
+ | type.nat as t
+ | type.bool as t
+ => id
+ end%type.
+ End interp.
+ Arguments unprestep {var t} _.
+ Arguments unprestep2 {var t} _.
+
+
+ (*Definition invert1 {var} {t : type}
+ : interp var t -> (var t + interp_step (interp var) t)
+ := match t with
+ | type.unit
+ | _
+ => id
+ end.
+
+ Definition generic {var : type -> Type} {t : type} : var t -> interp var t
+ := match t with
+ | type.unit
+ | _
+ => @inl _ _
+ end.*)
+
+ Notation expr_const := const.
+
+ Module expr.
+ Section reify.
+ Context {var : type -> Type}.
+ (** TODO: figure out if these names are good; [eta_expand] is maybe better called [reflect]? or [expand]? *)
+ Fixpoint reify {t : type} {struct t}
+ : interp var t -> @expr var t
+ := match t return interp var t -> expr t with
+ | type.unit as t => expr_const (t:=t)
+ | type.prod A B as t
+ => fun x : expr t + interp var A * interp var B
+ => match x with
+ | inl v => v
+ | inr (a, b) => (@reify A a, @reify B b)%expr
+ end
+ | type.arrow s d
+ => fun (f : interp var s -> interp var d)
+ => Abs (fun x
+ => @reify d (f (@eta_expand s (Var x))))
+ | type.list A as t
+ => fun x : expr t + list (interp var A)
+ => match x with
+ | inl v => v
+ | inr v => reify_list (List.map (@reify A) v)
+ end
+ | type.nat as t
+ | type.Z as t
+ | type.bool as t
+ => fun x : expr t + type.interp t
+ => match x with
+ | inl v => v
+ | inr v => expr_const (t:=t) v
+ end
+ end
+ with eta_expand {t : type}
+ : @expr var t -> interp var t
+ := match t return expr t -> interp var t with
+ | type.arrow s d
+ => fun (f : expr (s -> d)) (x : interp var s)
+ => @eta_expand d (App f (@reify s x))
+ | type.unit => fun _ => tt
+ | type.prod A B as t
+ => fun v : expr t
+ => let inr := @inr (expr t) (interp_prestep (interp var) t) in
+ let inl := @inl (expr t) (interp_prestep (interp var) t) in
+ match Smart_invert_Pair v with
+ | Some (a, b)
+ => inr (@eta_expand A a, @eta_expand B b)
+ | None
+ => inl v
+ end
+ | type.list A as t
+ => fun v : expr t
+ => let inr := @inr (expr t) (interp_prestep (interp var) t) in
+ let inl := @inl (expr t) (interp_prestep (interp var) t) in
+ match Smart_invert_list_full v with
+ | Some ls
+ => inr (List.map (@eta_expand A) ls)
+ | None
+ => inl v
+ end
+ | type.nat as t
+ => fun v : expr t
+ => let inr := @inr (expr t) (interp_prestep (interp var) t) in
+ let inl := @inl (expr t) (interp_prestep (interp var) t) in
+ match invert_nat_full v with
+ | Some v => inr v
+ | None => inl v
+ end
+ | type.Z as t
+ | type.bool as t
+ => fun v : expr t
+ => let inr := @inr (expr t) (interp_prestep (interp var) t) in
+ let inl := @inl (expr t) (interp_prestep (interp var) t) in
+ match invert_Const v with
+ | Some v => inr v
+ | None => inl v
+ end
+ end.
+ End reify.
+
+ Section SmartLetIn.
+ Context {var : type -> Type} {tC : type}.
+ (** TODO: Find a better name for this *)
+ (** N.B. This always inlines functions; not sure if this is the right thing to do *)
+ (** TODO: should we handle let-bound pairs, let-bound lists? What should we do with them? Here, I make the decision to always inline them; not sure if this is right *)
+ Fixpoint SmartLetIn {tx : type} : interp var tx -> (interp var tx -> interp var tC) -> interp var tC
+ := match tx return interp var tx -> (interp var tx -> interp var tC) -> interp var tC with
+ | type.unit => fun _ f => f tt
+ | type.arrow _ _
+ | type.prod _ _
+ | type.list _
+ => fun x f => f x
+ | type.nat as t
+ | type.Z as t
+ | type.bool as t
+ => fun (x : expr t + type.interp t) (f : expr t + type.interp t -> interp var tC)
+ => match x with
+ | inl e
+ => match invert_Var e, invert_Const e with
+ | Some v, _ => f (inl (Var v))
+ | _, Some v => f (inr v)
+ | None, None => eta_expand (expr_let y := e in reify (f (inl (Var y))))%expr
+ end
+ | inr v => f (inr v)
+ end
+ end.
+ End SmartLetIn.
+ End expr.
+ (*
+ Section const.
+ Context {var : type -> Type} (const_var_arrow : forall s d,
+ type.interp (s -> d) -> var (s -> d)%ctype).
+ Fixpoint const {t : type} : type.interp t -> interp var t.
+ refine match t return type.interp t -> interp var t with
+ | type.prod A B as t
+ => fun '((a, b) : type.interp A * type.interp B)
+ => @inr
+ (expr t) (interp var A * interp var B)
+ (@const A a, @const B b)
+ | type.arrow s d
+ => fun (f : type.interp s -> type.interp d) (x : interp var s)
+ => _ : interp var d
+ | type.list A as t
+ => fun ls : list (type.interp A)
+ => @inr (expr t) (list (interp var A))
+ (List.map (@const A) ls)
+ | type.unit as t
+ => id
+ | type.nat as t
+ | type.Z as t
+ | type.bool as t
+ => @inr (expr t) (type.interp t)
+ end.
+ cbn.
+ End const.
+*)
+ (*End rec.*)
+
+ (*Module ind.
+ Module arguments.
+ Inductive arguments : type -> Set :=
+ | generic {T} : arguments T
+ (*| cps {T} (aT : arguments T) : arguments T*)
+ | arrow {A B} (aB : arguments B) : arguments (A -> B)
+ | unit : arguments type.unit
+ | prod {A B} (aA : arguments A) (aB : arguments B) : arguments (A * B)
+ | list {T} (aT : arguments T) : arguments (type.list T)
+ | nat : arguments type.nat
+ | Z : arguments type.Z
+ | bool : arguments type.bool.
Definition preinvertT (t : type) :=
match t with
@@ -859,7 +1190,40 @@ Module Compilers.
End option.
End type.
- Module expr.
+ Module expr.
++ Section reify.
++ Context {var : type -> Type}.
++ Fixpoint reify {t : type} (v : interp (@expr var) t) {struct t}
++ : @expr var t
++ := match invert1 v with
++ | inl e => e
++ | inr e
++ => match t return interp_step (interp expr) t -> expr t with
++ | type.prod A B
++ => fun '((a, b) : interp expr A * interp expr B)
++ => Pair (@reify A a) (@reify B b)
++ | type.arrow s d
++ => fun f
++ => Abs (fun x => @reify d (f (generic (Var x))))
++ | type.list A
++ => fun e
++ => list_rect
++ (fun _ => expr (type.list A))
++ (Ident ident.nil)
++ (fun x _ xs
++ => App (App (Ident ident.cons) x) xs)
++ (List.map (@reify A) e)
++ | type.unit as t
++ | type.nat as t
++ | type.Z as t
++ | type.bool as t
++ => expr_const (t:=t)
++ end e
++ end.
++ End reify.
++
+ End ind.*)
+ (*
Section interp.
Context (var : type -> Type).
Fixpoint interp {t} (a : arguments t)
@@ -873,7 +1237,7 @@ Module Compilers.
B aB
match invert_Abs e, invert_Var arg with
| Some f, Some arg => f arg
- | _, _ => Op op.App (e, arg)
+ | _, _ => Op ident.App (e, arg)
end
| unit => fun _ => tt
| prod A B aA aB
@@ -910,58 +1274,411 @@ Module Compilers.
| Z => @const var type.Z
| bool => @const var type.bool
end.
- End reify.
- End expr.
-
+ End reify.*)
+ (*End expr.*)
+ (*
Module Export Notations.
Delimit Scope arguments_scope with arguments.
- Bind Scope arguments_scope with arguments.
- Notation "()" := unit : arguments_scope.
+ Bind Scope arguments_scope with interp.
+ Notation "()" := (inr tt) : arguments_scope.
Notation "A * B" := (prod A B) : arguments_scope.
Notation "A -> B" := (@arrow A _ B) (only printing) : arguments_scope.
Notation "A -> B" := (arrow B) (only parsing) : arguments_scope.
Global Coercion generic : type.type >-> arguments.
Notation arguments := arguments.
End Notations.
+ *)
+
+ Definition sum_arrow {A A' B B'} (f : A -> A') (g : B -> B')
+ (v : A + B)
+ : A' + B'
+ := match v with
+ | inl v => inl (f v)
+ | inr v => inr (g v)
+ end.
+ Infix "+" := sum_arrow : function_scope.
- Module op.
- Local Open Scope arguments_scope.
- Definition lookup {s d} (opc : op s d) : arguments s * arguments d
- := match opc in op s d return arguments s * arguments d with
- | op.Const t v => (generic, ground)
- | op.Let_In tx tC => (tx * (tx -> tC), generic)
- | op.App s d => ((s -> d) * s, generic)
- | op.S => (ground, ground)
- | op.nil t => (generic, ground)
- | op.cons t => (t * list t, list t)
- | op.fst A B => (A * B, generic)
- | op.snd A B => (A * B, generic)
- | op.bool_rect T => (T * T * bool, generic)
- | op.nat_rect P => (P * (nat -> P -> P) * nat, generic)
- | op.pred => (nat, ground)
- | op.List_seq => (nat * nat, ground)
- | op.List_repeat A => (A * nat, list A)
- | op.List_combine A B => (list A * list B, list (A * B))
- | op.List_map A B => ((A -> B) * list A, list B)
- | op.List_flat_map A B => ((A -> list B) * list A, list B)
- | op.List_partition A => ((A -> bool) * list A, list A * list A)
- | op.List_app A => (list A * list A, list A)
- | op.List_fold_right A B => ((B -> A -> A) * A * list B, generic)
- | op.List_update_nth T => (nat * (T -> T) * list T, list T)
- | op.Z_runtime_mul => (Z * Z, Z)
- | op.Z_runtime_add => (Z * Z, Z)
- | op.Z_add => (Z * Z, Z)
- | op.Z_mul => (Z * Z, Z)
- | op.Z_pow => (Z * Z, Z)
- | op.Z_opp => (Z, Z)
- | op.Z_div => (Z * Z, Z)
- | op.Z_modulo => (Z * Z, Z)
- | op.Z_eqb => (Z * Z, bool)
- | op.Z_of_nat => (nat, Z)
+ Module ident.
+ (*Local Open Scope arguments_scope.*)
+ Section interp.
+ Context {var : type -> Type}.
+ (*Notation default_App0 idc
+ := (inr (ident.interp idc))
+ (only parsing).
+ Notation default_App1 idc
+ := (inr (App (Ident idc) + ident.interp idc)%function)
+ (only parsing).
+ Notation default_App2 idc
+ := (inr (App (Ident idc)
+ + (fun x
+ => App (App (Ident idc) (expr_const x))
+ + ident.interp idc x))%function)
+ (only parsing).
+
+ Let default_App1e {A B}
+ (f : interp (@expr var) A -> interp (@expr var) B)
+ : interp (@expr var) (A -> B)
+ := inr f.
+ Let default_App2e {A B C}
+ (f : interp (@expr var) A -> interp (@expr var) B -> interp (@expr var) C)
+ : interp (@expr var) (A -> B -> C)
+ := inr (fun x => inr (f x)).
+ *)
+ Let defaulted_App_p_e {A B} (idc : ident (A -> B))
+ (F : interp_prestep (interp var) A
+ -> interp var B)
+ : @expr var A + interp_prestep (interp var) A
+ -> interp var B
+ := fun x
+ => match x with
+ | inl e => expr.eta_expand (App (Ident idc) e)
+ | inr x => F x
+ end.
+ Let defaulted_App_p_p {A B} (idc : ident (A -> B))
+ (F : interp_prestep (interp var) A
+ -> interp_prestep (interp var) B)
+ : @expr var A + interp_prestep (interp var) A
+ -> @expr var B + interp_prestep (interp var) B
+ := (App (Ident idc) + F)%function.
+ Let defaulted_App_ep_p {A B C} (idc : ident (A -> B -> C))
+ (F : interp var A
+ -> interp_prestep (interp var) B
+ -> interp_prestep (interp var) C)
+ : interp var A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + interp_prestep (interp var) C
+ := fun x
+ => (App (App (Ident idc) (expr.reify x))
+ + (F x))%function.
+ Let defaulted_App_eep_e {A B C D} (idc : ident (A -> B -> C -> D))
+ (F : interp var A
+ -> interp var B
+ -> interp_prestep (interp var) C
+ -> interp var D)
+ : interp var A
+ -> interp var B
+ -> @expr var C + interp_prestep (interp var) C
+ -> interp var D
+ := fun x y z
+ => match z with
+ | inl z => expr.eta_expand (App (App (App (Ident idc) (expr.reify x)) (expr.reify y)) z)
+ | inr z => F x y z
+ end.
+ Let defaulted_App_pe_p {A B C} (idc : ident (A -> B -> C))
+ (F : interp_prestep (interp var) A
+ -> interp var B
+ -> interp_prestep (interp var) C)
+ : @expr var A + interp_prestep (interp var) A
+ -> interp var B
+ -> @expr var C + interp_prestep (interp var) C
+ := fun x y
+ => match x with
+ | inl x => inl (App (App (Ident idc) x) (expr.reify y))
+ | inr x => inr (F x y)
+ end.
+ Let defaulted_App_pep_p {A B C D} (idc : ident (A -> B -> C -> D))
+ (F : interp_prestep (interp var) A
+ -> interp var B
+ -> interp_prestep (interp var) C
+ -> interp_prestep (interp var) D)
+ : @expr var A + interp_prestep (interp var) A
+ -> interp var B
+ -> @expr var C + interp_prestep (interp var) C
+ -> @expr var D + interp_prestep (interp var) D
+ := fun x y z
+ => let xz
+ := match x, z with
+ | inl x, inl z => inl (x, z)
+ | inr x, inl z => inl (expr.reify (unprestep x), z)
+ | inl x, inr z => inl (x, expr.reify (unprestep z))
+ | inr x, inr z => inr (x, z)
+ end in
+ match xz with
+ | inl (x, z) => inl (App (App (App (Ident idc) x) (expr.reify y)) z)
+ | inr (x, z) => inr (F x y z)
+ end.
+ Let defaulted_App_pp_p {A B C} (idc : ident (A -> B -> C))
+ (F : interp_prestep (interp var) A
+ -> interp_prestep (interp var) B
+ -> interp_prestep (interp var) C)
+ : @expr var A + interp_prestep (interp var) A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + interp_prestep (interp var) C
+ := fun x y
+ => let xy
+ := match x, y with
+ | inl x, inl y => inl (x, y)
+ | inr x, inl y => inl (expr.reify (unprestep x), y)
+ | inl x, inr y => inl (x, expr.reify (unprestep y))
+ | inr x, inr y => inr (x, y)
+ end in
+ match xy with
+ | inl (x, y) => inl (App (App (Ident idc) x) y)
+ | inr (x, y) => inr (F x y)
+ end.
+ Let defaulted_App_pp_p_or_pe_e_or_ep_e {A B C} (idc : ident (A -> B -> C))
+ (F : interp_prestep (interp var) A
+ -> interp_prestep (interp var) B
+ -> interp_prestep (interp var) C)
+ (F1 : interp_prestep (interp var) A
+ -> @expr var B
+ -> option (@expr var C + interp_prestep (interp var) C))
+ (F2 : @expr var A
+ -> interp_prestep (interp var) B
+ -> option (@expr var C + interp_prestep (interp var) C))
+ : @expr var A + interp_prestep (interp var) A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + interp_prestep (interp var) C
+ := fun x y
+ => let default := defaulted_App_pp_p idc F x y in
+ match x, y with
+ | inl x, inl y => inl (App (App (Ident idc) x) y)
+ | inl x, inr y => match F2 x y with
+ | Some Fxy => Fxy
+ | None => default
+ end
+ | inr x, inl y => match F1 x y with
+ | Some Fxy => Fxy
+ | None => default
+ end
+ | inr x, inr y => inr (F x y)
+ end.
+ Let defaulted_App_pp_p_or_pe_e_comm {A C} (idc : ident (A -> A -> C))
+ (F : interp_prestep (interp var) A
+ -> interp_prestep (interp var) A
+ -> interp_prestep (interp var) C)
+ (F1 : interp_prestep (interp var) A
+ -> @expr var A
+ -> option (@expr var C + interp_prestep (interp var) C))
+ : @expr var A + interp_prestep (interp var) A
+ -> @expr var A + interp_prestep (interp var) A
+ -> @expr var C + interp_prestep (interp var) C
+ := defaulted_App_pp_p_or_pe_e_or_ep_e
+ idc
+ F
+ F1
+ (fun x y => F1 y x).
+ Let defaulted_App_epp_e {A B C D} (idc : ident (A -> B -> C -> D))
+ (F : interp var A
+ -> interp_prestep (interp var) B
+ -> interp_prestep (interp var) C
+ -> interp var D)
+ : interp var A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + interp_prestep (interp var) C
+ -> interp var D
+ := fun x y z
+ => let yz
+ := match y, z with
+ | inl y, inl z => inl (y, z)
+ | inr y, inl z => inl (expr.reify (unprestep y), z)
+ | inl y, inr z => inl (y, expr.reify (unprestep z))
+ | inr y, inr z => inr (y, z)
+ end in
+ match yz with
+ | inl (y, z) => expr.eta_expand (App (App (App (Ident idc) (expr.reify x)) y) z)
+ | inr (y, z) => F x y z
+ end.
+ Let defaulted_App_pp_p2 {A B C} (idc : ident (A -> B -> C))
+ (F : interp_prestep (interp var) A
+ -> interp_prestep (interp var) B
+ -> interp_prestep (interp_prestep (interp var)) C)
+ : @expr var A + interp_prestep (interp var) A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + match C with
+ | type.arrow s d => interp_prestep (interp_prestep (interp var)) C
+ | C => interp_prestep (interp var) C
+ end
+ := fun x y
+ => let xy
+ := match x, y with
+ | inl x, inl y => inl (x, y)
+ | inr x, inl y => inl (expr.reify (unprestep x), y)
+ | inl x, inr y => inl (x, expr.reify (unprestep y))
+ | inr x, inr y => inr (x, y)
+ end in
+ match xy with
+ | inl (x, y) => inl (App (App (Ident idc) x) y)
+ | inr (x, y) => inr (unprestep2 (F x y))
+ end.
+ Let defaulted_App_ep_p2o {A B C} (idc : ident (A -> B -> C))
+ (F : interp var A
+ -> interp_prestep (interp var) B
+ -> option (interp_prestep (interp_prestep (interp var)) C))
+ : interp var A
+ -> @expr var B + interp_prestep (interp var) B
+ -> @expr var C + match C with
+ | type.arrow s d => interp_prestep (interp_prestep (interp var)) C
+ | C => interp_prestep (interp var) C
+ end
+ := fun x y
+ => match y with
+ | inl y => inl (App (App (Ident idc) (expr.reify x)) y)
+ | inr y
+ => match F x y with
+ | Some Fxy => inr (unprestep2 Fxy)
+ | None
+ => inl (App (App (Ident idc) (expr.reify x)) (expr.reify (unprestep y)))
+ end
+ end.
+
+
+
+ Let defaulted_App_ee_p {A B C} (idc : ident (A -> B -> C))
+ (F : interp var A
+ -> interp var B
+ -> interp_prestep (interp var) C)
+ : interp var A
+ -> interp var B
+ -> @expr var C + interp_prestep (interp var) C
+ := fun x y => inr (F x y).
+
+ Definition interp {t} (idc : ident t) : interp var t
+ := match idc in ident t return interp var t with
+ | ident.Const t v as idc
+ => expr.eta_expand (Ident idc)
+ | ident.Let_In tx tC
+ => expr.SmartLetIn
+ | ident.nil t
+ => inr (@nil (interp var t))
+ | ident.cons t as idc
+ => defaulted_App_ep_p idc (@cons (interp var t))
+ | ident.pair A B as idc
+ => defaulted_App_ee_p idc (@pair (interp var A) (interp var B))
+ | ident.fst A B as idc
+ => defaulted_App_p_e idc (@fst (interp var A) (interp var B))
+ | ident.snd A B as idc
+ => defaulted_App_p_e idc (@snd (interp var A) (interp var B))
+ | ident.bool_rect T as idc
+ => defaulted_App_eep_e idc (@bool_rect (fun _ => interp var T))
+ | ident.nat_rect P as idc
+ => defaulted_App_eep_e
+ idc
+ (fun O_case S_case n
+ => @nat_rect
+ (fun _ => interp var P)
+ O_case
+ (fun n' => S_case (inr n'))
+ n)
+ | ident.List_seq as idc
+ => defaulted_App_pp_p2 idc List.seq
+ | ident.List_repeat A as idc
+ => defaulted_App_ep_p idc (@List.repeat (interp var A))
+ | ident.List_combine A B as idc
+ => defaulted_App_pp_p2 idc (@List.combine (interp var A) (interp var B))
+ | ident.List_map A B as idc
+ => defaulted_App_ep_p idc (@List.map (interp var A) (interp var B))
+ | ident.List_flat_map A B as idc
+ => fun (f : interp var A -> expr (type.list B) + list (interp var B))
+ (ls : expr (type.list A) + list (interp var A))
+ => match ls return expr (type.list B) + list (interp var B) with
+ | inl lse
+ => inl (App (App (Ident idc) (expr.reify (t:=A->type.list B) f)) lse)
+ | inr ls
+ => match option_flat_map
+ (fun x => match f x with
+ | inl _ => None
+ | inr v => Some v
+ end)
+ ls
+ with
+ | Some res => inr res
+ | None
+ => let ls'
+ := List.map
+ (fun x => match f x with
+ | inl e => e
+ | inr v => reify_list (List.map expr.reify v)
+ end)
+ ls in
+ inl (reify_list_by_app ls')
+ end
+ end
+ | ident.List_partition A as idc
+ => defaulted_App_ep_p2o
+ idc
+ (fun f => option_partition (fun x => match f x with
+ | inl _ => None
+ | inr b => Some b
+ end))
+ | ident.List_app A as idc
+ => defaulted_App_pp_p idc (@List.app (interp var A))
+ | ident.List_rev A as idc
+ => defaulted_App_p_p idc (@List.rev (interp var A))
+ | ident.List_fold_right A B as idc
+ => defaulted_App_eep_e idc (@List.fold_right (interp var A) (interp var B))
+ | ident.List_update_nth T as idc
+ => defaulted_App_pep_p idc (@update_nth (interp var T))
+ | ident.List_nth_default T as idc
+ => defaulted_App_epp_e idc (@List.nth_default (interp var T))
+ | ident.pred as idc
+ | ident.S as idc
+ | ident.Z_of_nat as idc
+ | ident.Z_opp as idc
+ => defaulted_App_p_p idc (ident.interp idc)
+ | ident.Z_runtime_mul as idc
+ => defaulted_App_pp_p_or_pe_e_comm
+ idc (ident.interp idc)
+ (fun x e
+ => if Z.eqb x 0
+ then Some (inr 0%Z)
+ else if Z.eqb x 1
+ then Some (inl e)
+ else None)
+ | ident.Z_runtime_add as idc
+ => defaulted_App_pp_p_or_pe_e_comm
+ idc (ident.interp idc)
+ (fun x e
+ => if Z.eqb x 0
+ then Some (inl e)
+ else None)
+ | ident.Z_add as idc
+ | ident.Z_mul as idc
+ | ident.Z_pow as idc
+ | ident.Z_div as idc
+ | ident.Z_modulo as idc
+ | ident.Z_eqb as idc
+ | ident.Nat_sub as idc
+ => defaulted_App_pp_p idc (ident.interp idc)
+ end.
+ End interp. (*
+
+ Definition lookup {s d} (idc : op s d) : arguments s * arguments d
+ := match idc in op s d return arguments s * arguments d with
+ | ident.Const t v => (generic, ground)
+ | ident.Let_In tx tC => (tx * (tx -> tC), generic)
+ | ident.App s d => ((s -> d) * s, generic)
+ | ident.S => (ground, ground)
+ | ident.nil t => (generic, ground)
+ | ident.cons t => (t * list t, list t)
+ | ident.fst A B => (A * B, generic)
+ | ident.snd A B => (A * B, generic)
+ | ident.bool_rect T => (T * T * bool, generic)
+ | ident.nat_rect P => (P * (nat -> P -> P) * nat, generic)
+ | ident.pred => (nat, ground)
+ | ident.List_seq => (nat * nat, ground)
+ | ident.List_repeat A => (A * nat, list A)
+ | ident.List_combine A B => (list A * list B, list (A * B))
+ | ident.List_map A B => ((A -> B) * list A, list B)
+ | ident.List_flat_map A B => ((A -> list B) * list A, list B)
+ | ident.List_partition A => ((A -> bool) * list A, list A * list A)
+ | ident.List_app A => (list A * list A, list A)
+ | ident.List_fold_right A B => ((B -> A -> A) * A * list B, generic)
+ | ident.List_update_nth T => (nat * (T -> T) * list T, list T)
+ | ident.Z_runtime_mul => (Z * Z, Z)
+ | ident.Z_runtime_add => (Z * Z, Z)
+ | ident.Z_add => (Z * Z, Z)
+ | ident.Z_mul => (Z * Z, Z)
+ | ident.Z_pow => (Z * Z, Z)
+ | ident.Z_opp => (Z, Z)
+ | ident.Z_div => (Z * Z, Z)
+ | ident.Z_modulo => (Z * Z, Z)
+ | ident.Z_eqb => (Z * Z, bool)
+ | ident.Z_of_nat => (nat, Z)
end.
- Definition lookup_src {s d} opc := fst (@lookup s d opc).
- Definition lookup_dst {s d} opc := snd (@lookup s d opc).
+ Definition lookup_src {s d} idc := fst (@lookup s d idc).
+ Definition lookup_dst {s d} idc := snd (@lookup s d idc).
Definition option_map_prod {A B C} (f : A -> B -> C) (v : option (option A * option B))
: option C
@@ -974,122 +1691,88 @@ Module Compilers.
Definition rewrite
{var : type -> Type}
- {s d} (opc : op s d)
- (exploded_arguments : type.option.interp (@expr var) (@expr var) (lookup_src opc))
- : option (type.interp var (@expr var) (lookup_dst opc))
- := match opc in op s d
+ {s d} (idc : op s d)
+ (exploded_arguments : type.option.interp (@expr var) (@expr var) (lookup_src idc))
+ : option (type.interp var (@expr var) (lookup_dst idc))
+ := match idc in op s d
return
- (forall (exploded_arguments' : option (type.option.interp_to_arrow_or_generic expr expr (lookup_src opc))),
- option (type.interp var expr (lookup_dst opc)))
+ (forall (exploded_arguments' : option (type.option.interp_to_arrow_or_generic expr expr (lookup_src idc))),
+ option (type.interp var expr (lookup_dst idc)))
with
- | op.Const t v => fun _ => arguments.type.const_of_ground v
- | op.Let_In tx tC
+ | ident.Const t v => fun _ => arguments.type.const_of_ground v
+ | ident.Let_In tx tC
=> option_map
(fun '(ex, eC)
- => match invert_Var ex, invert_OpConst ex with
+ => match invert_Var ex, invert_Idconst ex with
| Some v, _ => eC ex
| None, Some v => eC ex
- | None, None => Op op.Let_In (ex, Abs (fun v => eC (Var v)))
+ | None, None => Op ident.Let_In (ex, Abs (fun v => eC (Var v)))
end)
- | op.App s d => option_map (fun '(f, x) => f x)
- | op.S as opc
- | op.pred as opc
- | op.Z_runtime_mul as opc
- | op.Z_runtime_add as opc
- | op.Z_add as opc
- | op.Z_mul as opc
- | op.Z_pow as opc
- | op.Z_opp as opc
- | op.Z_div as opc
- | op.Z_modulo as opc
- | op.Z_eqb as opc
- | op.Z_of_nat as opc
- => option_map (op.interp opc)
- | op.nil t => fun _ => Some (@nil (type.interp _ _ ground))
- | op.cons t => option_map (op.curry2 cons)
- | op.fst A B => option_map (@fst (expr A) (expr B))
- | op.snd A B => option_map (@snd (expr A) (expr B))
- | op.bool_rect T => option_map (op.curry3 (bool_rect (fun _ => _)))
- | op.nat_rect P
+ | ident.App s d => option_map (fun '(f, x) => f x)
+ | ident.S as idc
+ | ident.pred as idc
+ | ident.Z_runtime_mul as idc
+ | ident.Z_runtime_add as idc
+ | ident.Z_add as idc
+ | ident.Z_mul as idc
+ | ident.Z_pow as idc
+ | ident.Z_opp as idc
+ | ident.Z_div as idc
+ | ident.Z_modulo as idc
+ | ident.Z_eqb as idc
+ | ident.Z_of_nat as idc
+ => option_map (ident.interp idc)
+ | ident.nil t => fun _ => Some (@nil (type.interp _ _ ground))
+ | ident.cons t => option_map (ident.curry2 cons)
+ | ident.fst A B => option_map (@fst (expr A) (expr B))
+ | ident.snd A B => option_map (@snd (expr A) (expr B))
+ | ident.bool_rect T => option_map (ident.curry3 (bool_rect (fun _ => _)))
+ | ident.nat_rect P
=> option_map
(fun '(O_case, S_case, v)
=> nat_rect (fun _ => expr P) O_case (fun n (v : expr P) => S_case (@const _ type.nat n) v) v)
- | op.List_seq => option_map (op.curry2 List.seq)
- | op.List_repeat A => option_map (op.curry2 (@List.repeat (expr A)))
- | op.List_combine A B => option_map (op.curry2 (@List.combine (expr A) (expr B)))
- | op.List_map A B => option_map (op.curry2 (@List.map (expr A) (expr B)))
- | op.List_flat_map A B
+ | ident.List_seq => option_map (ident.curry2 List.seq)
+ | ident.List_repeat A => option_map (ident.curry2 (@List.repeat (expr A)))
+ | ident.List_combine A B => option_map (ident.curry2 (@List.combine (expr A) (expr B)))
+ | ident.List_map A B => option_map (ident.curry2 (@List.map (expr A) (expr B)))
+ | ident.List_flat_map A B
=> fun args : option ((expr A -> option (Datatypes.list (expr B))) * Datatypes.list (expr A))
=> match args with
| Some (f, ls) => option_flat_map f ls
| None => None
end
- | op.List_partition A
+ | ident.List_partition A
=> fun args : option ((expr A -> option Datatypes.bool) * Datatypes.list (expr A))
=> match args with
| Some (f, ls) => option_partition f ls
| None => None
end
- | op.List_app A => option_map (op.curry2 (@List.app (expr A)))
- | op.List_fold_right A B => option_map (op.curry3 (@List.fold_right (expr A) (expr B)))
- | op.List_update_nth T => option_map (op.curry3 (@update_nth (expr T)))
+ | ident.List_app A => option_map (ident.curry2 (@List.app (expr A)))
+ | ident.List_fold_right A B => option_map (ident.curry3 (@List.fold_right (expr A) (expr B)))
+ | ident.List_update_nth T => option_map (ident.curry3 (@update_nth (expr T)))
end
- (type.option.lift_interp exploded_arguments).
- End op.
+ (type.option.lift_interp exploded_arguments).*)
+ End ident.
End arguments.
- Export arguments.Notations.
+ (*Export arguments.Notations.*)
Section partial_reduce.
Context {var : type -> Type}.
- Local Notation partial_reduceT t a
- := ((@expr var t * arguments.type.option.interp (@expr var) (@expr var) a)%type)
- (only parsing).
-
- Fixpoint partial_reduce' {t} (e : @expr (@expr var) t)
- : forall a : arguments t, partial_reduceT t a
- := match e in expr t return (forall a : arguments t, partial_reduceT t a) with
- | TT
- => arguments.invert
- (fun a : arguments type.unit => partial_reduceT type.unit a)
- (TT, TT)
- (fun u => (TT, u))
- | Pair A B a b
- => arguments.invert
- (fun a => partial_reduceT (type.prod A B) a)
- (let ab := (fst (@partial_reduce' A a arguments.generic),
- fst (@partial_reduce' B b arguments.generic))%expr in
- (ab, ab))
- (fun '(aA, aB)
- => let '(a0, a1) := @partial_reduce' A a aA in
- let '(b0, b1) := @partial_reduce' B b aB in
- ((a0, b0)%expr, Some (a1, b1)))
- | Var t v
- => fun a => (v, arguments.expr.interp _ _ v)
- | Op s d opc args
- => let '(args0, args1) := @partial_reduce' s args (arguments.op.lookup_src opc) in
- let e :=
- match arguments.op.rewrite opc args1 with
- | Some e => arguments.expr.reify _ _ e
- | None => Op opc args0
- end in
- fun a => (e, arguments.expr.interp _ _ e)
+ Fixpoint partial_reduce' {t} (e : @expr (arguments.interp var) t)
+ : arguments.interp var t
+ := match e in expr t return arguments.interp var t with
+ | Var t v => v
+ | Ident t idc => arguments.ident.interp idc
+ | App s d f x
+ => @partial_reduce' _ f (@partial_reduce' _ x)
| Abs s d f
- => fun a
- => let e' := Abs (fun x => fst (@partial_reduce' d (f (Var x)) (arguments.invert_arrow a))) in
- arguments.invert
- (fun a => partial_reduceT (type.arrow s d) a)
- (e', e')
- (fun ad
- => (e',
- (fun x =>
- snd (@partial_reduce' d (f x) ad))))
- a
+ => fun x
+ => @partial_reduce' d (f x)
end.
-
- Definition partial_reduce {t} (e : @expr (@expr var) t) : @expr var t
- := snd (@partial_reduce' t e arguments.generic).
+ Definition partial_reduce {t} (e : @expr (arguments.interp var) t) : @expr var t
+ := arguments.expr.reify (@partial_reduce' t e).
End partial_reduce.
Definition PartialReduce {t} (e : Expr t) : Expr t
@@ -1098,6 +1781,8 @@ Module Compilers.
Ltac is_known_const_cps2 term on_success on_failure :=
let recurse term := is_known_const_cps2 term on_success on_failure in
lazymatch term with
+ | tt => on_success ()
+ | @nil _ => on_success ()
| S ?term => recurse term
| O => on_success ()
| Z0 => on_success ()
@@ -1113,94 +1798,93 @@ Module Compilers.
Ltac is_known_const term :=
is_known_const_cps2 term ltac:(fun _ => true) ltac:(fun _ => false).
- Definition Uncurry0 {A var} (opc : op type.unit A) : @expr var A
- := Op opc TT.
- Definition Uncurry1 {A B var} (opc : op A B) : @expr var (A -> B)
- := λ a, Op opc (Var a).
- Definition Uncurry2 {A B C var} (opc : op (A * B) C) : @expr var (A -> B -> C)
- := λ a b, Op opc (Var a, Var b).
- Definition Uncurry3 {A B C D var} (opc : op (A * B * C) D) : @expr var (A -> B -> C -> D)
- := λ a b c, Op opc (Var a, Var b, Var c).
-
- Ltac reify_op var term :=
+ Print ident.ident.
+ Ltac reify_ident term :=
(*let dummy := match goal with _ => idtac "attempting to reify_op" term end in*)
- let Uncurry0 x := constr:(Uncurry0 (var:=var) x) in
- let Uncurry1 x := constr:(Uncurry1 (var:=var) x) in
- let Uncurry2 x := constr:(Uncurry2 (var:=var) x) in
- let Uncurry3 x := constr:(Uncurry3 (var:=var) x) in
lazymatch term with
- | S => Uncurry1 op.S
+ | S => ident.S
| @nil ?T
=> let rT := type.reify T in
- Uncurry0 (@op.nil rT)
+ constr:(@ident.nil rT)
| @cons ?T
=> let rT := type.reify T in
- Uncurry2 (@op.cons rT)
- | seq => Uncurry2 op.List.seq
+ constr:(@ident.cons rT)
+ | @pair ?A ?B
+ => let rA := type.reify A in
+ let rB := type.reify B in
+ constr:(@ident.pair rA rB)
+ | @fst ?A ?B
+ => let rA := type.reify A in
+ let rB := type.reify B in
+ constr:(@ident.fst rA rB)
+ | @snd ?A ?B
+ => let rA := type.reify A in
+ let rB := type.reify B in
+ constr:(@ident.snd rA rB)
+ | @bool_rect (fun _ => ?T)
+ => let rT := type.reify T in
+ constr:(@ident.bool_rect rT)
+ | @nat_rect (fun _ => ?T)
+ => let rT := type.reify T in
+ constr:(@ident.nat_rect rT)
+ | pred => ident.pred
+ | seq => ident.List.seq
| @List.repeat ?A
=> let rA := type.reify A in
- Uncurry2 (@op.List.repeat rA)
+ constr:(@ident.List.repeat rA)
| @Let_In ?A (fun _ => ?B)
=> let rA := type.reify A in
let rB := type.reify B in
- Uncurry2 (@op.Let_In rA rB)
+ constr:(@ident.Let_In rA rB)
| @combine ?A ?B
=> let rA := type.reify A in
let rB := type.reify B in
- Uncurry2 (@op.List.combine rA rB)
+ constr:(@ident.List.combine rA rB)
| @List.map ?A ?B
=> let rA := type.reify A in
let rB := type.reify B in
- Uncurry2 (@op.List.map rA rB)
+ constr:(@ident.List.map rA rB)
| @List.flat_map ?A ?B
=> let rA := type.reify A in
let rB := type.reify B in
- Uncurry2 (@op.List.flat_map rA rB)
- | @fst ?A ?B
- => let rA := type.reify A in
- let rB := type.reify B in
- Uncurry1 (@op.fst rA rB)
- | @snd ?A ?B
- => let rA := type.reify A in
- let rB := type.reify B in
- Uncurry1 (@op.snd rA rB)
+ constr:(@ident.List.flat_map rA rB)
| @List.partition ?A
=> let rA := type.reify A in
- Uncurry2 (@op.List.partition rA)
+ constr:(@ident.List.partition rA)
| @List.app ?A
=> let rA := type.reify A in
- Uncurry2 (@op.List.app rA)
+ constr:(@ident.List.app rA)
+ | @List.rev ?A
+ => let rA := type.reify A in
+ constr:(@ident.List.rev rA)
| @List.fold_right ?A ?B
=> let rA := type.reify A in
let rB := type.reify B in
- Uncurry3 (@op.List.fold_right rA rB)
- | pred => Uncurry1 op.pred
+ constr:(@ident.List.fold_right rA rB)
| @update_nth ?T
=> let rT := type.reify T in
- Uncurry3 (@op.List.update_nth rT)
- | runtime_mul => Uncurry2 op.Z.runtime_mul
- | runtime_add => Uncurry2 op.Z.runtime_add
- | Z.add => Uncurry2 op.Z.add
- | Z.mul => Uncurry2 op.Z.mul
- | Z.pow => Uncurry2 op.Z.pow
- | Z.opp => Uncurry1 op.Z.opp
- | Z.div => Uncurry2 op.Z.div
- | Z.modulo => Uncurry2 op.Z.modulo
- | Z.eqb => Uncurry2 op.Z.eqb
- | Z.of_nat => Uncurry1 op.Z.of_nat
- | @nat_rect (fun _ => ?T)
- => let rT := type.reify T in
- Uncurry3 (@op.nat_rect rT)
- | @bool_rect (fun _ => ?T)
+ constr:(@ident.List.update_nth rT)
+ | @List.nth_default ?T
=> let rT := type.reify T in
- Uncurry3 (@op.bool_rect rT)
+ constr:(@ident.List.nth_default rT)
+ | runtime_mul => ident.Z.runtime_mul
+ | runtime_add => ident.Z.runtime_add
+ | Z.add => ident.Z.add
+ | Z.mul => ident.Z.mul
+ | Z.pow => ident.Z.pow
+ | Z.opp => ident.Z.opp
+ | Z.div => ident.Z.div
+ | Z.modulo => ident.Z.modulo
+ | Z.eqb => ident.Z.eqb
+ | Z.of_nat => ident.Z.of_nat
+ | Nat.sub => ident.Nat.sub
| _
=> let assert_const := match goal with
| _ => require_known_const term
end in
let T := type of term in
let rT := type.reify T in
- Uncurry0 (@op.Const rT term)
+ constr:(@ident.Const rT term)
end.
Module var_context.
@@ -1209,11 +1893,10 @@ Module Compilers.
| cons {t} (gallina_v : type.interp t) (v : var t) (ctx : list).
End var_context.
- (* cf COQBUG(https://github.com/coq/coq/issues/5448) *)
+ (* cf COQBUG(https://github.com/coq/coq/issues/5448) , COQBUG(https://github.com/coq/coq/issues/6315) *)
Ltac refresh n :=
let n' := fresh n in
- let n' := fresh n' in
- let n' := fresh n' in
+ let n' := fresh n in
n'.
Ltac type_of_first_argument_of f :=
@@ -1271,15 +1954,12 @@ Module Compilers.
=>
let term_is_known_const := is_known_const term in
lazymatch term_is_known_const with
- | true => reify_op var term
+ | true
+ => let rv := reify_ident term in
+ constr:(Ident (var:=var) rv)
| false
=>
lazymatch term with
- | tt => TT
- | @pair ?A ?B ?a ?b
- => let ra := reify_rec a in
- let rb := reify_rec b in
- constr:(Pair (var:=var) ra rb)
| match ?b with true => ?t | false => ?f end
=> let T := type of t in
reify_rec (@bool_rect (fun _ => T) t f b)
@@ -1299,7 +1979,7 @@ Module Compilers.
=>
let rx := reify_helper var x value_ctx tt in
let rf := reify_helper var f value_ctx template_ctx in
- constr:(Op (var:=var) op.App (Pair (var:=var) rf rx))
+ constr:(App (var:=var) rf rx)
end
| (fun x : ?T => ?f)
=>
@@ -1317,15 +1997,17 @@ Module Compilers.
let rT := type.reify T in
let not_x := refresh x in
let not_x2 := refresh not_x in
+ let not_x3 := refresh not_x2 in
let rf0 :=
constr:(
fun (x : T) (not_x : var rT)
- => match f return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *)
- | not_x2
+ => match f, @var_context.cons var rT x not_x value_ctx return _ with (* c.f. COQBUG(https://github.com/coq/coq/issues/6252#issuecomment-347041995) for [return _] *)
+ | not_x2, not_x3
=> ltac:(
let f := (eval cbv delta [not_x2] in not_x2) in
+ let var_ctx := (eval cbv delta [not_x3] in not_x3) in
(*idtac "rec call" f "was" term;*)
- let rf := reify_helper var f (@var_context.cons var rT x not_x value_ctx) template_ctx in
+ let rf := reify_helper var f var_ctx template_ctx in
exact rf)
end) in
lazymatch rf0 with
@@ -1347,7 +2029,8 @@ Module Compilers.
end
| _
=> let term := plug_template_ctx term template_ctx in
- reify_op var term
+ let idc := reify_ident term in
+ constr:(Ident (var:=var) idc)
end
end
end.
@@ -1361,13 +2044,63 @@ Module Compilers.
let RHS := lazymatch goal with |- _ = ?RHS => RHS end in
let R := Reify RHS in
transitivity (Interp R);
- [ | cbv beta iota delta [Interp interp op.interp Uncurry0 Uncurry1 Uncurry2 Uncurry3 Let_In type.interp bool_rect];
+ [ | cbv beta iota delta [Interp interp ident.interp Let_In type.interp bool_rect];
reflexivity ].
End Compilers.
Import Associational Positional Compilers.
Local Coercion Z.of_nat : nat >-> Z.
Local Coercion QArith_base.inject_Z : Z >-> Q.
Definition w (i:nat) : Z := 2^Qceiling((25+1/2)*i).
+
+(* TODO: is this the right way to do things? *)
+Definition expand_list_helper {A} (default : A) (ls : list A) (n : nat) (idx : nat) : list A
+ := nat_rect
+ (fun _ => nat -> list A)
+ (fun _ => nil)
+ (fun n' rec_call idx
+ => cons (List.nth_default default ls idx) (rec_call (S idx)))
+ n
+ idx.
+Definition expand_list {A} (default : A) (ls : list A) (n : nat) : list A
+ := expand_list_helper default ls n 0.
+Require Import Coq.micromega.Lia.
+(* TODO: MOVE ME *)
+Lemma expand_list_helper_correct {A} (default : A) (ls : list A) (n idx : nat) (H : (idx + n <= length ls)%nat)
+ : expand_list_helper default ls n idx
+ = List.firstn n (List.skipn idx ls).
+Proof.
+ cbv [expand_list_helper]; revert idx H.
+ induction n as [|n IHn]; cbn; intros.
+ { reflexivity. }
+ { rewrite IHn by omega.
+ erewrite (@skipn_nth_default _ idx ls) by omega.
+ reflexivity. }
+Qed.
+
+Lemma expand_list_correct (n : nat) {A} (default : A) (ls : list A) (H : List.length ls = n)
+ : expand_list default ls n = ls.
+Proof.
+ subst; cbv [expand_list]; rewrite expand_list_helper_correct by reflexivity.
+ rewrite skipn_0, firstn_all; reflexivity.
+Qed.
+
+Delimit Scope RT_expr_scope with RT_expr.
+Notation "ls _{ n }"
+ := (App (App (App (Ident ident.List.nth_default) _) ls%expr) (Ident (ident.Const n%nat)))
+ (at level 20, format "ls _{ n }")
+ : expr_scope.
+Print Grammar constr.
+Notation "x + y"
+ := (App (App (Ident ident.Z.runtime_add) x%RT_expr) y%RT_expr)
+ : RT_expr_scope.
+Notation "x * y"
+ := (App (App (Ident ident.Z.runtime_mul) x%RT_expr) y%RT_expr)
+ : RT_expr_scope.
+Notation "x" := (Ident (ident.Const x)) (only printing, at level 10) : expr_scope.
+Notation "x" := (Var x) (only printing, at level 10) : expr_scope.
+
+Require Import AdmitAxiom.
+
Example base_25_5_mul (*(f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g8 g9 : Z)
(f:=(f0 :: f1 :: f2 :: f3 :: f4 :: f5 :: f6 :: f7 :: f8 :: f9 :: nil)%list)
(g:=(f0 :: f1 :: f2 :: f3 :: f4 :: f5 :: f6 :: f7 :: f8 :: f9 :: nil)%list)*) (f g : list Z)
@@ -1389,23 +2122,59 @@ Example base_25_5_mul (*(f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g
(* (g9, g8, g7, g6, g5, g4, g3, g2, g1, g0) *)
(*cbv [f g].*)
cbv [w Qceiling Qfloor Qopp Qnum Qdiv Qplus inject_Z Qmult Qinv Qden Pos.mul].
- apply (f_equal (fun F => F f g)).
- cbv [n].
- cbv delta [mulmod w to_associational mul to_associational reduce from_associational add_to_nth zeros place split].
- assert True.
- { let v := Reify ((fun x => 2^x) 255)%Z in
- pose v as E.
- vm_compute in E.
- pose (PartialReduce E) as E'.
- vm_compute in E'.
- constructor. }
- Reify_rhs ().
- let e := match goal with |- _ = Interp ?e => e end in
- pose e as E.
- exfalso.
- Timeout 2 vm_compute in E.
- pose (PartialReduce E) as E'.
- Timeout 2 vm_compute in E'.
+ let ev := match goal with |- ?ev = _ => ev end in
+ set (e := ev).
+ rewrite <- (expand_list_correct n (-1)%Z f), <- (expand_list_correct n (-1)%Z g) by assumption; subst e.
+ etransitivity.
+ Focus 2.
+ {
+ repeat match goal with H : _ |- _ => clear H end; revert f g.
+ lazymatch goal with
+ | [ |- forall f g, ?ev = @?RHS f g ]
+ => refine (fun f g => f_equal (fun F => F f g) (_ : _ = RHS))
+ end.
+ cbv [n expand_list expand_list_helper].
+ cbv delta [mulmod w to_associational mul to_associational reduce from_associational add_to_nth zeros place split].
+ assert True.
+ { let v := Reify ((fun x => 2^x) 255)%Z in
+ pose v as E.
+ vm_compute in E.
+ pose (PartialReduce E) as E'.
+ vm_compute in E'.
+ lazymatch (eval cbv delta [E'] in E') with
+ | (fun var => Ident (ident.Const ?v)) => idtac
+ end.
+ constructor. }
+ assert True.
+ { let v := Reify (fun y : Z
+ => (fun k : Z * Z -> Z * Z
+ => let x := (y * y)%RT in
+ let z := (x * x)%RT in
+ k (z, z))
+ (fun v => v)) in
+ pose v as E.
+ vm_compute in E.
+ pose (PartialReduce E) as E'.
+ vm_compute in E'.
+ lazymatch (eval cbv delta [E'] in E') with
+ | (fun var : type -> Type =>
+ (λ x : var type.Z,
+ expr_let x0 := (Var x * Var x)%RT_expr in
+ expr_let x1 := (Var x0 * Var x0)%RT_expr in
+ (Var x1, Var x1))%expr) => idtac
+ end.
+ constructor. }
+ Reify_rhs ().
+ reflexivity.
+ } Unfocus.
+ cbv beta.
+ let e := match goal with |- _ = Interp ?e _ _ => e end in
+ set (E := e).
+ let E' := constr:(PartialReduce E) in
+ let E' := (eval vm_compute in E') in
+ pose E' as E''.
+ transitivity (Interp E'' f g); [ clear E | admit ].
+ reflexivity.
(*cbv -[runtime_mul runtime_add]; cbv [runtime_mul runtime_add].
ring_simplify_subterms.*)
(* ?fg =
@@ -1419,8 +2188,101 @@ Example base_25_5_mul (*(f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 g0 g1 g2 g3 g4 g5 g6 g7 g
f0*g2+ 2*f1*g1+ f2*g0+ 38*f3*g9+ 19*f4*g8+ 38*f5*g7+ 19*f6*g6+ 38*f7*g5+ 19*f8*g4+ 38*f9*g3,
f0*g1+ f1*g0+ 19*f2*g9+ 19*f3*g8+ 19*f4*g7+ 19*f5*g6+ 19*f6*g5+ 19*f7*g4+ 19*f8*g3+ 19*f9*g2,
f0*g0+ 38*f1*g9+ 19*f2*g8+ 38*f3*g7+ 19*f4*g6+ 38*f5*g5+ 19*f6*g4+ 38*f7*g3+ 19*f8*g2+ 38*f9*g1) *)
- (*trivial.
-Defined.*)
-Abort.
-
-(* Eval cbv on this one would produce an ugly term due to the use of [destruct] *)
+ (*trivial.*)
+Defined.
+
+Eval cbv [proj1_sig base_25_5_mul] in (fun f g Hf Hg => proj1_sig (base_25_5_mul f g Hf Hg)).
+(* = fun (f g : list Z) (_ : length f = 10%nat) (_ : length g = 10%nat) =>
+ Interp
+ (fun var : type -> Type =>
+ (λ x x0 : var (type.list type.Z),
+ (x_{0} * x0_{0} +
+ (2 * (19 * (x_{1} * x0_{9})) +
+ (19 * (x_{2} * x0_{8}) +
+ (2 * (19 * (x_{3} * x0_{7})) +
+ (19 * (x_{4} * x0_{6}) +
+ (2 * (19 * (x_{5} * x0_{5})) +
+ (19 * (x_{6} * x0_{4}) +
+ (2 * (19 * (x_{7} * x0_{3})) +
+ (19 * (x_{8} * x0_{2}) + 2 * (19 * (x_{9} * x0_{1})))))))))))%RT_expr
+ :: (x_{0} * x0_{1} +
+ (x_{1} * x0_{0} +
+ (19 * (x_{2} * x0_{9}) +
+ (19 * (x_{3} * x0_{8}) +
+ (19 * (x_{4} * x0_{7}) +
+ (19 * (x_{5} * x0_{6}) +
+ (19 * (x_{6} * x0_{5}) +
+ (19 * (x_{7} * x0_{4}) + (19 * (x_{8} * x0_{3}) + 19 * (x_{9} * x0_{2}))))))))))%RT_expr
+ :: (x_{0} * x0_{2} +
+ (2 * (x_{1} * x0_{1}) +
+ (x_{2} * x0_{0} +
+ (2 * (19 * (x_{3} * x0_{9})) +
+ (19 * (x_{4} * x0_{8}) +
+ (2 * (19 * (x_{5} * x0_{7})) +
+ (19 * (x_{6} * x0_{6}) +
+ (2 * (19 * (x_{7} * x0_{5})) +
+ (19 * (x_{8} * x0_{4}) + 2 * (19 * (x_{9} * x0_{3})))))))))))%RT_expr
+ :: (x_{0} * x0_{3} +
+ (x_{1} * x0_{2} +
+ (x_{2} * x0_{1} +
+ (x_{3} * x0_{0} +
+ (19 * (x_{4} * x0_{9}) +
+ (19 * (x_{5} * x0_{8}) +
+ (19 * (x_{6} * x0_{7}) +
+ (19 * (x_{7} * x0_{6}) +
+ (19 * (x_{8} * x0_{5}) + 19 * (x_{9} * x0_{4}))))))))))%RT_expr
+ :: (x_{0} * x0_{4} +
+ (2 * (x_{1} * x0_{3}) +
+ (x_{2} * x0_{2} +
+ (2 * (x_{3} * x0_{1}) +
+ (x_{4} * x0_{0} +
+ (2 * (19 * (x_{5} * x0_{9})) +
+ (19 * (x_{6} * x0_{8}) +
+ (2 * (19 * (x_{7} * x0_{7})) +
+ (19 * (x_{8} * x0_{6}) + 2 * (19 * (x_{9} * x0_{5})))))))))))%RT_expr
+ :: (x_{0} * x0_{5} +
+ (x_{1} * x0_{4} +
+ (x_{2} * x0_{3} +
+ (x_{3} * x0_{2} +
+ (x_{4} * x0_{1} +
+ (x_{5} * x0_{0} +
+ (19 * (x_{6} * x0_{9}) +
+ (19 * (x_{7} * x0_{8}) +
+ (19 * (x_{8} * x0_{7}) + 19 * (x_{9} * x0_{6}))))))))))%RT_expr
+ :: (x_{0} * x0_{6} +
+ (2 * (x_{1} * x0_{5}) +
+ (x_{2} * x0_{4} +
+ (2 * (x_{3} * x0_{3}) +
+ (x_{4} * x0_{2} +
+ (2 * (x_{5} * x0_{1}) +
+ (x_{6} * x0_{0} +
+ (2 * (19 * (x_{7} * x0_{9})) +
+ (19 * (x_{8} * x0_{8}) + 2 * (19 * (x_{9} * x0_{7})))))))))))%RT_expr
+ :: (x_{0} * x0_{7} +
+ (x_{1} * x0_{6} +
+ (x_{2} * x0_{5} +
+ (x_{3} * x0_{4} +
+ (x_{4} * x0_{3} +
+ (x_{5} * x0_{2} +
+ (x_{6} * x0_{1} +
+ (x_{7} * x0_{0} +
+ (19 * (x_{8} * x0_{9}) + 19 * (x_{9} * x0_{8}))))))))))%RT_expr
+ :: (x_{0} * x0_{8} +
+ (2 * (x_{1} * x0_{7}) +
+ (x_{2} * x0_{6} +
+ (2 * (x_{3} * x0_{5}) +
+ (x_{4} * x0_{4} +
+ (2 * (x_{5} * x0_{3}) +
+ (x_{6} * x0_{2} +
+ (2 * (x_{7} * x0_{1}) +
+ (x_{8} * x0_{0} + 2 * (19 * (x_{9} * x0_{9})))))))))))%RT_expr
+ :: (x_{0} * x0_{9} +
+ (x_{1} * x0_{8} +
+ (x_{2} * x0_{7} +
+ (x_{3} * x0_{6} +
+ (x_{4} * x0_{5} +
+ (x_{5} * x0_{4} +
+ (x_{6} * x0_{3} +
+ (x_{7} * x0_{2} + (x_{8} * x0_{1} + x_{9} * x0_{0})))))))))%RT_expr
+ :: [])%expr) f g
+ : forall f g : list Z, length f = 10%nat -> length g = 10%nat -> list Z *)