mirror of
https://github.com/c-cube/ocaml-containers.git
synced 2025-12-05 19:00:31 -05:00
Bij.{guard,fix} helpers
This commit is contained in:
parent
9774added9
commit
9d1843ecf8
3 changed files with 43 additions and 5 deletions
22
bij.ml
22
bij.ml
|
|
@ -36,6 +36,7 @@ type _ t =
|
|||
| Opt : 'a t -> 'a option t
|
||||
| Pair : 'a t * 'b t -> ('a * 'b) t
|
||||
| Triple : 'a t * 'b t * 'c t -> ('a * 'b * 'c) t
|
||||
| Guard : ('a -> bool) * 'a t -> 'a t
|
||||
| Map : ('a -> 'b) * ('b -> 'a) * 'b t -> 'a t
|
||||
| Switch : ('a -> char * 'a inject_branch) * (char -> 'a extract_branch) -> 'a t
|
||||
and _ inject_branch =
|
||||
|
|
@ -57,10 +58,24 @@ let many l = Many l
|
|||
let opt t = Opt t
|
||||
let pair a b = Pair(a,b)
|
||||
let triple a b c = Triple (a,b,c)
|
||||
let guard f t = Guard (f, t)
|
||||
|
||||
let map ~inject ~extract b = Map (inject, extract, b)
|
||||
let switch ~inject ~extract = Switch (inject, extract)
|
||||
|
||||
(** {2 Helpers} *)
|
||||
|
||||
let fix f =
|
||||
let rec bij = lazy (f (fun () -> Lazy.force bij)) in
|
||||
Lazy.force bij
|
||||
|
||||
type 'a versioned = string * 'a
|
||||
|
||||
let with_version v t =
|
||||
pair (guard (fun v' -> v = v') string_) t
|
||||
|
||||
(** {2 Exceptions} *)
|
||||
|
||||
exception EOF
|
||||
|
||||
exception EncodingError of string
|
||||
|
|
@ -263,6 +278,9 @@ module SexpEncode(Sink : SINK) = struct
|
|||
Sink.write_char sink ' ';
|
||||
encode bij_b b;
|
||||
Sink.write_char sink ')'
|
||||
| Guard (check, bij'), _ ->
|
||||
(if not (check x) then raise (EncodingError ("check failed")));
|
||||
encode bij' x
|
||||
| Triple (bij_a, bij_b, bij_c), (a, b, c) ->
|
||||
Sink.write_char sink '(';
|
||||
encode bij_a a;
|
||||
|
|
@ -344,6 +362,10 @@ module SexpDecode(Source : SOURCE) = struct
|
|||
let c = decode bijc in
|
||||
decode_close ();
|
||||
a, b, c
|
||||
| Guard (check, bij') ->
|
||||
let x = decode bij' in
|
||||
(if not (check x) then raise (DecodingError "check failed"));
|
||||
x
|
||||
| Map (_, extract, bij') ->
|
||||
let x = decode bij' in
|
||||
extract x
|
||||
|
|
|
|||
14
bij.mli
14
bij.mli
|
|
@ -40,6 +40,8 @@ val many : 'a t -> 'a list t (* non empty *)
|
|||
val opt : 'a t -> 'a option t
|
||||
val pair : 'a t -> 'b t -> ('a * 'b) t
|
||||
val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t
|
||||
val guard : ('a -> bool) -> 'a t -> 'a t
|
||||
(** Validate values at encoding and decoding *)
|
||||
|
||||
val map : inject:('a -> 'b) -> extract:('b -> 'a) -> 'b t -> 'a t
|
||||
|
||||
|
|
@ -55,6 +57,18 @@ val switch : inject:('a -> char * 'a inject_branch) ->
|
|||
type (the argument of the algebraic constructor);
|
||||
[extract] retrieves which type to parse based on the character. *)
|
||||
|
||||
(** {2 Helpers} *)
|
||||
|
||||
val fix : ((unit -> 'a t) -> 'a t) -> 'a t
|
||||
(** Helper for recursive encodings *)
|
||||
|
||||
type 'a versioned = string * 'a
|
||||
|
||||
val with_version : string -> 'a t -> 'a versioned t
|
||||
(** Guards the values with a given version *)
|
||||
|
||||
(** {2 Exceptions} *)
|
||||
|
||||
exception EOF
|
||||
|
||||
exception EncodingError of string
|
||||
|
|
|
|||
|
|
@ -32,18 +32,20 @@ type term =
|
|||
| App of term list
|
||||
|
||||
let bij_term =
|
||||
let rec mk_bij () =
|
||||
let bij = fix
|
||||
(fun bij ->
|
||||
switch
|
||||
~inject:(function
|
||||
| Const s -> 'c', BranchTo (string_, s)
|
||||
| Int i -> 'i', BranchTo (int_, i)
|
||||
| App l -> 'a', BranchTo (list_ (mk_bij ()), l))
|
||||
| App l -> 'a', BranchTo (list_ (bij ()), l))
|
||||
~extract:(function
|
||||
| 'c' -> BranchFrom (string_, fun x -> Const x)
|
||||
| 'i' -> BranchFrom (int_, fun x -> Int x)
|
||||
| 'a' -> BranchFrom (list_ (mk_bij ()), fun l -> App l)
|
||||
| _ -> raise (DecodingError "unexpected case switch"))
|
||||
in mk_bij ()
|
||||
| 'a' -> BranchFrom (list_ (bij ()), fun l -> App l)
|
||||
| _ -> raise (DecodingError "unexpected case switch")))
|
||||
in
|
||||
bij
|
||||
|
||||
let test_rec () =
|
||||
let t = App [Const "foo"; App [Const "bar"; Int 1; Int 2]; Int 3; Const "hello"] in
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue