summaryrefslogtreecommitdiff
path: root/lib/kernel/overlay.mli
blob: fff284eca57f5c3a8156e43eff06a3479dcbe18e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
(** The layer-merge algebra: ordered directives over slugs, last writer wins per
    field, [empty] the identity. *)

type 'r field_edit =
  | Set_rank of 'r
  | Set_colour of Colour.t
  | Set_subject of Subject.t
  | Set_name of Lang.t * string
  | Remove_name of Lang.t
  | Set_citation of Citation.part * string
  | Remove_citation of Citation.part
[@@deriving sexp]

type 'r directive =
  | Add of 'r Layer.entry
  | Suppress of Slug.t
  | Replace of Slug.t * 'r Layer.entry
  | Edit of Slug.t * 'r field_edit list
[@@deriving sexp]

type 'r t = { id : string; directives : 'r directive list } [@@deriving sexp]

(** A directive that did not apply cleanly. Never silently dropped, never fatal:
    an overlay written against a slightly different base must stay usable, and an
    authoring error must still be visible. *)
type diagnostic = { overlay : string; directive : string; slug : string; message : string }

val diagnostic_to_string : diagnostic -> string

(** The identity overlay: [apply l empty = (l, [])]. *)
val empty : 'r t

val apply : 'r Layer.t -> 'r t -> 'r Layer.t * diagnostic list

(** Folds overlays in order; diagnostics accumulate in application order. *)
val merge : 'r Layer.t -> 'r t list -> 'r Layer.t * diagnostic list

(** Loads an overlay from a sexp file. Parse and validation failures come back
    as [Error], never as an exception. *)
val load : (Sexplib0.Sexp.t -> 'r) -> string -> ('r t, string) result