ocaml-containers/conv.mli

276 lines
7.7 KiB
OCaml

(*
copyright (c) 2013, simon cruanes
all rights reserved.
redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. redistributions in binary
form must reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided with
the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)
(** {1 Bidirectional Conversion} *)
exception ConversionFailure of string
(** {6 Sinks}
A sink is used to traverse values of some type 'a *)
module Sink : sig
(** A specific sink that requires a given shape to produce
a value of type 'a *)
type 'a t = private
| Unit : 'a -> 'a t
| Bool : (bool -> 'a) -> 'a t
| Float : (float -> 'a) -> 'a t
| Int : (int -> 'a) -> 'a t
| String : (string -> 'a) -> 'a t
| List : (('b t -> 'b list) -> 'a) -> 'a t
| Record : 'a record_sink -> 'a t
| Tuple : 'a hlist -> 'a t
| Sum : (string -> 'a hlist) -> 'a t
| Map : 'a t * ('a -> 'b) -> 'b t
| Fix : ('a t -> 'a t) -> 'a t
and 'r record_sink =
| RecordField : string * 'a t * ('a -> 'r record_sink) -> 'r record_sink
| RecordStop : 'r -> 'r record_sink
and 't hlist =
| HCons : 'a t * ('a -> 't hlist) -> 't hlist
| HNil : 't -> 't hlist
val unit_ : unit t
val bool_ : bool t
val float_ : float t
val int_ : int t
val string_ : string t
val list_ : 'a t -> 'a list t
val map : ('a -> 'b) -> 'a t -> 'b t
val array_ : 'a t -> 'a array t
val field : string -> 'a t -> ('a -> 'r record_sink) -> 'r record_sink
val yield_record : 'r -> 'r record_sink
val record : 'r record_sink -> 'r t
val record_fix : ('r t -> 'r record_sink) -> 'r t
val (|+|) : 'a t -> ('a -> 't hlist) -> 't hlist
val yield : 'a -> 'a hlist
val tuple : 't hlist -> 't t
val pair : 'a t -> 'b t -> ('a * 'b) t
val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t
val quad : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
val sum : (string -> 'a hlist) -> 'a t
val sum_fix : ('a t -> string -> 'a hlist) -> 'a t
val opt : 'a t -> 'a option t
(** What is expected by the sink? *)
type expected =
| ExpectInt
| ExpectBool
| ExpectUnit
| ExpectFloat
| ExpectString
| ExpectRecord
| ExpectTuple
| ExpectList
| ExpectSum
val expected : _ t -> expected
(** To be used by sources that have ambiguities to know what is expected.
maps and fixpoints are unrolled. *)
(** Universal sink, such as a serialization format *)
class type ['a] universal = object
method unit_ : 'a
method bool_ : bool -> 'a
method float_ : float -> 'a
method int_ : int -> 'a
method string_ : string -> 'a
method list_ : 'a list -> 'a
method record : (string*'a) list -> 'a
method tuple : 'a list -> 'a
method sum : string -> 'a list -> 'a
end
end
(** {6 Sources}
A source is used to build values of some type 'a *)
module Source : sig
(** A specific source that follows the shape of the type 'a *)
type 'a t = private
| Unit : unit t
| Bool : bool t
| Float : float t
| Int : int t
| String : string t
| List : 'a t -> 'a list t
| Record : 'a record_src -> 'a t
| Tuple : 'a tuple_src -> 'a t
| Sum : ('a -> string * sum_src) -> 'a t
| Map : 'a t * ('b -> 'a) -> 'b t
| Fix : ('a t -> 'a t) -> 'a t
and 'r record_src =
| RecordField : string * ('r -> 'a) * 'a t * 'r record_src -> 'r record_src
| RecordStop : 'r record_src
and 't tuple_src =
| TupleField : 'a t * ('t -> 'a) * 't tuple_src -> 't tuple_src
| TupleStop : 't tuple_src
and sum_src =
| SumCons : 'a t * 'a * sum_src -> sum_src
| SumNil : sum_src
val unit_ : unit t
val bool_ : bool t
val float_ : float t
val int_ : int t
val string_ : string t
val list_ : 'a t -> 'a list t
val map : ('b -> 'a) -> 'a t -> 'b t
val array_ : 'a t -> 'a array t
val field : string -> ('r -> 'a) -> 'a t -> 'r record_src -> 'r record_src
val record_stop : 'r record_src
val record : 'r record_src -> 'r t
val record_fix : ('r t -> 'r record_src) -> 'r t
val tuple_field : 'a t -> ('t -> 'a) -> 't tuple_src -> 't tuple_src
val tuple_stop : 't tuple_src
val tuple : 't tuple_src -> 't t
val pair : 'a t -> 'b t -> ('a * 'b) t
val triple : 'a t -> 'b t -> 'c t -> ('a * 'b * 'c) t
val quad : 'a t -> 'b t -> 'c t -> 'd t -> ('a * 'b * 'c * 'd) t
val sum_nil : sum_src
val sum_cons : 'a t -> 'a -> sum_src -> sum_src
val sum : ('a -> string * sum_src) -> 'a t
val sum_fix : ('a t -> 'a -> string * sum_src) -> 'a t
val opt : 'a t -> 'a option t
(** Universal source from type 'a. A universal type should inherit from it
and implement the visit method by calling self-methods. *)
class virtual ['a] universal : object
method private unit_ : 'b. 'b Sink.t -> 'b
method private bool_ : 'b. 'b Sink.t -> bool -> 'b
method private float_ : 'b. 'b Sink.t -> float -> 'b
method private int_ : 'b. 'b Sink.t -> int -> 'b
method private string_ : 'b. 'b Sink.t -> string -> 'b
method private list_ : 'b. 'b Sink.t -> 'a list -> 'b
method private record : 'b. 'b Sink.t -> (string*'a) list -> 'b
method private tuple : 'b. 'b Sink.t -> 'a list -> 'b
method private sum : 'b. 'b Sink.t -> string -> 'a list -> 'b
method virtual visit : 'b. 'b Sink.t -> 'a -> 'b
end
end
(** {6 Conversion Functions} *)
val into : 'a Source.t -> 'b Sink.universal -> 'a -> 'b
(** Conversion to universal sink *)
val from : 'a Source.universal -> 'b Sink.t -> 'a -> 'b
(** Conversion from universal source *)
(* TODO for format conversion
val between : 'a Source.universal -> 'b Sink.universal -> 'a -> 'b
*)
(** {6 Exemples} *)
module Json : sig
type t = [
| `Int of int
| `Float of float
| `Bool of bool
| `Null
| `String of string
| `List of t list
| `Assoc of (string * t) list
]
val source : t Source.universal
val sink : t Sink.universal
end
module Sexp : sig
type t =
| Atom of string
| List of t list
val source : t Source.universal
val sink : t Sink.universal
val fmt : Format.formatter -> t -> unit (* for debug *)
end
module Bencode : sig
type t =
| Int of int
| String of string
| List of t list
| Assoc of (string * t) list
val source : t Source.universal
val sink : t Sink.universal
end
(** Tests *)
module Point : sig
type t = {
x : int;
y : int;
color : string;
prev : t option; (* previous position, say *)
}
val source : t Source.t
val sink : t Sink.t
val p : t
val p2 : Json.t
val p4 : Json.t
val p2_sexp : Sexp.t
val p4_sexp : Sexp.t
end
module Lambda : sig
type t =
| Var of string
| App of t * t
| Lambda of string * t
val source : t Source.t
val sink : t Sink.t
val t1 : t
val t1_json : Json.t
val t1_bencode : Bencode.t
val t1_sexp : Sexp.t
end