Skip to content

Commit 19f6f1e

Browse files
committed
feat: Add Rewrite Rules to TemplateMonad
First hacky attempt, basically parsing the whole `Rewrite Rule` vernac command. More robust solution would probably require updating Rocq's API.
1 parent 7b09130 commit 19f6f1e

File tree

9 files changed

+136
-1
lines changed

9 files changed

+136
-1
lines changed

template-rocq/src/plugin_core.ml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,36 @@ let tmDefinition (nm : ident) ?poly:(poly=false) ?opaque:(opaque=false) (typ : t
9393
let evm = Evd.from_env env in
9494
success ~st env evm (Names.Constant.canonical (Globnames.destConstRef n))
9595

96+
let tmRewriteRule (id : ident) (rules : (string option * string * string) list) : unit tm =
97+
fun ~st env evm success _fail ->
98+
let one_rule (udecl, lhs, rhs) =
99+
"| " ^
100+
(match udecl with
101+
| None -> ""
102+
| Some u -> u ^ " |- ") ^
103+
lhs ^ " => " ^ rhs
104+
in
105+
let cmd =
106+
"Rewrite Rule " ^ Names.Id.to_string id ^ " :=\n" ^
107+
String.concat "\n" (List.map one_rule rules) ^
108+
"."
109+
in
110+
let parsed =
111+
Procq.parse_string (Procq.eoi_entry (Pvernac.main_entry None)) cmd
112+
in
113+
let parsed =
114+
match parsed with
115+
| Some x -> x
116+
| None -> CErrors.user_err (Pp.str "Empty command while parsing tmRewriteRule")
117+
in
118+
let vst = Vernacstate.freeze_full_state () in
119+
let _vst' =
120+
Vernacinterp.interp ~intern:Vernacinterp.fs_intern ~verbosely:false ~st:vst parsed
121+
in
122+
let env = Global.env () in
123+
let evm = Evd.from_env env in
124+
success ~st env evm ()
125+
96126
let tmAxiom (nm : ident) ?poly:(poly=false) (typ : term) : kername tm =
97127
fun ~st env evm success _fail ->
98128
let univs = Evd.univ_entry ~poly evm in

template-rocq/src/plugin_core.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ val reduce : Environ.env -> Evd.evar_map -> reduction_strategy -> term -> Evd.ev
4848
val tmEval : reduction_strategy -> term -> term tm
4949

5050
val tmDefinition : ident -> ?poly:bool -> ?opaque:bool -> term option -> term -> kername tm
51+
val tmRewriteRule : ident -> (string option * string * string) list -> unit tm
5152
val tmAxiom : ident -> ?poly:bool -> term -> kername tm
5253
val tmLemma : ident -> ?poly:bool -> term -> kername tm
5354

template-rocq/src/run_template_monad.ml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,14 @@ let unquote_map_option f trm =
6767

6868
let unquote_option = unquote_map_option (fun x -> x)
6969

70+
let unquote_rewrite_rule trm : string option * string * string =
71+
let lhsrhs, rhs = unquote_pair trm in
72+
let udecl, lhs = unquote_pair lhsrhs in
73+
let udecl = unquote_map_option unquote_string udecl in
74+
let lhs = unquote_string lhs in
75+
let rhs = unquote_string rhs in
76+
(udecl, lhs, rhs)
77+
7078
let rec unquote_pos trm : int =
7179
let (h,args) = app_full trm [] in
7280
match args with
@@ -408,6 +416,15 @@ let rec run_template_program_rec ~poly ?(intactic=false) (k : Constr.t Plugin_co
408416
Plugin_core.run ~st
409417
(Plugin_core.tmDefinition name ~poly ~opaque typ body) env evm
410418
(fun ~st env evm res -> k ~st env evm (quote_kn res))
419+
| TmRewriteRule (name, rules) ->
420+
if intactic
421+
then not_in_tactic "tmRewriteRule"
422+
else
423+
let name = unquote_ident (reduce_all env evm name) in
424+
let rules = List.map unquote_rewrite_rule (unquote_list (reduce_all env evm rules)) in
425+
Plugin_core.run ~st
426+
(Plugin_core.tmRewriteRule name rules) env evm
427+
(fun ~st env evm _ -> k ~st env evm (Lazy.force unit_tt))
411428
| TmLemmaTerm (name, typ) ->
412429
let ident = unquote_ident (reduce_all env evm name) in
413430
let evm,typ = denote_term env evm (reduce_all env evm typ) in

template-rocq/src/template_monad.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ let (ptmReturn,
2020

2121
ptmLemma,
2222
ptmDefinitionRed,
23+
ptmRewriteRule,
2324
ptmAxiomRed,
2425
ptmMkDefinition,
2526
ptmMkInductive,
@@ -64,6 +65,7 @@ let (ptmReturn,
6465

6566
r_template_monad_prop_p "tmLemma",
6667
r_template_monad_prop_p "tmDefinitionRed_",
68+
r_template_monad_prop_p "tmRewriteRule_",
6769
r_template_monad_prop_p "tmAxiomRed",
6870
r_template_monad_prop_p "tmMkDefinition",
6971
r_template_monad_prop_p "tmMkInductive",
@@ -174,6 +176,7 @@ type template_monad =
174176

175177
(* creating definitions *)
176178
| TmDefinition of Constr.t * Constr.t * Constr.t * Constr.t * Constr.t
179+
| TmRewriteRule of Constr.t * Constr.t
177180
| TmDefinitionTerm of Constr.t * Constr.t * Constr.t * Constr.t
178181
| TmLemma of Constr.t * Constr.t
179182
| TmLemmaTerm of Constr.t * Constr.t
@@ -283,6 +286,11 @@ let next_action env evd (pgm : constr) : template_monad * _ =
283286
| opaque::name::s::typ::body::[] ->
284287
(TmDefinition (opaque, name, s, typ, body), universes)
285288
| _ -> monad_failure "tmDefinitionRed" 4
289+
else if eq_gr ptmRewriteRule then
290+
match args with
291+
| name::rules::[] ->
292+
(TmRewriteRule (name, rules), universes)
293+
| _ -> monad_failure "tmRewriteRule" 2
286294
else if eq_gr ttmDefinition then
287295
match args with
288296
| opaque::name::typ::body::[] ->

template-rocq/src/template_monad.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type template_monad =
2323

2424
(* creating definitions *)
2525
| TmDefinition of Constr.t * Constr.t * Constr.t * Constr.t * Constr.t
26+
| TmRewriteRule of Constr.t * Constr.t
2627
| TmDefinitionTerm of Constr.t * Constr.t * Constr.t * Constr.t
2728
| TmLemma of Constr.t * Constr.t
2829
| TmLemmaTerm of Constr.t * Constr.t

template-rocq/theories/Constants.v

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ Register MetaRocq.Template.TemplateMonad.Core.tmVariable as metarocq.templatemon
254254
Register MetaRocq.Template.TemplateMonad.Core.tmSymbol as metarocq.templatemonad.prop.tmSymbol.
255255
Register MetaRocq.Template.TemplateMonad.Core.tmLemma as metarocq.templatemonad.prop.tmLemma.
256256
Register MetaRocq.Template.TemplateMonad.Core.tmDefinitionRed_ as metarocq.templatemonad.prop.tmDefinitionRed_.
257+
Register MetaRocq.Template.TemplateMonad.Core.tmRewriteRule_ as metarocq.templatemonad.prop.tmRewriteRule_.
257258
Register MetaRocq.Template.TemplateMonad.Core.tmAxiomRed as metarocq.templatemonad.prop.tmAxiomRed.
258259
Register MetaRocq.Template.TemplateMonad.Core.tmMkDefinition as metarocq.templatemonad.prop.tmMkDefinition.
259260
Register MetaRocq.Template.TemplateMonad.Core.tmMkInductive as metarocq.templatemonad.prop.tmMkInductive.

template-rocq/theories/TemplateMonad/Core.v

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Cumulative Inductive TemplateMonad@{t u} : Type@{t} -> Prop :=
3131
(* Return the defined constant *)
3232
| tmLemma : ident -> forall A : Type@{t}, TemplateMonad A
3333
| tmDefinitionRed_ : forall (opaque : bool), ident -> option reductionStrategy -> forall {A:Type@{t}}, A -> TemplateMonad A
34+
| tmRewriteRule_ : ident -> list (option string * string * string) -> TemplateMonad unit
3435
| tmAxiomRed : ident -> option reductionStrategy -> forall A : Type@{t}, TemplateMonad A
3536
| tmVariable : ident -> Type@{t} -> TemplateMonad unit
3637
| tmSymbol : ident -> Type@{t} -> TemplateMonad unit
@@ -121,6 +122,14 @@ Definition tmMkInductive' (mind : mutual_inductive_body) : TemplateMonad unit
121122

122123
Definition tmAxiom id := tmAxiomRed id None.
123124
Definition tmDefinition id {A} t := @tmDefinitionRed_ false id None A t.
125+
Definition tmRewriteRule (id : ident) (rules : list (string * string)) : TemplateMonad unit :=
126+
tmRewriteRule_ id
127+
(List.map (fun x =>
128+
let '(lhs, rhs) := x in
129+
(None, lhs, rhs))
130+
rules).
131+
Definition tmRewriteRuleU (id : ident) (rules : list (option string * string * string)) : TemplateMonad unit :=
132+
tmRewriteRule_ id rules.
124133

125134
(** We keep the original behaviour of [tmQuoteRec]: it quotes all the dependencies regardless of the opaqueness settings *)
126135
Definition tmQuoteRec {A} (a : A) := tmQuoteRecTransp a true.

test-suite/_RocqProject.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ tmFix.v
5151
tmFreshName.v
5252
tmInferInstance.v
5353
tmQuoteModule.v
54+
tmRewriteRule.v
5455
tmVariable.v
5556
unfold.v
5657
univ.v
5758
vs.v
5859
ind_fresh_univ.v
59-

test-suite/tmRewriteRule.v

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
From MetaRocq.Utils Require Import utils.
2+
From MetaRocq.Template Require Import All.
3+
From Stdlib Require Import List.
4+
Import ListNotations.
5+
Import MRMonadNotation.
6+
7+
8+
(* Rewrite Rule pplus_rewrite :=
9+
| ?n ++ 0 => ?n
10+
| ?n ++ S ?m => S (?n ++ ?m)
11+
| 0 ++ ?n => ?n
12+
| S ?n ++ ?m => S (?n ++ ?m). *)
13+
14+
MetaRocq Run (
15+
tmSymbol "f_rr" (nat -> nat -> nat) ;;
16+
tmRewriteRule "pplus_n_0_rewrite_tm"
17+
[ ("f_rr ?n 0", "?n") ]).
18+
19+
About f_rr.
20+
Infix "++" := f_rr.
21+
22+
Eval cbn in 1 ++ 0.
23+
(* Doesn't reduce *)
24+
Eval cbn in 0 ++ 1.
25+
26+
MetaRocq Run (tmRewriteRule "pplus_rewrite"
27+
[ ("?n ++ S ?m", "S (?n ++ ?m)");
28+
("S ?n ++ ?m", "S (?n ++ ?m)");
29+
("0 ++ ?n", "?n") ]).
30+
31+
Eval cbn in 0 ++ 1.
32+
Eval cbn in 1 ++ 3.
33+
Eval cbn in 3 ++ 1.
34+
35+
Set Universe Polymorphism.
36+
#[universes(polymorphic=no)]
37+
Sort Exc.
38+
39+
#[unfold_fix]
40+
Symbol (raise : forall (A : Type@{Exc; Set}), A).
41+
42+
Inductive nat : Type@{Exc; Set} :=
43+
| O : nat
44+
| S : nat -> nat.
45+
46+
Inductive bool : Type@{Exc; Set} :=
47+
| true
48+
| false.
49+
50+
Rewrite Rule raise_nat_match :=
51+
| match raise nat as t0 return ?P with
52+
| O => _
53+
| _ => _
54+
end => raise (?P@{t0 := raise nat}).
55+
56+
Eval cbn in match raise nat with | O => O | S n => S n end.
57+
Eval cbn in match raise nat with | O => true | S n => false end.
58+
59+
Eval cbn in match raise bool with | true => O | false => S O end.
60+
61+
MetaRocq Run (tmRewriteRule "raise_bool_match"
62+
[ ("match raise bool as t0 return ?P with | true => _ | _ => _ end", "raise (?P@{t0 := raise bool})")]).
63+
64+
Eval cbn in match raise bool with | true => O | false => S O end.
65+
66+
67+
68+

0 commit comments

Comments
 (0)