Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work on inference, unification and subject-reduction #328

Merged
merged 71 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
f2bd761
fix #303 handling of metavariables in RHS
fblanqui Apr 2, 2020
8f068a0
fix typo in comment
fblanqui Apr 2, 2020
a8b9916
fix typo in comment
fblanqui Apr 2, 2020
50069df
prepare fix
fblanqui Apr 2, 2020
17a6a50
fix typos in comments
fblanqui Apr 2, 2020
465215c
fix typo in comment
fblanqui Apr 2, 2020
9865cc8
fix typo in comment
fblanqui Apr 2, 2020
ce199bc
indentation
fblanqui Apr 2, 2020
d82b019
comment optim: reserve space for all LHS variables and not only those…
fblanqui Apr 3, 2020
db583e2
remove subst_from_constrs as it is useless
fblanqui Apr 3, 2020
e91ee90
basics: add fresh_vars
fblanqui Apr 3, 2020
588eddc
infer: change in log message
fblanqui Apr 3, 2020
d369293
Terms.set_meta: do not erase the type!
fblanqui Apr 3, 2020
2706e78
unif: log instantiations
fblanqui Apr 3, 2020
212e1cc
scope: replace wildcard pattern variables by fresh named pattern vari…
fblanqui Apr 3, 2020
7790644
fix sr by replacing LHS metas by fresh function symbols before solvin…
fblanqui Apr 3, 2020
b2b7d03
details in tests
fblanqui Apr 3, 2020
28e84a0
new test
fblanqui Apr 3, 2020
05996f8
infer: change in log message
fblanqui Apr 3, 2020
0b8037a
add basics.add_metas
fblanqui Apr 3, 2020
e7b7bc7
sr: details
fblanqui Apr 3, 2020
e285838
terms: add MetaMap
fblanqui Apr 3, 2020
e0d283d
improve sr
fblanqui Apr 3, 2020
05710a7
Merge remote-tracking branch 'lp/master' into rhs_metas
fblanqui Apr 4, 2020
c051cef
change some log message
fblanqui Apr 4, 2020
542660b
unif: improvement
fblanqui Apr 4, 2020
f798b2a
handle first example of #330
fblanqui Apr 4, 2020
27ceb83
fix bug in infer
fblanqui Apr 5, 2020
5a3040c
fix second problem in #330
fblanqui Apr 5, 2020
a94a34b
remove old comment
fblanqui Apr 5, 2020
95057aa
sanity
fblanqui Apr 5, 2020
d5dd1ee
remove lib directory
fblanqui Apr 6, 2020
105d47d
move eq from basics to rewrite
fblanqui Apr 6, 2020
036b8b5
infer: use eq_modulo in conv + more log messages
fblanqui Apr 6, 2020
f440308
scope: fix some comments
fblanqui Apr 6, 2020
4aa951e
remove Solve.can_instantiate and Terms.internal
fblanqui Apr 6, 2020
f86ad7b
improvement in sr
fblanqui Apr 6, 2020
f727612
remove warnings
fblanqui Apr 6, 2020
fccfd7c
update comment
fblanqui Apr 6, 2020
b0e1bb9
Terms.set_meta: erase type again for saving memory usage
fblanqui Apr 6, 2020
d1e0561
test 330 does not pass anymore
fblanqui Apr 6, 2020
cd798e5
rewrite: use eq_modulo for checking builtins
fblanqui Apr 6, 2020
759131a
changes in log messages
fblanqui Apr 6, 2020
6245738
details
fblanqui Apr 6, 2020
d1f39eb
details
fblanqui Apr 6, 2020
91a1452
details
fblanqui Apr 6, 2020
f76704b
why3_tactic: replace Rewrite.eq by Eval.eq_modulo
fblanqui Apr 7, 2020
935bff8
Makefile: add lib root for tests
fblanqui Apr 7, 2020
a5c3611
Merge remote-tracking branch 'lp/master' into rhs_metas
fblanqui Apr 7, 2020
abe7462
Makefile: change lib root to /tmp
fblanqui Apr 7, 2020
a188591
sr: remove useless comments + replace ? by & in function symbol names
fblanqui Apr 7, 2020
ee234b9
unif: improve nl_distinct_vars and instantiation to take into account…
fblanqui Apr 7, 2020
9c9ce7c
Unif.instantiation optim: do not apply sym_to_var if m is empty
fblanqui Apr 7, 2020
f1a94f1
change log message
fblanqui Apr 9, 2020
6b532da
fix remarks by Gabriel
fblanqui Apr 9, 2020
445be54
Merge remote-tracking branch 'lp/master' into rhs_metas
fblanqui Apr 9, 2020
f6a3405
comments by Rodolphe
fblanqui Apr 9, 2020
057d6a0
comment by Gabriel
fblanqui Apr 9, 2020
2d7742b
put back lib directory
fblanqui Apr 9, 2020
8277830
remark by Rodolphe
fblanqui Apr 9, 2020
17c2d41
add tests/OK/328.lp
fblanqui Apr 9, 2020
264dd66
sr: simplification of to_m (type extension is taken care by unificati…
fblanqui Apr 9, 2020
81557c2
Merge remote-tracking branch 'lp/master' into rhs_metas
fblanqui Apr 10, 2020
e5dd8a6
Merge remote-tracking branch 'lp/master' into rhs_metas
fblanqui Apr 10, 2020
8a784d1
Cleaning up SR and scoping of rules.
rlepigre Apr 9, 2020
2af80c3
Apply a comment I forgot.
rlepigre Apr 10, 2020
5eb7eda
Typo.
rlepigre Apr 10, 2020
07a3f39
Apply my own comments.
rlepigre Apr 10, 2020
d367273
Add missing comment.
rlepigre Apr 10, 2020
0cc857f
Apply my own comment again.
rlepigre Apr 10, 2020
a0e1f3e
Added comment.
rlepigre Apr 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 15 additions & 81 deletions src/core/basics.ml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@ open Extra
open Timed
open Terms

(** Sets and maps of variables. *)
module Var =
struct
type t = term Bindlib.var
let compare = Bindlib.compare_vars
end

module VarSet = Set.Make(Var)
module VarMap = Map.Make(Var)
(** Create an array of fresh variables [|x1;..;xn|]. *)
let fresh_vars : int -> tvar array = fun n ->
Bindlib.new_mvar mkfree (Array.init n (Printf.sprintf "x%i"))
rlepigre marked this conversation as resolved.
Show resolved Hide resolved

(** [to_tvar t] returns [x] if [t] is of the form [Vari x] and fails
otherwise. *)
Expand Down Expand Up @@ -71,48 +65,6 @@ let add_args : term -> term list -> term = fun t args ->
| u::args -> add_args (Appl(t,u)) args
in add_args t args

(** [eq ctx t u] tests the equality of [t] and [u] (up to α-equivalence). It
fails if [t] or [u] contain terms of the form [Patt(i,s,e)] or
[TEnv(te,env)]. In the process, subterms of the form [TRef(r)] in [t] and
[u] may be set with the corresponding value to enforce equality, and
variables appearing in [ctx] can be unfolded. In other words, [eq t u] can
be used to implement non-linear matching (see {!module:Rewrite}). When the
matching feature is used, one should make sure that [TRef] constructors do
not appear both in [t] and in [u] at the same time. Indeed, the references
are set naively, without checking occurrence. *)
let eq : ctxt -> term -> term -> bool = fun ctx a b -> a == b ||
let exception Not_equal in
let rec eq l =
match l with
| [] -> ()
| (a,b)::l ->
match (Ctxt.unfold ctx a, Ctxt.unfold ctx b) with
| (a , b ) when a == b -> eq l
| (Vari(x1) , Vari(x2) ) when Bindlib.eq_vars x1 x2 -> eq l
| (Type , Type )
| (Kind , Kind ) -> eq l
| (Symb(s1,_) , Symb(s2,_) ) when s1 == s2 -> eq l
| (Prod(a1,b1), Prod(a2,b2))
| (Abst(a1,b1), Abst(a2,b2)) -> let (_, b1, b2) = Bindlib.unbind2 b1 b2 in
eq ((a1,a2)::(b1,b2)::l)
| (LLet(a1,t1,u1), LLet(a2,t2,u2)) ->
let (_, u1, u2) = Bindlib.unbind2 u1 u2 in
eq ((a1,a2)::(t1,t2)::(u1,u2)::l)
| (Appl(t1,u1), Appl(t2,u2)) -> eq ((t1,t2)::(u1,u2)::l)
| (Meta(m1,e1), Meta(m2,e2)) when m1 == m2 ->
eq (if e1 == e2 then l else List.add_array2 e1 e2 l)
| (Wild , _ )
| (_ , Wild ) -> eq l
| (TRef(r) , b ) -> r := Some(b); eq l
| (a , TRef(r) ) -> r := Some(a); eq l
| (Patt(_,_,_), _ )
| (_ , Patt(_,_,_))
| (TEnv(_,_) , _ )
| (_ , TEnv(_,_) ) -> assert false
| (_ , _ ) -> raise Not_equal
in
try eq [(a,b)]; true with Not_equal -> false

fblanqui marked this conversation as resolved.
Show resolved Hide resolved
(** [is_symb s t] tests whether [t] is of the form [Symb(s)]. *)
let is_symb : sym -> term -> bool = fun s t ->
match unfold t with
Expand Down Expand Up @@ -178,13 +130,18 @@ let occurs : meta -> term -> bool =
let fn p = if m == p then raise Found in
try iter_meta false fn t; false with Found -> true

(** [get_metas b t] returns the list of all the metavariables in [t], and in
the types of metavariables recursively if [b], sorted wrt [cmp_meta]. *)
let get_metas : bool -> term -> meta list = fun b t ->
(** [add_metas b t ms] extends [ms] with all the metavariables of [t], and
those in the types of these metavariables recursively if [b]. *)
let add_metas : bool -> term -> MetaSet.t -> MetaSet.t = fun b t ms ->
let open Stdlib in
let l = ref [] in
iter_meta b (fun m -> l := m :: !l) t;
List.sort_uniq cmp_meta !l
fblanqui marked this conversation as resolved.
Show resolved Hide resolved
let ms = ref ms in
iter_meta b (fun m -> ms := MetaSet.add m !ms) t;
!ms

(** [get_metas b t] returns the set of all the metavariables in [t], and in
the types of metavariables recursively if [b]. *)
let get_metas : bool -> term -> MetaSet.t = fun b t ->
add_metas b t MetaSet.empty

(** [has_metas b t] checks whether there are metavariables in [t], and in the
types of metavariables recursively if [b] is true. *)
Expand All @@ -209,29 +166,6 @@ let distinct_vars : ctxt -> term array -> tvar array option = fun ctx ts ->
in
try Some (Array.map to_var ts) with Not_unique_var -> None

(** [nl_distinct_vars ctx ts] checks that [ts] is made of variables [vs] only
and returns some copy of [vs] where variables occurring more than once are
replaced by fresh variables. Variables defined in [ctx] are unfolded. It
returns [None] otherwise. *)
let nl_distinct_vars : ctxt -> term array -> tvar array option = fun ctx ts ->
let exception Not_a_var in
let open Stdlib in
let vars = ref VarSet.empty
and nl_vars = ref VarSet.empty in
let to_var t =
match Ctxt.unfold ctx t with
| Vari(x) ->
if VarSet.mem x !vars then nl_vars := VarSet.add x !nl_vars else
vars := VarSet.add x !vars;
x
| _ -> raise Not_a_var
in
let replace_nl_var x =
if VarSet.mem x !nl_vars then Bindlib.new_var mkfree "_" else x
in
try Some (Array.map replace_nl_var (Array.map to_var ts))
with Not_a_var -> None

(** {3 Conversion of a rule into a "pair" of terms} *)

(** [terms_of_rule r] converts the RHS (right hand side) of the rewriting rule
Expand All @@ -246,4 +180,4 @@ let term_of_rhs : rule -> term = fun r ->
let p = _Patt (Some(i)) name (Array.map Bindlib.box_var vars) in
TE_Some(Bindlib.unbox (Bindlib.bind_mvar vars p))
in
Bindlib.msubst r.rhs (Array.mapi fn r.vars)
Bindlib.msubst r.rhs (Array.mapi fn r.pvs)
2 changes: 1 addition & 1 deletion src/core/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ type stack = term list

(** [whnf_beta t] computes a weak head beta normal form of the term [t]. *)
let rec whnf_beta : term -> term = fun t ->
if !log_enabled then log_eval "evaluating [%a]" pp t;
if !log_enabled then log_eval "evaluating %a" pp t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I would keep the brackets for readability.

let s = Stdlib.(!steps) in
let (u, stk) = whnf_beta_stk t [] in
if Stdlib.(!steps) <> s then add_args u stk else unfold t
Expand Down
9 changes: 9 additions & 0 deletions src/core/extra.ml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,15 @@ module List =
| _ -> false
in in_sorted

(** [insert cmp x l] inserts [x] in the list [l] assuming that [l] is
sorted wrt [cmp]. *)
let insert : 'a cmp -> 'a -> 'a list -> 'a list = fun cmp x ->
let rec insert acc l =
match l with
| y :: m when cmp x y > 0 -> insert (y::acc) m
| _ -> List.rev_append acc (x::l)
in insert []

rlepigre marked this conversation as resolved.
Show resolved Hide resolved
end

module Array =
Expand Down
2 changes: 1 addition & 1 deletion src/core/handle.ml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ let handle_cmd : sig_state -> p_command -> sig_state * proof_data option =
if !(s.sym_def) <> None then
fatal pr.pos "Rewriting rules cannot be given for defined \
symbol [%s]." s.sym_name;
Sr.check_rule ss.builtins r; r
Sr.check_rule ss.builtins r
rlepigre marked this conversation as resolved.
Show resolved Hide resolved
in
let rs = List.map handle_rule rs in
(* Adding the rules all at once. *)
Expand Down
70 changes: 20 additions & 50 deletions src/core/infer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let constraints = Stdlib.ref []

(** Function adding a constraint. *)
let conv ctx a b =
if not (Basics.eq ctx a b) then
if not (Eval.eq_modulo ctx a b) then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using equality here had a significant positive impact on performances if I remember well. Conversion on the other end can be very costly, and if it fails it is gonna be tested again partially by unification.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not clear. We should compare the performances.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't compare anymore because eq is in the wrong module now (cyclic depencency).

begin
if !log_enabled then log_infr (yel "add %a") pp_constr (ctx,a,b);
let open Stdlib in constraints := (ctx,a,b) :: !constraints
Expand All @@ -37,7 +37,7 @@ let make_meta_codomain : ctxt -> term -> tbinder = fun ctx a ->
constraints are satisfied. [ctx] must be well-formed. This function
never fails (but constraints may be unsatisfiable). *)
let rec infer : ctxt -> term -> term = fun ctx t ->
if !log_enabled then log_infr "infer [%a]" pp t;
if !log_enabled then log_infr "infer %a%a" pp_ctxt ctx pp t;
match unfold t with
| Patt(_,_,_) -> assert false (* Forbidden case. *)
| TEnv(_,_) -> assert false (* Forbidden case. *)
Expand All @@ -51,11 +51,19 @@ let rec infer : ctxt -> term -> term = fun ctx t ->

(* ---------------------------------
ctx ⊢ Vari(x) ⇒ Ctxt.find x ctx *)
| Vari(x) -> (try Ctxt.type_of x ctx with Not_found -> assert false)
| Vari(x) ->
let a = try Ctxt.type_of x ctx with Not_found -> assert false in
if !log_enabled then
log_infr (blu "%a : %a") pp_term t pp_term a;
a

(* -------------------------------
ctx ⊢ Symb(s) ⇒ !(s.sym_type) *)
| Symb(s,_) -> !(s.sym_type)
| Symb(s,_) ->
let a = !(s.sym_type) in
if !log_enabled then
log_infr (blu "%a : %a") pp_term t pp_term a;
a

(* ctx ⊢ a ⇐ Type ctx, x : a ⊢ b<x> ⇒ s
-----------------------------------------
Expand Down Expand Up @@ -127,54 +135,16 @@ let rec infer : ctxt -> term -> term = fun ctx t ->
(* ctx ⊢ term_of_meta m e ⇒ a
----------------------------
ctx ⊢ Meta(m,e) ⇒ a *)
| Meta(m,e) ->
if !log_enabled then
log_infr (yel "%s is of type [%a]") (meta_name m) pp !(m.meta_type);
infer ctx (term_of_meta m e)
| Meta(m,ts) ->
infer ctx (term_of_meta m ts)

(** [check ctx t c] checks that the term [t] has type [c] in context
[ctx], possibly under some constraints recorded in [constraints]
using [conv]. [ctx] must be well-formed and [c] well-sorted. This
function never fails (but constraints may be unsatisfiable). *)

(* [check ctx t c] could be reduced to the default case [conv
(infer ctx t) c]. We however provide some more efficient
code when [t] is an abstraction, as witnessed by 'make holide':

Finished in 3:56.61 at 99% with 3180096Kb of RAM

Finished in 3:46.13 at 99% with 2724844Kb of RAM

This avoids to build a product to destructure it just after. *)
and check : ctxt -> term -> term -> unit = fun ctx t c ->
if !log_enabled then log_infr "check [%a] [%a]" pp t pp c;
match unfold t with
(* c → Prod(d,b) a ~ d ctx, x : A ⊢ t<x> ⇐ b<x>
----------------------------------------------------
ctx ⊢ Abst(a,t) ⇐ c *)
| Abst(a,t) ->
(* We ensure that [a] is of type [Type]. *)
check ctx a Type;
(* We (hopefully) evaluate [c] to a product, and get its body. *)
let b =
let c = Eval.whnf ctx c in
match c with
| Prod(d,b) -> conv ctx d a; b (* Domains must be convertible. *)
| Meta(m,ts) ->
let mxs, p, _bp1, bp2 = Env.extend_meta_type m in
conv ctx mxs p; Bindlib.msubst bp2 ts
| _ ->
let b = make_meta_codomain ctx a in
conv ctx c (Prod(a,b)); b
in
(* We type-check the body with the codomain. *)
let (x,t,ctx') = Ctxt.unbind ctx a None t in
check ctx' t (Bindlib.subst b (Vari(x)))
| t ->
(* ctx ⊢ t ⇒ a
-------------
ctx ⊢ t ⇐ a *)
conv ctx (infer ctx t) c
if !log_enabled then log_infr "check %a : %a" pp t pp c;
conv ctx (infer ctx t) c
Comment on lines +146 to +147
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember well, this had a significant performance impact. Did you run benchmarks?


(** [infer ctx t] returns a pair [(a,cs)] where [a] is a type for the
term [t] in the context [ctx], under unification constraints [cs].
Expand All @@ -187,8 +157,8 @@ let infer : ctxt -> term -> term * unif_constrs = fun ctx t ->
let constrs = Stdlib.(!constraints) in
if !log_enabled then
begin
log_infr (gre "infer [%a] yields [%a]") pp t pp a;
List.iter (log_infr " assuming %a" pp_constr) constrs;
log_infr (gre "infer %a : %a") pp t pp a;
fblanqui marked this conversation as resolved.
Show resolved Hide resolved
List.iter (log_infr " if %a" pp_constr) constrs;
end;
Stdlib.(constraints := []);
(a, constrs)
Expand All @@ -204,8 +174,8 @@ let check : ctxt -> term -> term -> unif_constrs = fun ctx t c ->
let constrs = Stdlib.(!constraints) in
if !log_enabled then
begin
log_infr (gre "check [%a] [%a]") pp t pp c;
List.iter (log_infr " assuming %a" pp_constr) constrs;
log_infr (gre "check %a : %a") pp t pp c;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel that brackets were useful for readability here.

List.iter (log_infr " if %a" pp_constr) constrs;
end;
Stdlib.(constraints := []);
constrs
6 changes: 6 additions & 0 deletions src/core/proof.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ module Goal :

(** [simpl g] simplifies the given goal, evaluating its type to SNF. *)
val simpl : t -> t

(** Comparison function. *)
val compare : t -> t -> int
fblanqui marked this conversation as resolved.
Show resolved Hide resolved
end =
struct
type t =
Expand All @@ -42,6 +45,9 @@ module Goal :

let simpl : t -> t = fun g ->
{g with goal_type = Eval.snf (Env.to_ctxt g.goal_hyps) g.goal_type}

let compare : t -> t -> int = fun g1 g2 ->
Meta.compare g1.goal_meta g2.goal_meta
end

(** Representation of the proof state of a theorem. *)
Expand Down
2 changes: 1 addition & 1 deletion src/core/queries.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let handle_query : sig_state -> Proof.t option -> p_query -> unit =
| (Some(a), Some(b)) ->
let pb = { no_problems with to_solve = [[], a, b] } in
begin
match solve ss.builtins true pb with
match solve ss.builtins pb with
| None -> fatal q.pos "Infered types are not convertible."
| Some [] -> Eval.eq_modulo [] t u
| Some cs ->
Expand Down
51 changes: 48 additions & 3 deletions src/core/rewrite.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,51 @@ open Print
let log_rewr = new_logger 'r' "rewr" "the rewrite tactic"
let log_rewr = log_rewr.logger

(** [eq ctx t u] tests the equality of [t] and [u] (up to α-equivalence). It
fails if [t] or [u] contain terms of the form [Patt(i,s,e)] or
[TEnv(te,env)]. In the process, subterms of the form [TRef(r)] in [t] and
[u] may be set with the corresponding value to enforce equality, and
variables appearing in [ctx] can be unfolded. In other words, [eq t u] can
be used to implement non-linear matching. When the
matching feature is used, one should make sure that [TRef] constructors do
not appear both in [t] and in [u] at the same time. Indeed, the references
are set naively, without occurrence checking. *)
let eq : ctxt -> term -> term -> bool = fun ctx a b -> a == b ||
let exception Not_equal in
let rec eq l =
match l with
| [] -> ()
| (a,b)::l ->
begin
if !log_enabled then log_rewr "eq [%a] [%a]" pp_term a pp_term b;
match (Ctxt.unfold ctx a, Ctxt.unfold ctx b) with
| (a , b ) when a == b -> eq l
| (Vari(x1) , Vari(x2) ) when Bindlib.eq_vars x1 x2 -> eq l
| (Type , Type )
| (Kind , Kind ) -> eq l
| (Symb(s1,_) , Symb(s2,_) ) when s1 == s2 -> eq l
| (Prod(a1,b1), Prod(a2,b2))
| (Abst(a1,b1), Abst(a2,b2)) -> let (_, b1, b2) = Bindlib.unbind2 b1 b2 in
eq ((a1,a2)::(b1,b2)::l)
| (LLet(a1,t1,u1), LLet(a2,t2,u2)) ->
let (_, u1, u2) = Bindlib.unbind2 u1 u2 in
eq ((a1,a2)::(t1,t2)::(u1,u2)::l)
| (Appl(t1,u1), Appl(t2,u2)) -> eq ((t1,t2)::(u1,u2)::l)
| (Meta(m1,e1), Meta(m2,e2)) when m1 == m2 ->
eq (if e1 == e2 then l else List.add_array2 e1 e2 l)
| (Wild , _ )
| (_ , Wild ) -> eq l
| (TRef(r) , b ) -> r := Some(b); eq l
| (a , TRef(r) ) -> r := Some(a); eq l
| (Patt(_,_,_), _ )
| (_ , Patt(_,_,_))
| (TEnv(_,_) , _ )
| (_ , TEnv(_,_) ) -> assert false
| (_ , _ ) -> raise Not_equal
end
in
try eq [(a,b)]; true with Not_equal -> false
Comment on lines +16 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think this has nothing to do in the Rewrite module. The previous discussion was not over. Again, the point of reviews is to convince the reviewer that they are wrong, or that you are right.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And frankly, I should really not have to review that kind of changes as part of this PR.


(** Rewrite patterns as in Coq/SSReflect. See "A Small Scale
Reflection Extension for the Coq system", by Georges Gonthier,
Assia Mahboubi and Enrico Tassi, INRIA Research Report 6455, 2016,
Expand Down Expand Up @@ -165,7 +210,7 @@ let break_prod : term -> term * tvar array = fun a ->
let match_pattern : to_subst -> term -> term array option = fun (xs,p) t ->
let ts = Array.map (fun _ -> TRef(ref None)) xs in
let p = Bindlib.msubst (Bindlib.unbox (Bindlib.bind_mvar xs (lift p))) ts in
if Basics.eq [] p t then Some(Array.map unfold ts) else None
if eq [] p t then Some(Array.map unfold ts) else None

(** [find_subst t (xs,p)] is given a term [t] and a pattern [p] (with “pattern
variables” of [xs]), and it finds the first instance of (a term matching)
Expand Down Expand Up @@ -198,7 +243,7 @@ let find_subst : term -> to_subst -> term array option = fun t (xs,p) ->
let make_pat : term -> term -> bool = fun t p ->
let time = Time.save () in
let rec make_pat_aux : term -> bool = fun t ->
if Basics.eq [] t p then true else
if eq [] t p then true else
begin
Time.restore time;
match unfold t with
Expand All @@ -218,7 +263,7 @@ let make_pat : term -> term -> bool = fun t p ->
let bind_match : term -> term -> tbinder = fun p t ->
let x = Bindlib.new_var mkfree "X" in
let rec lift_subst : term -> tbox = fun t ->
if Basics.eq [] p t then _Vari x else
if eq [] p t then _Vari x else
match unfold t with
| Vari(y) -> _Vari y
| Type -> _Type
Expand Down
Loading