···11type t =
22 | Any
33+ (* KLUDGE: Since we do not perform "real unification". Any is mostly here
44+ for dealing with empty list. When we can't compute a proper
55+ type for something. Since the goal of Kind is not to
66+ perform "type checking" but to produce UI on top of
77+ validation, let's assume that this is ... ok*)
38 | Or of t * t
49 | Null
510 | Unit
···1217 | Pair of t * t
1318 | List of t
1419 | Constr of string * t option
1515- | Record of (string * t) list
2020+ | Record of fields
2121+2222+and fields = t Util.String_map.t
2323+2424+let any = Any
2525+let or_ a b = Or (a, b)
2626+let null = Null
2727+let unit = Unit
2828+let bool = Bool
2929+let int = Int
3030+let int64 = Int64
3131+let float = Float
3232+let char = Char
3333+let string = String
3434+let pair a b = Pair (a, b)
3535+let list k = List k
3636+let constr ?value k = Constr (k, value)
3737+let record fields = Record (Util.String_map.of_list fields)
3838+3939+let rec equal a b =
4040+ match a, b with
4141+ | Any, Any
4242+ | Null, Null
4343+ | Unit, Unit
4444+ | Bool, Bool
4545+ | Int, Int
4646+ | Int64, Int64
4747+ | Float, Float
4848+ | Char, Char
4949+ | String, String -> true
5050+ | Or (a, b), Or (x, y) | Pair (a, b), Pair (x, y) -> equal a x && equal b y
5151+ | List a, List b -> equal a b
5252+ | Constr (ka, va), Constr (kb, vb) ->
5353+ String.equal ka kb && Option.equal equal va vb
5454+ | Record a, Record b -> Util.String_map.equal equal a b
5555+ | Any, _
5656+ | Or (_, _), _
5757+ | Null, _
5858+ | Unit, _
5959+ | Bool, _
6060+ | Int, _
6161+ | Int64, _
6262+ | Float, _
6363+ | Char, _
6464+ | String, _
6565+ | Pair (_, _), _
6666+ | List _, _
6767+ | Constr (_, _), _
6868+ | Record _, _ -> false
6969+;;
16701771let rec to_string = function
7272+ (* NOTE: I guess that this function is probably useful only for testing
7373+ puprpose so let's be lax on the way that we display stuff. *)
1874 | Any -> "any"
1975 | Null -> "null"
2076 | Unit -> "unit"
···2985 | List xs -> "list(" ^ to_string xs ^ ")"
3086 | Constr (k, Some v) -> "#" ^ k ^ "(" ^ to_string v ^ ")"
3187 | Constr (k, None) -> "#" ^ k
3232- | Record _ -> assert false
8888+ | Record fields ->
8989+ let fields =
9090+ (* TODO: Can be improved later. *)
9191+ fields
9292+ |> Util.String_map.to_list
9393+ |> List.map (fun (k, v) -> "[" ^ k ^ "] " ^ to_string v)
9494+ |> String.concat "; "
9595+ in
9696+ "record{ " ^ fields ^ " }"
3397;;
34983535-(* module S = Set.Make (struct *)
3636-(* type nonrec t = t *)
3737-(* let compare *)
3838-(* end) *)
9999+module S = Set.Make (struct
100100+ type nonrec t = t
101101+102102+ let compare a b =
103103+ (* NOTE: Order si not really important. *)
104104+ let a = to_string a
105105+ and b = to_string b in
106106+ String.compare a b
107107+ ;;
108108+ end)
109109+110110+let rec from_repr = function
111111+ | Repr.Null -> null
112112+ | Repr.Unit -> unit
113113+ | Repr.Bool _ -> bool
114114+ | Repr.Int _ -> int
115115+ | Repr.Int64 _ -> int64
116116+ | Repr.Float _ -> float
117117+ | Repr.Char _ -> char
118118+ | Repr.String _ -> string
119119+ | Repr.Pair (a, b) -> pair (from_repr a) (from_repr b)
120120+ | Repr.Constr (k, v) ->
121121+ let value = Option.map from_repr v in
122122+ constr ?value k
123123+ | Repr.Record fields ->
124124+ fields
125125+ |> Repr.fields_to_assoc
126126+ |> List.map (fun (k, v) -> k, from_repr v)
127127+ |> record
128128+ | Repr.List _ -> assert false
129129+130130+and from_list xs =
131131+ match
132132+ (* KLUDGE: It can obviously be improved since we are doing a lot of
133133+ traversal just for computing something trivial but it is ok for
134134+ the moment since we are not expecting big big lists. *)
135135+ xs
136136+ |> List.fold_left (fun acc t -> S.add (from_repr t) acc) S.empty
137137+ |> S.to_list
138138+ with
139139+ | [] -> Any
140140+ | x :: xs -> List.fold_left (fun prev t -> or_ t prev) x xs
141141+;;
+32
lib/pidgin/kind.mli
···11+(** Represent the "main shape" of a term. *)
22+33+(** The main idea of a kind is to be able to derive the global shape for a
44+ formlet using the [kind] of a validation. *)
55+66+(** {1 Types} *)
77+88+(** Describes the kind of a term. *)
99+type t
1010+1111+(** {1 Build kinds} *)
1212+1313+val any : t
1414+val or_ : t -> t -> t
1515+val null : t
1616+val unit : t
1717+val bool : t
1818+val int : t
1919+val int64 : t
2020+val float : t
2121+val char : t
2222+val string : t
2323+val pair : t -> t -> t
2424+val list : t -> t
2525+val constr : ?value:t -> string -> t
2626+val record : (string * t) list -> t
2727+val from_repr : Repr.t -> t
2828+2929+(** {1 Utils} *)
3030+3131+val equal : t -> t -> bool
3232+val to_string : t -> string
+5-5
lib/pidgin/repr.ml
···11-module Fields = Stdlib.Map.Make (String)
22-31type t =
42 | Null
53 | Unit
···1412 | Constr of string * t option
1513 | Record of fields
16141717-and fields = t Fields.t
1515+and fields = t Util.String_map.t
1616+1717+let fields_to_assoc = Util.String_map.to_list
18181919type 'a conv = 'a -> t
2020···3333 | List a, List b -> List.equal equal a b
3434 | Constr (ka, va), Constr (kb, vb) ->
3535 String.equal ka kb && Option.equal equal va vb
3636- | Record a, Record b -> Fields.equal equal a b
3636+ | Record a, Record b -> Util.String_map.equal equal a b
3737 | Null, _
3838 | Unit, _
3939 | Bool _, _
···111111;;
112112113113let list conv xs = xs |> List.map conv |> Lit.list
114114-let record fields = Record (Fields.of_list fields)
114114+let record fields = Record (Util.String_map.of_list fields)
115115let option some = Option.fold ~none:Lit.null ~some
116116117117let result ok err =
+1
lib/pidgin/repr.mli
···110110111111(** {1 Helpers} *)
112112113113+val fields_to_assoc : fields -> (string * t) list
113114val use : ('b -> 'a) -> 'a conv -> 'b conv
114115val equal : t -> t -> bool
115116