Skip to content

Commit 17a0f00

Browse files
authored
Merge pull request #604 from rlepigre/janno/structured-synterp
Structured synterp actions
2 parents 4d0bcea + f3192fb commit 17a0f00

16 files changed

+558
-108
lines changed

Changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
- New `coq.parse-attributes` support for the `attlabel` specification,
77
see `coq-lib-common.elpi` for its documentation.
88
- New `coq.goal->pp`
9+
- Replace `coq.replay-all-missing-synterp-actions` by (nestable) groups of actions
10+
- New `coq.begin-synterp-group` and `coq.end-synterp-group` primitives
11+
- New `coq.replay-synterp-action-group` primitive (replaces `coq.replay-all-missing-synterp-actions` in conjunction with a group)
12+
- New `coq.replay-next-synterp-actions` to replay all synterp actions until the next beginning/end of a synterp group
913

1014
## [2.0.2] - 01/02/2024
1115

README.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,23 @@ The synterp-command can output data of that type, but also any other data it
290290
wishes.
291291

292292
The second way to communicate data is implicit, but limited to synterp actions.
293-
During the interp phase commands can use the `coq.next-synterp-action` API to
294-
peek into the list of actions yet to be performed.
295-
Once an action is performed, the API reveals the next one. See also the
296-
related utilities `coq.replay-synterp-action` and
297-
`coq.replay-all-missing-synterp-actions`.
293+
Such synterp actions can be recorded into (nested) groups whose structure is
294+
declared using well-bracketed calls to predicates `coq.begin-synterp-group`
295+
and `coq.end-synterp-group` in the synterp phase. In the interp phase, one can
296+
then use predicate `coq.replay-synterp-action-group` to replay all the synterp
297+
actions of the group with the given name at once.
298+
299+
In the case where one wishes to interleave code between the actions of a given
300+
group, it is also possible to match the synterp group structure at interp, via
301+
`coq.begin-synterp-group` and `coq.end-synterp-group`. Individual actions that
302+
are contained in the group then need to be replayed individually.
303+
304+
One can use `coq.replay-next-synterp-actions` to replay all synterp actions
305+
until the next beginning/end of a synterp group. However, this is discouraged
306+
in favour of using groups explicitly, as this is more modular. Code that used
307+
to rely on the now-removed `coq.replay-all-missing-synterp-actions` predicate
308+
can rely on `coq.replay-next-synterp-actions` instead, but this is discouraged
309+
in favour of using groups explicitly)
298310

299311
##### Syntax of the `#[phase]` attribute
300312

_CoqProject.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,4 @@ tests/test_query_extra_dep.v
5656
tests/test_toposort.v
5757
tests/test_synterp.v
5858
tests/test_checker.v
59+
tests/test_replay.v

apps/NES/elpi/nes_interp.elpi

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ print-path Path PP :- std.do! [
88
coq.say {coq.pp->string Out},
99
].
1010

11+
pred begin-path.
12+
begin-path :- coq.replay-synterp-action-group "nes.begin-path".
13+
14+
pred end-path.
15+
end-path :- coq.replay-synterp-action-group "nes.end-path".
16+
17+
pred open-path.
18+
open-path :- coq.replay-synterp-action-group "nes.open-path".
19+
1120
namespace print {
1221

1322
pred pp-list i:list A, i:(A -> coq.pp -> prop), o:coq.pp.
@@ -82,4 +91,4 @@ namespace print {
8291
}
8392

8493

85-
}
94+
}

apps/NES/elpi/nes_synterp.elpi

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,12 @@ pred ns->string i:list string, o:string.
8989
ns->string NS S :- std.string.concat "." NS S.
9090

9191
pred begin-path i:list string, o:list prop.
92-
begin-path [] [].
92+
begin-path [] [] :- std.do! [
93+
coq.begin-synterp-group "nes.begin-path" Group,
94+
coq.end-synterp-group Group,
95+
].
9396
begin-path ([_|_] as Path) Out :- std.do! [
97+
coq.begin-synterp-group "nes.begin-path" Group,
9498
coq.env.current-path CP,
9599
if (open-ns _ NSCP) (std.assert! (NSCP = CP) "NS: cannot begin a namespace inside a module that is inside a namespace") true,
96100
std.map {std.findall (open-ns Y_ P_)} open-ns->string Stack,
@@ -107,7 +111,7 @@ begin-path ([_|_] as Path) Out :- std.do! [
107111
iter<- Stack {std.rev Path} begin-ns [] Out,
108112

109113
open-super-path Path [],
110-
114+
coq.end-synterp-group Group,
111115
].
112116

113117
pred std.time-do! i:list prop.
@@ -118,18 +122,25 @@ std.time-do! [P|PS] :-
118122
std.time-do! PS.
119123

120124
pred end-path i:list string, o:list prop.
121-
end-path [] [].
125+
end-path [] [] :- std.do! [
126+
coq.begin-synterp-group "nes.end-path" Group,
127+
coq.end-synterp-group Group,
128+
].
122129
end-path ([_|_] as Path) Out :- std.do! [
130+
coq.begin-synterp-group "nes.end-path" Group,
123131
std.map {std.findall (open-ns X_ P_)} nes.open-ns->string Stack,
124132
std.assert! (std.appendR {std.rev Path} Bottom Stack) "NES: Ending a namespace that is not begun",
125133
nes.iter-> Bottom {std.rev Path} nes.end-ns [] Out,
134+
coq.end-synterp-group Group,
126135
].
127136

128137

129138
pred open-path i:list string.
130139
open-path Path :- std.do! [
140+
coq.begin-synterp-group "nes.open-path" Group,
131141
std.map {std.findall (ns Path M_)} nes.ns->modpath Mods,
132-
std.forall Mods coq.env.import-module
142+
std.forall Mods coq.env.import-module,
143+
coq.end-synterp-group Group,
133144
].
134145

135146
pred open-super-path i:list string, i:list string.

apps/NES/tests/test_NES.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ NES.Begin X.
7474
Module Y.
7575
Fail NES.Begin Z.
7676
End Y.
77-
NES.End X.
77+
NES.End X.

apps/NES/tests/test_NES_lib.v

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
From elpi.apps.NES Extra Dependency "nes_synterp.elpi" as nes_synterp.
2+
From elpi.apps.NES Extra Dependency "nes_interp.elpi" as nes_interp.
23
From elpi.apps Require Import NES.
34

45
Elpi Command Make.
5-
#[synterp] Elpi Accumulate Db NES.db.
6+
#[phase="both"] Elpi Accumulate Db NES.db.
67
#[synterp] Elpi Accumulate File nes_synterp.
8+
#[interp] Elpi Accumulate File nes_interp.
79
#[synterp] Elpi Accumulate lp:{{
810

9-
main-synterp [str Path] ActionsToOpen :- std.do! [
11+
main [str Path] :- std.do! [
1012
nes.string->ns Path NS,
1113
nes.begin-path NS OpenNS,
12-
coq.synterp-actions ActionsToOpen,
1314
OpenNS => nes.end-path NS _NewNS,
1415
].
1516
main _ :- coq.error "usage: Make <DotSeparatedPath>".
1617

1718
}}.
1819
#[interp] Elpi Accumulate lp:{{
19-
main-interp [str _] ActionsBefore :- std.do! [
20-
std.forall ActionsBefore coq.replay-synterp-action,
20+
main _ :- std.do! [
21+
nes.begin-path,
2122
coq.env.add-const "x" {{ 42 }} _ @transparent! _C,
22-
coq.replay-all-missing-synterp-actions,
23+
nes.end-path,
2324
].
2425
}}.
2526
Elpi Typecheck.

apps/NES/theories/NES.v

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ pred open-ns o:string, o:list string.
99
:name "open-ns:begin"
1010
open-ns _ _ :- fail.
1111

12+
}}.
13+
14+
#[phase="both"] Elpi Accumulate NES.db lp:{{
15+
1216
typeabbrev path (list string).
1317

1418
:index (2)
1519
pred ns o:path, o:modpath.
16-
1720
}}.
1821

1922
Elpi Command NES.Status.
@@ -32,56 +35,56 @@ Elpi Export NES.Status.
3235

3336
Elpi Command NES.Begin.
3437
#[synterp] Elpi Accumulate File nes_synterp.
38+
#[interp] Elpi Accumulate File nes_interp.
39+
#[phase="both"] Elpi Accumulate Db NES.db.
3540
#[synterp] Elpi Accumulate lp:{{
3641

3742
main [str NS] :- !, nes.begin-path {nes.string->non-empty-ns NS} _.
3843
main _ :- coq.error "usage: NES.Begin <DotSeparatedPath>".
3944

4045
}}.
41-
#[synterp] Elpi Accumulate Db NES.db.
42-
#[interp] Elpi Accumulate lp:{{ main _ :- coq.replay-all-missing-synterp-actions. }}.
46+
#[interp] Elpi Accumulate lp:{{ main _ :- nes.begin-path. }}.
4347
Elpi Typecheck.
4448
Elpi Export NES.Begin.
4549

4650
Elpi Command NES.End.
4751
#[synterp] Elpi Accumulate File nes_synterp.
52+
#[interp] Elpi Accumulate File nes_interp.
53+
#[phase="both"] Elpi Accumulate Db NES.db.
4854
#[synterp] Elpi Accumulate lp:{{
4955

5056
main [str NS] :- nes.end-path {nes.string->non-empty-ns NS} _.
5157
main _ :- coq.error "usage: NES.End <DotSeparatedPath>".
5258

5359
}}.
54-
#[synterp] Elpi Accumulate Db NES.db.
55-
#[interp] Elpi Accumulate lp:{{ main _ :- coq.replay-all-missing-synterp-actions. }}.
60+
#[interp] Elpi Accumulate lp:{{ main _ :- nes.end-path. }}.
5661
Elpi Typecheck.
5762
Elpi Export NES.End.
5863

5964

6065
Elpi Command NES.Open.
61-
#[synterp] Elpi Accumulate Db NES.db.
6266
#[synterp] Elpi Accumulate File nes_synterp.
67+
#[interp] Elpi Accumulate File nes_interp.
68+
#[phase="both"] Elpi Accumulate Db NES.db.
6369
#[synterp] Elpi Accumulate lp:{{
6470

6571
main [str NS] :- nes.open-path {nes.resolve NS}.
6672
main _ :- coq.error "usage: NES.Open <DotSeparatedPath>".
6773

6874
}}.
69-
#[interp] Elpi Accumulate lp:{{ main _ :- coq.replay-all-missing-synterp-actions. }}.
75+
#[interp] Elpi Accumulate lp:{{ main _ :- nes.open-path. }}.
7076
Elpi Typecheck.
7177
Elpi Export NES.Open.
7278

7379
(* List the contents a namespace *)
7480
Elpi Command NES.List.
75-
#[synterp] Elpi Accumulate Db NES.db.
81+
#[phase="both"] Elpi Accumulate Db NES.db.
7682
#[synterp] Elpi Accumulate File nes_synterp.
7783
#[interp] Elpi Accumulate File nes_interp.
7884
#[synterp] Elpi Accumulate lp:{{
7985
main-synterp [str NS] (pr DB Path) :- nes.resolve NS Path, std.findall (ns O_ P_) DB.
8086
}}.
8187
#[interp] Elpi Accumulate lp:{{
82-
typeabbrev path (list string).
83-
pred ns o:path, o:modpath.
84-
8588
pred pp-gref i:gref, o:coq.pp.
8689
pp-gref GR PP :- coq.term->pp (global GR) PP.
8790

@@ -94,16 +97,13 @@ Elpi Export NES.List.
9497

9598
(* NES.List with types *)
9699
Elpi Command NES.Print.
97-
#[synterp] Elpi Accumulate Db NES.db.
100+
#[phase="both"] Elpi Accumulate Db NES.db.
98101
#[synterp] Elpi Accumulate File nes_synterp.
99102
#[interp] Elpi Accumulate File nes_interp.
100103
#[synterp] Elpi Accumulate lp:{{
101104
main-synterp [str NS] (pr DB Path) :- nes.resolve NS Path, std.findall (ns O_ P_) DB.
102105
}}.
103106
Elpi Accumulate lp:{{
104-
typeabbrev path (list string).
105-
pred ns o:path, o:modpath.
106-
107107
pred pp-gref i:gref, o:coq.pp.
108108
pp-gref GR PP :- std.do! [
109109
coq.env.typeof GR Ty,

coq-builtin-synterp.elpi

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,14 @@ type export-module modpath -> synterp-action.
363363
% parsing phase (aka synterp) up to now.
364364
external pred coq.synterp-actions o:list synterp-action.
365365

366+
% [coq.begin-synterp-group ID Group] Create and open a new synterp action
367+
% group with the given name.
368+
external pred coq.begin-synterp-group i:id, o:group.
369+
370+
% [coq.end-synterp-group Group] End the synterp action group Group. Group
371+
% must refer to the most recently openned group.
372+
external pred coq.end-synterp-group i:group.
373+
366374
% Generic attribute value
367375
kind attribute-value type.
368376
type leaf-str string -> attribute-value.

coq-builtin.elpi

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,14 +1797,29 @@ type include-module-type modtypath -> synterp-action.
17971797
type import-module modpath -> synterp-action.
17981798
type export-module modpath -> synterp-action.
17991799

1800+
% Synterp action group
1801+
typeabbrev group (ctype "group").
1802+
1803+
18001804
% [coq.next-synterp-action A] Get the next action performed during parsing
18011805
% (aka synterp), that is also the next action to be performed during
18021806
% execution (aka interp). See also coq.replay-synterp-action
18031807
external pred coq.next-synterp-action o:synterp-action.
18041808

1805-
% [coq.replay-all-missing-synterp-actions] Execute all actions needed in
1806-
% order to match the actions performed at parsing time (aka synterp)
1807-
external pred coq.replay-all-missing-synterp-actions .
1809+
% [coq.replay-synterp-action-group ID] Execute all actions of synterp action
1810+
% group ID. ID must be the name of the next group, it must not be opened
1811+
% already, and there must not be any actions before it.
1812+
external pred coq.replay-synterp-action-group i:id.
1813+
1814+
% [coq.begin-synterp-group ID Group] Match a begin-synterp-group synterp
1815+
% operation. ID must be the name of the next synterp action group and there
1816+
% must not be any actions before it.
1817+
external pred coq.begin-synterp-group i:id, o:group.
1818+
1819+
% [coq.end-synterp-group Group] Match a end-synterp-group synterp operation.
1820+
% Group must be the currently opened synterp action group and the group must
1821+
% not have any more synterp actions or groups left to replay.
1822+
external pred coq.end-synterp-group i:group.
18081823

18091824
% -- Utils ------------------------------------------------------------
18101825

0 commit comments

Comments
 (0)