Skip to content

Commit 78d8c2c

Browse files
authored
Merge pull request #521 from LPCIC/fix-HOAS-primproj
API to fold/unfold primproj
2 parents 84cd737 + a2b302e commit 78d8c2c

File tree

5 files changed

+56
-1
lines changed

5 files changed

+56
-1
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
- New `coq.begin-synterp-group` and `coq.end-synterp-group` primitives
1515
- New `coq.replay-synterp-action-group` primitive (replaces `coq.replay-all-missing-synterp-actions` in conjunction with a group)
1616
- New `coq.replay-next-synterp-actions` to replay all synterp actions until the next beginning/end of a synterp group
17+
- New `coq.primitive.projection-unfolded` to fold/unfold a primitive projection.
18+
Note that unfolded primitive projections are still compact terms, but they
19+
are displayed as `match` expressions and some Ltac code can see that.
1720

1821
## [2.0.2] - 01/02/2024
1922

apps/derive/elpi/lens.elpi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ declare-lens Prefix I FieldName RawBody (lens-db I FieldName C):-
6868
% In order to support primitive records we call the elaborator, which
6969
% eventually compiles the match into primitive projections
7070
std.assert-ok! (coq.elaborate-skeleton RawBody Ty Body) "derive.lens generates illtyped term",
71-
coq.env.add-const Name Body Ty @transparent! C,
71+
(pi P P1 N\ copy (primitive (proj P N)) (primitive (proj P1 N)) :- coq.primitive.projection-unfolded P1 P) => copy Body Body1,
72+
coq.env.add-const Name Body1 Ty @transparent! C,
7273
std.map {std.iota Nparams} (_\r\ r = maximal) Implicits,
7374
if (Nparams > 0)
7475
(@global! => coq.arguments.set-implicit (const C) [Implicits, []])

apps/derive/tests/test_lens.v

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,32 @@ match goal with
2929
end.
3030
Abort.
3131

32+
#[projections(primitive=yes)]
33+
Record R := MkR {
34+
proj : nat;
35+
}.
3236

37+
Elpi derive.lens R "R__".
3338

39+
Lemma failing r :
40+
r.(proj) = 0 ->
41+
view R__proj r = r.(proj).
42+
Proof.
43+
simpl.
44+
intros Hpr.
45+
rewrite Hpr.
46+
reflexivity.
47+
Abort.
48+
49+
Lemma working r :
50+
match r with MkR r_proj => r_proj end = 0 ->
51+
view R__proj r = match r with MkR r_proj => r_proj end.
52+
Proof.
53+
simpl.
54+
intros Hpr.
55+
rewrite Hpr.
56+
Fail reflexivity.
57+
unfold proj.
58+
rewrite Hpr.
59+
reflexivity.
60+
Qed.

coq-builtin.elpi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,12 @@ external pred coq.float64->float i:float64, o:float.
11021102
% on 64 bits. Currently, it should not fail.
11031103
external pred coq.float->float64 i:float, o:float64.
11041104

1105+
% [coq.primitive.projection-unfolded P PU] Relates a primitive projection P
1106+
% to its unfolded version PU. PU is still a primitive projection, but it is
1107+
% displayed as a match and some Ltac code can see that.
1108+
external pred coq.primitive.projection-unfolded o:projection,
1109+
o:projection.
1110+
11051111

11061112
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11071113
% API for extra logical objects

src/coq_elpi_builtins.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,24 @@ declared as cumulative.|};
25572557
!: (Float64.of_float f))),
25582558
DocAbove);
25592559
2560+
MLCode(Pred("coq.primitive.projection-unfolded",
2561+
InOut(B.ioarg projection,"P",
2562+
InOut(B.ioarg projection,"PU",
2563+
Read(global, "Relates a primitive projection P to its unfolded version PU. PU is still a primitive projection, but it is displayed as a match and some Ltac code can see that."))),
2564+
(fun p q ~depth:_ coq_context _ _ ->
2565+
let test_folded = function Data x -> if Projection.unfolded x then raise No_clause | _ -> () in
2566+
let test_unfolded = function Data x -> if not (Projection.unfolded x) then raise No_clause | _ -> () in
2567+
test_folded p;
2568+
test_unfolded q;
2569+
match p, q with
2570+
| Data p, Data q ->
2571+
if Environ.QProjection.Repr.equal coq_context.env (Projection.repr p) (Projection.repr q) then ?: None +? None else raise No_clause
2572+
| NoData, NoData -> U.type_error "coq.projection.unfolded: got no input data"
2573+
| Data p, NoData -> ?: None +! Projection.(make (repr p) true)
2574+
| NoData, Data q -> !: Projection.(make (repr q) false) +? None
2575+
)),
2576+
DocAbove);
2577+
25602578
LPCode {|
25612579
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
25622580
% API for extra logical objects

0 commit comments

Comments
 (0)