Skip to content

Commit

Permalink
typereg: store cliques, not just single defs; add map
Browse files Browse the repository at this point in the history
  • Loading branch information
c-cube committed Jul 16, 2024
1 parent 62cf23c commit fe81817
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 58 deletions.
16 changes: 10 additions & 6 deletions src/typereg/imandrakit_typereg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ module Tbl = Str_tbl
module Ty_expr = Ty_expr
module Ty_def = Ty_def

type t = { tbl: Ty_def.t Tbl.t } [@@unboxed]
type t = {
tbl: (Ty_def.t * Ty_def.clique) Tbl.t;
mutable cliques: Ty_def.clique list;
}

let[@inline] key_ ~path ~name : string = spf "%s$%s" path name
let[@inline] key_of_d_ (d : Ty_def.t) : string = key_ ~path:d.path ~name:d.name
let create () : t = { tbl = Tbl.create 8 }
let create () : t = { tbl = Tbl.create 8; cliques = [] }
let top = create ()

let declare (self : t) ~__FILE__ (decls : Ty_def.t list) : unit =
let declare (self : t) ~__FILE__ (clique : Ty_def.clique) : unit =
self.cliques <- clique :: self.cliques;
List.iter
(fun d ->
let key = key_of_d_ d in
Expand All @@ -18,10 +22,10 @@ let declare (self : t) ~__FILE__ (decls : Ty_def.t list) : unit =
(spf
"typereg collision in '%s': type def %S in %S is already present."
__FILE__ d.name d.path);
Tbl.add self.tbl key d)
decls
Tbl.add self.tbl key (d, clique))
clique

let[@inline] to_iter self k : unit = Tbl.iter (fun _ d -> k d) self.tbl
let[@inline] to_iter self k : unit = List.iter k self.cliques
let[@inline] find self ~path ~name () = Tbl.get self.tbl (key_ ~path ~name)
let[@inline] find_exn self ~path ~name () = Tbl.find self.tbl (key_ ~path ~name)

Expand Down
12 changes: 8 additions & 4 deletions src/typereg/imandrakit_typereg.mli
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ val top : t
(** Toplevel (default) register *)

val declare : t -> __FILE__:string -> Ty_def.t list -> unit
(** [declare reg ~__FILE__ tys] declares types to the registry,
(** [declare reg ~__FILE__ tys] declares a clique of
types to the registry,
with these types being declared in [__FILE__].
@raise Failure if some types are already registered. *)

val to_iter : t -> Ty_def.t Iter.t
val find : t -> path:string -> name:string -> unit -> Ty_def.t option
val to_iter : t -> Ty_def.clique Iter.t

val find_exn : t -> path:string -> name:string -> unit -> Ty_def.t
val find :
t -> path:string -> name:string -> unit -> (Ty_def.t * Ty_def.clique) option

val find_exn :
t -> path:string -> name:string -> unit -> Ty_def.t * Ty_def.clique
(** Same as {!find} but:
@raise Not_found if not present *)
15 changes: 15 additions & 0 deletions src/typereg/ty_def.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ type ty = Ty_expr.t [@@deriving show, eq, yojson]
type record = { fields: (string * ty) list }
[@@deriving show { with_path = false }, eq, yojson]

let map_record ~f { fields } : record =
{ fields = List.map (fun (s, ty) -> s, f ty) fields }

type cstor = {
c: string; (** Constructor name *)
args: ty list;
Expand All @@ -13,13 +16,21 @@ type cstor = {
}
[@@deriving show { with_path = false }, eq, yojson]

let map_cstor ~f (c : cstor) : cstor = { c with args = List.map f c.args }

(** Definition *)
type decl =
| Alias of ty
| Alg of cstor list
| Record of record
[@@deriving show { with_path = false }, eq, yojson]

let map_decl ~f (d : decl) : decl =
match d with
| Alias ty -> Alias (f ty)
| Alg cs -> Alg (List.map (map_cstor ~f) cs)
| Record r -> Record (map_record ~f r)

type t = {
path: string; (** Path *)
name: string; (** Name of the type *)
Expand All @@ -28,5 +39,9 @@ type t = {
}
[@@deriving show { with_path = false }, eq, yojson]

type clique = t list

let map ~f (self : t) : t = { self with decl = map_decl ~f self.decl }

let compare_by_name (d1 : t) (d2 : t) =
compare (d1.path, d1.name) (d2.path, d2.name)
7 changes: 7 additions & 0 deletions src/typereg/ty_expr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ type t =
| Tuple of t list
[@@deriving show { with_path = false }, eq, yojson]

let map_shallow ~f (self : t) =
match self with
| Var _ -> self
| Cstor (s, l) -> Cstor (s, List.map f l)
| Arrow (lbl, a, b) -> Arrow (lbl, f a, f b)
| Tuple l -> Tuple (List.map f l)

let var v : t = Var v
let cstor c l : t = Cstor (c, l)
let arrow ?label a b : t = Arrow (label, a, b)
Expand Down
2 changes: 1 addition & 1 deletion test/typereg/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(tests
(names t1 t2 t3)
(libraries imandrakit.typereg hex ppx_deriving.runtime)
(libraries containers imandrakit.typereg hex ppx_deriving.runtime)
(package imandrakit)
(flags :standard -w -34-60)
(preprocess
Expand Down
5 changes: 3 additions & 2 deletions test/typereg/fail/t1.ml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
let dump () =
Imandrakit_typereg.(
to_iter top |> Iter.to_rev_list
|> List.sort Ty_def.compare_by_name
|> List.iter (fun d -> Format.printf "%a@." Ty_def.pp d))
|> List.sort (CCList.compare Ty_def.compare_by_name)
|> List.iter (fun d ->
Format.printf "%a@." (CCFormat.Dump.list Ty_def.pp) d))

module Yolo = struct
type t = float option list array [@@deriving typereg]
Expand Down
30 changes: 15 additions & 15 deletions test/typereg/t1.expected
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
t1:
{ path = "Dune__exe__T1"; name = "bar"; params = [];
decl =
(Alias
(Tuple
[(Cstor ("foo", []));
(Cstor ("option", [(Cstor ("list", [(Cstor ("int", []))]))]))]))
}
{ path = "Dune__exe__T1"; name = "foo"; params = [];
decl = (Alias (Cstor ("int", []))) }
{ path = "Dune__exe__T1"; name = "t"; params = [];
decl =
(Alias
(Cstor ("array",
[(Cstor ("list", [(Cstor ("option", [(Cstor ("float", []))]))]))])))
}
[{ path = "Dune__exe__T1"; name = "bar"; params = [];
decl =
(Alias
(Tuple
[(Cstor ("foo", []));
(Cstor ("option", [(Cstor ("list", [(Cstor ("int", []))]))]))]))
}]
[{ path = "Dune__exe__T1"; name = "foo"; params = [];
decl = (Alias (Cstor ("int", []))) }]
[{ path = "Dune__exe__T1"; name = "t"; params = [];
decl =
(Alias
(Cstor ("array",
[(Cstor ("list", [(Cstor ("option", [(Cstor ("float", []))]))]))])))
}]
48 changes: 24 additions & 24 deletions test/typereg/t2.expected
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
t2:
{ path = "Dune__exe__T2"; name = "bar"; params = [];
decl =
(Alg
[{ c = "A"; args = []; labels = None };
{ c = "B"; args = [(Cstor ("int", []))]; labels = None };
{ c = "C"; args = [(Cstor ("int", [])); (Cstor ("string", []))];
labels = None };
{ c = "D";
args =
[(Cstor ("int", []));
(Cstor ("list",
[(Tuple [(Cstor ("string", [])); (Cstor ("foo", []))])]))
];
labels = (Some ["x"; "y"]) }
])
}
{ path = "Dune__exe__T2"; name = "foo"; params = [];
decl =
(Record
{ fields =
[("x", (Cstor ("int", [])));
("y", (Cstor ("option", [(Cstor ("float", []))])))]
})
}
[{ path = "Dune__exe__T2"; name = "bar"; params = [];
decl =
(Alg
[{ c = "A"; args = []; labels = None };
{ c = "B"; args = [(Cstor ("int", []))]; labels = None };
{ c = "C"; args = [(Cstor ("int", [])); (Cstor ("string", []))];
labels = None };
{ c = "D";
args =
[(Cstor ("int", []));
(Cstor ("list",
[(Tuple [(Cstor ("string", [])); (Cstor ("foo", []))])]))
];
labels = (Some ["x"; "y"]) }
])
}]
[{ path = "Dune__exe__T2"; name = "foo"; params = [];
decl =
(Record
{ fields =
[("x", (Cstor ("int", [])));
("y", (Cstor ("option", [(Cstor ("float", []))])))]
})
}]
2 changes: 2 additions & 0 deletions test/typereg/t2.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
open Util_

[@@@ocaml.warning "-37-69"]

type foo = {
x: int;
y: float option;
Expand Down
8 changes: 4 additions & 4 deletions test/typereg/t3.expected
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
t3:
{ path = "Dune__exe__T3"; name = "A.t"; params = [];
decl = (Alias (Cstor ("int", []))) }
{ path = "Dune__exe__T3"; name = "B.t"; params = [];
decl = (Alias (Cstor ("bool", []))) }
[{ path = "Dune__exe__T3"; name = "A.t"; params = [];
decl = (Alias (Cstor ("int", []))) }]
[{ path = "Dune__exe__T3"; name = "B.t"; params = [];
decl = (Alias (Cstor ("bool", []))) }]
5 changes: 3 additions & 2 deletions test/typereg/util_.ml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
let dump () =
Imandrakit_typereg.(
to_iter top |> Iter.to_rev_list
|> List.sort Ty_def.compare_by_name
|> List.iter (fun d -> Format.printf "%a@." Ty_def.pp d))
|> List.sort (CCList.compare Ty_def.compare_by_name)
|> List.iter (fun d ->
Format.printf "%a@." (CCFormat.Dump.list Ty_def.pp) d))

0 comments on commit fe81817

Please sign in to comment.