aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jason Gross <jgross@mit.edu>2016-09-21 16:41:27 -0400
committerGravatar Jason Gross <jgross@mit.edu>2016-09-21 16:41:27 -0400
commitb60c2d2e2f4e8f2940e01a9857fecce93d6b3592 (patch)
tree4fde69bb9fd074d15cd177873ef190ef33a9d17c
parent2311b4df116eee1e35465cd225c419c55456899f (diff)
Add some util files for reflective let bindings
-rw-r--r--_CoqProject3
-rw-r--r--src/Reflection/CountLets.v55
-rw-r--r--src/Reflection/FilterLive.v76
-rw-r--r--src/Reflection/Named/NameUtil.v41
4 files changed, 175 insertions, 0 deletions
diff --git a/_CoqProject b/_CoqProject
index a14a022f2..a61d2ea0c 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -62,6 +62,8 @@ src/ModularArithmetic/Montgomery/Z.v
src/ModularArithmetic/Montgomery/ZBounded.v
src/ModularArithmetic/Montgomery/ZProofs.v
src/Reflection/CommonSubexpressionElimination.v
+src/Reflection/CountLets.v
+src/Reflection/FilterLive.v
src/Reflection/Inline.v
src/Reflection/InlineInterp.v
src/Reflection/InlineWf.v
@@ -76,6 +78,7 @@ src/Reflection/TestCase.v
src/Reflection/WfProofs.v
src/Reflection/WfReflective.v
src/Reflection/WfRel.v
+src/Reflection/Named/NameUtil.v
src/Spec/CompleteEdwardsCurve.v
src/Spec/EdDSA.v
src/Spec/Encoding.v
diff --git a/src/Reflection/CountLets.v b/src/Reflection/CountLets.v
new file mode 100644
index 000000000..43f152da1
--- /dev/null
+++ b/src/Reflection/CountLets.v
@@ -0,0 +1,55 @@
+(** * Counts how many binders there are *)
+Require Import Crypto.Reflection.Syntax.
+
+Local Open Scope ctype_scope.
+Section language.
+ Context {base_type_code : Type}
+ {interp_base_type : base_type_code -> Type}
+ {op : flat_type base_type_code -> flat_type base_type_code -> Type}.
+
+ Local Notation flat_type := (flat_type base_type_code).
+ Local Notation type := (type base_type_code).
+ Local Notation interp_type := (interp_type interp_base_type).
+ Local Notation interp_flat_type := (interp_flat_type_gen interp_base_type).
+ Local Notation Expr := (@Expr base_type_code interp_base_type op).
+
+ Fixpoint count_pairs (t : flat_type) : nat
+ := match t with
+ | Tbase _ => 1
+ | Prod A B => count_pairs A + count_pairs B
+ end%nat.
+
+ Section with_var.
+ Context {var : base_type_code -> Type}
+ (mkVar : forall t, var t).
+
+ Local Notation exprf := (@exprf base_type_code interp_base_type op var).
+ Local Notation expr := (@expr base_type_code interp_base_type op var).
+
+ Section gen.
+ Context (count_type : flat_type -> nat).
+
+ Fixpoint count_lets_genf {t} (e : exprf t) : nat
+ := match e with
+ | LetIn tx _ _ eC
+ => count_type tx + @count_lets_genf _ (eC (SmartVal var mkVar tx))
+ | _ => 0
+ end.
+ Fixpoint count_lets_gen {t} (e : expr t) : nat
+ := match e with
+ | Return _ x
+ => count_lets_genf x
+ | Abs tx _ f => @count_lets_gen _ (f (mkVar tx))
+ end.
+ End gen.
+
+ Definition count_letsf {t} (e : exprf t) : nat
+ := count_lets_genf count_pairs e.
+ Definition count_lets {t} (e : expr t) : nat
+ := count_lets_gen count_pairs e.
+ End with_var.
+
+ Definition CountLetsGen (count_type : flat_type -> nat) {t} (e : Expr t) : nat
+ := count_lets_gen (fun _ => tt) count_type (e _).
+ Definition CountLets {t} (e : Expr t) : nat := CountLetsGen count_pairs e.
+End language.
diff --git a/src/Reflection/FilterLive.v b/src/Reflection/FilterLive.v
new file mode 100644
index 000000000..a16ff19e3
--- /dev/null
+++ b/src/Reflection/FilterLive.v
@@ -0,0 +1,76 @@
+(** * Computes a list of live variables *)
+Require Import Crypto.Reflection.Syntax.
+Require Import Crypto.Reflection.Named.NameUtil.
+Require Import Crypto.Util.ListUtil.
+
+Local Notation eta x := (fst x, snd x).
+
+Local Open Scope ctype_scope.
+Section language.
+ Context (base_type_code : Type)
+ (interp_base_type : base_type_code -> Type)
+ (op : flat_type base_type_code -> flat_type base_type_code -> Type)
+ (Name : Type)
+ (dead_name : Name)
+ (merge_names : Name -> Name -> Name)
+ (* equations:
+ - [merge_names x dead_name = merge_names dead_name x = x]
+ - [merge_names x x = x] *).
+
+ Local Notation flat_type := (flat_type base_type_code).
+ Local Notation type := (type base_type_code).
+ Let Tbase := @Tbase base_type_code.
+ Local Coercion Tbase : base_type_code >-> Syntax.flat_type.
+ Local Notation interp_type := (interp_type interp_base_type).
+ Local Notation interp_flat_type := (interp_flat_type_gen interp_base_type).
+ Local Notation var := (fun t : base_type_code => list Name).
+ Local Notation exprf := (@exprf base_type_code interp_base_type op var).
+ Local Notation expr := (@expr base_type_code interp_base_type op var).
+ Local Notation Expr := (@Expr base_type_code interp_base_type op var).
+
+ Fixpoint merge_name_lists (ls1 ls2 : list Name) : list Name :=
+ match ls1, ls2 with
+ | cons x xs, cons y ys => cons (merge_names x y) (merge_name_lists xs ys)
+ | ls1, nil => ls1
+ | nil, ls2 => ls2
+ end.
+
+ Fixpoint count_pairs (t : flat_type) : nat
+ := match t with
+ | Syntax.Tbase _ => 1
+ | Prod A B => count_pairs A + count_pairs B
+ end%nat.
+
+ Definition names_to_list {t} : interp_flat_type_gen (fun _ => Name) t -> list Name
+ := smart_interp_flat_map base_type_code (g:=fun _ => list Name) (fun _ x => x :: nil)%list (fun _ _ x y => x ++ y)%list.
+
+ Fixpoint filter_live_namesf (prefix remaining : list Name) {t} (e : exprf t) : list Name
+ := match e with
+ | Const _ x => prefix
+ | Var _ x => x
+ | Op _ _ op args => @filter_live_namesf prefix remaining _ args
+ | LetIn tx ex _ eC
+ => let namesx := @filter_live_namesf prefix nil _ ex in
+ let '(ns, remaining') := eta (split_names tx remaining) in
+ match ns with
+ | Some n =>
+ @filter_live_namesf
+ (prefix ++ repeat dead_name (count_pairs tx))%list remaining' _
+ (eC (SmartVal (fun _ => list Name) (fun _ => namesx ++ names_to_list n)%list _))
+ | None => nil
+ end
+ | Pair _ ex _ ey => merge_name_lists (@filter_live_namesf prefix remaining _ ex)
+ (@filter_live_namesf prefix remaining _ ey)
+ end.
+
+ Fixpoint filter_live_names (prefix remaining : list Name) {t} (e : expr t) : list Name
+ := match e, remaining with
+ | Return _ x, _ => filter_live_namesf prefix remaining x
+ | Abs src _ ef, cons n remaining'
+ => let prefix' := (prefix ++ (n :: nil))%list in
+ @filter_live_names
+ prefix' remaining' _
+ (ef prefix')
+ | Abs _ _ _, nil => nil
+ end.
+End language.
diff --git a/src/Reflection/Named/NameUtil.v b/src/Reflection/Named/NameUtil.v
new file mode 100644
index 000000000..bab860585
--- /dev/null
+++ b/src/Reflection/Named/NameUtil.v
@@ -0,0 +1,41 @@
+Require Import Crypto.Reflection.Syntax.
+
+Local Open Scope core_scope.
+Local Notation eta x := (fst x, snd x).
+
+Section language.
+ Context {base_type_code : Type}
+ {Name : Type}.
+
+ Section monad.
+ Context (MName : Type) (force : MName -> option Name).
+ Fixpoint split_mnames
+ (t : flat_type base_type_code) (ls : list MName)
+ : option (interp_flat_type_gen (fun _ => Name) t) * list MName
+ := match t return option (@interp_flat_type_gen base_type_code (fun _ => Name) t) * _ with
+ | Syntax.Tbase _
+ => match ls with
+ | cons n ls'
+ => match force n with
+ | Some n => (Some n, ls')
+ | None => (None, ls')
+ end
+ | nil => (None, nil)
+ end
+ | Prod A B
+ => let '(a, ls) := eta (@split_mnames A ls) in
+ let '(b, ls) := eta (@split_mnames B ls) in
+ (match a, b with
+ | Some a', Some b' => Some (a', b')
+ | _, _ => None
+ end,
+ ls)
+ end.
+ End monad.
+ Definition split_onames := @split_mnames (option Name) (fun x => x).
+ Definition split_names := @split_mnames Name (@Some _).
+End language.
+
+Global Arguments split_mnames {_ _ MName} force _ _, {_ _} MName force _ _.
+Global Arguments split_onames {_ _} _ _.
+Global Arguments split_names {_ _} _ _.