Skip to content

Commit e8b50c7

Browse files
authored
Merge pull request #177 from LPCIC/replace-clause
New attribute :replace
2 parents 6d9608b + 24cdb1b commit e8b50c7

File tree

12 files changed

+82
-7
lines changed

12 files changed

+82
-7
lines changed

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# UNRELEASED
2+
3+
- Elpi:
4+
- New attribute `:replace` which replaces a named clause by an unnamed one
5+
16
# v1.16.9 (March 2023)
27

38
Requires Menhir 20211230 and OCaml 4.08 or above.

ELPI.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,25 @@ such clause using the `:before` attribute.
241241
fatal-error Msg :- !, M is "elpi: " ^ Msg, coq-err M.
242242
```
243243

244-
The `:after` attribute is also available.
244+
The `:after` and `:replace` attributes is also available.
245+
246+
The `:replace` attribute cannot be given to a named clause. This is to avoid
247+
the following ambiguity:
248+
249+
```prolog
250+
:name "replace-me"
251+
p 1.
252+
253+
% from one accumulated file
254+
:replace "replace-me" :name "replace-me"
255+
p 2.
256+
257+
% from another accumulated file
258+
:replace "replace-me" :name "replace-me"
259+
p 3.
260+
```
261+
Here the order in which replacement is performed would matter.
262+
245263

246264
## Conditional compilation
247265

src/compiler.ml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,8 @@ end = struct (* {{{ *)
559559
error ~loc ("duplicate attribute " ^ s) in
560560
let illegal_err a =
561561
error ~loc ("illegal attribute " ^ show_raw_attribute a) in
562+
let illegal_replace s =
563+
error ~loc ("replacing clause for "^ s ^" cannot have a name attribute") in
562564
let rec aux r = function
563565
| [] -> r
564566
| Name s :: rest ->
@@ -570,13 +572,21 @@ end = struct (* {{{ *)
570572
| Before s :: rest ->
571573
if r.insertion <> None then duplicate_err "insertion";
572574
aux { r with insertion = Some (Before s) } rest
575+
| Replace s :: rest ->
576+
if r.insertion <> None then duplicate_err "insertion";
577+
aux { r with insertion = Some (Replace s) } rest
573578
| If s :: rest ->
574579
if r.ifexpr <> None then duplicate_err "if";
575580
aux { r with ifexpr = Some s } rest
576581
| (External | Index _) as a :: _-> illegal_err a
577582
in
578-
{ c with Clause.attributes =
579-
aux { insertion = None; id = None; ifexpr = None } attributes }
583+
let attributes = aux { insertion = None; id = None; ifexpr = None } attributes in
584+
begin
585+
match attributes.insertion, attributes.id with
586+
| Some (Replace x), Some _ -> illegal_replace x
587+
| _ -> ()
588+
end;
589+
{ c with Clause.attributes }
580590

581591
let structure_chr_attributes ({ Chr.attributes; loc } as c) =
582592
let duplicate_err s =
@@ -590,7 +600,7 @@ end = struct (* {{{ *)
590600
| If s :: rest ->
591601
if r.cifexpr <> None then duplicate_err "if";
592602
aux { r with cifexpr = Some s } rest
593-
| (Before _ | After _ | External | Index _) as a :: _ -> illegal_err a
603+
| (Before _ | After _ | Replace _ | External | Index _) as a :: _ -> illegal_err a
594604
in
595605
let cid = Loc.show loc in
596606
{ c with Chr.attributes = aux { cid; cifexpr = None } attributes }
@@ -614,7 +624,7 @@ end = struct (* {{{ *)
614624
| Some (Structured.Index _) -> duplicate_err "index"
615625
| Some _ -> error ~loc "external predicates cannot be indexed"
616626
end
617-
| (Before _ | After _ | Name _ | If _) as a :: _ -> illegal_err a
627+
| (Before _ | After _ | Replace _ | Name _ | If _) as a :: _ -> illegal_err a
618628
in
619629
let attributes = aux None attributes in
620630
let attributes =
@@ -1910,8 +1920,12 @@ end = struct (* {{{ *)
19101920
match l, loc_name with
19111921
| [],_ -> error ~loc:c.Ast.Clause.loc ("unable to graft this clause: no clause named " ^
19121922
match loc_name with
1923+
| Ast.Structured.Replace x -> x
19131924
| Ast.Structured.After x -> x
19141925
| Ast.Structured.Before x -> x)
1926+
| { Ast.Clause.attributes = { Assembled.id = Some n }} :: xs,
1927+
Ast.Structured.Replace name when n = name ->
1928+
c :: xs
19151929
| { Ast.Clause.attributes = { Assembled.id = Some n }} as x :: xs,
19161930
Ast.Structured.After name when n = name ->
19171931
c :: x :: xs

src/parser/ast.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ type raw_attribute =
133133
| Name of string
134134
| After of string
135135
| Before of string
136+
| Replace of string
136137
| External
137138
| Index of int list
138139
[@@deriving show]
@@ -299,7 +300,7 @@ and attribute = {
299300
id : string option;
300301
ifexpr : string option;
301302
}
302-
and insertion = Before of string | After of string
303+
and insertion = Before of string | After of string | Replace of string
303304
and cattribute = {
304305
cid : string;
305306
cifexpr : string option

src/parser/ast.mli

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ type raw_attribute =
7070
| Name of string
7171
| After of string
7272
| Before of string
73+
| Replace of string
7374
| External
7475
| Index of int list
7576
[@@ deriving show]
@@ -205,7 +206,7 @@ and attribute = {
205206
id : string option;
206207
ifexpr : string option;
207208
}
208-
and insertion = Before of string | After of string
209+
and insertion = Before of string | After of string | Replace of string
209210
and cattribute = {
210211
cid : string;
211212
cifexpr : string option

src/parser/grammar.mly

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ attribute:
294294
| NAME; s = STRING { Name s }
295295
| AFTER; s = STRING { After s }
296296
| BEFORE; s = STRING { Before s }
297+
| REPLACE; s = STRING { Replace s }
297298
| EXTERNAL { External }
298299
| INDEX; LPAREN; l = nonempty_list(indexing) ; RPAREN { Index l }
299300

@@ -393,6 +394,7 @@ constant:
393394
| NAME { Func.from_string "name" }
394395
| BEFORE { Func.from_string "before" }
395396
| AFTER { Func.from_string "after" }
397+
| REPLACE { Func.from_string "replace" }
396398
| INDEX { Func.from_string "index" }
397399
| c = IO { Func.from_string @@ String.make 1 c }
398400
| CUT { Func.cutf }

src/parser/lexer.mll.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ and token = parse
164164
| "sigma" { SIGMA }
165165
| "after" { AFTER }
166166
| "before" { BEFORE }
167+
| "replace" { REPLACE }
167168
| "name" { NAME }
168169
| "if" { IF }
169170
| "index" { INDEX }

src/parser/test_lexer.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type t = Tokens.token =
1414
| SHORTEN
1515
| RULE
1616
| RPAREN
17+
| REPLACE
1718
| RCURLY
1819
| RBRACKET
1920
| QUOTED of ( string )

src/parser/tokens.mly

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
%token IF
5858
%token BEFORE
5959
%token AFTER
60+
%token REPLACE
6061
%token NAME
6162
%token INDEX
6263
%token CONS
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
pred p o:int.
2+
:name "replace_me"
3+
p 1.
4+
5+
:name "foo"
6+
:replace "replace_me"
7+
p 2.
8+
9+
main :- fail.

0 commit comments

Comments
 (0)