From 7b66c13b1582c99c6d1aab4ffe429a671574d0b9 Mon Sep 17 00:00:00 2001 From: Emile Trotignon Date: Wed, 22 Feb 2023 16:59:00 +0100 Subject: [PATCH 01/35] Add test for omitting parent type in constructor reference (#447) Co-authored-by: Paul-Elliot Signed-off-by: Paul-Elliot --- test/xref2/github_issue_447.t/a.mli | 15 +++++++++++++++ test/xref2/github_issue_447.t/run.t | 15 +++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/xref2/github_issue_447.t/a.mli create mode 100644 test/xref2/github_issue_447.t/run.t diff --git a/test/xref2/github_issue_447.t/a.mli b/test/xref2/github_issue_447.t/a.mli new file mode 100644 index 0000000000..b212ff8481 --- /dev/null +++ b/test/xref2/github_issue_447.t/a.mli @@ -0,0 +1,15 @@ +type u = Bar + +(** {!constructor-Bar} {!u.constructor-Bar} *) + +module M : sig + type t = Foo +end + +(** {!M.constructor-Foo} and {!M.Foo} + + {!M.t.constructor-Foo} and {!M.t.Foo} *) + +class t : object end + +(** {!t.constructor-A} *) diff --git a/test/xref2/github_issue_447.t/run.t b/test/xref2/github_issue_447.t/run.t new file mode 100644 index 0000000000..5fd7cd674c --- /dev/null +++ b/test/xref2/github_issue_447.t/run.t @@ -0,0 +1,15 @@ +This test tests the ability to reference constructors, omitting the type they +are coming from. + + $ ocamlc -c -bin-annot a.mli + $ odoc compile --warn-error -I . a.cmti + +Currently, it is only possible to omit the parent type of the constructor in the +toplevel: only [{!M.constructor-Foo}] does not resolve, as it cannot find a type +named [M]. + + $ odoc link a.odoc + File "a.mli", line 15, characters 4-22: + Warning: Failed to resolve reference unresolvedroot(t).A Couldn't find "t" + File "a.mli", line 9, characters 4-24: + Warning: Failed to resolve reference unresolvedroot(M).Foo Couldn't find "M" From d318a5fac650e04280c554de53601081ee3d8d5a Mon Sep 17 00:00:00 2001 From: Emile Trotignon Date: Mon, 27 Feb 2023 16:16:38 +0100 Subject: [PATCH 02/35] Allow signature to be parent in constructor references This allows to omit the type the constructor is coming from. The constructor will be fetched from the environment. The commit does this in a similar way to fields, which can have type `parent` for parents of type references. Co-authored-by: Paul-Elliot Signed-off-by: Paul-Elliot --- src/loader/cmi.ml | 4 +- src/loader/cmti.ml | 6 +-- src/model/paths.ml | 9 ++-- src/model/paths.mli | 4 +- src/model/paths_types.ml | 10 ++--- src/model/reference.ml | 34 ++------------- src/xref2/env.ml | 5 ++- src/xref2/lang_of.ml | 13 +++--- src/xref2/lang_of.mli | 2 +- src/xref2/ref_tools.ml | 59 +++++++++++++------------- test/xref2/github_issue_447.t/a.mli | 4 +- test/xref2/github_issue_447.t/run.t | 22 +++++++--- test/xref2/refs/refs.md | 65 +++++++++++++++++++++++++---- 13 files changed, 133 insertions(+), 104 deletions(-) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index 8429d3bd15..3f136ccf44 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -628,7 +628,7 @@ let read_constructor_declaration_arguments env parent arg = let read_constructor_declaration env parent cd = let open TypeDecl.Constructor in let id = Ident_env.find_constructor_identifier env cd.cd_id in - let container = (parent : Identifier.DataType.t :> Identifier.LabelParent.t) in + let container = (parent :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag container cd.cd_attributes in let args = read_constructor_declaration_arguments env @@ -713,7 +713,7 @@ let read_type_declaration env parent id decl = let params = mark_type_declaration decl in let manifest = opt_map (read_type_expr env) decl.type_manifest in let constraints = read_type_constraints env params in - let representation = read_type_kind env id decl.type_kind in + let representation = read_type_kind env (id :> Identifier.Parent.t) decl.type_kind in let abstr = match decl.type_kind with Type_abstract -> diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 53297e98dd..a2e9f6bbe8 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -214,7 +214,7 @@ let read_constructor_declaration_arguments env parent label_parent arg = let read_constructor_declaration env parent cd = let open TypeDecl.Constructor in let id = Ident_env.find_constructor_identifier env cd.cd_id in - let container = (parent : Identifier.DataType.t :> Identifier.Parent.t) in + let container = parent in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container cd.cd_attributes in let args = @@ -231,7 +231,7 @@ let read_type_kind env parent = let cstrs = List.map (read_constructor_declaration env parent) cstrs in Some (Variant cstrs) | Ttype_record lbls -> - let parent = (parent : Identifier.DataType.t :> Identifier.Parent.t) in + let parent = (parent ) in let label_parent = (parent :> Identifier.LabelParent.t) in let lbls = List.map (read_label_declaration env parent label_parent) lbls in @@ -260,7 +260,7 @@ let read_type_declaration env parent decl = let doc, canonical = Doc_attr.attached Odoc_model.Semantics.Expect_canonical container decl.typ_attributes in let canonical = (canonical :> Path.Type.t option) in let equation = read_type_equation env container decl in - let representation = read_type_kind env (id :> Identifier.DataType.t) decl.typ_kind in + let representation = read_type_kind env (id :> Identifier.Parent.t) decl.typ_kind in {id; locs; doc; canonical; equation; representation} let read_type_declarations env parent rec_flag decls = diff --git a/src/model/paths.ml b/src/model/paths.ml index 31e8f2e2df..5002ca9cd3 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -165,7 +165,7 @@ module Identifier = struct | { iv = `Label (p, _); _ } -> p | { iv = `Method (p, _); _ } | { iv = `InstanceVariable (p, _); _ } -> (p : class_signature :> label_parent) - | { iv = `Constructor (p, _); _ } -> (p : datatype :> label_parent) + | { iv = `Constructor (p, _); _ } -> (p : parent :> label_parent) | { iv = `Field (p, _); _ } -> (p : parent :> label_parent) let label_parent n = label_parent_aux (n :> Id.non_src) @@ -572,8 +572,8 @@ module Identifier = struct mk_fresh (fun s -> s) "coret" (fun s -> `CoreType (TypeName.make_std s)) let constructor : - Type.t * ConstructorName.t -> - [> `Constructor of Type.t * ConstructorName.t ] id = + Parent.t * ConstructorName.t -> + [> `Constructor of Parent.t * ConstructorName.t ] id = mk_parent ConstructorName.to_string "ctor" (fun (p, n) -> `Constructor (p, n)) @@ -1013,8 +1013,7 @@ module Reference = struct | `Class _ | `ClassType _ | `ModuleType _ ) as r -> (label_parent_identifier r :> Identifier.t) | `Field (p, n) -> Identifier.Mk.field (parent_identifier p, n) - | `Constructor (s, n) -> - Identifier.Mk.constructor (parent_type_identifier s, n) + | `Constructor (s, n) -> Identifier.Mk.constructor (parent_identifier s, n) | `Extension (p, q) -> Identifier.Mk.extension (parent_signature_identifier p, q) | `ExtensionDecl (p, q, r) -> diff --git a/src/model/paths.mli b/src/model/paths.mli index 901a0c8df7..be0f504740 100644 --- a/src/model/paths.mli +++ b/src/model/paths.mli @@ -290,8 +290,8 @@ module Identifier : sig val core_type : string -> [> `CoreType of TypeName.t ] id val constructor : - Type.t * ConstructorName.t -> - [> `Constructor of Type.t * ConstructorName.t ] id + Parent.t * ConstructorName.t -> + [> `Constructor of Parent.t * ConstructorName.t ] id val field : Parent.t * FieldName.t -> [> `Field of Parent.t * FieldName.t ] id diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index 1fd7fb2cc7..a20be58bd4 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -132,7 +132,7 @@ module Identifier = struct and type_ = type_pv id (** @canonical Odoc_model.Paths.Identifier.Type.t *) - type constructor_pv = [ `Constructor of type_ * ConstructorName.t ] + type constructor_pv = [ `Constructor of parent * ConstructorName.t ] (** @canonical Odoc_model.Paths.Identifier.Constructor.t_pv *) and constructor = constructor_pv id @@ -666,7 +666,7 @@ module rec Reference : sig [ `Resolved of Resolved_reference.constructor | `Root of string * [ `TConstructor | `TExtension | `TException | `TUnknown ] | `Dot of label_parent * string - | `Constructor of datatype * ConstructorName.t + | `Constructor of parent * ConstructorName.t | `Extension of signature * ExtensionName.t | `Exception of signature * ExceptionName.t ] (** @canonical Odoc_model.Paths.Reference.Constructor.t *) @@ -756,7 +756,7 @@ module rec Reference : sig | `Module of signature * ModuleName.t | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t - | `Constructor of datatype * ConstructorName.t + | `Constructor of parent * ConstructorName.t | `Field of parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t @@ -847,7 +847,7 @@ and Resolved_reference : sig type constructor = [ `Identifier of Identifier.reference_constructor - | `Constructor of datatype * ConstructorName.t + | `Constructor of parent * ConstructorName.t | `Extension of signature * ExtensionName.t | `Exception of signature * ExceptionName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.Constructor.t *) @@ -920,7 +920,7 @@ and Resolved_reference : sig | `Hidden of module_ | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t - | `Constructor of datatype * ConstructorName.t + | `Constructor of parent * ConstructorName.t | `Field of parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t * ExtensionName.t diff --git a/src/model/reference.ml b/src/model/reference.ml index 57e690ad1c..33624a334d 100644 --- a/src/model/reference.ml +++ b/src/model/reference.ml @@ -219,13 +219,10 @@ let parse whole_reference_location s : match tokens with | [] -> ( match kind with - | (`TUnknown | `TModule | `TModuleType | `TType | `TClass | `TClassType) - as kind -> + | (`TUnknown | `TModule | `TModuleType | `TType) as kind -> `Root (identifier, kind) | _ -> - expected - [ "module"; "module-type"; "type"; "class"; "class-type" ] - location + expected [ "module"; "module-type"; "type" ] location |> Error.raise_exception) | next_token :: tokens -> ( match kind with @@ -238,15 +235,8 @@ let parse whole_reference_location s : (signature next_token tokens, ModuleTypeName.make_std identifier) | `TType -> `Type (signature next_token tokens, TypeName.make_std identifier) - | `TClass -> - `Class (signature next_token tokens, ClassName.make_std identifier) - | `TClassType -> - `ClassType - (signature next_token tokens, ClassTypeName.make_std identifier) | _ -> - expected - [ "module"; "module-type"; "type"; "class"; "class-type" ] - location + expected [ "module"; "module-type"; "type" ] location |> Error.raise_exception) in @@ -273,22 +263,6 @@ let parse whole_reference_location s : ) in - let datatype (kind, identifier, location) tokens : DataType.t = - let kind = match_reference_kind location kind in - match tokens with - | [] -> ( - match kind with - | (`TUnknown | `TType) as kind -> `Root (identifier, kind) - | _ -> expected [ "type" ] location |> Error.raise_exception) - | next_token :: tokens -> ( - match kind with - | `TUnknown -> - `Dot ((parent next_token tokens :> LabelParent.t), identifier) - | `TType -> - `Type (signature next_token tokens, TypeName.make_std identifier) - | _ -> expected [ "type" ] location |> Error.raise_exception) - in - let rec label_parent (kind, identifier, location) tokens : LabelParent.t = let kind = match_reference_kind location kind in match tokens with @@ -360,7 +334,7 @@ let parse whole_reference_location s : `Type (signature next_token tokens, TypeName.make_std identifier) | `TConstructor -> `Constructor - (datatype next_token tokens, ConstructorName.make_std identifier) + (parent next_token tokens, ConstructorName.make_std identifier) | `TField -> `Field (parent next_token tokens, FieldName.make_std identifier) | `TExtension -> diff --git a/src/xref2/env.ml b/src/xref2/env.ml index 23d5df1150..c7806870c1 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -288,13 +288,14 @@ let add_module identifier m docs env = let env' = add_to_elts Kind_Module identifier (`Module (identifier, m)) env in if env.linking then add_cdocs identifier docs env' else env' -let add_type identifier t env = +let add_type (identifier : Identifier.Type.t) t env = let open Component in let open_typedecl cs = let add_cons env (cons : TypeDecl.Constructor.t) = let ident = Paths.Identifier.Mk.constructor - (identifier, ConstructorName.make_std cons.name) + ( (identifier :> Identifier.Parent.t), + ConstructorName.make_std cons.name ) in add_to_elts Kind_Constructor ident (`Constructor (ident, cons)) env and add_field env (field : TypeDecl.Field.t) = diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index f780747dba..d59a628c88 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -940,7 +940,9 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : Odoc_model.Lang.TypeDecl.Representation.t = match t with | Extensible -> Extensible - | Variant cs -> Variant (List.map (type_decl_constructor map id) cs) + | Variant cs -> + Variant + (List.map (type_decl_constructor map (id :> Identifier.Parent.t)) cs) | Record fs -> Record (List.map @@ -949,7 +951,7 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : and type_decl_constructor : maps -> - Odoc_model.Paths.Identifier.Type.t -> + Odoc_model.Paths.Identifier.Parent.t -> Component.TypeDecl.Constructor.t -> Odoc_model.Lang.TypeDecl.Constructor.t = fun map id t -> @@ -959,11 +961,8 @@ and type_decl_constructor : { id = identifier; doc = docs (id :> Identifier.LabelParent.t) t.doc; - args = - type_decl_constructor_argument map - (id :> Odoc_model.Paths.Identifier.Parent.t) - t.args; - res = Opt.map (type_expr map (id :> Identifier.Parent.t)) t.res; + args = type_decl_constructor_argument map id t.args; + res = Opt.map (type_expr map id) t.res; } and type_expr_package map parent t = diff --git a/src/xref2/lang_of.mli b/src/xref2/lang_of.mli index 24ccf08a2c..0e8a3358a2 100644 --- a/src/xref2/lang_of.mli +++ b/src/xref2/lang_of.mli @@ -217,7 +217,7 @@ val type_decl_representation : val type_decl_constructor : maps -> - Identifier.Type.t -> + Identifier.Parent.t -> Component.TypeDecl.Constructor.t -> Odoc_model.Lang.TypeDecl.Constructor.t diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index f3ac027c94..a4b37a93cb 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -279,15 +279,6 @@ module DT = struct let of_component _env t ~parent_ref name = Ok (`Type (parent_ref, name), t) let of_element _env (`Type (id, t)) : t = (`Identifier id, t) - - let in_env env name = - env_lookup_by_name Env.s_type name env >>= fun e -> Ok (of_element env e) - - let in_signature _env ((parent', parent_cp, sg) : signature_lookup_result) - name = - let sg = Tools.prefix_signature (parent_cp, sg) in - find Find.datatype_in_sig sg name >>= fun (`FType (name, t)) -> - Ok (`Type (parent', name), t) end module T = struct @@ -448,14 +439,33 @@ module CS = struct env_lookup_by_name Env.s_constructor name env >>= fun (`Constructor (id, _)) -> Ok (`Identifier id :> t) - let in_datatype _env ((parent', t) : datatype_lookup_result) name = + let got_a_field name = + (* Let's pretend we didn't see the field and say we didn't find anything. *) + Error (`Find_by_name (`Cons, name)) + + let in_parent _env (parent : label_parent_lookup_result) name = let name_s = ConstructorName.to_string name in - find Find.any_in_type t name_s >>= function - | `FConstructor _ -> Ok (`Constructor (parent', name)) - | `FField _ -> Error (`Find_by_name (`Cons, name_s)) + match parent with + | `S (parent', parent_cp, sg) -> ( + let sg = Tools.prefix_signature (parent_cp, sg) in + find_ambiguous Find.any_in_type_in_sig sg name_s >>= function + | `In_type (_, _, `FField _) -> got_a_field name_s + | `In_type (typ_name, _, `FConstructor _) -> + Ok (`Constructor (`Type (parent', typ_name), name))) + | `T (parent', t) -> ( + find Find.any_in_type t name_s >>= function + | `FField _ -> got_a_field name_s + | `FConstructor _ -> + Ok + (`Constructor + ((parent' : Resolved.DataType.t :> Resolved.Parent.t), name))) + | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = - Ok (`Constructor (parent, ConstructorName.make_std name)) + Ok + (`Constructor + ( (parent : Resolved.DataType.t :> Resolved.Parent.t), + ConstructorName.make_std name )) end module F = struct @@ -479,7 +489,8 @@ module F = struct find_ambiguous Find.any_in_type_in_sig sg name_s >>= function | `In_type (_, _, `FConstructor _) -> got_a_constructor name_s | `In_type (typ_name, _, `FField _) -> - Ok (`Field (`Type (parent', typ_name), name))) + Ok (`Field ((`Type (parent', typ_name) :> Resolved.Parent.t), name)) + ) | `T (parent', t) -> ( find Find.any_in_type t name_s >>= function | `FConstructor _ -> got_a_constructor name_s @@ -662,20 +673,6 @@ and resolve_signature_reference : in resolve env' -and resolve_datatype_reference : - Env.t -> DataType.t -> datatype_lookup_result ref_result = - fun env r -> - match r with - | `Resolved _ -> failwith "TODO" - | `Root (name, (`TType | `TUnknown)) -> DT.in_env env name - | `Type (parent, name) -> - resolve_signature_reference env parent >>= fun p -> - DT.in_signature env p (TypeName.to_string name) - | `Dot (parent, name) -> - resolve_label_parent_reference env parent - >>= signature_lookup_result_of_label_parent - >>= fun p -> DT.in_signature env p name - and resolve_module_reference env (r : Module.t) : M.t ref_result = match r with | `Resolved _r -> failwith "What's going on!?" @@ -818,8 +815,8 @@ let resolve_reference = | `Dot (parent, name) -> resolve_reference_dot env parent name | `Root (name, `TConstructor) -> CS.in_env env name >>= resolved1 | `Constructor (parent, name) -> - resolve_datatype_reference env parent >>= fun p -> - CS.in_datatype env p name >>= resolved1 + resolve_label_parent_reference env (parent : Parent.t :> LabelParent.t) + >>= fun p -> CS.in_parent env p name >>= resolved1 | `Root (name, `TException) -> EX.in_env env name >>= resolved1 | `Exception (parent, name) -> resolve_signature_reference env parent >>= fun p -> diff --git a/test/xref2/github_issue_447.t/a.mli b/test/xref2/github_issue_447.t/a.mli index b212ff8481..9bd7d30a3b 100644 --- a/test/xref2/github_issue_447.t/a.mli +++ b/test/xref2/github_issue_447.t/a.mli @@ -1,6 +1,6 @@ -type u = Bar +type u = Foo -(** {!constructor-Bar} {!u.constructor-Bar} *) +(** {!constructor-Foo} {!u.constructor-Foo} *) module M : sig type t = Foo diff --git a/test/xref2/github_issue_447.t/run.t b/test/xref2/github_issue_447.t/run.t index 5fd7cd674c..9e9382af34 100644 --- a/test/xref2/github_issue_447.t/run.t +++ b/test/xref2/github_issue_447.t/run.t @@ -4,12 +4,22 @@ are coming from. $ ocamlc -c -bin-annot a.mli $ odoc compile --warn-error -I . a.cmti -Currently, it is only possible to omit the parent type of the constructor in the -toplevel: only [{!M.constructor-Foo}] does not resolve, as it cannot find a type -named [M]. +It is possible to omit type parent in constructor reference, and use directly +the parent module. All references in [a.mli] resolve without warning, except the +faulty reference. $ odoc link a.odoc File "a.mli", line 15, characters 4-22: - Warning: Failed to resolve reference unresolvedroot(t).A Couldn't find "t" - File "a.mli", line 9, characters 4-24: - Warning: Failed to resolve reference unresolvedroot(M).Foo Couldn't find "M" + Warning: Failed to resolve reference unresolvedroot(t).A is of kind class but expected signature or type + +Let's now check that the reference point to the right page/anchor: + + $ odoc html-generate --output-dir html --indent a.odocl + + $ cat html/A/index.html | grep \# | grep Foo | grep -v anchor +

Foo + u.Foo +

M.t.Foo and + M.t.Foo +

M.t.Foo and + M.t.Foo diff --git a/test/xref2/refs/refs.md b/test/xref2/refs/refs.md index f40426be05..18e7972955 100644 --- a/test/xref2/refs/refs.md +++ b/test/xref2/refs/refs.md @@ -448,8 +448,24 @@ Explicit, in sig: M); ihash = 716453475; ikey = "m_M.r_Root.p_None"}, E2) -# resolve_ref "constructor:M.C2" (* Not allowed by types *) ;; -Exception: Failure "resolve_reference: Couldn't find \"M\"". +# resolve_ref "constructor:M.C2" ;; +- : ref = +`Constructor + (`Type + (`Identifier + {Odoc_model__Paths_types.iv = + `Module + ({Odoc_model__Paths_types.iv = + `Root + (Some + {Odoc_model__Paths_types.iv = `Page (None, None); + ihash = 236059787; ikey = "p_None"}, + Root); + ihash = 818126955; ikey = "r_Root.p_None"}, + M); + ihash = 716453475; ikey = "m_M.r_Root.p_None"}, + t2), + C2) # resolve_ref "val:M.e2" ;; - : ref = `Value @@ -515,7 +531,7 @@ Exception: Failure "resolve_reference: Couldn't find \"M\"". ihash = 716453475; ikey = "m_M.r_Root.p_None"}, x2) # resolve_ref "constructor:M.X2" (* X2 is an extension constructor *) ;; -Exception: Failure "resolve_reference: Couldn't find \"M\"". +Exception: Failure "resolve_reference: Couldn't find \"X2\"". # resolve_ref "extension:M.X2" ;; - : ref = `Extension @@ -2634,7 +2650,7 @@ Exception: Failure "resolve_reference: Couldn't find field \"C\"". Exception: Failure "resolve_reference: is of kind type but expected class". # (* Lookup a constructor but find a field *) resolve_ref "M.constructor-f" ;; -Exception: Failure "resolve_reference: Couldn't find \"M\"". +Exception: Failure "resolve_reference: Couldn't find constructor \"f\"". # resolve_ref "M.u.constructor-f" ;; Exception: Failure "resolve_reference: Couldn't find constructor \"f\"". ``` @@ -2666,8 +2682,9 @@ Failure # resolve_ref "M.t.method-m" ;; Exception: Failure "resolve_reference: is of kind type but expected class or class type". -# resolve_ref "c.constructor-C" (* Type in env but find class (parent of constructor is "datatype") *) ;; -Exception: Failure "resolve_reference: Couldn't find \"c\"". +# resolve_ref "c.constructor-C" (* Type in env but find class (parent of constructor is "parent") *) ;; +Exception: +Failure "resolve_reference: is of kind class but expected signature or type". # resolve_ref "c.field-f" (* Field in class (parent of field is "label_parent") *) ;; Exception: Failure "resolve_reference: is of kind class but expected signature or type". @@ -2922,7 +2939,23 @@ Unambiguous: ihash = 895481052; ikey = "m_X.r_Root.p_None"}, u) # resolve_ref "X.constructor-Y" ;; -Exception: Failure "resolve_reference: Couldn't find \"X\"". +- : ref = +`Constructor + (`Type + (`Identifier + {Odoc_model__Paths_types.iv = + `Module + ({Odoc_model__Paths_types.iv = + `Root + (Some + {Odoc_model__Paths_types.iv = `Page (None, None); + ihash = 236059787; ikey = "p_None"}, + Root); + ihash = 818126955; ikey = "r_Root.p_None"}, + X); + ihash = 895481052; ikey = "m_X.r_Root.p_None"}, + u), + Y) # resolve_ref "X.module-Y" ;; - : ref = `Module @@ -3037,7 +3070,23 @@ Unambiguous 2: ihash = 895481052; ikey = "m_X.r_Root.p_None"}, u) # resolve_ref "constructor:X.Y" ;; -Exception: Failure "resolve_reference: Couldn't find \"X\"". +- : ref = +`Constructor + (`Type + (`Identifier + {Odoc_model__Paths_types.iv = + `Module + ({Odoc_model__Paths_types.iv = + `Root + (Some + {Odoc_model__Paths_types.iv = `Page (None, None); + ihash = 236059787; ikey = "p_None"}, + Root); + ihash = 818126955; ikey = "r_Root.p_None"}, + X); + ihash = 895481052; ikey = "m_X.r_Root.p_None"}, + u), + Y) # resolve_ref "module:X.Y" ;; - : ref = `Module From be87d3a433efea7e237d317a19e74d17d986057e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 28 Feb 2023 12:50:38 +0100 Subject: [PATCH 03/35] move `class_signature_pv` from `parent` to `label_parent` Indeed, `parent` is for constructor and fields: they can only have signature or datatype as parent. Signed-off-by: Paul-Elliot Co-authored-by: Emile Trotignon --- src/model/paths.ml | 6 +++--- src/model/paths_types.ml | 8 ++------ src/xref2/compile.ml | 33 ++++++++++++++++++--------------- src/xref2/ident.ml | 10 +++++++--- src/xref2/lang_of.ml | 33 ++++++++++++++++++--------------- src/xref2/lang_of.mli | 8 ++++---- src/xref2/link.ml | 4 ++-- 7 files changed, 54 insertions(+), 48 deletions(-) diff --git a/src/model/paths.ml b/src/model/paths.ml index 5002ca9cd3..39e048ce71 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -997,14 +997,14 @@ module Reference = struct as sg -> (parent_signature_identifier sg :> Identifier.Parent.t) | `Type _ as t -> (parent_type_identifier t :> Identifier.Parent.t) - | (`Class _ | `ClassType _) as c -> - (parent_class_signature_identifier c :> Identifier.Parent.t) and label_parent_identifier : label_parent -> Identifier.LabelParent.t = function | `Identifier id -> id + | (`Class _ | `ClassType _) as c -> + (parent_class_signature_identifier c :> Identifier.LabelParent.t) | ( `Hidden _ | `Alias _ | `AliasModuleType _ | `Module _ | `ModuleType _ - | `Type _ | `Class _ | `ClassType _ ) as r -> + | `Type _ ) as r -> (parent_identifier r :> Identifier.LabelParent.t) and identifier : t -> Identifier.t = function diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index a20be58bd4..a66e662515 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -81,13 +81,13 @@ module Identifier = struct and datatype = datatype_pv id (** @canonical Odoc_model.Paths.Identifier.DataType.t *) - type parent_pv = [ signature_pv | datatype_pv | class_signature_pv ] + type parent_pv = [ signature_pv | datatype_pv ] (** @canonical Odoc_model.Paths.Identifier.Parent.t_pv *) and parent = parent_pv id (** @canonical Odoc_model.Paths.Identifier.Parent.t *) - type label_parent_pv = [ parent_pv | page_pv ] + type label_parent_pv = [ parent_pv | page_pv | class_signature_pv ] (** @canonical Odoc_model.Paths.Identifier.LabelParent.t_pv *) and label_parent = label_parent_pv id @@ -623,8 +623,6 @@ module rec Reference : sig | `Dot of label_parent * string | `Module of signature * ModuleName.t | `ModuleType of signature * ModuleTypeName.t - | `Class of signature * ClassName.t - | `ClassType of signature * ClassTypeName.t | `Type of signature * TypeName.t ] (** @canonical Odoc_model.Paths.Reference.Parent.t *) @@ -813,8 +811,6 @@ and Resolved_reference : sig | `Module of signature * ModuleName.t | `Hidden of module_ | `ModuleType of signature * ModuleTypeName.t - | `Class of signature * ClassName.t - | `ClassType of signature * ClassTypeName.t | `Type of signature * TypeName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.Parent.t *) diff --git a/src/xref2/compile.ml b/src/xref2/compile.ml index 716222eb63..7f2312ff17 100644 --- a/src/xref2/compile.ml +++ b/src/xref2/compile.ml @@ -103,7 +103,7 @@ and content env id = and value_ env parent t = let open Value in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in try { t with type_ = type_expression env container t.type_ } with _ -> Errors.report ~what:(`Value t.id) `Compile; @@ -111,14 +111,14 @@ and value_ env parent t = and exception_ env parent e = let open Exception in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in let res = Opt.map (type_expression env container) e.res in let args = type_decl_constructor_argument env container e.args in { e with res; args } and extension env parent t = let open Extension in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in let constructor c = let open Constructor in { @@ -133,7 +133,7 @@ and extension env parent t = and class_type_expr env parent = let open ClassType in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in function | Constr (path, texps) -> Constr @@ -169,7 +169,7 @@ and class_type env c = and class_signature env parent c = let open ClassSignature in - let container = (parent : Id.ClassSignature.t :> Id.Parent.t) in + let container = (parent : Id.ClassSignature.t :> Id.LabelParent.t) in let env = Env.open_class_signature c env in let map_item = function | Method m -> Method (method_ env parent m) @@ -186,12 +186,12 @@ and class_signature env parent c = and method_ env parent m = let open Method in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in { m with type_ = type_expression env container m.type_ } and instance_variable env parent i = let open InstanceVariable in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in { i with type_ = type_expression env container i.type_ } and class_constraint env parent cst = @@ -208,7 +208,7 @@ and inherit_ env parent ih = and class_ env parent c = let open Class in - let container = (parent :> Id.Parent.t) in + let container = (parent :> Id.LabelParent.t) in let expansion = match let open Utils.OptionMonad in @@ -513,7 +513,7 @@ and module_type_expr_sub id ~fragment_root (sg_res, env, subs) lsub = Errors.report ~what:(`With_type cfrag) `Compile; (cfrag, frag) in - let eqn' = type_decl_equation env (id :> Id.Parent.t) eqn in + let eqn' = type_decl_equation env (id :> Id.LabelParent.t) eqn in let ceqn' = Component.Of_Lang.(type_equation (empty ()) eqn') in Tools.fragmap ~mark_substituted:true env (Component.ModuleType.TypeEq (cfrag', ceqn')) @@ -556,7 +556,7 @@ and module_type_expr_sub id ~fragment_root (sg_res, env, subs) lsub = Errors.report ~what:(`With_type cfrag) `Compile; (cfrag, frag) in - let eqn' = type_decl_equation env (id :> Id.Parent.t) eqn in + let eqn' = type_decl_equation env (id :> Id.LabelParent.t) eqn in let ceqn' = Component.Of_Lang.(type_equation (empty ()) eqn') in Tools.fragmap ~mark_substituted:true env (Component.ModuleType.TypeSubst (cfrag', ceqn')) @@ -739,7 +739,7 @@ and type_decl : Env.t -> TypeDecl.t -> TypeDecl.t = let open TypeDecl in let container = match t.id.iv with - | `Type (parent, _) -> (parent :> Id.Parent.t) + | `Type (parent, _) -> (parent :> Id.LabelParent.t) | `CoreType _ -> assert false in let equation = type_decl_equation env container t.equation in @@ -749,7 +749,7 @@ and type_decl : Env.t -> TypeDecl.t -> TypeDecl.t = { t with equation; representation } and type_decl_equation : - Env.t -> Id.Parent.t -> TypeDecl.Equation.t -> TypeDecl.Equation.t = + Env.t -> Id.LabelParent.t -> TypeDecl.Equation.t -> TypeDecl.Equation.t = fun env parent t -> let open TypeDecl.Equation in let manifest = Opt.map (type_expression env parent) t.manifest in @@ -763,7 +763,7 @@ and type_decl_equation : and type_decl_representation : Env.t -> - Id.Parent.t -> + Id.LabelParent.t -> TypeDecl.Representation.t -> TypeDecl.Representation.t = fun env parent r -> @@ -784,7 +784,10 @@ and type_decl_constructor_argument env parent c = | Record fs -> Record (List.map (type_decl_field env parent) fs) and type_decl_constructor : - Env.t -> Id.Parent.t -> TypeDecl.Constructor.t -> TypeDecl.Constructor.t = + Env.t -> + Id.LabelParent.t -> + TypeDecl.Constructor.t -> + TypeDecl.Constructor.t = fun env parent c -> let open TypeDecl.Constructor in let args = type_decl_constructor_argument env parent c.args in @@ -853,7 +856,7 @@ and type_expression_package env parent p = })) | Error _ -> { p with path = Lang_of.(Path.module_type (empty ()) cp) } -and type_expression : Env.t -> Id.Parent.t -> _ -> _ = +and type_expression : Env.t -> Id.LabelParent.t -> _ -> _ = fun env parent texpr -> let open TypeExpr in match texpr with diff --git a/src/xref2/ident.ml b/src/xref2/ident.ml index 5b1de490fe..dfee7a4956 100644 --- a/src/xref2/ident.ml +++ b/src/xref2/ident.ml @@ -16,10 +16,13 @@ type class_signature = type datatype = [ `LType of TypeName.t * int ] -type parent = [ signature | datatype | class_signature ] +type parent = [ signature | datatype ] type label_parent = - [ parent | `LPage of PageName.t * int | `LLeafPage of PageName.t * int ] + [ parent + | `LPage of PageName.t * int + | `LLeafPage of PageName.t * int + | class_signature ] type module_ = [ `LRoot of ModuleName.t * int @@ -143,11 +146,12 @@ module Of_Identifier = struct match p with | { iv = #Signature.t_pv; _ } as s -> (signature s :> parent) | { iv = #DataType.t_pv; _ } as s -> (datatype s :> parent) - | { iv = #ClassSignature.t_pv; _ } as s -> (class_signature s :> parent) let label_parent : LabelParent.t -> label_parent = fun p -> match p with + | { iv = #ClassSignature.t_pv; _ } as s -> + (class_signature s :> label_parent) | { iv = #Parent.t_pv; _ } as s -> (parent s :> label_parent) | { iv = `Page (_, n); _ } -> `LPage (n, fresh_int ()) | { iv = `LeafPage (_, n); _ } -> `LLeafPage (n, fresh_int ()) diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index d59a628c88..45ed04fdf1 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -513,7 +513,7 @@ and class_decl map parent c = | Arrow (lbl, t, d) -> Arrow ( lbl, - type_expr map (parent :> Identifier.Parent.t) t, + type_expr map (parent :> Identifier.LabelParent.t) t, class_decl map parent d ) and class_type_expr map parent c = @@ -521,7 +521,7 @@ and class_type_expr map parent c = | Component.ClassType.Constr (p, ts) -> Constr ( Path.class_type map p, - List.rev_map (type_expr map (parent :> Identifier.Parent.t)) ts + List.rev_map (type_expr map (parent :> Identifier.LabelParent.t)) ts |> List.rev ) | Signature s -> Signature (class_signature map parent s) @@ -548,7 +548,7 @@ and class_type map parent id c = and class_signature map parent sg = let open Component.ClassSignature in - let pparent = (parent :> Identifier.Parent.t) in + let pparent = (parent :> Identifier.LabelParent.t) in let items = List.rev_map (function @@ -573,7 +573,7 @@ and method_ map parent id m = doc = docs (parent :> Identifier.LabelParent.t) m.doc; private_ = m.private_; virtual_ = m.virtual_; - type_ = type_expr map (parent :> Identifier.Parent.t) m.type_; + type_ = type_expr map (parent :> Identifier.LabelParent.t) m.type_; } and instance_variable map parent id i = @@ -587,7 +587,7 @@ and instance_variable map parent id i = doc = docs (parent :> Identifier.LabelParent.t) i.doc; mutable_ = i.mutable_; virtual_ = i.virtual_; - type_ = type_expr map (parent :> Identifier.Parent.t) i.type_; + type_ = type_expr map (parent :> Identifier.LabelParent.t) i.type_; } and class_constraint map parent cst = @@ -686,7 +686,7 @@ and value_ map parent id v = id = identifier; locs = v.locs; doc = docs (parent :> Identifier.LabelParent.t) v.doc; - type_ = type_expr map (parent :> Identifier.Parent.t) v.type_; + type_ = type_expr map (parent :> Identifier.LabelParent.t) v.type_; value = v.value; } @@ -712,7 +712,7 @@ and extension_constructor map parent c = doc = docs (parent :> Identifier.LabelParent.t) c.doc; args = type_decl_constructor_argument map (parent :> Identifier.Parent.t) c.args; - res = Opt.map (type_expr map (parent :> Identifier.Parent.t)) c.res; + res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) c.res; } and module_ map parent id m = @@ -893,7 +893,8 @@ and type_decl_constructor_argument : Odoc_model.Lang.TypeDecl.Constructor.argument = fun map parent a -> match a with - | Tuple ls -> Tuple (List.map (type_expr map parent) ls) + | Tuple ls -> + Tuple (List.map (type_expr map (parent :> Identifier.LabelParent.t)) ls) | Record fs -> Record (List.map (type_decl_field map parent) fs) and type_decl_field : @@ -907,12 +908,13 @@ and type_decl_field : id = identifier; doc = docs (parent :> Identifier.LabelParent.t) f.doc; mutable_ = f.mutable_; - type_ = type_expr map parent f.type_; + type_ = type_expr map (parent :> Identifier.LabelParent.t) f.type_; } and type_decl_equation map (parent : Identifier.Parent.t) (eqn : Component.TypeDecl.Equation.t) : Odoc_model.Lang.TypeDecl.Equation.t = + let parent = (parent :> Identifier.LabelParent.t) in { params = eqn.params; private_ = eqn.private_; @@ -958,14 +960,15 @@ and type_decl_constructor : let identifier = Identifier.Mk.constructor (id, ConstructorName.make_std t.name) in + let parent = (id :> Identifier.LabelParent.t) in { id = identifier; doc = docs (id :> Identifier.LabelParent.t) t.doc; args = type_decl_constructor_argument map id t.args; - res = Opt.map (type_expr map id) t.res; + res = Opt.map (type_expr map parent) t.res; } -and type_expr_package map parent t = +and type_expr_package map (parent : Identifier.LabelParent.t) t = { Lang.TypeExpr.Package.path = Path.module_type map t.Component.TypeExpr.Package.path; @@ -976,8 +979,8 @@ and type_expr_package map parent t = t.substitutions; } -and type_expr map (parent : Identifier.Parent.t) (t : Component.TypeExpr.t) : - Odoc_model.Lang.TypeExpr.t = +and type_expr map (parent : Identifier.LabelParent.t) (t : Component.TypeExpr.t) + : Odoc_model.Lang.TypeExpr.t = try match t with | Var s -> Var s @@ -1009,7 +1012,7 @@ and type_expr_polyvar map parent v = c.Component.TypeExpr.Polymorphic_variant.Constructor.name; constant = c.constant; arguments = List.map (type_expr map parent) c.arguments; - doc = docs (parent :> Identifier.LabelParent.t) c.doc; + doc = docs parent c.doc; } in let element = function @@ -1054,7 +1057,7 @@ and exception_ map parent id (e : Component.Exception.t) : doc = docs (parent :> Identifier.LabelParent.t) e.doc; args = type_decl_constructor_argument map (parent :> Identifier.Parent.t) e.args; - res = Opt.map (type_expr map (parent :> Identifier.Parent.t)) e.res; + res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) e.res; } and block_element parent diff --git a/src/xref2/lang_of.mli b/src/xref2/lang_of.mli index 0e8a3358a2..e5d1025ade 100644 --- a/src/xref2/lang_of.mli +++ b/src/xref2/lang_of.mli @@ -223,25 +223,25 @@ val type_decl_constructor : val type_expr_package : maps -> - Identifier.Parent.t -> + Identifier.LabelParent.t -> Component.TypeExpr.Package.t -> Odoc_model.Lang.TypeExpr.Package.t val type_expr : maps -> - Identifier.Parent.t -> + Identifier.LabelParent.t -> Component.TypeExpr.t -> Odoc_model.Lang.TypeExpr.t val type_expr_polyvar : maps -> - Identifier.Parent.t -> + Identifier.LabelParent.t -> Component.TypeExpr.Polymorphic_variant.t -> Odoc_model.Lang.TypeExpr.Polymorphic_variant.t val type_expr_object : maps -> - Identifier.Parent.t -> + Identifier.LabelParent.t -> Component.TypeExpr.Object.t -> Odoc_model.Lang.TypeExpr.Object.t diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 04f088c2c7..70843fdeb9 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -1047,7 +1047,7 @@ and type_expression : Env.t -> Id.Signature.t -> _ -> _ = let t' = Expand_tools.type_expr map Lang_of.( - type_expr (empty ()) (parent :> Id.Parent.t) expr) + type_expr (empty ()) (parent :> Id.LabelParent.t) expr) in type_expression env parent (p :: visited) t' with @@ -1066,7 +1066,7 @@ and type_expression : Env.t -> Id.Signature.t -> _ -> _ = Constr (`Resolved p, ts) | Ok (_cp, `FType_removed (_, x, _eq)) -> (* Type variables ? *) - Lang_of.(type_expr (empty ()) (parent :> Id.Parent.t) x) + Lang_of.(type_expr (empty ()) (parent :> Id.LabelParent.t) x) | Error _ -> Constr (path', ts)) | Polymorphic_variant v -> Polymorphic_variant (type_expression_polyvar env parent visited v) From c28015454eb8b30e5a5d401f0f9520b91286780e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 28 Feb 2023 13:22:34 +0100 Subject: [PATCH 04/35] Force identifiers + resolved references to have a datatype as parent Resolved references/ids already always had datatype as parent, but it is now enforced by the subtyping system. The reason we cannot symmetrically do the same for fields is the following: ```ocaml type t = .. type t += Inline of { a : int} ``` In this example, `a` cannot have a `datatype` as parent. Parent for fields should ideally be `[datatype | constructor | extension]`. Signed-off-by: Paul-Elliot Co-authored-by: Emile Trotignon --- src/loader/cmi.ml | 2 +- src/loader/cmti.ml | 6 +- src/model/paths.ml | 10 +-- src/model/paths.mli | 4 +- src/model/paths_types.ml | 6 +- src/xref2/env.ml | 2 +- src/xref2/lang_of.ml | 13 ++-- src/xref2/lang_of.mli | 2 +- src/xref2/ref_tools.ml | 7 +-- test/model/semantics/test.ml | 114 +++++++++++++++++------------------ 10 files changed, 82 insertions(+), 84 deletions(-) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index 3f136ccf44..d602d50ac0 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -713,7 +713,7 @@ let read_type_declaration env parent id decl = let params = mark_type_declaration decl in let manifest = opt_map (read_type_expr env) decl.type_manifest in let constraints = read_type_constraints env params in - let representation = read_type_kind env (id :> Identifier.Parent.t) decl.type_kind in + let representation = read_type_kind env (id :> Identifier.DataType.t) decl.type_kind in let abstr = match decl.type_kind with Type_abstract -> diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index a2e9f6bbe8..9e7424c64f 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -214,7 +214,7 @@ let read_constructor_declaration_arguments env parent label_parent arg = let read_constructor_declaration env parent cd = let open TypeDecl.Constructor in let id = Ident_env.find_constructor_identifier env cd.cd_id in - let container = parent in + let container = (parent :> Identifier.Parent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container cd.cd_attributes in let args = @@ -231,7 +231,7 @@ let read_type_kind env parent = let cstrs = List.map (read_constructor_declaration env parent) cstrs in Some (Variant cstrs) | Ttype_record lbls -> - let parent = (parent ) in + let parent = (parent :> Identifier.Parent.t) in let label_parent = (parent :> Identifier.LabelParent.t) in let lbls = List.map (read_label_declaration env parent label_parent) lbls in @@ -260,7 +260,7 @@ let read_type_declaration env parent decl = let doc, canonical = Doc_attr.attached Odoc_model.Semantics.Expect_canonical container decl.typ_attributes in let canonical = (canonical :> Path.Type.t option) in let equation = read_type_equation env container decl in - let representation = read_type_kind env (id :> Identifier.Parent.t) decl.typ_kind in + let representation = read_type_kind env id decl.typ_kind in {id; locs; doc; canonical; equation; representation} let read_type_declarations env parent rec_flag decls = diff --git a/src/model/paths.ml b/src/model/paths.ml index 39e048ce71..7eb3f834c8 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -165,7 +165,7 @@ module Identifier = struct | { iv = `Label (p, _); _ } -> p | { iv = `Method (p, _); _ } | { iv = `InstanceVariable (p, _); _ } -> (p : class_signature :> label_parent) - | { iv = `Constructor (p, _); _ } -> (p : parent :> label_parent) + | { iv = `Constructor (p, _); _ } -> (p : datatype :> label_parent) | { iv = `Field (p, _); _ } -> (p : parent :> label_parent) let label_parent n = label_parent_aux (n :> Id.non_src) @@ -572,8 +572,8 @@ module Identifier = struct mk_fresh (fun s -> s) "coret" (fun s -> `CoreType (TypeName.make_std s)) let constructor : - Parent.t * ConstructorName.t -> - [> `Constructor of Parent.t * ConstructorName.t ] id = + DataType.t * ConstructorName.t -> + [> `Constructor of DataType.t * ConstructorName.t ] id = mk_parent ConstructorName.to_string "ctor" (fun (p, n) -> `Constructor (p, n)) @@ -1013,7 +1013,9 @@ module Reference = struct | `Class _ | `ClassType _ | `ModuleType _ ) as r -> (label_parent_identifier r :> Identifier.t) | `Field (p, n) -> Identifier.Mk.field (parent_identifier p, n) - | `Constructor (s, n) -> Identifier.Mk.constructor (parent_identifier s, n) + | `Constructor (s, n) -> + Identifier.Mk.constructor + ((parent_type_identifier s :> Identifier.DataType.t), n) | `Extension (p, q) -> Identifier.Mk.extension (parent_signature_identifier p, q) | `ExtensionDecl (p, q, r) -> diff --git a/src/model/paths.mli b/src/model/paths.mli index be0f504740..a7bada2699 100644 --- a/src/model/paths.mli +++ b/src/model/paths.mli @@ -290,8 +290,8 @@ module Identifier : sig val core_type : string -> [> `CoreType of TypeName.t ] id val constructor : - Parent.t * ConstructorName.t -> - [> `Constructor of Parent.t * ConstructorName.t ] id + DataType.t * ConstructorName.t -> + [> `Constructor of DataType.t * ConstructorName.t ] id val field : Parent.t * FieldName.t -> [> `Field of Parent.t * FieldName.t ] id diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index a66e662515..bbf1f6a567 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -132,7 +132,7 @@ module Identifier = struct and type_ = type_pv id (** @canonical Odoc_model.Paths.Identifier.Type.t *) - type constructor_pv = [ `Constructor of parent * ConstructorName.t ] + type constructor_pv = [ `Constructor of datatype * ConstructorName.t ] (** @canonical Odoc_model.Paths.Identifier.Constructor.t_pv *) and constructor = constructor_pv id @@ -843,7 +843,7 @@ and Resolved_reference : sig type constructor = [ `Identifier of Identifier.reference_constructor - | `Constructor of parent * ConstructorName.t + | `Constructor of datatype * ConstructorName.t | `Extension of signature * ExtensionName.t | `Exception of signature * ExceptionName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.Constructor.t *) @@ -916,7 +916,7 @@ and Resolved_reference : sig | `Hidden of module_ | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t - | `Constructor of parent * ConstructorName.t + | `Constructor of datatype * ConstructorName.t | `Field of parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t * ExtensionName.t diff --git a/src/xref2/env.ml b/src/xref2/env.ml index c7806870c1..9928691d4f 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -294,7 +294,7 @@ let add_type (identifier : Identifier.Type.t) t env = let add_cons env (cons : TypeDecl.Constructor.t) = let ident = Paths.Identifier.Mk.constructor - ( (identifier :> Identifier.Parent.t), + ( (identifier :> Identifier.DataType.t), ConstructorName.make_std cons.name ) in add_to_elts Kind_Constructor ident (`Constructor (ident, cons)) env diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index 45ed04fdf1..6dae535405 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -895,7 +895,8 @@ and type_decl_constructor_argument : match a with | Tuple ls -> Tuple (List.map (type_expr map (parent :> Identifier.LabelParent.t)) ls) - | Record fs -> Record (List.map (type_decl_field map parent) fs) + | Record fs -> + Record (List.map (type_decl_field map (parent :> Identifier.Parent.t)) fs) and type_decl_field : maps -> @@ -942,9 +943,7 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : Odoc_model.Lang.TypeDecl.Representation.t = match t with | Extensible -> Extensible - | Variant cs -> - Variant - (List.map (type_decl_constructor map (id :> Identifier.Parent.t)) cs) + | Variant cs -> Variant (List.map (type_decl_constructor map id) cs) | Record fs -> Record (List.map @@ -953,7 +952,7 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : and type_decl_constructor : maps -> - Odoc_model.Paths.Identifier.Parent.t -> + Odoc_model.Paths.Identifier.DataType.t -> Component.TypeDecl.Constructor.t -> Odoc_model.Lang.TypeDecl.Constructor.t = fun map id t -> @@ -963,8 +962,8 @@ and type_decl_constructor : let parent = (id :> Identifier.LabelParent.t) in { id = identifier; - doc = docs (id :> Identifier.LabelParent.t) t.doc; - args = type_decl_constructor_argument map id t.args; + doc = docs parent t.doc; + args = type_decl_constructor_argument map (id :> Identifier.Parent.t) t.args; res = Opt.map (type_expr map parent) t.res; } diff --git a/src/xref2/lang_of.mli b/src/xref2/lang_of.mli index e5d1025ade..83b4ab6e04 100644 --- a/src/xref2/lang_of.mli +++ b/src/xref2/lang_of.mli @@ -217,7 +217,7 @@ val type_decl_representation : val type_decl_constructor : maps -> - Identifier.Parent.t -> + Identifier.DataType.t -> Component.TypeDecl.Constructor.t -> Odoc_model.Lang.TypeDecl.Constructor.t diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index a4b37a93cb..594e8ffa1a 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -456,16 +456,13 @@ module CS = struct find Find.any_in_type t name_s >>= function | `FField _ -> got_a_field name_s | `FConstructor _ -> - Ok - (`Constructor - ((parent' : Resolved.DataType.t :> Resolved.Parent.t), name))) + Ok (`Constructor ((parent' : Resolved.DataType.t), name))) | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = Ok (`Constructor - ( (parent : Resolved.DataType.t :> Resolved.Parent.t), - ConstructorName.make_std name )) + ((parent : Resolved.DataType.t), ConstructorName.make_std name)) end module F = struct diff --git a/test/model/semantics/test.ml b/test/model/semantics/test.ml index 29855b6dc8..75cc97890d 100644 --- a/test/model/semantics/test.ml +++ b/test/model/semantics/test.ml @@ -1645,79 +1645,79 @@ let%expect_test _ = test "{!class-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"class-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_class_type = test "{!class-type-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"class-type-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-16:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-type-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-16:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_constructor = test "{!constructor-Foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"constructor-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-17:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"constructor-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-17:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_exception = test "{!exception-Foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"exception-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"exception-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_extension = test "{!extension-Foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"extension-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"extension-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_field = test "{!field-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"field-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"field-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_section = test "{!section-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"section-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-13:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"section-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-13:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_instance_variable = test "{!instance-variable-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"instance-variable-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-23:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"instance-variable-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-23:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_method = test "{!method-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"method-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-12:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"method-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-12:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_module = test "{!module-Foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"module-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-12:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Reference":[{"`Constructor":[{"`Root":["Foo","`TModule"]},"Bar"]},[]]}]}],"warnings":[]} |}] let constructor_in_module_type = test "{!module-type-Foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"module-type-Foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-17:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Reference":[{"`Constructor":[{"`Root":["Foo","`TModuleType"]},"Bar"]},[]]}]}],"warnings":[]} |}] let constructor_in_page = test "{!page-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_val = test "{!val-foo.constructor-Bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"val-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-9:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"val-foo.constructor-Bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-9:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_something_nested = test "{!foo.bar.constructor-Baz}"; @@ -1735,79 +1735,79 @@ let%expect_test _ = test "{!Foo.class-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_class_type_nested = test "{!Foo.class-type-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-type-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-20:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-type-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-20:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_constructor_nested = test "{!Foo.constructor-Bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.constructor-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-21:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.constructor-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-21:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_exception_nested = test "{!Foo.exception-Bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.exception-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.exception-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_extension_nested = test "{!Foo.extension-Bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.extension-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.extension-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_field_nested = test "{!foo.field-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.field-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.field-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_section_nested = test "{!foo.section-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.section-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-17:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.section-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-17:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_instance_variable_nested = test "{!foo.instance-variable-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.instance-variable-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-27:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.instance-variable-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-27:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_method_nested = test "{!foo.method-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.method-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-16:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.method-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-16:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_module_nested = test "{!Foo.module-Bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.module-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-16:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Reference":[{"`Constructor":[{"`Module":[{"`Root":["Foo","`TUnknown"]},"Bar"]},"Baz"]},[]]}]}],"warnings":[]} |}] let constructor_in_module_type_nested = test "{!Foo.module-type-Bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.module-type-Bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-21:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Reference":[{"`Constructor":[{"`ModuleType":[{"`Root":["Foo","`TUnknown"]},"Bar"]},"Baz"]},[]]}]}],"warnings":[]} |}] let constructor_in_page_nested = test "{!foo.page-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.page-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-14:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.page-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-14:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let constructor_in_val_nested = test "{!Foo.val-bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.val-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-13:\nExpected 'type-' or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.val-bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-13:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_empty = test "{!.field-foo}"; @@ -1843,67 +1843,67 @@ let%expect_test _ = test "{!class-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`Root":["foo","`TClass"]},"bar"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_class_type = test "{!class-type-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`Root":["foo","`TClassType"]},"bar"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-type-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-16:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_constructor = test "{!constructor-Foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"constructor-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-17:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"constructor-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-17:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_exception = test "{!exception-Foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"exception-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"exception-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_extension = test "{!extension-Foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"extension-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"extension-Foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_field = test "{!field-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"field-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"field-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_section = test "{!section-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"section-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-13:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"section-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-13:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_instance_variable = test "{!instance-variable-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"instance-variable-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-23:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"instance-variable-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-23:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_method = test "{!method-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"method-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-12:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"method-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-12:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_page = test "{!page-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_val = test "{!val-foo.field-bar}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"val-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-9:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"val-foo.field-bar"}]}],"warnings":["File \"f.ml\", line 1, characters 2-9:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_something_nested = test "{!foo.bar.field-baz}"; @@ -1933,67 +1933,67 @@ let%expect_test _ = test "{!Foo.class-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`Class":[{"`Root":["Foo","`TUnknown"]},"bar"]},"baz"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_class_type_nested = test "{!Foo.class-type-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`ClassType":[{"`Root":["Foo","`TUnknown"]},"bar"]},"baz"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.class-type-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-20:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_constructor_nested = test "{!Foo.constructor-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.constructor-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-21:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.constructor-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-21:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_exception_nested = test "{!Foo.exception-Bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.exception-Bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.exception-Bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_extension_nested = test "{!Foo.extension-Bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.extension-Bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.extension-Bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-19:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_field_nested = test "{!Foo.field-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.field-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.field-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-15:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_section_nested = test "{!foo.section-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.section-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-17:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.section-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-17:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_instance_variable_nested = test "{!foo.instance-variable-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.instance-variable-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-27:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.instance-variable-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-27:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_method_nested = test "{!foo.method-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.method-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-16:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.method-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-16:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_page_nested = test "{!foo.page-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"foo.page-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-14:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"foo.page-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-14:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let field_in_val_nested = test "{!Foo.val-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"Foo.val-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-13:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"Foo.val-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 6-13:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let exception_in_something = test "{!Foo.exception-Bar}"; @@ -2371,13 +2371,13 @@ let%expect_test _ = test "{!class-foo.bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`Dot":[{"`Root":["foo","`TClass"]},"bar"]},"baz"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-foo.bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_parent_something_in_page = test "{!page-foo.bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_parent_module_in_module = test "{!module-Foo.module-Bar.field-baz}"; @@ -2419,25 +2419,25 @@ let%expect_test _ = test "{!module-Foo.class-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`Class":[{"`Root":["Foo","`TModule"]},"bar"]},"baz"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"module-Foo.class-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 13-22:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_parent_class_in_class = test "{!class-foo.class-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"class-foo.class-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-foo.class-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 12-21:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_parent_class_type_in_module = test "{!module-Foo.class-type-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Reference":[{"`Field":[{"`ClassType":[{"`Root":["Foo","`TModule"]},"bar"]},"baz"]},[]]}]}],"warnings":[]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"module-Foo.class-type-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 13-27:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_parent_class_type_in_class = test "{!class-foo.class-type-bar.field-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"class-foo.class-type-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-11:\nExpected 'module-', 'module-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"class-foo.class-type-bar.field-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 12-26:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_label_parent_something_in_something = test "{!foo.bar.baz}"; @@ -2527,7 +2527,7 @@ let%expect_test _ = test "{!page-foo.bar.method-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.method-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.method-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_class_signature_class_in_module = test "{!module-Foo.class-bar.method-baz}"; @@ -2563,7 +2563,7 @@ let%expect_test _ = test "{!page-foo.bar.type-baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.type-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.type-baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_signature_module_in_module = test "{!module-Foo.module-Bar.type-baz}"; @@ -2599,7 +2599,7 @@ let%expect_test _ = test "{!page-foo.bar.constructor-Baz}"; [%expect {| - {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', 'class-', 'class-type-', or an unqualified reference."]} |}] + {"value":[{"`Paragraph":[{"`Code_span":"page-foo.bar.constructor-Baz"}]}],"warnings":["File \"f.ml\", line 1, characters 2-10:\nExpected 'module-', 'module-type-', 'type-', or an unqualified reference."]} |}] let inner_datatype_type_in_module = test "{!module-Foo.type-bar.constructor-Baz}"; From bed9ef28afd170e48e14f49ef10ee53a357a9717 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 29 Mar 2023 10:40:28 +0200 Subject: [PATCH 05/35] rename `parent` into `fragment_type_parent` The former was too generic. Added some comments at the definition. Signed-off-by: Paul-Elliot --- src/loader/cmi.ml | 8 +++---- src/loader/cmti.ml | 8 +++---- src/model/paths.ml | 27 +++++++++++++---------- src/model/paths.mli | 17 ++++++++------- src/model/paths_types.ml | 47 +++++++++++++++++++++++----------------- src/model/reference.ml | 2 +- src/xref2/env.ml | 2 +- src/xref2/ident.ml | 4 ++-- src/xref2/lang_of.ml | 40 ++++++++++++++++++++++++---------- src/xref2/lang_of.mli | 6 ++--- src/xref2/link.ml | 2 +- src/xref2/ref_tools.ml | 17 ++++++++++----- 12 files changed, 107 insertions(+), 73 deletions(-) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index d602d50ac0..aabeff262d 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -632,7 +632,7 @@ let read_constructor_declaration env parent cd = let doc = Doc_attr.attached_no_tag container cd.cd_attributes in let args = read_constructor_declaration_arguments env - (parent :> Identifier.Parent.t) cd.cd_args + (parent :> Identifier.FragmentTypeParent.t) cd.cd_args in let res = opt_map (read_type_expr env) cd.cd_res in {id; doc; args; res} @@ -652,7 +652,7 @@ let read_type_kind env parent = | Type_record(lbls, _) -> let lbls = List.map - (read_label_declaration env (parent :> Identifier.Parent.t)) + (read_label_declaration env (parent :> Identifier.FragmentTypeParent.t)) lbls in Some (Record lbls) @@ -745,7 +745,7 @@ let read_extension_constructor env parent id ext = let doc = Doc_attr.attached_no_tag container ext.ext_attributes in let args = read_constructor_declaration_arguments env - (parent : Identifier.Signature.t :> Identifier.Parent.t) ext.ext_args + (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) ext.ext_args in let res = opt_map (read_type_expr env) ext.ext_ret_type in {id; locs; doc; args; res} @@ -779,7 +779,7 @@ let read_exception env parent id ext = mark_exception ext; let args = read_constructor_declaration_arguments env - (parent : Identifier.Signature.t :> Identifier.Parent.t) ext.ext_args + (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) ext.ext_args in let res = opt_map (read_type_expr env) ext.ext_ret_type in {id; locs; doc; args; res} diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 9e7424c64f..8ea332f11d 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -214,7 +214,7 @@ let read_constructor_declaration_arguments env parent label_parent arg = let read_constructor_declaration env parent cd = let open TypeDecl.Constructor in let id = Ident_env.find_constructor_identifier env cd.cd_id in - let container = (parent :> Identifier.Parent.t) in + let container = (parent :> Identifier.FragmentTypeParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container cd.cd_attributes in let args = @@ -231,7 +231,7 @@ let read_type_kind env parent = let cstrs = List.map (read_constructor_declaration env parent) cstrs in Some (Variant cstrs) | Ttype_record lbls -> - let parent = (parent :> Identifier.Parent.t) in + let parent = (parent :> Identifier.FragmentTypeParent.t) in let label_parent = (parent :> Identifier.LabelParent.t) in let lbls = List.map (read_label_declaration env parent label_parent) lbls in @@ -292,7 +292,7 @@ let read_extension_constructor env parent ext = let open Extension.Constructor in let id = Env.find_extension_identifier env ext.ext_id in let locs = None in - let container = (parent : Identifier.Signature.t :> Identifier.Parent.t) in + let container = (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container ext.ext_attributes in match ext.ext_kind with @@ -325,7 +325,7 @@ let read_exception env parent (ext : extension_constructor) = let open Exception in let id = Env.find_exception_identifier env ext.ext_id in let locs = None in - let container = (parent : Identifier.Signature.t :> Identifier.Parent.t) in + let container = (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container ext.ext_attributes in match ext.ext_kind with diff --git a/src/model/paths.ml b/src/model/paths.ml index 7eb3f834c8..38a4e338e2 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -166,7 +166,7 @@ module Identifier = struct | { iv = `Method (p, _); _ } | { iv = `InstanceVariable (p, _); _ } -> (p : class_signature :> label_parent) | { iv = `Constructor (p, _); _ } -> (p : datatype :> label_parent) - | { iv = `Field (p, _); _ } -> (p : parent :> label_parent) + | { iv = `Field (p, _); _ } -> (p : fragment_type_parent :> label_parent) let label_parent n = label_parent_aux (n :> Id.non_src) @@ -217,9 +217,9 @@ module Identifier = struct type t_pv = Id.datatype_pv end - module Parent = struct - type t = Id.parent - type t_pv = Id.parent_pv + module FragmentTypeParent = struct + type t = Paths_types.Identifier.fragment_type_parent + type t_pv = Paths_types.Identifier.fragment_type_parent_pv end module LabelParent = struct @@ -578,7 +578,8 @@ module Identifier = struct `Constructor (p, n)) let field : - Parent.t * FieldName.t -> [> `Field of Parent.t * FieldName.t ] id = + FragmentTypeParent.t * FieldName.t -> + [> `Field of FragmentTypeParent.t * FieldName.t ] id = mk_parent FieldName.to_string "fld" (fun (p, n) -> `Field (p, n)) let extension : @@ -991,12 +992,14 @@ module Reference = struct | `ClassType (sg, s) -> Identifier.Mk.class_type (parent_signature_identifier sg, s) - and parent_identifier : parent -> Identifier.Parent.t = function + and parent_identifier : + fragment_type_parent -> Identifier.FragmentTypeParent.t = function | `Identifier id -> id | (`Hidden _ | `Alias _ | `AliasModuleType _ | `Module _ | `ModuleType _) as sg -> - (parent_signature_identifier sg :> Identifier.Parent.t) - | `Type _ as t -> (parent_type_identifier t :> Identifier.Parent.t) + (parent_signature_identifier sg :> Identifier.FragmentTypeParent.t) + | `Type _ as t -> + (parent_type_identifier t :> Identifier.FragmentTypeParent.t) and label_parent_identifier : label_parent -> Identifier.LabelParent.t = function @@ -1042,8 +1045,8 @@ module Reference = struct type t = Paths_types.Resolved_reference.datatype end - module Parent = struct - type t = Paths_types.Resolved_reference.parent + module FragmentTypeParent = struct + type t = Paths_types.Resolved_reference.fragment_type_parent end module LabelParent = struct @@ -1127,8 +1130,8 @@ module Reference = struct type t = Paths_types.Reference.datatype end - module Parent = struct - type t = Paths_types.Reference.parent + module FragmentTypeParent = struct + type t = Paths_types.Reference.fragment_type_parent end module LabelParent = struct diff --git a/src/model/paths.mli b/src/model/paths.mli index a7bada2699..b1c0fd8af5 100644 --- a/src/model/paths.mli +++ b/src/model/paths.mli @@ -79,9 +79,9 @@ module Identifier : sig type t = Id.datatype type t_pv = Id.datatype_pv end - module Parent : sig - type t = Id.parent - type t_pv = Id.parent_pv + module FragmentTypeParent : sig + type t = Id.fragment_type_parent + type t_pv = Id.fragment_type_parent_pv end module FunctorResult : sig @@ -294,7 +294,8 @@ module Identifier : sig [> `Constructor of DataType.t * ConstructorName.t ] id val field : - Parent.t * FieldName.t -> [> `Field of Parent.t * FieldName.t ] id + FragmentTypeParent.t * FieldName.t -> + [> `Field of FragmentTypeParent.t * FieldName.t ] id val extension : Signature.t * ExtensionName.t -> @@ -507,8 +508,8 @@ module rec Reference : sig type t = Paths_types.Resolved_reference.datatype end - module Parent : sig - type t = Paths_types.Resolved_reference.parent + module FragmentTypeParent : sig + type t = Paths_types.Resolved_reference.fragment_type_parent end module LabelParent : sig @@ -592,8 +593,8 @@ module rec Reference : sig type t = Paths_types.Reference.datatype end - module Parent : sig - type t = Paths_types.Reference.parent + module FragmentTypeParent : sig + type t = Paths_types.Reference.fragment_type_parent end module LabelParent : sig diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index bbf1f6a567..58e9dc969e 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -81,13 +81,17 @@ module Identifier = struct and datatype = datatype_pv id (** @canonical Odoc_model.Paths.Identifier.DataType.t *) - type parent_pv = [ signature_pv | datatype_pv ] - (** @canonical Odoc_model.Paths.Identifier.Parent.t_pv *) + type fragment_type_parent_pv = [ signature_pv | datatype_pv ] + (** @canonical Odoc_model.Paths.Identifier.FragmentTypeParent.t_pv *) - and parent = parent_pv id - (** @canonical Odoc_model.Paths.Identifier.Parent.t *) + (* fragment_type_parent in identifiers is for record fields parent. It’s type + (for usual record fields) or [signature] for fields of inline records of + extension constructor. *) + and fragment_type_parent = fragment_type_parent_pv id + (** @canonical Odoc_model.Paths.Identifier.FragmentTypeParent.t *) - type label_parent_pv = [ parent_pv | page_pv | class_signature_pv ] + type label_parent_pv = + [ fragment_type_parent_pv | page_pv | class_signature_pv ] (** @canonical Odoc_model.Paths.Identifier.LabelParent.t_pv *) and label_parent = label_parent_pv id @@ -138,7 +142,7 @@ module Identifier = struct and constructor = constructor_pv id (** @canonical Odoc_model.Paths.Identifier.Constructor.t *) - type field_pv = [ `Field of parent * FieldName.t ] + type field_pv = [ `Field of fragment_type_parent * FieldName.t ] (** @canonical Odoc_model.Paths.Identifier.Field.t_pv *) and field = field_pv id @@ -206,7 +210,7 @@ module Identifier = struct [ signature_pv | class_signature_pv | datatype_pv - | parent_pv + | fragment_type_parent_pv | label_parent_pv | module_pv | functor_parameter_pv @@ -617,14 +621,15 @@ module rec Reference : sig | `Type of signature * TypeName.t ] (** @canonical Odoc_model.Paths.Reference.DataType.t *) - and parent = - [ `Resolved of Resolved_reference.parent + (* Parent of fields and constructor. Can be either a type or [signature] *) + and fragment_type_parent = + [ `Resolved of Resolved_reference.fragment_type_parent | `Root of string * tag_parent | `Dot of label_parent * string | `Module of signature * ModuleName.t | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t ] - (** @canonical Odoc_model.Paths.Reference.Parent.t *) + (** @canonical Odoc_model.Paths.Reference.FragmentTypeParent.t *) and label_parent = [ `Resolved of Resolved_reference.label_parent @@ -664,7 +669,7 @@ module rec Reference : sig [ `Resolved of Resolved_reference.constructor | `Root of string * [ `TConstructor | `TExtension | `TException | `TUnknown ] | `Dot of label_parent * string - | `Constructor of parent * ConstructorName.t + | `Constructor of fragment_type_parent * ConstructorName.t | `Extension of signature * ExtensionName.t | `Exception of signature * ExceptionName.t ] (** @canonical Odoc_model.Paths.Reference.Constructor.t *) @@ -673,7 +678,7 @@ module rec Reference : sig [ `Resolved of Resolved_reference.field | `Root of string * [ `TField | `TUnknown ] | `Dot of label_parent * string - | `Field of parent * FieldName.t ] + | `Field of fragment_type_parent * FieldName.t ] (** @canonical Odoc_model.Paths.Reference.Field.t *) type extension = @@ -754,8 +759,8 @@ module rec Reference : sig | `Module of signature * ModuleName.t | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t - | `Constructor of parent * ConstructorName.t - | `Field of parent * FieldName.t + | `Constructor of fragment_type_parent * ConstructorName.t + | `Field of fragment_type_parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t | `Exception of signature * ExceptionName.t @@ -803,16 +808,18 @@ and Resolved_reference : sig | `ClassType of signature * ClassTypeName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.ClassSignature.t *) - (* parent is [ signature | class_signature ] *) - and parent = - [ `Identifier of Identifier.parent + (* fragment_type_parent in resolved references is for record fields parent. + It’s type (for usual record fields) or [signature] for fields of inline + records of extension constructor. *) + and fragment_type_parent = + [ `Identifier of Identifier.fragment_type_parent | `Alias of Resolved_path.module_ * module_ | `AliasModuleType of Resolved_path.module_type * module_type | `Module of signature * ModuleName.t | `Hidden of module_ | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t ] - (** @canonical Odoc_model.Paths.Reference.Resolved.Parent.t *) + (** @canonical Odoc_model.Paths.Reference.Resolved.FragmentTypeParent.t *) (* The only difference between parent and label_parent is that the Identifier allows more types *) @@ -850,7 +857,7 @@ and Resolved_reference : sig type field = [ `Identifier of Identifier.reference_field - | `Field of parent * FieldName.t ] + | `Field of fragment_type_parent * FieldName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.Field.t *) type extension = @@ -917,7 +924,7 @@ and Resolved_reference : sig | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t | `Constructor of datatype * ConstructorName.t - | `Field of parent * FieldName.t + | `Field of fragment_type_parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t * ExtensionName.t | `Exception of signature * ExceptionName.t diff --git a/src/model/reference.ml b/src/model/reference.ml index 33624a334d..1f9b98c5a6 100644 --- a/src/model/reference.ml +++ b/src/model/reference.ml @@ -214,7 +214,7 @@ let parse whole_reference_location s : | _ -> expected [ "module"; "module-type" ] location |> Error.raise_exception) - and parent (kind, identifier, location) tokens : Parent.t = + and parent (kind, identifier, location) tokens : FragmentTypeParent.t = let kind = match_reference_kind location kind in match tokens with | [] -> ( diff --git a/src/xref2/env.ml b/src/xref2/env.ml index 9928691d4f..47a888907d 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -301,7 +301,7 @@ let add_type (identifier : Identifier.Type.t) t env = and add_field env (field : TypeDecl.Field.t) = let ident = Paths.Identifier.Mk.field - ( (identifier :> Paths.Identifier.Parent.t), + ( (identifier :> Paths.Identifier.FragmentTypeParent.t), FieldName.make_std field.name ) in add_to_elts Kind_Field ident (`Field (ident, field)) env diff --git a/src/xref2/ident.ml b/src/xref2/ident.ml index dfee7a4956..8028c887a5 100644 --- a/src/xref2/ident.ml +++ b/src/xref2/ident.ml @@ -141,7 +141,7 @@ module Of_Identifier = struct | `Type (_, n) -> `LType (n, i) | `CoreType _n -> failwith "Bad" - let parent : Parent.t -> parent = + let parent : FragmentTypeParent.t -> parent = fun p -> match p with | { iv = #Signature.t_pv; _ } as s -> (signature s :> parent) @@ -152,7 +152,7 @@ module Of_Identifier = struct match p with | { iv = #ClassSignature.t_pv; _ } as s -> (class_signature s :> label_parent) - | { iv = #Parent.t_pv; _ } as s -> (parent s :> label_parent) + | { iv = #FragmentTypeParent.t_pv; _ } as s -> (parent s :> label_parent) | { iv = `Page (_, n); _ } -> `LPage (n, fresh_int ()) | { iv = `LeafPage (_, n); _ } -> `LLeafPage (n, fresh_int ()) diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index 6dae535405..828b569534 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -711,7 +711,9 @@ and extension_constructor map parent c = locs = c.locs; doc = docs (parent :> Identifier.LabelParent.t) c.doc; args = - type_decl_constructor_argument map (parent :> Identifier.Parent.t) c.args; + type_decl_constructor_argument map + (parent :> Identifier.FragmentTypeParent.t) + c.args; res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) c.res; } @@ -767,11 +769,15 @@ and mty_substitution map identifier = function | TypeEq (frag, eqn) -> TypeEq ( Path.type_fragment map frag, - type_decl_equation map (identifier :> Identifier.Parent.t) eqn ) + type_decl_equation map + (identifier :> Identifier.FragmentTypeParent.t) + eqn ) | TypeSubst (frag, eqn) -> TypeSubst ( Path.type_fragment map frag, - type_decl_equation map (identifier :> Identifier.Parent.t) eqn ) + type_decl_equation map + (identifier :> Identifier.FragmentTypeParent.t) + eqn ) | ModuleTypeEq (frag, eqn) -> ModuleTypeEq (Path.module_type_fragment map frag, module_type_expr map identifier eqn) @@ -888,7 +894,7 @@ and module_type_substitution : and type_decl_constructor_argument : maps -> - Paths.Identifier.Parent.t -> + Paths.Identifier.FragmentTypeParent.t -> Component.TypeDecl.Constructor.argument -> Odoc_model.Lang.TypeDecl.Constructor.argument = fun map parent a -> @@ -896,11 +902,14 @@ and type_decl_constructor_argument : | Tuple ls -> Tuple (List.map (type_expr map (parent :> Identifier.LabelParent.t)) ls) | Record fs -> - Record (List.map (type_decl_field map (parent :> Identifier.Parent.t)) fs) + Record + (List.map + (type_decl_field map (parent :> Identifier.FragmentTypeParent.t)) + fs) and type_decl_field : maps -> - Identifier.Parent.t -> + Identifier.FragmentTypeParent.t -> Component.TypeDecl.Field.t -> Odoc_model.Lang.TypeDecl.Field.t = fun map parent f -> @@ -912,7 +921,7 @@ and type_decl_field : type_ = type_expr map (parent :> Identifier.LabelParent.t) f.type_; } -and type_decl_equation map (parent : Identifier.Parent.t) +and type_decl_equation map (parent : Identifier.FragmentTypeParent.t) (eqn : Component.TypeDecl.Equation.t) : Odoc_model.Lang.TypeDecl.Equation.t = let parent = (parent :> Identifier.LabelParent.t) in @@ -932,7 +941,10 @@ and type_decl map parent id (t : Component.TypeDecl.t) : { id = identifier; locs = t.locs; - equation = type_decl_equation map (parent :> Identifier.Parent.t) t.equation; + equation = + type_decl_equation map + (parent :> Identifier.FragmentTypeParent.t) + t.equation; doc = docs (parent :> Identifier.LabelParent.t) t.doc; canonical = t.canonical; representation = @@ -947,7 +959,8 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : | Record fs -> Record (List.map - (type_decl_field map (id :> Odoc_model.Paths.Identifier.Parent.t)) + (type_decl_field map + (id :> Odoc_model.Paths.Identifier.FragmentTypeParent.t)) fs) and type_decl_constructor : @@ -963,7 +976,10 @@ and type_decl_constructor : { id = identifier; doc = docs parent t.doc; - args = type_decl_constructor_argument map (id :> Identifier.Parent.t) t.args; + args = + type_decl_constructor_argument map + (id :> Identifier.FragmentTypeParent.t) + t.args; res = Opt.map (type_expr map parent) t.res; } @@ -1055,7 +1071,9 @@ and exception_ map parent id (e : Component.Exception.t) : locs = e.locs; doc = docs (parent :> Identifier.LabelParent.t) e.doc; args = - type_decl_constructor_argument map (parent :> Identifier.Parent.t) e.args; + type_decl_constructor_argument map + (parent :> Identifier.FragmentTypeParent.t) + e.args; res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) e.res; } diff --git a/src/xref2/lang_of.mli b/src/xref2/lang_of.mli index 83b4ab6e04..c962b37535 100644 --- a/src/xref2/lang_of.mli +++ b/src/xref2/lang_of.mli @@ -186,19 +186,19 @@ val simple_expansion : val type_decl_constructor_argument : maps -> - Identifier.Parent.t -> + Identifier.FragmentTypeParent.t -> Component.TypeDecl.Constructor.argument -> Odoc_model.Lang.TypeDecl.Constructor.argument val type_decl_field : maps -> - Identifier.Parent.t -> + Identifier.FragmentTypeParent.t -> Component.TypeDecl.Field.t -> Odoc_model.Lang.TypeDecl.Field.t val type_decl_equation : maps -> - Identifier.Parent.t -> + Identifier.FragmentTypeParent.t -> Component.TypeDecl.Equation.t -> Odoc_model.Lang.TypeDecl.Equation.t diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 70843fdeb9..3fd6131e18 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -921,7 +921,7 @@ and type_decl : Env.t -> Id.Signature.t -> TypeDecl.t -> TypeDecl.t = try Expand_tools.collapse_eqns default.equation (Lang_of.type_decl_equation (Lang_of.empty ()) - (parent :> Id.Parent.t) + (parent :> Id.FragmentTypeParent.t) t'.equation) params with _ -> default.equation diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index 594e8ffa1a..75798070d2 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -486,18 +486,21 @@ module F = struct find_ambiguous Find.any_in_type_in_sig sg name_s >>= function | `In_type (_, _, `FConstructor _) -> got_a_constructor name_s | `In_type (typ_name, _, `FField _) -> - Ok (`Field ((`Type (parent', typ_name) :> Resolved.Parent.t), name)) - ) + Ok + (`Field + ( (`Type (parent', typ_name) :> Resolved.FragmentTypeParent.t), + name ))) | `T (parent', t) -> ( find Find.any_in_type t name_s >>= function | `FConstructor _ -> got_a_constructor name_s - | `FField _ -> Ok (`Field ((parent' :> Resolved.Parent.t), name))) + | `FField _ -> + Ok (`Field ((parent' :> Resolved.FragmentTypeParent.t), name))) | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = Ok (`Field - ( (parent : Resolved.DataType.t :> Resolved.Parent.t), + ( (parent : Resolved.DataType.t :> Resolved.FragmentTypeParent.t), FieldName.make_std name )) end @@ -812,7 +815,8 @@ let resolve_reference = | `Dot (parent, name) -> resolve_reference_dot env parent name | `Root (name, `TConstructor) -> CS.in_env env name >>= resolved1 | `Constructor (parent, name) -> - resolve_label_parent_reference env (parent : Parent.t :> LabelParent.t) + resolve_label_parent_reference env + (parent : FragmentTypeParent.t :> LabelParent.t) >>= fun p -> CS.in_parent env p name >>= resolved1 | `Root (name, `TException) -> EX.in_env env name >>= resolved1 | `Exception (parent, name) -> @@ -828,7 +832,8 @@ let resolve_reference = ED.in_signature env p name >>= resolved1 | `Root (name, `TField) -> F.in_env env name >>= resolved1 | `Field (parent, name) -> - resolve_label_parent_reference env (parent : Parent.t :> LabelParent.t) + resolve_label_parent_reference env + (parent : FragmentTypeParent.t :> LabelParent.t) >>= fun p -> F.in_parent env p name >>= resolved1 | `Root (name, `TMethod) -> MM.in_env env name >>= resolved1 | `Method (parent, name) -> From 725d90098826840ee2eba9a2e17558a73dc1653e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 29 Mar 2023 10:54:14 +0200 Subject: [PATCH 06/35] renaming fragment_type_parent to field_parent in resolved ref and id since they are not used in resolved ref and id of cosntructor: for those, the parent is a type. Signed-off-by: Paul-Elliot --- src/loader/cmi.ml | 8 ++++---- src/loader/cmti.ml | 8 ++++---- src/model/paths.ml | 29 ++++++++++++++--------------- src/model/paths.mli | 14 +++++++------- src/model/paths_types.ml | 25 ++++++++++++------------- src/xref2/env.ml | 2 +- src/xref2/ident.ml | 4 ++-- src/xref2/lang_of.ml | 32 +++++++++++--------------------- src/xref2/lang_of.mli | 6 +++--- src/xref2/link.ml | 2 +- src/xref2/ref_tools.ml | 8 +++----- 11 files changed, 62 insertions(+), 76 deletions(-) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index aabeff262d..88576665ae 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -632,7 +632,7 @@ let read_constructor_declaration env parent cd = let doc = Doc_attr.attached_no_tag container cd.cd_attributes in let args = read_constructor_declaration_arguments env - (parent :> Identifier.FragmentTypeParent.t) cd.cd_args + (parent :> Identifier.FieldParent.t) cd.cd_args in let res = opt_map (read_type_expr env) cd.cd_res in {id; doc; args; res} @@ -652,7 +652,7 @@ let read_type_kind env parent = | Type_record(lbls, _) -> let lbls = List.map - (read_label_declaration env (parent :> Identifier.FragmentTypeParent.t)) + (read_label_declaration env (parent :> Identifier.FieldParent.t)) lbls in Some (Record lbls) @@ -745,7 +745,7 @@ let read_extension_constructor env parent id ext = let doc = Doc_attr.attached_no_tag container ext.ext_attributes in let args = read_constructor_declaration_arguments env - (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) ext.ext_args + (parent : Identifier.Signature.t :> Identifier.FieldParent.t) ext.ext_args in let res = opt_map (read_type_expr env) ext.ext_ret_type in {id; locs; doc; args; res} @@ -779,7 +779,7 @@ let read_exception env parent id ext = mark_exception ext; let args = read_constructor_declaration_arguments env - (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) ext.ext_args + (parent : Identifier.Signature.t :> Identifier.FieldParent.t) ext.ext_args in let res = opt_map (read_type_expr env) ext.ext_ret_type in {id; locs; doc; args; res} diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 8ea332f11d..b7108f5eda 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -214,7 +214,7 @@ let read_constructor_declaration_arguments env parent label_parent arg = let read_constructor_declaration env parent cd = let open TypeDecl.Constructor in let id = Ident_env.find_constructor_identifier env cd.cd_id in - let container = (parent :> Identifier.FragmentTypeParent.t) in + let container = (parent :> Identifier.FieldParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container cd.cd_attributes in let args = @@ -231,7 +231,7 @@ let read_type_kind env parent = let cstrs = List.map (read_constructor_declaration env parent) cstrs in Some (Variant cstrs) | Ttype_record lbls -> - let parent = (parent :> Identifier.FragmentTypeParent.t) in + let parent = (parent :> Identifier.FieldParent.t) in let label_parent = (parent :> Identifier.LabelParent.t) in let lbls = List.map (read_label_declaration env parent label_parent) lbls in @@ -292,7 +292,7 @@ let read_extension_constructor env parent ext = let open Extension.Constructor in let id = Env.find_extension_identifier env ext.ext_id in let locs = None in - let container = (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) in + let container = (parent : Identifier.Signature.t :> Identifier.FieldParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container ext.ext_attributes in match ext.ext_kind with @@ -325,7 +325,7 @@ let read_exception env parent (ext : extension_constructor) = let open Exception in let id = Env.find_exception_identifier env ext.ext_id in let locs = None in - let container = (parent : Identifier.Signature.t :> Identifier.FragmentTypeParent.t) in + let container = (parent : Identifier.Signature.t :> Identifier.FieldParent.t) in let label_container = (container :> Identifier.LabelParent.t) in let doc = Doc_attr.attached_no_tag label_container ext.ext_attributes in match ext.ext_kind with diff --git a/src/model/paths.ml b/src/model/paths.ml index 38a4e338e2..1d9e9c7193 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -166,7 +166,7 @@ module Identifier = struct | { iv = `Method (p, _); _ } | { iv = `InstanceVariable (p, _); _ } -> (p : class_signature :> label_parent) | { iv = `Constructor (p, _); _ } -> (p : datatype :> label_parent) - | { iv = `Field (p, _); _ } -> (p : fragment_type_parent :> label_parent) + | { iv = `Field (p, _); _ } -> (p : field_parent :> label_parent) let label_parent n = label_parent_aux (n :> Id.non_src) @@ -217,9 +217,9 @@ module Identifier = struct type t_pv = Id.datatype_pv end - module FragmentTypeParent = struct - type t = Paths_types.Identifier.fragment_type_parent - type t_pv = Paths_types.Identifier.fragment_type_parent_pv + module FieldParent = struct + type t = Paths_types.Identifier.field_parent + type t_pv = Paths_types.Identifier.field_parent_pv end module LabelParent = struct @@ -578,8 +578,8 @@ module Identifier = struct `Constructor (p, n)) let field : - FragmentTypeParent.t * FieldName.t -> - [> `Field of FragmentTypeParent.t * FieldName.t ] id = + FieldParent.t * FieldName.t -> + [> `Field of FieldParent.t * FieldName.t ] id = mk_parent FieldName.to_string "fld" (fun (p, n) -> `Field (p, n)) let extension : @@ -992,14 +992,13 @@ module Reference = struct | `ClassType (sg, s) -> Identifier.Mk.class_type (parent_signature_identifier sg, s) - and parent_identifier : - fragment_type_parent -> Identifier.FragmentTypeParent.t = function + and field_parent_identifier : field_parent -> Identifier.FieldParent.t = + function | `Identifier id -> id | (`Hidden _ | `Alias _ | `AliasModuleType _ | `Module _ | `ModuleType _) as sg -> - (parent_signature_identifier sg :> Identifier.FragmentTypeParent.t) - | `Type _ as t -> - (parent_type_identifier t :> Identifier.FragmentTypeParent.t) + (parent_signature_identifier sg :> Identifier.FieldParent.t) + | `Type _ as t -> (parent_type_identifier t :> Identifier.FieldParent.t) and label_parent_identifier : label_parent -> Identifier.LabelParent.t = function @@ -1008,14 +1007,14 @@ module Reference = struct (parent_class_signature_identifier c :> Identifier.LabelParent.t) | ( `Hidden _ | `Alias _ | `AliasModuleType _ | `Module _ | `ModuleType _ | `Type _ ) as r -> - (parent_identifier r :> Identifier.LabelParent.t) + (field_parent_identifier r :> Identifier.LabelParent.t) and identifier : t -> Identifier.t = function | `Identifier id -> id | ( `Alias _ | `AliasModuleType _ | `Module _ | `Hidden _ | `Type _ | `Class _ | `ClassType _ | `ModuleType _ ) as r -> (label_parent_identifier r :> Identifier.t) - | `Field (p, n) -> Identifier.Mk.field (parent_identifier p, n) + | `Field (p, n) -> Identifier.Mk.field (field_parent_identifier p, n) | `Constructor (s, n) -> Identifier.Mk.constructor ((parent_type_identifier s :> Identifier.DataType.t), n) @@ -1045,8 +1044,8 @@ module Reference = struct type t = Paths_types.Resolved_reference.datatype end - module FragmentTypeParent = struct - type t = Paths_types.Resolved_reference.fragment_type_parent + module FieldParent = struct + type t = Paths_types.Resolved_reference.field_parent end module LabelParent = struct diff --git a/src/model/paths.mli b/src/model/paths.mli index b1c0fd8af5..bf0b7b1bab 100644 --- a/src/model/paths.mli +++ b/src/model/paths.mli @@ -79,9 +79,9 @@ module Identifier : sig type t = Id.datatype type t_pv = Id.datatype_pv end - module FragmentTypeParent : sig - type t = Id.fragment_type_parent - type t_pv = Id.fragment_type_parent_pv + module FieldParent : sig + type t = Id.field_parent + type t_pv = Id.field_parent_pv end module FunctorResult : sig @@ -294,8 +294,8 @@ module Identifier : sig [> `Constructor of DataType.t * ConstructorName.t ] id val field : - FragmentTypeParent.t * FieldName.t -> - [> `Field of FragmentTypeParent.t * FieldName.t ] id + FieldParent.t * FieldName.t -> + [> `Field of FieldParent.t * FieldName.t ] id val extension : Signature.t * ExtensionName.t -> @@ -508,8 +508,8 @@ module rec Reference : sig type t = Paths_types.Resolved_reference.datatype end - module FragmentTypeParent : sig - type t = Paths_types.Resolved_reference.fragment_type_parent + module FieldParent : sig + type t = Paths_types.Resolved_reference.field_parent end module LabelParent : sig diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index 58e9dc969e..75c58f26ae 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -81,17 +81,16 @@ module Identifier = struct and datatype = datatype_pv id (** @canonical Odoc_model.Paths.Identifier.DataType.t *) - type fragment_type_parent_pv = [ signature_pv | datatype_pv ] - (** @canonical Odoc_model.Paths.Identifier.FragmentTypeParent.t_pv *) + type field_parent_pv = [ signature_pv | datatype_pv ] + (** @canonical Odoc_model.Paths.Identifier.FieldParent.t_pv *) (* fragment_type_parent in identifiers is for record fields parent. It’s type (for usual record fields) or [signature] for fields of inline records of extension constructor. *) - and fragment_type_parent = fragment_type_parent_pv id - (** @canonical Odoc_model.Paths.Identifier.FragmentTypeParent.t *) + and field_parent = field_parent_pv id + (** @canonical Odoc_model.Paths.Identifier.FieldParent.t *) - type label_parent_pv = - [ fragment_type_parent_pv | page_pv | class_signature_pv ] + type label_parent_pv = [ field_parent_pv | page_pv | class_signature_pv ] (** @canonical Odoc_model.Paths.Identifier.LabelParent.t_pv *) and label_parent = label_parent_pv id @@ -142,7 +141,7 @@ module Identifier = struct and constructor = constructor_pv id (** @canonical Odoc_model.Paths.Identifier.Constructor.t *) - type field_pv = [ `Field of fragment_type_parent * FieldName.t ] + type field_pv = [ `Field of field_parent * FieldName.t ] (** @canonical Odoc_model.Paths.Identifier.Field.t_pv *) and field = field_pv id @@ -210,7 +209,7 @@ module Identifier = struct [ signature_pv | class_signature_pv | datatype_pv - | fragment_type_parent_pv + | field_parent_pv | label_parent_pv | module_pv | functor_parameter_pv @@ -623,7 +622,7 @@ module rec Reference : sig (* Parent of fields and constructor. Can be either a type or [signature] *) and fragment_type_parent = - [ `Resolved of Resolved_reference.fragment_type_parent + [ `Resolved of Resolved_reference.field_parent | `Root of string * tag_parent | `Dot of label_parent * string | `Module of signature * ModuleName.t @@ -811,8 +810,8 @@ and Resolved_reference : sig (* fragment_type_parent in resolved references is for record fields parent. It’s type (for usual record fields) or [signature] for fields of inline records of extension constructor. *) - and fragment_type_parent = - [ `Identifier of Identifier.fragment_type_parent + and field_parent = + [ `Identifier of Identifier.field_parent | `Alias of Resolved_path.module_ * module_ | `AliasModuleType of Resolved_path.module_type * module_type | `Module of signature * ModuleName.t @@ -857,7 +856,7 @@ and Resolved_reference : sig type field = [ `Identifier of Identifier.reference_field - | `Field of fragment_type_parent * FieldName.t ] + | `Field of field_parent * FieldName.t ] (** @canonical Odoc_model.Paths.Reference.Resolved.Field.t *) type extension = @@ -924,7 +923,7 @@ and Resolved_reference : sig | `ModuleType of signature * ModuleTypeName.t | `Type of signature * TypeName.t | `Constructor of datatype * ConstructorName.t - | `Field of fragment_type_parent * FieldName.t + | `Field of field_parent * FieldName.t | `Extension of signature * ExtensionName.t | `ExtensionDecl of signature * ExtensionName.t * ExtensionName.t | `Exception of signature * ExceptionName.t diff --git a/src/xref2/env.ml b/src/xref2/env.ml index 47a888907d..e7330ebd43 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -301,7 +301,7 @@ let add_type (identifier : Identifier.Type.t) t env = and add_field env (field : TypeDecl.Field.t) = let ident = Paths.Identifier.Mk.field - ( (identifier :> Paths.Identifier.FragmentTypeParent.t), + ( (identifier :> Paths.Identifier.FieldParent.t), FieldName.make_std field.name ) in add_to_elts Kind_Field ident (`Field (ident, field)) env diff --git a/src/xref2/ident.ml b/src/xref2/ident.ml index 8028c887a5..65adeb2bf3 100644 --- a/src/xref2/ident.ml +++ b/src/xref2/ident.ml @@ -141,7 +141,7 @@ module Of_Identifier = struct | `Type (_, n) -> `LType (n, i) | `CoreType _n -> failwith "Bad" - let parent : FragmentTypeParent.t -> parent = + let field_parent : FieldParent.t -> parent = fun p -> match p with | { iv = #Signature.t_pv; _ } as s -> (signature s :> parent) @@ -152,7 +152,7 @@ module Of_Identifier = struct match p with | { iv = #ClassSignature.t_pv; _ } as s -> (class_signature s :> label_parent) - | { iv = #FragmentTypeParent.t_pv; _ } as s -> (parent s :> label_parent) + | { iv = #FieldParent.t_pv; _ } as s -> (field_parent s :> label_parent) | { iv = `Page (_, n); _ } -> `LPage (n, fresh_int ()) | { iv = `LeafPage (_, n); _ } -> `LLeafPage (n, fresh_int ()) diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index 828b569534..3a40397c4b 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -712,7 +712,7 @@ and extension_constructor map parent c = doc = docs (parent :> Identifier.LabelParent.t) c.doc; args = type_decl_constructor_argument map - (parent :> Identifier.FragmentTypeParent.t) + (parent :> Identifier.FieldParent.t) c.args; res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) c.res; } @@ -769,15 +769,11 @@ and mty_substitution map identifier = function | TypeEq (frag, eqn) -> TypeEq ( Path.type_fragment map frag, - type_decl_equation map - (identifier :> Identifier.FragmentTypeParent.t) - eqn ) + type_decl_equation map (identifier :> Identifier.FieldParent.t) eqn ) | TypeSubst (frag, eqn) -> TypeSubst ( Path.type_fragment map frag, - type_decl_equation map - (identifier :> Identifier.FragmentTypeParent.t) - eqn ) + type_decl_equation map (identifier :> Identifier.FieldParent.t) eqn ) | ModuleTypeEq (frag, eqn) -> ModuleTypeEq (Path.module_type_fragment map frag, module_type_expr map identifier eqn) @@ -894,7 +890,7 @@ and module_type_substitution : and type_decl_constructor_argument : maps -> - Paths.Identifier.FragmentTypeParent.t -> + Paths.Identifier.FieldParent.t -> Component.TypeDecl.Constructor.argument -> Odoc_model.Lang.TypeDecl.Constructor.argument = fun map parent a -> @@ -903,13 +899,11 @@ and type_decl_constructor_argument : Tuple (List.map (type_expr map (parent :> Identifier.LabelParent.t)) ls) | Record fs -> Record - (List.map - (type_decl_field map (parent :> Identifier.FragmentTypeParent.t)) - fs) + (List.map (type_decl_field map (parent :> Identifier.FieldParent.t)) fs) and type_decl_field : maps -> - Identifier.FragmentTypeParent.t -> + Identifier.FieldParent.t -> Component.TypeDecl.Field.t -> Odoc_model.Lang.TypeDecl.Field.t = fun map parent f -> @@ -921,7 +915,7 @@ and type_decl_field : type_ = type_expr map (parent :> Identifier.LabelParent.t) f.type_; } -and type_decl_equation map (parent : Identifier.FragmentTypeParent.t) +and type_decl_equation map (parent : Identifier.FieldParent.t) (eqn : Component.TypeDecl.Equation.t) : Odoc_model.Lang.TypeDecl.Equation.t = let parent = (parent :> Identifier.LabelParent.t) in @@ -942,9 +936,7 @@ and type_decl map parent id (t : Component.TypeDecl.t) : id = identifier; locs = t.locs; equation = - type_decl_equation map - (parent :> Identifier.FragmentTypeParent.t) - t.equation; + type_decl_equation map (parent :> Identifier.FieldParent.t) t.equation; doc = docs (parent :> Identifier.LabelParent.t) t.doc; canonical = t.canonical; representation = @@ -960,7 +952,7 @@ and type_decl_representation map id (t : Component.TypeDecl.Representation.t) : Record (List.map (type_decl_field map - (id :> Odoc_model.Paths.Identifier.FragmentTypeParent.t)) + (id :> Odoc_model.Paths.Identifier.FieldParent.t)) fs) and type_decl_constructor : @@ -977,9 +969,7 @@ and type_decl_constructor : id = identifier; doc = docs parent t.doc; args = - type_decl_constructor_argument map - (id :> Identifier.FragmentTypeParent.t) - t.args; + type_decl_constructor_argument map (id :> Identifier.FieldParent.t) t.args; res = Opt.map (type_expr map parent) t.res; } @@ -1072,7 +1062,7 @@ and exception_ map parent id (e : Component.Exception.t) : doc = docs (parent :> Identifier.LabelParent.t) e.doc; args = type_decl_constructor_argument map - (parent :> Identifier.FragmentTypeParent.t) + (parent :> Identifier.FieldParent.t) e.args; res = Opt.map (type_expr map (parent :> Identifier.LabelParent.t)) e.res; } diff --git a/src/xref2/lang_of.mli b/src/xref2/lang_of.mli index c962b37535..136eeba668 100644 --- a/src/xref2/lang_of.mli +++ b/src/xref2/lang_of.mli @@ -186,19 +186,19 @@ val simple_expansion : val type_decl_constructor_argument : maps -> - Identifier.FragmentTypeParent.t -> + Identifier.FieldParent.t -> Component.TypeDecl.Constructor.argument -> Odoc_model.Lang.TypeDecl.Constructor.argument val type_decl_field : maps -> - Identifier.FragmentTypeParent.t -> + Identifier.FieldParent.t -> Component.TypeDecl.Field.t -> Odoc_model.Lang.TypeDecl.Field.t val type_decl_equation : maps -> - Identifier.FragmentTypeParent.t -> + Identifier.FieldParent.t -> Component.TypeDecl.Equation.t -> Odoc_model.Lang.TypeDecl.Equation.t diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 3fd6131e18..ec9dba822f 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -921,7 +921,7 @@ and type_decl : Env.t -> Id.Signature.t -> TypeDecl.t -> TypeDecl.t = try Expand_tools.collapse_eqns default.equation (Lang_of.type_decl_equation (Lang_of.empty ()) - (parent :> Id.FragmentTypeParent.t) + (parent :> Id.FieldParent.t) t'.equation) params with _ -> default.equation diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index 75798070d2..c854d82672 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -488,19 +488,17 @@ module F = struct | `In_type (typ_name, _, `FField _) -> Ok (`Field - ( (`Type (parent', typ_name) :> Resolved.FragmentTypeParent.t), - name ))) + ((`Type (parent', typ_name) :> Resolved.FieldParent.t), name))) | `T (parent', t) -> ( find Find.any_in_type t name_s >>= function | `FConstructor _ -> got_a_constructor name_s - | `FField _ -> - Ok (`Field ((parent' :> Resolved.FragmentTypeParent.t), name))) + | `FField _ -> Ok (`Field ((parent' :> Resolved.FieldParent.t), name))) | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = Ok (`Field - ( (parent : Resolved.DataType.t :> Resolved.FragmentTypeParent.t), + ( (parent : Resolved.DataType.t :> Resolved.FieldParent.t), FieldName.make_std name )) end From c2228c09e34af2e6e3dc3855ce94d09a89993ca2 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 30 Mar 2023 07:55:51 +0200 Subject: [PATCH 07/35] invert type and datatype in Component To match the semantics of references Signed-off-by: Paul-Elliot --- src/xref2/component.ml | 8 ++++---- src/xref2/component.mli | 8 ++++---- src/xref2/env.ml | 6 +++--- src/xref2/env.mli | 4 ++-- src/xref2/ref_tools.ml | 3 +-- src/xref2/tools.ml | 12 +++++++----- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/xref2/component.ml b/src/xref2/component.ml index bdca92cf18..f135a71d28 100644 --- a/src/xref2/component.ml +++ b/src/xref2/component.ml @@ -496,7 +496,7 @@ module Element = struct type module_type = [ `ModuleType of Identifier.ModuleType.t * ModuleType.t ] - type type_ = [ `Type of Identifier.Type.t * TypeDecl.t ] + type datatype = [ `Type of Identifier.Type.t * TypeDecl.t ] type value = [ `Value of Identifier.Value.t * Value.t ] @@ -506,7 +506,7 @@ module Element = struct type class_type = [ `ClassType of Identifier.ClassType.t * ClassType.t ] - type datatype = [ type_ | class_ | class_type ] + type type_ = [ datatype | class_ | class_type ] type signature = [ module_ | module_type ] @@ -527,12 +527,12 @@ module Element = struct (* No component for pages yet *) type page = [ `Page of Identifier.Page.t * Odoc_model.Lang.Page.t ] - type label_parent = [ signature | datatype | page ] + type label_parent = [ signature | type_ | page ] type any = [ signature | value - | type_ + | datatype | label | class_ | class_type diff --git a/src/xref2/component.mli b/src/xref2/component.mli index 34261d1430..a8fab8e5f4 100644 --- a/src/xref2/component.mli +++ b/src/xref2/component.mli @@ -460,7 +460,7 @@ module Element : sig type module_type = [ `ModuleType of Identifier.ModuleType.t * ModuleType.t ] - type type_ = [ `Type of Identifier.Type.t * TypeDecl.t ] + type datatype = [ `Type of Identifier.Type.t * TypeDecl.t ] type value = [ `Value of Identifier.Value.t * Value.t ] @@ -470,7 +470,7 @@ module Element : sig type class_type = [ `ClassType of Identifier.ClassType.t * ClassType.t ] - type datatype = [ type_ | class_ | class_type ] + type type_ = [ datatype | class_ | class_type ] type signature = [ module_ | module_type ] @@ -491,12 +491,12 @@ module Element : sig (* No component for pages yet *) type page = [ `Page of Identifier.Page.t * Odoc_model.Lang.Page.t ] - type label_parent = [ signature | datatype | page ] + type label_parent = [ signature | type_ | page ] type any = [ signature | value - | type_ + | datatype | label | class_ | class_type diff --git a/src/xref2/env.ml b/src/xref2/env.ml index e7330ebd43..fa9ec6415f 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -543,12 +543,12 @@ let s_module_type : Component.Element.module_type scope = | #Component.Element.module_type as r -> Some r | _ -> None) -let s_datatype : Component.Element.datatype scope = - make_scope (function #Component.Element.datatype as r -> Some r | _ -> None) - let s_type : Component.Element.type_ scope = make_scope (function #Component.Element.type_ as r -> Some r | _ -> None) +let s_datatype : Component.Element.datatype scope = + make_scope (function #Component.Element.datatype as r -> Some r | _ -> None) + let s_class : Component.Element.class_ scope = make_scope (function #Component.Element.class_ as r -> Some r | _ -> None) diff --git a/src/xref2/env.mli b/src/xref2/env.mli index 72aa01ae48..fb9cccea36 100644 --- a/src/xref2/env.mli +++ b/src/xref2/env.mli @@ -122,10 +122,10 @@ val s_module : Component.Element.module_ scope val s_module_type : Component.Element.module_type scope -val s_datatype : Component.Element.datatype scope - val s_type : Component.Element.type_ scope +val s_datatype : Component.Element.datatype scope + val s_class : Component.Element.class_ scope val s_class_type : Component.Element.class_type scope diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index c854d82672..f5e7eafa6e 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -292,8 +292,7 @@ module T = struct | `ClassType _ as e -> `CT (CT.of_element env e) let in_env env name = - env_lookup_by_name Env.s_datatype name env >>= fun e -> - Ok (of_element env e) + env_lookup_by_name Env.s_type name env >>= fun e -> Ok (of_element env e) (* Don't handle name collisions between class, class types and type decls *) let in_signature _env ((parent', parent_cp, sg) : signature_lookup_result) diff --git a/src/xref2/tools.ml b/src/xref2/tools.ml index bbf35ecede..90d84806a4 100644 --- a/src/xref2/tools.ml +++ b/src/xref2/tools.ml @@ -52,7 +52,7 @@ let c_ty_poss env p = match p with | `Dot (p, n) -> ( let rest = List.map (fun p -> `Dot (p, n)) (c_mod_poss env p) in - match Env.lookup_by_name Env.s_type n env with + match Env.lookup_by_name Env.s_datatype n env with | Ok (`Type (id, _)) -> `Identifier ((id :> Odoc_model.Paths.Identifier.Path.Type.t), false) :: rest @@ -64,7 +64,7 @@ let c_daty_poss env p = match p with | `Dot (p, n) -> ( let rest = List.map (fun p -> `Dot (p, n)) (c_mod_poss env p) in - match Env.lookup_by_name Env.s_type n env with + match Env.lookup_by_name Env.s_datatype n env with | Ok (`Type (id, _)) -> `Identifier ((id :> Odoc_model.Paths.Identifier.Path.DataType.t), false) @@ -436,7 +436,7 @@ let simplify_type : Env.t -> Cpath.Resolved.type_ -> Cpath.Resolved.type_ = match m with | `Type (`Module (`Gpath (`Identifier p)), name) -> ( let ident = (Mk.type_ ((p :> Signature.t), name) : Path.Type.t) in - match Env.(lookup_by_id s_type (ident :> Path.Type.t) env) with + match Env.(lookup_by_id s_datatype (ident :> Path.Type.t) env) with | Some _ -> `Gpath (`Identifier ident) | None -> m) | _ -> m @@ -858,7 +858,8 @@ and lookup_type_gpath : next clause. We just look them up here in the list of core types *) Ok (`FType (name, List.assoc (TypeName.to_string name) core_types)) | `Identifier ({ iv = `Type _; _ } as i) -> - of_option ~error:(`Lookup_failureT i) (Env.(lookup_by_id s_type) i env) + of_option ~error:(`Lookup_failureT i) + (Env.(lookup_by_id s_datatype) i env) >>= fun (`Type ({ iv = `CoreType name | `Type (_, name); _ }, t)) -> Ok (`FType (name, t)) | `Identifier ({ iv = `Class _; _ } as i) -> @@ -899,7 +900,8 @@ and lookup_datatype_gpath : next clause. We just look them up here in the list of core types *) Ok (`FType (name, List.assoc (TypeName.to_string name) core_types)) | `Identifier ({ iv = `Type _; _ } as i) -> - of_option ~error:(`Lookup_failureT i) (Env.(lookup_by_id s_type) i env) + of_option ~error:(`Lookup_failureT i) + (Env.(lookup_by_id s_datatype) i env) >>= fun (`Type ({ iv = `CoreType name | `Type (_, name); _ }, t)) -> Ok (`FType (name, t)) | `CanonicalDataType (t1, _) -> lookup_datatype_gpath env t1 From b63750175446ecfaaaead8e50089e3e74e7b8345 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 30 Mar 2023 08:21:27 +0200 Subject: [PATCH 08/35] do not look for class when resolving a fragment_type_parent This changes the error message, from "wrong type", to unresolved. Signed-off-by: Paul-Elliot --- src/model/paths_types.ml | 3 +- src/xref2/component.ml | 2 + src/xref2/component.mli | 2 + src/xref2/env.ml | 5 +++ src/xref2/env.mli | 2 + src/xref2/ref_tools.ml | 68 ++++++++++++++++++++++++----- test/xref2/github_issue_447.t/run.t | 2 +- test/xref2/refs/refs.md | 6 +-- 8 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index 75c58f26ae..c14b5314f4 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -583,8 +583,7 @@ module rec Reference : sig type tag_datatype = [ `TUnknown | `TType ] - type tag_parent = - [ `TUnknown | `TModule | `TModuleType | `TClass | `TClassType | `TType ] + type tag_parent = [ `TUnknown | `TModule | `TModuleType | `TType ] type tag_label_parent = [ `TUnknown diff --git a/src/xref2/component.ml b/src/xref2/component.ml index f135a71d28..5ccfaa4655 100644 --- a/src/xref2/component.ml +++ b/src/xref2/component.ml @@ -529,6 +529,8 @@ module Element = struct type label_parent = [ signature | type_ | page ] + type fragment_type_parent = [ signature | datatype ] + type any = [ signature | value diff --git a/src/xref2/component.mli b/src/xref2/component.mli index a8fab8e5f4..ca945cb8f3 100644 --- a/src/xref2/component.mli +++ b/src/xref2/component.mli @@ -493,6 +493,8 @@ module Element : sig type label_parent = [ signature | type_ | page ] + type fragment_type_parent = [ signature | datatype ] + type any = [ signature | value diff --git a/src/xref2/env.ml b/src/xref2/env.ml index fa9ec6415f..a0cb34a970 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -592,6 +592,11 @@ let s_label_parent : Component.Element.label_parent scope = | #Component.Element.label_parent as r -> Some r | _ -> None) +let s_fragment_type_parent : Component.Element.fragment_type_parent scope = + make_scope ~root:lookup_root_module_fallback (function + | #Component.Element.fragment_type_parent as r -> Some r + | _ -> None) + let len = ref 0 let n = ref 0 diff --git a/src/xref2/env.mli b/src/xref2/env.mli index fb9cccea36..8be6e82135 100644 --- a/src/xref2/env.mli +++ b/src/xref2/env.mli @@ -144,6 +144,8 @@ val s_field : Component.Element.field scope val s_label_parent : Component.Element.label_parent scope +val s_fragment_type_parent : Component.Element.fragment_type_parent scope + (* val open_component_signature : Paths_types.Identifier.signature -> Component.Signature.t -> t -> t *) diff --git a/src/xref2/ref_tools.ml b/src/xref2/ref_tools.ml index f5e7eafa6e..e838726abb 100644 --- a/src/xref2/ref_tools.ml +++ b/src/xref2/ref_tools.ml @@ -30,6 +30,9 @@ type label_parent_lookup_result = | type_lookup_result | `P of page_lookup_result ] +type fragment_type_parent_lookup_result = + [ `S of signature_lookup_result | `T of datatype_lookup_result ] + type 'a ref_result = ('a, Errors.Tools_error.reference_lookup_error) Result.result (** The result type for every functions in this module. *) @@ -279,6 +282,16 @@ module DT = struct let of_component _env t ~parent_ref name = Ok (`Type (parent_ref, name), t) let of_element _env (`Type (id, t)) : t = (`Identifier id, t) + + let in_env env name = + env_lookup_by_name Env.s_datatype name env >>= fun e -> + Ok (of_element env e) + + let in_signature _env ((parent', parent_cp, sg) : signature_lookup_result) + name = + let sg = Tools.prefix_signature (parent_cp, sg) in + find Find.datatype_in_sig sg name >>= function + | `FType (name, t) -> Ok (`T (`Type (parent', name), t)) end module T = struct @@ -429,6 +442,24 @@ module EX = struct Ok (`Exception (parent', name)) end +module FTP = struct + (** Fragment type parent *) + + type t = fragment_type_parent_lookup_result + + let of_element env : _ -> t ref_result = function + | `Module _ as e -> + M.of_element env e |> module_lookup_to_signature_lookup env >>= fun r -> + Ok (`S r) + | `ModuleType _ as e -> + MT.of_element env e |> module_type_lookup_to_signature_lookup env + >>= fun r -> Ok (`S r) + | `Type _ as e -> Ok (`T (DT.of_element env e)) + + let in_env env name = + env_lookup_by_name Env.s_fragment_type_parent name env >>= of_element env +end + module CS = struct (** Constructor *) @@ -442,7 +473,7 @@ module CS = struct (* Let's pretend we didn't see the field and say we didn't find anything. *) Error (`Find_by_name (`Cons, name)) - let in_parent _env (parent : label_parent_lookup_result) name = + let in_parent _env (parent : fragment_type_parent_lookup_result) name = let name_s = ConstructorName.to_string name in match parent with | `S (parent', parent_cp, sg) -> ( @@ -456,7 +487,6 @@ module CS = struct | `FField _ -> got_a_field name_s | `FConstructor _ -> Ok (`Constructor ((parent' : Resolved.DataType.t), name))) - | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = Ok @@ -477,7 +507,7 @@ module F = struct (* Let's pretend we didn't see the constructor and say we didn't find anything. *) Error (`Find_by_name (`Field, name)) - let in_parent _env (parent : label_parent_lookup_result) name = + let in_parent _env (parent : fragment_type_parent_lookup_result) name = let name_s = FieldName.to_string name in match parent with | `S (parent', parent_cp, sg) -> ( @@ -492,7 +522,6 @@ module F = struct find Find.any_in_type t name_s >>= function | `FConstructor _ -> got_a_constructor name_s | `FField _ -> Ok (`Field ((parent' :> Resolved.FieldParent.t), name))) - | (`C _ | `CT _ | `P _) as r -> wrong_kind_error [ `S; `T ] r let of_component _env parent name = Ok @@ -624,6 +653,27 @@ let rec resolve_label_parent_reference env r = resolve_signature_reference env (`Root (name, `TModule)) >>= fun s -> Ok (`S s) +and resolve_fragment_type_parent_reference (env : Env.t) + (r : FragmentTypeParent.t) : (fragment_type_parent_lookup_result, _) result + = + let fragment_type_parent_res_of_type_res : datatype_lookup_result -> _ = + fun r -> Ok (`T r) + in + match r with + | `Resolved _ -> failwith "unimplemented" + | `Root (name, `TUnknown) -> FTP.in_env env name + | (`Module _ | `ModuleType _ | `Root (_, (`TModule | `TModuleType))) as sr -> + resolve_signature_reference env sr >>= fun s -> Ok (`S s) + | `Root (name, `TType) -> + DT.in_env env name >>= fragment_type_parent_res_of_type_res + | `Type (parent, name) -> + resolve_signature_reference env parent >>= fun p -> + DT.in_signature env p (TypeName.to_string name) + | `Dot (parent, name) -> + resolve_label_parent_reference env parent + >>= signature_lookup_result_of_label_parent + >>= fun p -> DT.in_signature env p name + and resolve_signature_reference : Env.t -> Signature.t -> signature_lookup_result ref_result = fun env' r -> @@ -812,9 +862,8 @@ let resolve_reference = | `Dot (parent, name) -> resolve_reference_dot env parent name | `Root (name, `TConstructor) -> CS.in_env env name >>= resolved1 | `Constructor (parent, name) -> - resolve_label_parent_reference env - (parent : FragmentTypeParent.t :> LabelParent.t) - >>= fun p -> CS.in_parent env p name >>= resolved1 + resolve_fragment_type_parent_reference env parent >>= fun p -> + CS.in_parent env p name >>= resolved1 | `Root (name, `TException) -> EX.in_env env name >>= resolved1 | `Exception (parent, name) -> resolve_signature_reference env parent >>= fun p -> @@ -829,9 +878,8 @@ let resolve_reference = ED.in_signature env p name >>= resolved1 | `Root (name, `TField) -> F.in_env env name >>= resolved1 | `Field (parent, name) -> - resolve_label_parent_reference env - (parent : FragmentTypeParent.t :> LabelParent.t) - >>= fun p -> F.in_parent env p name >>= resolved1 + resolve_fragment_type_parent_reference env parent >>= fun p -> + F.in_parent env p name >>= resolved1 | `Root (name, `TMethod) -> MM.in_env env name >>= resolved1 | `Method (parent, name) -> resolve_class_signature_reference env parent >>= fun p -> diff --git a/test/xref2/github_issue_447.t/run.t b/test/xref2/github_issue_447.t/run.t index 9e9382af34..5b89e1c8e8 100644 --- a/test/xref2/github_issue_447.t/run.t +++ b/test/xref2/github_issue_447.t/run.t @@ -10,7 +10,7 @@ faulty reference. $ odoc link a.odoc File "a.mli", line 15, characters 4-22: - Warning: Failed to resolve reference unresolvedroot(t).A is of kind class but expected signature or type + Warning: Failed to resolve reference unresolvedroot(t).A Couldn't find "t" Let's now check that the reference point to the right page/anchor: diff --git a/test/xref2/refs/refs.md b/test/xref2/refs/refs.md index 18e7972955..cbc5bb2229 100644 --- a/test/xref2/refs/refs.md +++ b/test/xref2/refs/refs.md @@ -2683,11 +2683,9 @@ Failure Exception: Failure "resolve_reference: is of kind type but expected class or class type". # resolve_ref "c.constructor-C" (* Type in env but find class (parent of constructor is "parent") *) ;; -Exception: -Failure "resolve_reference: is of kind class but expected signature or type". +Exception: Failure "resolve_reference: Couldn't find \"c\"". # resolve_ref "c.field-f" (* Field in class (parent of field is "label_parent") *) ;; -Exception: -Failure "resolve_reference: is of kind class but expected signature or type". +Exception: Failure "resolve_reference: Couldn't find \"c\"". ``` ## Ambiguous references From c2c16a47082464659bef30d63b8a536b9c2aed3e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 6 Dec 2023 10:04:03 +0100 Subject: [PATCH 09/35] Improve test for omitted type in constructor parent Signed-off-by: Paul-Elliot --- test/xref2/github_issue_447.t/a.mli | 2 +- test/xref2/github_issue_447.t/run.t | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/xref2/github_issue_447.t/a.mli b/test/xref2/github_issue_447.t/a.mli index 9bd7d30a3b..6122752420 100644 --- a/test/xref2/github_issue_447.t/a.mli +++ b/test/xref2/github_issue_447.t/a.mli @@ -1,6 +1,6 @@ type u = Foo -(** {!constructor-Foo} {!u.constructor-Foo} *) +(** {!constructor-Foo} {!u.constructor-Foo} {!Foo} *) module M : sig type t = Foo diff --git a/test/xref2/github_issue_447.t/run.t b/test/xref2/github_issue_447.t/run.t index 5b89e1c8e8..b8c7efad73 100644 --- a/test/xref2/github_issue_447.t/run.t +++ b/test/xref2/github_issue_447.t/run.t @@ -18,7 +18,8 @@ Let's now check that the reference point to the right page/anchor: $ cat html/A/index.html | grep \# | grep Foo | grep -v anchor

Foo - u.Foo + u.Foo + Foo

M.t.Foo and M.t.Foo

M.t.Foo and From 3c90fe0b0fb11fd1d3add310faf41b6ae503fa07 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 6 Dec 2023 10:04:23 +0100 Subject: [PATCH 10/35] Changelog entry for #933 Signed-off-by: Paul-Elliot --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 14dd7dda99..c130f19939 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,8 @@ Tags: ### Added - Display 'private' keyword for private type extensions (@gpetiot, #1019) - Add support for search (@panglesd, @EmileTrotignon, #972) +- Allow to omit parent type in constructor reference (@panglesd, + @EmileTrotignon, #933) ### Fixed From cea5c1b93804585289e29e858a7880cfbf8f3a27 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Mon, 30 Oct 2023 12:08:35 +0100 Subject: [PATCH 11/35] Ident_env: Turn all maps into hashtbl OCaml Idents are unique, so there is no risk with keeping "out of scope" idents. However, it is practical to keep the full environment at the end of a traverse, for render source code purpose. Signed-off-by: Paul-Elliot --- src/loader/cmi.ml | 17 +-- src/loader/cmt.ml | 17 +-- src/loader/cmti.ml | 10 +- src/loader/ident_env.cppo.ml | 196 ++++++++++++++++++---------------- src/loader/ident_env.cppo.mli | 8 +- src/loader/implementation.ml | 19 ++-- 6 files changed, 139 insertions(+), 128 deletions(-) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index 88576665ae..8365e5b22a 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -924,17 +924,18 @@ let rec read_module_type env parent (mty : Odoc_model.Compat.module_type) = | Mty_ident p -> Path {p_path = Env.Path.read_module_type env p; p_expansion=None } | Mty_signature sg -> Signature (read_signature env parent sg) | Mty_functor(parameter, res) -> - let f_parameter, env = + let f_parameter = match parameter with - | Unit -> Odoc_model.Lang.FunctorParameter.Unit, env + | Unit -> Odoc_model.Lang.FunctorParameter.Unit | Named (id_opt, arg) -> - let id, env = match id_opt with - | None -> Identifier.Mk.parameter(parent, Odoc_model.Names.ModuleName.make_std "_"), env - | Some id -> let env = Env.add_parameter parent id (ModuleName.of_ident id) env in - Ident_env.find_parameter_identifier env id, env + let id = match id_opt with + | None -> Identifier.Mk.parameter(parent, Odoc_model.Names.ModuleName.make_std "_") + | Some id -> + let () = Env.add_parameter parent id (ModuleName.of_ident id) env in + Ident_env.find_parameter_identifier env id in let arg = read_module_type env (id :> Identifier.Signature.t) arg in - Odoc_model.Lang.FunctorParameter.Named ({ FunctorParameter. id; expr = arg }), env + Odoc_model.Lang.FunctorParameter.Named ({ FunctorParameter. id; expr = arg }) in let res = read_module_type env (Identifier.Mk.result parent) res in Functor( f_parameter, res) @@ -1082,7 +1083,7 @@ and read_signature_noenv env parent (items : Odoc_model.Compat.signature) = loop ([],{s_modules=[]; s_module_types=[]; s_values=[];s_types=[]; s_classes=[]; s_class_types=[]}) items and read_signature env parent (items : Odoc_model.Compat.signature) = - let env = Env.handle_signature_type_items parent items env in + let () = Env.handle_signature_type_items parent items env in fst @@ read_signature_noenv env parent items diff --git a/src/loader/cmt.ml b/src/loader/cmt.ml index 34d8a5d7da..682333588a 100644 --- a/src/loader/cmt.ml +++ b/src/loader/cmt.ml @@ -363,19 +363,20 @@ let rec read_module_expr env parent label_parent mexpr = Signature sg #if OCAML_VERSION >= (4,10,0) | Tmod_functor(parameter, res) -> - let f_parameter, env = + let f_parameter = match parameter with - | Unit -> FunctorParameter.Unit, env + | Unit -> FunctorParameter.Unit | Named (id_opt, _, arg) -> - let id, env = + let id = match id_opt with - | None -> Identifier.Mk.parameter (parent, Odoc_model.Names.ModuleName.make_std "_"), env - | Some id -> let env = Env.add_parameter parent id (ModuleName.of_ident id) env in - Env.find_parameter_identifier env id, env + | None -> Identifier.Mk.parameter (parent, Odoc_model.Names.ModuleName.make_std "_") + | Some id -> + let () = Env.add_parameter parent id (ModuleName.of_ident id) env in + Env.find_parameter_identifier env id in let arg = Cmti.read_module_type env (id :> Identifier.Signature.t) label_parent arg in - Named { id; expr=arg }, env + Named { id; expr=arg } in let res = read_module_expr env (Identifier.Mk.result parent) label_parent res in Functor (f_parameter, res) @@ -576,7 +577,7 @@ and read_structure : 'tags. 'tags Odoc_model.Semantics.handle_internal_tags -> _ -> _ -> _ -> _ * 'tags = fun internal_tags env parent str -> - let env = Env.add_structure_tree_items parent str env in + let () = Env.add_structure_tree_items parent str env in let items, (doc, doc_post), tags = let classify item = match item.str_desc with diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index b7108f5eda..870cd18f69 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -517,12 +517,12 @@ and read_module_type env parent label_parent mty = match parameter with | Unit -> FunctorParameter.Unit, env | Named (id_opt, _, arg) -> - let id, env = + let id = match id_opt with - | None -> Identifier.Mk.parameter (parent, ModuleName.make_std "_"), env + | None -> Identifier.Mk.parameter (parent, ModuleName.make_std "_") | Some id -> - let env = Env.add_parameter parent id (ModuleName.of_ident id) env in - Env.find_parameter_identifier env id, env + let () = Env.add_parameter parent id (ModuleName.of_ident id) env in + Env.find_parameter_identifier env id in let arg = read_module_type env (id :> Identifier.Signature.t) label_parent arg in Named { id; expr = arg; }, env @@ -772,7 +772,7 @@ and read_signature : 'tags. 'tags Odoc_model.Semantics.handle_internal_tags -> _ -> _ -> _ -> _ * 'tags = fun internal_tags env parent sg -> - let env = Env.add_signature_tree_items parent sg env in + let () = Env.add_signature_tree_items parent sg env in let items, (doc, doc_post), tags = let classify item = match item.sig_desc with diff --git a/src/loader/ident_env.cppo.ml b/src/loader/ident_env.cppo.ml index 0d2dea858f..bcda19b082 100644 --- a/src/loader/ident_env.cppo.ml +++ b/src/loader/ident_env.cppo.ml @@ -29,36 +29,42 @@ module LocHashtbl = Hashtbl.Make(struct let hash = Hashtbl.hash end) +module IdentHashtbl = Hashtbl.Make(struct + type t = Ident.t + let equal l1 l2 = l1 = l2 + let hash = Hashtbl.hash + end) + type t = - { modules : Id.Module.t Ident.tbl; - parameters : Id.FunctorParameter.t Ident.tbl; - module_paths : P.Module.t Ident.tbl; - module_types : Id.ModuleType.t Ident.tbl; - types : Id.DataType.t Ident.tbl; - exceptions: Id.Exception.t Ident.tbl; - extensions: Id.Extension.t Ident.tbl; - constructors: Id.Constructor.t Ident.tbl; - values: Id.Value.t Ident.tbl; - classes : Id.Class.t Ident.tbl; - class_types : Id.ClassType.t Ident.tbl; + { modules : Id.Module.t IdentHashtbl.t; + parameters : Id.FunctorParameter.t IdentHashtbl.t; + module_paths : P.Module.t IdentHashtbl.t; + module_types : Id.ModuleType.t IdentHashtbl.t; + types : Id.DataType.t IdentHashtbl.t; + exceptions: Id.Exception.t IdentHashtbl.t; + extensions: Id.Extension.t IdentHashtbl.t; + constructors: Id.Constructor.t IdentHashtbl.t; + values: Id.Value.t IdentHashtbl.t; + classes : Id.Class.t IdentHashtbl.t; + class_types : Id.ClassType.t IdentHashtbl.t; loc_to_ident : Id.t LocHashtbl.t; - hidden : Ident.t list; (* we use term hidden to mean shadowed and idents_in_doc_off_mode items*) + hidden : unit IdentHashtbl.t; (* we use term hidden to mean shadowed and idents_in_doc_off_mode items*) } let empty () = - { modules = Ident.empty; - parameters = Ident.empty; - module_paths = Ident.empty; - module_types = Ident.empty; - types = Ident.empty; - exceptions = Ident.empty; - constructors = Ident.empty; - extensions = Ident.empty; - values = Ident.empty; - classes = Ident.empty; - class_types = Ident.empty; + { modules = IdentHashtbl.create 10; + parameters = IdentHashtbl.create 10; + module_paths = IdentHashtbl.create 10; + module_types = IdentHashtbl.create 10; + types = IdentHashtbl.create 10; + exceptions = IdentHashtbl.create 10; + constructors = IdentHashtbl.create 10; + extensions = IdentHashtbl.create 10; + values = IdentHashtbl.create 10; + classes = IdentHashtbl.create 10; + class_types = IdentHashtbl.create 10; loc_to_ident = LocHashtbl.create 100; - hidden = []; + hidden = IdentHashtbl.create 100; } (* The boolean is an override for whether it should be hidden - true only for @@ -481,84 +487,84 @@ let class_name_exists name items = let class_type_name_exists name items = List.exists (function | `ClassType (id',_,_,_,_) when Ident.name id' = name -> true | _ -> false) items -let add_items : Id.Signature.t -> item list -> t -> t = fun parent items env -> +let add_items : Id.Signature.t -> item list -> t -> unit = fun parent items env -> let open Odoc_model.Paths.Identifier in let rec inner items env = match items with | `Type (t, is_hidden_item, loc) :: rest -> let name = Ident.name t in let is_hidden = is_hidden_item || type_name_exists name rest in - let identifier, hidden = + let identifier = if is_hidden - then Mk.type_(parent, TypeName.internal_of_string name), t :: env.hidden - else Mk.type_(parent, TypeName.make_std name), env.hidden + then (IdentHashtbl.add env.hidden t (); Mk.type_(parent, TypeName.internal_of_string name)) + else Mk.type_(parent, TypeName.make_std name) in - let types = Ident.add t identifier env.types in + let () = IdentHashtbl.add env.types t identifier in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with types; hidden } + inner rest env | `Constructor (t, t_parent, loc) :: rest -> let name = Ident.name t in let identifier = - let parent = Ident.find_same t_parent env.types in + let parent = IdentHashtbl.find env.types t_parent in Mk.constructor(parent, ConstructorName.make_std name) in - let constructors = Ident.add t identifier env.constructors in + let () = IdentHashtbl.add env.constructors t identifier in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with constructors } + inner rest env | `Exception (t, loc) :: rest -> let name = Ident.name t in let identifier = Mk.exception_(parent, ExceptionName.make_std name) in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - let exceptions = Ident.add t identifier env.exceptions in - inner rest {env with exceptions } + let () = IdentHashtbl.add env.exceptions t identifier in + inner rest env | `Extension (t, loc) :: rest -> let name = Ident.name t in let identifier = Mk.extension(parent, ExtensionName.make_std name) in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - let extensions = Ident.add t identifier env.extensions in - inner rest {env with extensions } + let () = IdentHashtbl.add env.extensions t identifier in + inner rest env | `Value (t, is_hidden_item, loc) :: rest -> let name = Ident.name t in let is_hidden = is_hidden_item || value_name_exists name rest in - let identifier, hidden = + let identifier = if is_hidden - then Mk.value(parent, ValueName.internal_of_string name), t :: env.hidden - else Mk.value(parent, ValueName.make_std name), env.hidden + then (IdentHashtbl.add env.hidden t (); Mk.value(parent, ValueName.internal_of_string name)) + else Mk.value(parent, ValueName.make_std name) in - let values = Ident.add t identifier env.values in + let () = IdentHashtbl.add env.values t identifier in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with values; hidden } + inner rest env | `ModuleType (t, is_hidden_item, loc) :: rest -> let name = Ident.name t in let is_hidden = is_hidden_item || module_type_name_exists name rest in - let identifier, hidden = + let identifier = if is_hidden - then Mk.module_type(parent, ModuleTypeName.internal_of_string name), t :: env.hidden - else Mk.module_type(parent, ModuleTypeName.make_std name), env.hidden + then (IdentHashtbl.add env.hidden t (); Mk.module_type(parent, ModuleTypeName.internal_of_string name)) + else Mk.module_type(parent, ModuleTypeName.make_std name) in - let module_types = Ident.add t identifier env.module_types in + let () = IdentHashtbl.add env.module_types t identifier in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with module_types; hidden } + inner rest env | `Module (t, is_hidden_item, loc) :: rest -> let name = Ident.name t in let double_underscore = Odoc_model.Root.contains_double_underscore name in let is_hidden = is_hidden_item || module_name_exists name rest || double_underscore in - let identifier, hidden = - if is_hidden - then Mk.module_(parent, ModuleName.internal_of_string name), t :: env.hidden - else Mk.module_(parent, ModuleName.make_std name), env.hidden + let identifier = + if is_hidden + then (IdentHashtbl.add env.hidden t (); Mk.module_(parent, ModuleName.internal_of_string name)) + else Mk.module_(parent, ModuleName.make_std name) in let path = `Identifier(identifier, is_hidden) in - let modules = Ident.add t identifier env.modules in - let module_paths = Ident.add t path env.module_paths in + let () = IdentHashtbl.add env.modules t identifier in + let () = IdentHashtbl.add env.module_paths t path in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with modules; module_paths; hidden } + inner rest env | `Class (t,t2,t3,t4, is_hidden_item, loc) :: rest -> let name = Ident.name t in @@ -567,19 +573,21 @@ let add_items : Id.Signature.t -> item list -> t -> t = fun parent items env -> | None -> [t;t2;t3] | Some t4 -> [t;t2;t3;t4] in - let identifier, hidden = + let identifier = if is_hidden - then Mk.class_(parent, ClassName.internal_of_string name), class_types @ env.hidden - else Mk.class_(parent, ClassName.make_std name), env.hidden + then ( + List.iter (fun t -> IdentHashtbl.add env.hidden t ()) class_types; + Mk.class_(parent, ClassName.internal_of_string name)) + else Mk.class_(parent, ClassName.make_std name) in - let classes = - List.fold_right (fun id classes -> Ident.add id identifier classes) - class_types env.classes in + let () = + List.fold_right (fun id () -> IdentHashtbl.add env.classes id identifier) + class_types () in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with classes; hidden } + inner rest env | `ClassType (t,t2,t3, is_hidden_item, loc) :: rest -> let name = Ident.name t in @@ -588,18 +596,20 @@ let add_items : Id.Signature.t -> item list -> t -> t = fun parent items env -> | None -> [t;t2] | Some t3 -> [t;t2;t3] in - let identifier, hidden = + let identifier = if is_hidden - then Mk.class_type(parent, ClassTypeName.internal_of_string name), class_types @ env.hidden - else Mk.class_type(parent, ClassTypeName.make_std name), env.hidden + then ( + List.iter (fun t -> IdentHashtbl.add env.hidden t ()) class_types; + Mk.class_type(parent, ClassTypeName.internal_of_string name)) + else Mk.class_type(parent, ClassTypeName.make_std name) in - let class_types = - List.fold_right (fun id class_types -> Ident.add id identifier class_types) - class_types env.class_types in + let () = + List.fold_right (fun id () -> IdentHashtbl.add env.class_types id identifier) + class_types () in (match loc with | Some l -> LocHashtbl.add env.loc_to_ident l (identifier :> Id.any) | _ -> ()); - inner rest { env with class_types; hidden } + inner rest env - | [] -> env + | [] -> () in inner items env let identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option = fun env loc -> @@ -608,17 +618,17 @@ let identifier_of_loc : t -> Location.t -> Odoc_model.Paths.Identifier.t option let iter_located_identifier : t -> (Location.t -> Odoc_model.Paths.Identifier.t -> unit) -> unit = fun env f -> LocHashtbl.iter f env.loc_to_ident -let add_signature_tree_items : Paths.Identifier.Signature.t -> Typedtree.signature -> t -> t = +let add_signature_tree_items : Paths.Identifier.Signature.t -> Typedtree.signature -> t -> unit = fun parent sg env -> let items = extract_signature_tree_items false sg.sig_items |> flatten_includes in add_items parent items env -let add_structure_tree_items : Paths.Identifier.Signature.t -> Typedtree.structure -> t -> t = +let add_structure_tree_items : Paths.Identifier.Signature.t -> Typedtree.structure -> t -> unit = fun parent sg env -> let items = extract_structure_tree_items false sg.str_items |> flatten_includes in add_items parent items env -let handle_signature_type_items : Paths.Identifier.Signature.t -> Compat.signature -> t -> t = +let handle_signature_type_items : Paths.Identifier.Signature.t -> Compat.signature -> t -> unit = fun parent sg env -> let items = extract_signature_type_items sg in add_items parent items env @@ -627,47 +637,47 @@ let add_parameter parent id name env = let hidden = ModuleName.is_hidden name in let oid = Odoc_model.Paths.Identifier.Mk.parameter(parent, name) in let path = `Identifier (oid, hidden) in - let module_paths = Ident.add id path env.module_paths in - let modules = Ident.add id oid env.modules in - let parameters = Ident.add id oid env.parameters in - { env with module_paths; modules; parameters } + let () = IdentHashtbl.add env.module_paths id path in + let () = IdentHashtbl.add env.modules id oid in + let () = IdentHashtbl.add env.parameters id oid in + () let find_module env id = - Ident.find_same id env.module_paths + IdentHashtbl.find env.module_paths id let find_module_identifier env id = - Ident.find_same id env.modules + IdentHashtbl.find env.modules id let find_parameter_identifier env id = - Ident.find_same id env.parameters + IdentHashtbl.find env.parameters id let find_module_type env id = - Ident.find_same id env.module_types + IdentHashtbl.find env.module_types id let find_type_identifier env id = - Ident.find_same id env.types + IdentHashtbl.find env.types id let find_constructor_identifier env id = - Ident.find_same id env.constructors + IdentHashtbl.find env.constructors id let find_exception_identifier env id = - Ident.find_same id env.exceptions + IdentHashtbl.find env.exceptions id let find_extension_identifier env id = - Ident.find_same id env.extensions + IdentHashtbl.find env.extensions id let find_value_identifier env id = - Ident.find_same id env.values + IdentHashtbl.find env.values id let find_type env id = try - (Ident.find_same id env.types :> Id.Path.Type.t) + (IdentHashtbl.find env.types id :> Id.Path.Type.t) with Not_found -> try - (Ident.find_same id env.classes :> Id.Path.Type.t) + (IdentHashtbl.find env.classes id :> Id.Path.Type.t) with Not_found -> try - (Ident.find_same id env.class_types :> Id.Path.Type.t) + (IdentHashtbl.find env.class_types id :> Id.Path.Type.t) with Not_found -> if List.mem id builtin_idents then match core_type_identifier (Ident.name id) with @@ -677,19 +687,19 @@ let find_type env id = let find_class_type env id = try - (Ident.find_same id env.classes :> Id.Path.ClassType.t) + (IdentHashtbl.find env.classes id :> Id.Path.ClassType.t) with Not_found -> - (Ident.find_same id env.class_types :> Id.Path.ClassType.t) + (IdentHashtbl.find env.class_types id :> Id.Path.ClassType.t) let find_class_identifier env id = - Ident.find_same id env.classes + IdentHashtbl.find env.classes id let find_class_type_identifier env id = - Ident.find_same id env.class_types + IdentHashtbl.find env.class_types id let is_shadowed env id = - List.mem id env.hidden + IdentHashtbl.mem env.hidden id module Path = struct let read_module_ident env id = diff --git a/src/loader/ident_env.cppo.mli b/src/loader/ident_env.cppo.mli index 2be505ca18..076421173c 100644 --- a/src/loader/ident_env.cppo.mli +++ b/src/loader/ident_env.cppo.mli @@ -21,16 +21,16 @@ type t val empty : unit -> t val add_parameter : - Paths.Identifier.Signature.t -> Ident.t -> Names.ModuleName.t -> t -> t + Paths.Identifier.Signature.t -> Ident.t -> Names.ModuleName.t -> t -> unit val handle_signature_type_items : - Paths.Identifier.Signature.t -> Compat.signature -> t -> t + Paths.Identifier.Signature.t -> Compat.signature -> t -> unit val add_signature_tree_items : - Paths.Identifier.Signature.t -> Typedtree.signature -> t -> t + Paths.Identifier.Signature.t -> Typedtree.signature -> t -> unit val add_structure_tree_items : - Paths.Identifier.Signature.t -> Typedtree.structure -> t -> t + Paths.Identifier.Signature.t -> Typedtree.structure -> t -> unit module Path : sig val read_module : t -> Path.t -> Paths.Path.Module.t diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 6b8bc6c9f6..c743438788 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -15,12 +15,12 @@ module Env = struct open Odoc_model.Paths let rec structure env parent str = - let env' = Ident_env.add_structure_tree_items parent str env in - List.iter (structure_item env' parent) str.str_items + let () = Ident_env.add_structure_tree_items parent str env in + List.iter (structure_item env parent) str.str_items and signature env parent sg = - let env' = Ident_env.add_signature_tree_items parent sg env in - List.iter (signature_item env' parent) sg.sig_items + let () = Ident_env.add_signature_tree_items parent sg env in + List.iter (signature_item env parent) sg.sig_items and signature_item env parent item = match item.sig_desc with @@ -95,20 +95,19 @@ module Env = struct | Tmod_structure str -> structure env parent str | Tmod_functor (parameter, res) -> let open Odoc_model.Names in - let env = + let () = match parameter with - | Unit -> env + | Unit -> () | Named (id_opt, _, arg) -> ( match id_opt with | Some id -> - let env = + let () = Ident_env.add_parameter parent id (ModuleName.of_ident id) env in let id = Ident_env.find_module_identifier env id in - module_type env (id :> Identifier.Signature.t) arg; - env - | None -> env) + module_type env (id :> Identifier.Signature.t) arg + | None -> ()) in module_expr env (Odoc_model.Paths.Identifier.Mk.result parent) res | Tmod_constraint (me, _, constr, _) -> From f0036f00c9082716f76705be757d2fb9f6607450 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 23 May 2023 11:16:36 +0200 Subject: [PATCH 12/35] Collect occurrences info Signed-off-by: Paul-Elliot --- doc/driver.mld | 17 ++- src/document/generator.ml | 36 +++++-- src/document/types.ml | 6 +- src/html/html_source.ml | 28 ++++- src/html_support_files/odoc.css | 10 +- .../odoc_html_support_files.ml | 4 + src/loader/ident_env.cppo.ml | 15 +++ src/loader/ident_env.cppo.mli | 2 + src/loader/implementation.ml | 85 ++++++++++----- src/loader/implementation.mli | 1 + src/loader/odoc_loader.ml | 23 ++-- src/loader/odoc_loader.mli | 2 + src/loader/typedtree_traverse.ml | 102 ++++++++++++++---- src/model/lang.ml | 20 +++- src/model/paths.ml | 11 +- src/model/paths.mli | 8 -- src/model/paths_types.ml | 8 +- src/model_desc/lang_desc.ml | 2 +- src/odoc/bin/main.ml | 38 ++++++- src/odoc/compile.ml | 9 +- src/odoc/compile.mli | 1 + src/odoc/html_page.ml | 8 +- src/odoc/occurrences.ml | 58 ++++++++++ src/xref2/compile.ml | 23 +++- src/xref2/component.ml | 27 +++-- src/xref2/cpath.ml | 6 +- src/xref2/env.ml | 4 +- src/xref2/errors.ml | 2 +- src/xref2/find.ml | 5 +- src/xref2/lang_of.ml | 6 +- src/xref2/link.ml | 62 +++++++++-- src/xref2/shape_tools.cppo.ml | 56 +++++++++- src/xref2/shape_tools.cppo.mli | 5 + src/xref2/tools.ml | 48 +++++++-- test/occurrences/double_wrapped.t/a.ml | 7 ++ test/occurrences/double_wrapped.t/b.ml | 13 +++ test/occurrences/double_wrapped.t/c.ml | 3 + test/occurrences/double_wrapped.t/main.ml | 5 + test/occurrences/double_wrapped.t/main__.ml | 10 ++ test/occurrences/double_wrapped.t/root.mld | 1 + test/occurrences/double_wrapped.t/run.t | 59 ++++++++++ test/occurrences/dune | 11 ++ test/occurrences/source.t/a.ml | 1 + test/occurrences/source.t/b.ml | 1 + test/occurrences/source.t/root.mld | 1 + test/occurrences/source.t/run.t | 38 +++++++ test/odoc_print/dune | 12 +-- test/odoc_print/occurrences_print.ml | 27 +++++ test/sources/functor.t/run.t | 8 ++ test/sources/lookup_def.t/run.t | 2 + test/sources/recursive_module.t/run.t | 8 ++ test/sources/source.t/run.t | 25 ++++- 52 files changed, 832 insertions(+), 138 deletions(-) create mode 100644 src/odoc/occurrences.ml create mode 100644 test/occurrences/double_wrapped.t/a.ml create mode 100644 test/occurrences/double_wrapped.t/b.ml create mode 100644 test/occurrences/double_wrapped.t/c.ml create mode 100644 test/occurrences/double_wrapped.t/main.ml create mode 100644 test/occurrences/double_wrapped.t/main__.ml create mode 100644 test/occurrences/double_wrapped.t/root.mld create mode 100644 test/occurrences/double_wrapped.t/run.t create mode 100644 test/occurrences/dune create mode 100644 test/occurrences/source.t/a.ml create mode 100644 test/occurrences/source.t/b.ml create mode 100644 test/occurrences/source.t/root.mld create mode 100644 test/occurrences/source.t/run.t create mode 100644 test/odoc_print/occurrences_print.ml diff --git a/doc/driver.mld b/doc/driver.mld index 014a05fefb..3ea57bbe38 100644 --- a/doc/driver.mld +++ b/doc/driver.mld @@ -135,7 +135,8 @@ Compiling a file with [odoc] requires a few arguments: the file to compile, an optional parent, a list of include paths, a list of children for [.mld] files, optional parent and name for source implementation, and an output path. Include paths can be just ['.'], and we can calculate the output file from the input -because all of the files are going into the same directory. +because all of the files are going into the same directory. If we wish to count +occurrences of each identifier, we need to pass the [--count-occurrences] flag. Linking a file with [odoc] requires the input file and a list of include paths. As for compile, we will hard-code the include path. @@ -148,6 +149,9 @@ Using the [--source] argument with an [.odocl] file that was not compiled with [--source-parent-file] and [--source-name] will result in an error, as will omitting [--source] when generating HTML of an [odocl] that was compiled with [--source-parent-file] and [--source-name]. +To get the number of uses of each identifier, we can use the [count-occurrences] +command. + In all of these, we'll capture [stdout] and [stderr] so we can check it later. {[ @@ -209,7 +213,7 @@ let add_prefixed_output cmd list prefix lines = !list @ Bos.Cmd.to_string cmd :: List.map (fun l -> prefix ^ ": " ^ l) lines -let compile file ?parent ?(output_dir = Fpath.v "./") +let compile file ?(count_occurrences = true) ?parent ?(output_dir = Fpath.v "./") ?(ignore_output = false) ?source_args children = let output_basename = let ext = Fpath.get_ext file in @@ -237,8 +241,9 @@ let compile file ?parent ?(output_dir = Fpath.v "./") | _ -> Cmd.empty else Cmd.empty in + let occ = if count_occurrences then Cmd.v "--count-occurrences" else Cmd.empty in let cmd = - odoc % "compile" % Fpath.to_string file %% source_args %% cmt_arg + odoc % "compile" % Fpath.to_string file %% source_args %% occ %% cmt_arg % "-I" % "." % "-o" % p output_file |> List.fold_right (fun child cmd -> cmd % "--child" % child) children in @@ -289,6 +294,11 @@ let support_files () = let open Cmd in let cmd = odoc % "support-files" % "-o" % "html/odoc" in run cmd + +let count_occurrences output = + let open Cmd in + let cmd = odoc % "count-occurrences" % "-I" % "." % "-o" % p output in + run cmd ]} @@ -750,6 +760,7 @@ let compiled = compile_all () in let linked = link_all compiled in let () = index_generate () in let _ = js_index () in +let _ = count_occurrences (Fpath.v "occurrences.txt") in generate_all linked ]} diff --git a/src/document/generator.ml b/src/document/generator.ml index d5babb232f..bb411cacfb 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -252,18 +252,42 @@ module Make (Syntax : SYNTAX) = struct let path id = Url.Path.from_identifier id let url id = Url.from_path (path id) + let to_link documentation implementation = + let documentation = + let open Paths.Path.Resolved in + match documentation with + | Some (`Resolved p) when not (is_hidden (p :> t)) -> ( + let id = identifier (p :> t) in + match Url.from_identifier ~stop_before:false id with + | Ok link -> Some link + | _ -> None) + | _ -> None + in + let implementation = + match implementation with + | Some (Odoc_model.Lang.Source_info.Resolved id) -> ( + match Url.Anchor.from_identifier (id :> Paths.Identifier.t) with + | Ok url -> Some url + | Error _ -> None) + | _ -> None + in + Some (Source_page.Link { implementation; documentation }) + let info_of_info : Lang.Source_info.annotation -> Source_page.info option = function - | Value id -> ( - match Url.Anchor.from_identifier (id :> Paths.Identifier.t) with - | Ok url -> Some (Link url) - | Error _ -> None) | Definition id -> ( match id.iv with | `SourceLocation (_, def) -> Some (Anchor (DefName.to_string def)) | `SourceLocationInternal (_, local) -> Some (Anchor (LocalName.to_string local)) | _ -> None) + | Module { documentation; _ } -> to_link documentation None + | ModuleType { documentation; _ } -> to_link documentation None + | Type { documentation; _ } -> to_link documentation None + | ClassType { documentation; _ } -> to_link documentation None + | Value { documentation; implementation } -> + to_link documentation implementation + | Constructor { documentation; _ } -> to_link documentation None let source id syntax_info infos source_code = let url = path id in @@ -1784,8 +1808,8 @@ module Make (Syntax : SYNTAX) = struct in let source_anchor = match t.source_info with - | Some src -> Some (Source_page.url src.id) - | None -> None + | Some { id = Some id; _ } -> Some (Source_page.url id) + | _ -> None in let page = make_expansion_page ~source_anchor url [ unit_doc ] items in Document.Page page diff --git a/src/document/types.ml b/src/document/types.ml index 2053ce902e..34e9b502d9 100644 --- a/src/document/types.ml +++ b/src/document/types.ml @@ -183,7 +183,11 @@ end = Page and Source_page : sig - type info = Syntax of string | Anchor of string | Link of Url.Anchor.t + type target = { + documentation : Url.Anchor.t option; + implementation : Url.Anchor.t option; + } + type info = Syntax of string | Anchor of string | Link of target type code = span list and span = Tagged_code of info * code | Plain_code of string diff --git a/src/html/html_source.ml b/src/html/html_source.ml index ab08665780..edd3cd32d4 100644 --- a/src/html/html_source.ml +++ b/src/html/html_source.ml @@ -24,9 +24,31 @@ let html_of_doc ~config ~resolve docs = let children = List.concat @@ List.map (doc_to_html ~is_in_a) docs in match info with | Syntax tok -> [ span ~a:[ a_class [ tok ] ] children ] - | Link anchor -> - let href = Link.href ~config ~resolve anchor in - [ a ~a:[ a_href href ] children ] + | Link { documentation; implementation } -> ( + let href_implementation = + Option.map (Link.href ~config ~resolve) implementation + in + let href_documentation = + Option.map (Link.href ~config ~resolve) documentation + in + let body = + match href_implementation with + | Some href -> [ a ~a:[ a_href href ] children ] + | None -> children + in + match href_documentation with + | None -> body + | Some href -> + [ + span + ~a:[ a_class [ "jump-to-doc-container" ] ] + [ + span ~a:[] body; + a + ~a:[ a_href href; a_class [ "jump-to-doc" ] ] + [ txt " 📖" ]; + ]; + ]) | Anchor lbl -> [ span ~a:[ a_id lbl ] children ]) in span ~a:[] @@ List.concat @@ List.map (doc_to_html ~is_in_a:false) docs diff --git a/src/html_support_files/odoc.css b/src/html_support_files/odoc.css index 92d4125d82..bb5e9d8ff7 100644 --- a/src/html_support_files/odoc.css +++ b/src/html_support_files/odoc.css @@ -1203,6 +1203,14 @@ td.def-doc *:first-child { color: #657b83; } +.jump-to-doc-container:hover .jump-to-doc { + display: inline; +} + +.jump-to-doc { + display: none; +} + /* Source directories */ .odoc-directory::before { @@ -1387,4 +1395,4 @@ td.def-doc *:first-child { WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ---------------------------------------------------------------------------*/ \ No newline at end of file + ---------------------------------------------------------------------------*/ diff --git a/src/html_support_files/odoc_html_support_files.ml b/src/html_support_files/odoc_html_support_files.ml index cbc9498a1e..54812d8baf 100644 --- a/src/html_support_files/odoc_html_support_files.ml +++ b/src/html_support_files/odoc_html_support_files.ml @@ -128,6 +128,8 @@ module Internal = struct let d_4a0d6b1f3fe23870dc64a5c9998fab74 = "wOF2\000\001\000\000\000\000?\020\000\017\000\000\000\000\134\224\000\000>\178\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\026\028\027\030\028\136$\006`\000\132|\b\129\018\t\151\023\017\b\n\129\201h\129\172t\011\132\026\000\0016\002$\003\135B\004 \005\131T\007\137\028\012\129 \027*u\005\227\152%\224<\000\129\146\245\0192\138`\227\000\146\024\188\027E\176q\128`\191\029\221\252\127=n\012\017\236\136V\181\014%$\184\218T\228\158\166U(Wg\163{\147a:=eRp1\147J^\223\209\2050\133\133\228d\197\175\140\135\219wT\007\025\238^\197\219\016\196\021\023\132\127`{b\209\027R\240Ew\255\224A\173@\130\006%\186\244\193\195\239\004\165\168OFR\248\156\191\220\248\232\b\141}\146\011U,[\247\236\127&$\225\016\158\194\135\168\192\168\168q\022\148@HT\242_\b\159\212\237\146\029\149\193\145n!\232\169J\228\014\192\220\028\130\003F\245\"a\209l\205\130U\177J6bT\140L\005\251\162\024\137\141\145`\005f\222G\164\149\015\255+U}\239\253\191\187\000I\145\162U\154{\191\177\164\168\204\144^\151\170\225\192p\131\145V\024\235\152\243\197\247SB\004\141\177f\015\151\012\161\019E\155y\018Mb\157\140GR\164v\154\254\031<\212^\219\219\250kK\178I\255\185\163\021\133\208\027\154\187u\224\016\150A6\165\025\020H\135D!T\243\159t\234\251\167\147-\019\004\248\146\179\212T\186 +>;\132\176g,\224\180u\0243v\157\218\006\247\223\007\248\1919\255\243^\0250\177$#H\182c;y\196gF\003\152\161v\213.\187\236~\247?\031\234\210S\203\167t\011\179?\192,\217\133u\r\001?C${-lc\136\245\249\159\181\026\"\030\228\135\015\222\221k\214X\198V%A\1471l\214\228p\164r;\189\244:\000!\142e.\212<\000\202\031)S)\006B\185\253\159\174\223\223I6\200\189\025^EoEIQA\143\143DX\194{\001\1949\193e\13429\180n\203\195\190\152U\201\006\241|\207W\249{S\205\246\191]\174\004R\014\132\194\012\229\172\211\197\216\175\194\217\2449\151v\229\162s\251\241\255_\252\221\191X`\177K\222-\022:\029\024\164#A\209\002\b\158D\018\180\006\1297\179\1608\030E\135\016%9\209\174HP\129\162\018%9\166Xt\030W\149K\183eJ\157{\023U\239\162\247\024\250\246\139\213y\243\023\148m\1916c6\029\026\014-El^\185\028\rY\196\146|\239O\200\131\140\229\230i\150\001s\171\237_/\219l6Hjt\168\006\011{a\137\183g\246\134\211{\127\179\255C\023\186\166\215K\144\208\000\145\153\136B{\191\158\\\004\001k\128\017;\019U\014\185\234\1730ijA\026\182\r\155?\157YA\020:S`#`\197\202\155\133\130\231u\238\188\228\229\014\241\166\177\207\156N\011X5\227-\222-\243\231\164+\225\238\185\165\150\186\133\209\173T`u\006\028\243\166$%\219\\\170L\022\233\163:\014B r\138\203\178\019\004\150}Y6\002\178`.\203\138_&\244eY\240\017\131\186,\197K\020\242\178\004\015\017\136Kb\220\132\193\1836\b\023\025\175,\243\247U\002{\146z\127K\167\210\031\163\240 \232%\030\211\142o(]N\148AR\196\"\252'\191\145\159=\"\252u\153s\251\132_.\001\128\216e$\131Ld,\179\202,2\0056,Y\201\137\011w\150\003_\201wI\241\219\193\183\019\127\145g,?}g\141DHa\154\1381E\241\202\012\194G\169M\187\014\157\186t\235\209\171O?\132\023\165\"_\208Z\131\134\012\0271j\204\184\t\147(\170bD\214,\194@v\245\133\154eAT\020\174\138\201\243\003\130\180*\208u\238\023\020F\215\207\1536`H\155~ \005\233U\005\195\003&A\212\196\245\166Y\137\023K*4r\137[\175\162\023\238\189p\204]\130\151\147\031u\204\175~\243;\128rU\143\127\157\143\187\232\015\127\250K\024>\021*U\169V\163V\157z\r\026\029v\196=?\2489: \172pB\004\132\247c;.\196DV6!\134@5\133\139\240:d\201\203L\201\246\160$\152\011\167`\136\221\197\220\b[\253\137\190\211<\159\1702\239\162\178\b\203\212\222\194\203\141/`6\200S\222\r\128\171\188\174{0\"\004\144\014\155tS\031\194S\160\149\179\030m\022\2428/\238?\211\185\225\007\128\251\148F\191\001\240\012 \189\153\006,6\161X\185'\028\nG\148w\031\217CH\017\196\197\209\195\215\239\1274\208\1503\185Zn\151\187#\\\200=Q)jE\131pD\191(\200g\203/\247\138\245\191\251\174A\176\161\228\031\243\0207|\157<\186<\155g\213\214\149\187\162\\T\175\177\239\011\165\127\000p\r\000-\001\134\149LSK\149\027\000\171\143\193\234\193\247\196+\255za\1925\223\185\234e\000\254\253b\187\025\191}\239\185\221\254\216\166\2209K4k\181\133\029\011V\156\216p\224\194KD\178\020\169`\192 \160\018e#\192\194!\193\251\017\017\023\011\027\135\016U\136\156\132\148\146\140\130\138\150Y\001#\019/'\0237\189R\149\202\148\171V\225KU\218\181h\213\166G\157^d5.\187\228\182;na\198\147ANrW\029\144^\000}\184#\231x\172~Q\150X\189\028\165\127:\"\2250\193O\188\021\128V`\217\240\203\020\020\001\171\186`\136\134\014\016_\028B`\249\163Fg\021\0267m\157\252\170\006\179\221\161\005\011\199\021.\011)\129M@s>\003A[\021\131\020\196A=\006ST%\188\155\193\157\143Y#\133u\161R\152\252\164%K\2257\b\011\227Z\1947\130\208+n\234\2214\020\182\029\174\138\198\166V\199\002\169U\180b\209{\014\213\201\127i\n\0206lO\b\169\b\139R7\234\2544\176\198\024\001\242\140a`A\215\140\137a(*\016\184\237\170\004S\143k\152R! \149\144\210\128\014bp\197\146%U\131y\164h\195\198''\015\198A\1921\233\202\129\167\201\159\167\247\135^h5mpgB\219q\225&\141f3N\249S\218\011\225\022\211\029\209\163M\133\160~\157\129\005\007\005\244 f\152\000\215\227\192\142\234\1988\014\030L7\248AEf\230Gt\229\128\227\136\021Y}\223\026pm>9\146\165\178`\004\186\160^\201p\163Py\248ca\154\020y<\200\128\219\182\238\247\242\144\170\177rP\021\207\205\016U\240#\132\173nKb\249Q&\018\025 \137\220\028\160j\138\162\196\165\169\179H\216(j)X\154WR\015\137\169\192X\017'\178\142\024q\021l\"\227\232\193\001\"OO*#!uX\130\024\222\251\018\138\144\012\202\016:\2248\246\242pR\215V\247\001g\152\131x\170\164\026\154\214\129\159\228\205\147O\205\167\188\165\167z\221\019zhj\153\0202\200\153\011\167U@B\207\232\137{\004\232P!\225\025\151\178\204V!\186\130\216\016P)\019\012{\017!|6x3\237\191\156\0319\229J\254\024\173\197\004\002\177\b\209M\174AT\151\016\131H\191\194\197\026\203%\014\193\012z2`\2155\003Y\248e\178\170\138aM5B\002\217\026\154C\\KGX\015]q\145Qiz\195\138\133Dl^qR\247rM\018\154)\251\250e\225\200*\227\227\248\221\171wz\225\163\017z\189qG\230#\244y^\136\020.\187\243\189\135wc\226\181\216EF.=\248l\183\006\144\136\2490\014\190\199\133\031;\199A\030\168\169o<\214\179\011\1430T\228|\148\202\208\t\249\014\185\212\195\220\140\004\159\145\135\140\167\022\250\170~\217\144$q[\2396\242\168\151P\176\002\163\132z\\\248#\024\r\137\205\250\141\209\0250\201\1911\1610\166\164\134\001;\251C\157p\227\231\2552I\153\253\220\177\024\241aPQ\200T\253\005\162\183@\227\162\210=]\241E|\224\234Z\1894\216\163\143\234\184\192\250\004\226\190M\197(\248\207\141\023\171F\"\221<\027\254\158\218\017\004\132\181pN\196\018\169\176\1996p\186\142\196\159\005\147\146\179gfRuV\250\239\130\244\031\140\196a\030\224\182\128?\2279\202\t6\225\250\243\208\176\164\218\184\232=\231\153\028\146\0188z\200F\004\1743=\200\234c\206\184\245]\202i\t.\165>\199(\248\161^LaB\137\212\020\132\127\178\227\232\205q#\209\189\030\193:\225\179\204g\028\150\183G\005L\175\030\191\237 fC\218\173UL\247Ae(\236~\1747\250\183&9\174\150\180|Q\248\225L\131\175\r\194\186\225\214);\197\181\017\140\014u\020Ed`Ai\174X'\247F\164j.\152\134\158v\238\136i\154\"`\130\183i\171\241\151\222\248j\229/&$\129[\222I/\167'\187,j!\239\161\026\167\146\154ro\219\200{}\246\014&\175\244\235zH[\184\160\158A\196p\244OZ2TL}\1499\144\140\217\024\002g\136\177\189.9\174YRG\199\217'\177\000\128\004:&A\031\2507\157\023\248\242\248\023)\156]\004C\201\031\232\217:\200\156y\127:\225,\029w\221\141\242|\024Q\027#\255#`\162F\220e1\1901]\175\131\174}O\185&\007=\253\255\235\140\150W,\222\211f\2187\022\201\229?\150w\2327\130\169\141\254D\166\2370\\\134kJ\r-[\184\231w\211S\177n\n\180\030\232\252a\168G\211\215\194\180\228W\253\173\t\2017\025i\219>n\140Gv\192b2C=\168j%\017z\134\0003\177\202\006\179g\248\141\233\173h\2517\143w\178\237\191\231\232\223B\174Al\221q\154\172H\194pW\007\019\239W\141\004<\245\163Z\025_\199\192c\216b\215\251\203\030\175\203u\213J\155\198\192~V\230z\138=UF\137\168u\\\019q\174\227\156\169\174\146+k\2482:\025\245\229\1715\bW\149\154+\172\237\021{\188\230\004j\224\184\133\179h\225\\\200\026P\169?\001j\r\173C\018w\188\167%\144\139\149=\\\012}\026\011)\155\167\240D\242\020\133\236\137\197\192\190\004,\241TV\226\004\157\2454K\206\173]zi\223u>x\029\248!(\177/\149\183\131w2\133\183\130ghH|\016\186\165\235\1405cW\198\217\159JFUgd\031O\191\140\217\144\200;\143^\181\006\179\178\246\194i\007\2378M\145\157Y\209t\029\148U\243$\184\191\254rY\146\243X\253Mt\029\151\230\200Z#\222\243\171g\221\203r\226q\169\215\239\240\180\215:\197\139\211M\r\2046\137\190\168\133\207\254\170\132M\213c\254y\026\022\170F\151\163c\239\251q\\\137\007K\150\019\"\183\170v\129\1602\018\234\243(\215W\163\233P\007\200'\207\249K\249\229\021f\185c\160m\167P}j\165 \184Tf.\200\139\214b\188YQQE\170\172:\217\201\199\229l(Q\191\204\189Jb\178K`\183\217\144\031_C;\154B\021\188\197\153\230N^CN<\244\204\130\024\011~\167\028\129\239\232\252\007\189J\238\\&\210\023\182rY\005%u\167\208r\165\177\178\139\165\023O\186\217\167\241E/\252\204\015\219E\225\198\158\181\141F\241\158\137h\1577\154\234XmI\020\155\133M`gW%\236$QR\223qG-\159\214\127\186\030\202\175\153\025L\187\179\189\206\1949\216\209\2362\190\132^\189Y\1973\23053\217o\023\195C\143\138\150?b\228mx\199$\219R\221\174\1860Y\231\151\213\210y~\133\1383\214\2364\018^\159\028\133\214\208^\175\166\200\132\229)\196\028]\250\159\014\179F#\019T\2409\241\212\182?\248\"V\147\182Z_\155F9\234\219\005Z\237\243\"ey:\r\254\237\221\017\239\141ZE\243S\245Q_\196&\253\161\201! B\251\139X\226\1384y\189tD\174\214\244\195[\154\024\141\169vyc\141T[\128\235xB\168LQ1\219-\160\022K0\213\210Q\235\179\203I\028\223j\234\232\251\170:\174\252>t\253\248\186Az#\252:+RNP\177\020t`t\237\029\r\134\224\172l\243\219$\011\235\235\1558mRuq=\203'\225\208\245\152\175\222\132\245\190\136\150*\197\185E\236\225y\154\031\n\176o\005s\165\131x\244|\253\167\011\150\164\192\231=|\166\251\031\136\0302\175\135pB-O\t\149@\149\252\189\249\1767\132\250z\t\251\233\145\193U'7\169\249\018\173OW\\\251\245\201\140\255\029Y\173 \147)H\021\2517\178n\161\254\211\189b\221\221Y\201\254\140\180O -\015\184B\153H\152\133rz\231\193\002\224\003\180D)\202-b\143\204\211\253P\128\020-i\134^\002\225\155\219\187F*\201t\208+\163x\236\188\0302\181\210\189\194\193\166S_n\253\215\205*\155~I%\189\217\003F\179\134\222\180\209]N\196\006\201 \001\221\252\210Q\141\242\tX\253\247\127G\021A\190\1512\173*\\\216U\004\187\t?\2462\214\149~\185E\220\213\211h\231\239\025\175k\136\198{\234\139;6?^\223`\233\228nKr\177,X5o\187\139%\197\217\127\127\151\224\019\216\249\011\237Y3l\172\158\022$\127`\029\193/\1945\1960\167\247\235\187p\240)\189\212X\208@\165\188\177\222#\141\024\197\198\130h\025\249\137\025mZ!\231\197\178\155\213\1872W\251*Q\159{x\190\026M\172\135g\145[\226\r\241\158F\187`\207H]\132\239\160,\025\028q\137\007K\145\019~lr\nKs6\148p\132.\160\242\133[\029w\186\131\229\026n\238l\000{\171\0062#\212\150;\173\142\198\176\139wh\1609\196\153-yv\143X \019\234\139\162f\006\024\251\031\244*!j\250k*\213\205ws\014\0145G\152\179\197\207.\136S\134./\136\177\153\015\141\b\156\227^\136\225\132\187%wn4\149\229\027pd\187\167\189\214-Y\156ih\136\135\1855\215\230\193k\194r\193\141\166K\244\197-|\246_0\239N\2281\242\174\203\2242Qy\158\006\245\171!\255\nXQ{\212, o\024B[\149*\231\003Y6\028\165\205\006\225\240\163\200\028\149I\204d:\154\232fu'\149c\182}n\197\239\205\131\172\158\251~T\158L+\1602\141ue\026o\168\233\242\205M\170\0312\026&\227m\149A\139\148\232\016\205\173\203\134n\156{\178\255\025\018\157\234\011\011\r\232\0316\242\235\023\138\b\148b\216\155o\254\157\137\241X\243\225\248\248\226\156\163yfP\155\252\221T\187\194!\255N\237x\227\156\021\192^\r\005m\196\227#?\153\160h\189\201\164\207\198\162~\209\131Z\172\136\248\004\b2~-\162%\234\169\003\203\213\018\b\138\189v\158V\003]#UA\168\028G\153}^\015\153\\i\214\007\252mh\2007\144\235>\2001\204\158\185=r\026\003\186\004\185\n\154\236\159\188\134\129,\172\\X\191\176+c\161w\193\144\014\217\245\247\168\220\019\178\251]\247\207\\\145u\254~\130~\210\127R'Z\145\252\220\183\233\171Z\141@3\245\019\174\019r\016u\250\192\233\131\178\023 \160b \169\t\214\179\027\212\150J\186\004\238\214GxVpx\254\170\030\211\169\236/\026S\155\138\254\159Us_(\196\180\231L\176C\141l\210\162Z\131\156F5E\216P\245O\249(\130S\027.!\188\197\158Af\143\213\006\020\163\227\025\174 tK\1981\150B\028?&W]\195jZ\206j}\192\019\254\203\207t\142\250\209G\193\136;\148\019\030\2223(\200~\131\213\134\182\128\156\193\213)\249v\143\006\146\149J\166$l\143\227\138W\243r2\138\153\170\028h\213`%\136\208\195$R@\208\153UEk\248{/\149z\229\127\189\245\151\221\025\2187S`\230!\145\1595e\246m\203\236\187?\185/\232u\026\132\177f\153\214SS\229x\186^:N\029\177J\166fQ\136>\153\146\1375\131\251\246\131\007\190\212>\025E\163Y7\131\156\172\194\248.\028\190\190\002\134u\165Wn\007E\191\155\247\239X\157Jr\205\135Y\233M\2434\159\254\203\011\1477\240\031\213\0154\143\215\183Nm\018\192U\174k\030\171\207\239\202\020\244.9!\237\162!W\226\127B\031\147v\210lg\015\249\014\237\214%\205{X\029?\2078\131\023\252\020\154\149\201\"\215Nm\024\011\131\147\156G\156\207\232\2161:1Zf\"\162'P\232\011L\151\149\029\231\234\\\163\023\162^\173@\239\181\228\238\208\169%\028a\243\1606`hbg\249M\007N\227\216J\005\031\247\001\157\143h\198\242\r\004D\r\006\171,\161(+\171bDEgn\178\184\220\144\189u7tk!(\239\215k\195\244\135k;K\247O\230\238\175\248\156\241#t\211\167\250rO\176R\"\026\024u\133\r\017\182\196o\005\233%J\151\196e\202]\187\177\145\222\252\216\226\210\019\201A\183\132;\209W]\221\209<\212\213\235xeaL\131\231\172\210\171\163\241\156>\168[)\176\018\"\140f)\241cX\241\198\153\154R~\146\166\236\167C\160F\133n\154Z\154.\004\015\019e\147k\196\234\240\136\192\173\175/\227\216\217[U\182gx0\138`\nq\002\134O@\192\193\170g\193\245\019C\r\130W'\2316\133\162c\195Q\193kS\243\154\248]\162\225\226K\022\225sp\170x]\209E\187\240\005\152}m\207\b\184\231Jf\207\001\254\194n\023\167\233\231\153\025\245\216r:\149jg\178hu\027\183N6\021'9\143x2\163c\231\208\214\245\\\015\t\219\131\197\202Q\024\183%\210\182\2215\176\028\192\211u\020\169\165\198\146\187\211T.\019\202\155\199U\129\242\024G\225/\207p\n\140*\129\181^\129h.\019\n\228\004\248\199\165\006\141T\227i\172\154\238\204J\182\140\171\161\182\249VU\144\145\247\215\179\195>ol\170\192\159\156\204;Ya\002\027#\001\163\241\255\210%I@\2342\229n\184\213\184\130i\222\139h\255={\014\192\141\171\170\169P\tG&*\026\215-\189\144\020\244\2029S}>_K\203p|\192\246\206\222\137M\158YE%\143\206s\133\161>\170\166\004\143i/\235V\016>\132s\217\201a\b\190\130\195\156\196i+\130\211,>\028qe\175\186\152\022\014\135\023\233W\006u\017*\2197\139\212\225oSk\209*2\157\021l\147:\170;\\F\190\208\165D\142~\193!*\177\193\237\143\222\163\224P\004\228o\129\162\012\029\253\240\198[\141\006\135{\183\180\250\210r\233\218\250\027\015\2373\188$-\195%\155k\017\158g,ez*\193\205W\240\134\214:\170%?\163j5\"zH\230\144\011\190q\193\207\234]6\019e\157W\175\208\021\173F\202@\213\255>\160\186K\1994\184\226l\002nL\141+\129Z\248\135\005\135c$N\144G0\029\244Hs\207\234\2294\"E\173\021\0258\167\242<\216\212\248\206\171^\131\197\134\129\216\161y*\141\140\171+\247;\242\207\234x\020\194D\209v\"\129\196P\184\208\1720M\165\226\173\241qj\135\231\220/\193\231[\242K\136\249H\018\229>U\199\247v\212\156HwQ\210\226[R\029\183RM\011\233U\232\161\015\180\b\191'\221\223cv\030\000\026\252h\234i\014\139a\173$\011|t\181\134\251*\025\181\015G\196\023\190g\129\127\145\127\014^t\131\195\162\217\157e,\163\222n0\241G\027L\026\225&\154b\016\134J\186:\203\023\251\2027\184\156\031 \197\175k!\197\169\214\230\198\195\169\166\231kkq\215\153gR]\024\193C\024\018\247\158\027-2\216\165tK\000\141\228 \251\140h\142\210\204\161 \157\143\251F\175\229\129\127\209^j\017A\176\132d\185W\030$2S\255\007\005z9\223[r\214b\144N\156~lw\001\168\175\019\236\165\183Z\246\021Q\223a\211i&\023\137\165z\017\131\190\163\000\023`s\138%\00460=\161\195\215\163\248\222\155\149]r\251M\020\155\186\022\233\n\191n\205\152\167\191\000\220\1460JZ\004||-\163\253p\146\017J\184\147\012\184\1477\155\239\012\199-\180\001\235`\141\165\189n:\143\215\223#Z5k\019avTB\204\186D\003\236\029\217\000\003\204\027\001X\223\184\165\198\239!\160\030\161\t\235\137\176?\222S(X$\130V\141'\178-a\255\234k4x\002\0288\229\208Ce>\245\172}\214\163\188\240\184+q\003\177\132\254\031a\233\136ui(\147\194\2546\159\174\231z\149\249\136W\142\216\174\180S\174h\024w\248\160<\rnv\228\"\161\2100v\150\187\172U1\239\2402*Y\212\232\168!\181d$\203Mv\237\142\215\214\206\253I\011\165\223\176\236M\203&\183\130\129U\214\031\253\163\017\149i79\187'\191\140\178\186\252j\023<\247\181b\137L\236\177F\162\027\231^\155\182\127\128\243w\207\215\171\023\222\n9d,\172\178\226\232\nmW\001\200~rv_\030\133\188&\235\2338<\247\213\018\201\191\030k\164ac\165c/4w\019?\151\r\180\223K\031\135\231:F\198\016\128\128-\224\254\239\178\250q\172{*\246\211|P\158\022\203\127<\196j\228\028WW\134\n@\185Z\204\250\145\139\132\200p\150\155\226;\199C\240\185y\201\244&I(+\184>8\221r\226:\021\140,\188\182&-\175\001\147V\212\224W(s\138\242/\"A\178\249\240\172a,\174\186\220\167\143\162\014\161*\132%X\239\218\147\148,T\193\r\206Cs3\203c\161'b\224\1745)\161\139\248\220C\220\148\248\139k\192\150,\127\238\199\241y\015r\026\006Cy\007|\184\029xC\131\136\160e6!'mC\162G\237\151\170\154\000\160\237\153\204\193\200)\219\160\248Q,\225m\168\214\232\195\225\220\207\133\210\157\004C\147\b\016r\127\224\216\131\208\028\191O\139\199iJ\219\245\157\206\171\1740\128\017?pt9<\145\207\175-\197)\241\177\195\214\001\128\192\172\191Y}\159\128\251`\159\233\171]\165\127OA\001\216~\133G\146l\254Q\198s\017\247y\243\1420\0048FZxW\024z\253\029\143l\225\185A\143\000\241\135;\153\188\207\138=\1796\217\190e-F\142;%\189\166\215\200\207L\005\233zx~fl\224\184M\152\191nJ.\145\212\012Sr\246\156\142\156\1994PS\135KA\157\169k4\130\179w\182A\183\026\210T\175\151\215\223\250\011tu\172A\1656\149\027\165R\177\201\168V\027\203W\203e\171\141\133.\183\154\196R\217\003L*\181\225\207\249\211\173\005lV\001\149V\192b\023\208\234\143\0148}Zk\211@sf\206\178\142\156\221\159e2~\2458\228r/\235\007\"\226xg%\194\238\149Y\155\219k\210\178\231\182\231\204\249\179\228R\171M\206\214\149\177\208%\137\215\252\007\1656\145\247\007\132\253\131T\205\1390\2195\233\155\002\141\149\148Qq\208\b&\198\198\215%\183\185\225610\218\006\183\203J[\142\24677\155E\242\170C\163\232\r\1277\228\132)\200\238\1672:\188\179\169L~\1562\205\166\200\b\166W\2474\134\135%\225\176\226kW\137)\205\149^}9\205\182\004\212F\218\014\189\021\017H\181\141\166j\199\210\146,\184s~22\248\238\135\189T[pDy\208\149\1270\127\239\139\006\251\\]\021\157v\181\r\182e\230\212v\228,t\166\171\173\021n\145\220\199\145\211\168\2407\231\006\194\236UJ*\201\237\021+\128\217K:\236\151W C\161v8v\154\203T\152\146\207\228\185\204>G\1858[\249\011\194\254Q\138\230%\184\237\250\n\205:\190\210J\002U\\4\128I\173k\135\000\221\021\b\1558" let d_4fff47472c2ce7d1d0360d2345161ba6 = "7\217o\133\154d\153\202\187q\218QB\027\029\185\t\143ds\142)F\003\223H\170ma4f\024\0126D\140\149En\006\007\138\180sm\1751\027A\178\178\218\221\2360\173\218\178a\030\130\252\166\004z\148(\146\021\236[\134\138\229\025\220bR\030=I\242PXL\143\226\178\004\175\158\181\180\128V\193\216R)\240\1737 \224\221\025pr\022(\173\214Bo\216\155R\019\200z\004\000\236\160\182\222\239&PP\141\007F\221^\200Q\186cW\128\027wT\153\156\225#\003\130_O\236\248\206\207\186*I\172\244\145\b\213\144\2161\b\199\239\"\246\253\203\234\139\189\239\251\222\178\226q\141'\174\236X\152\133\208\142\153uj\197Aha\161X\242nfa\181\031?\181VQ[\1593T\215\023f\198\244\",\200\248\233\211\224\139l\025&\202J\020a[.\014\029mZ\248Y\139\225l\194P\128\1939 \005\022x\017wg\168\171\007\000\218\128\014 \201o\217!c\178\182l\160\024\026\003\168\244\228\1825\200m\161\174\168\178\232\234\133M\245\243<\178\003\004\137\133`\170{*\252Y\128\162\218:;J\167\238JKd\158\162\158\193<\199\240\002\221K\132W\173\227\181\183\164w\b9\210G\179U\031\251\132\230S_\2081U\232\0140|\143\233\007,?\194\253\164md\227\196\141\023_\023\137\133\237\016\134?\192\254\196\240\151\024\149\215\028\141=\2045\252\169\016\162\029\141\159*\192\017\240s\132\011M\145#\214J\188\207\220,U\017\017/\244\162\021N\015\0143\199\246?\248\192\193=\147?\141I\132\163\154}7\128\153\2204\188\1759\244\183\014\210\235\174|\166\180\243(W\141m\030Q-\143\136\149\014\165\210\177\183\182<\242\168\221\030\223\250\1969\231]p.\151B\030\141l\173\216\253\138\tCR\003|+%\198\127\177\230\194\180\180\211\030\223RiI]\162l\006\127\182\137B\142\227\191h\175H\1483\128a\003\193<\246\141$u\141\255\203\213@7\219\1853U\234\161a\158xH\014Z\135\180\195\196h\171\0306R\140\022\170\201iT0\216t\215\020\163F\1694\169Y\1433\215\230r\174\024\247\244#\222\220\014w\205\146[y~\237@\233\254\023\165\bU\132\150{\242|\005\225$\002\159GKFU6#\158\218\238\156{\166\251\210\152\136\179\026\254\130\164\141\022[\158\245\130x\138\234\016r\"I\242\233\141E\136\0257\139\t\146\246\220 c3\215SSm\1673\160\016X\016\180\022\188M\030\1404gb\235\243\026x\171\182\158\026\028\176V\219\147z(e\021g\204\003\204\140\209\183\209b6\154\002K\168\162\025F\141K\1520Vv\\\151\136\029K< \203\019.\183\174\199\177\178\177I^\171Om\198L\152\228\166\023\212\131W\217\176\181c\230r\155\163\188\132|)$w\148Y\255\150\005E\157\254\187{.F3\"\159)\235\r\\=\167\131\231\"\171_\222x\173>\146\187\004z\132\235S\161eS\0200H\134\021\184KsO\190B\029\220j\247\1333\177\026\203\148\152\188\144#\195a\018nC\129\027\2450j\199w-\143\207\200U\131\200\020 \001\011\226$E$l/\193\177\187\148\n\132\252\161L\189\1278}\024\241\208)\141\245\170\185\128\022\145nJ\193\184w\188b_,is\131Lf\139\151\245\128~\150\023\0270\223\020z\160\1620\172 \173\206\255\212\027\001h\130\250H\158Z\171\219a\145\237\128=2\137>\131\253\226\030Jg\027\r\154\241p\t\177\1739@\147\228\023}\218\151\228\1620\231\1405\213\235\208=\132E\180\237w\195\178\153Qv\249.5\217S\206]F\217@`l\210\168|!\018ECFs\172\028\027\145\248\164\205P&\186\150GI\163}\226n\016\003\218CO[\159[\192\148\130.\217rR\154\154P\162$\182\136\182zY\004\217\2168dq\b6\227)8\006\175\128\200*\2499E\225\206w\148\242\134\213\nL\222\204^\244I\178\\\245\217\1662\158.1\031\250\020\2397=\176Nl\213\007\235-d\bN\003\028iI7\029l\231\194\2061\018E0f\\\210\166Xx]\198\201\177\191\137j\178d6;H\140\167(F$w \240\0303\194\194\130'\1440\182\017\006\161\016\216x\237sI\251\2425\021H\000\211\203^#\225\204\245Sa\157\204\023\163\142\224rX\202(\254W\131\029\028@\018i\200\004\178Z\\\133\\\179\007\017P\175Ac?@U\163\170\2294_\209\031\194\"\025\164\138I\220\192\1916B@5\144$5\024\t\212Aj\233r%\005eP\221\128\2459`\159b\r\223\188\232E\191A\027 \203\240\027\127\130q\180\012\248i\174\217\143Rt/p\b7\211?\207\007P\142b[+\230.}6Nrx\030\161T\203\164\000\135\247\200~ka7\239\231;`ys\220\207\166\183j\207\234)\235\245\129\182\142\026`\0114I\195f\248\217\027\156\134\231\200O~\176M@@\168\218\18422\164\231\223\172\141\197\135\224\133;\151\210\026\181\251\144\021\014\237\153FS0\224\170\235w\159j\136\133\002\199\242#P\151\140-\0191\224CMD\183\214\155G\136\253Y\193sd\234\189m=z\189b>U\184Pp0\237\187bI?AX\201\217\2385\158K\244\196\"uK\170\031Z\\q^j\158[\\1\159Z\177\132\14512\030?\2064\187\138J\004\011\154\244\1476\229\191\232uQ\192t^\140d\163\232\132\231Z\244\204X+\241\164\183-\197A\239y\184\227\255*\177\129\225\006\202\199\130\171n&\247\189\244\154\153\189r\133O-\131y@\225\012\236\001\028\169-j\015\005\135\140\n_\170\199f2\218>g\138\018\185C\185\253\146\006\130\2553\149\167&2\181u\236\198\179\203,l\146n^\225\170\234\154X;r\237\233\203\179\186y\201Q\209\017[:t\229\201\203\147\220\188`+k\027[8p\233\241\2033\023\252\137g\173\150\145\153}\023\030\133;\1830\166\162\166\161=\2312\028\174\127\188\148\161\160a`\215\153\251\2150\161\011\230\226\206\220q\234.p\224W\179\190PO\234\196\173\231\230\225\233\188\202z,\246\252\129ZPU\131\133~$}CW]\133\005\204\253\159My;\197\188>\210\190\213Z\146\135\137.\207\022Tb\1740\014\184\204\177\209\145V\224\148\162_\239\\\165G_\238\223\011\159\020\189\011+\031\157\232\139+\014\187\012\024\168\016\128\195\144\145\016\017P:f\026\232\151\024FMA\154U\028\210\137\193\194\2170\230\203\243\025\185\015\022\240\143:\179\165\213T\153/\153\011\211\023\158\208\149gv\017@\249\167b\130p\1411\022)\141\204\234\023b\129\133\022Yl\137\165\150\2337`\249\223w\253\177T\169\159*\253\r0\208 \131A\184p\014T\146d(\176\194J\171\172\182\198Z\235\172\183\193\198\191\003\1875\1692\189\244\214G_\229*\026%\217\1341&h\205\015g\195\236\254\245\240\154clh\145\128\176\242V\003\136\131\213\b\169\213\233-\n\0213\139[\216\031\132\202p\016\143\210`/\230\\\r\213K\227\138\001\191\213+\000w#h\012\160'\180d/G\248\019R\191T\133V\133P\181\018\017\236\250\159}\202x\165]\133\171\016\0188$\157\194(\bA\166\208\149\1762\225}\186W\014%\201\150d\153I2\018F\171;\019I^*\190\207\2232\166\153n\134\153f\153m\142\185\230\153\239\164\215\222x\235\157\247>d\t\"\"\018\"#\n\162\"\0262@td\136\024\200Z.\024\178\241\166\130G\135\226\169\176\012\127rA )\162\"&\194J@\150\178.\254`\198\235\209k\130\137&\153\172\207\020S\ry\234\153\231\210N&\195\240$\019xqn:\140_\202k\155\131!\154f>\240Z\169M\243\218\007v\b\136\001\172\234,+L\200Ne{ID\158\005\217\170(!\176\194FLl\176\242\000B\";m\186\232\242\201\245;P\229\241&O\027\207\1362T\250\207\252\231\202B7\208\161\028=\136B8G\016\194\016\014\024B\233\225\183\157G\003'\160}\171t;\127\208\004\134F\020\204\195\22031G=(xg\232p\157F\025\r\193\197\2356\018.\217!\0068Ud#\002Y\196\230ZXF+-\131\216\189Vj\203\144\186&\250\233\138\218\144z>#G\133\145\170\004m\015\226N\146\016\138\200/PPnM\218\254\198-?\155 N6\146\248\001\165\005\t\255/\180\209\192\017\160\029\023]pT\029\004#\025\254\191w>\222\198\000\242NH\229\129\030\005(\2372\b\232[\185\128=\219\017\190\127\203'\148\185\128\249\002\016a\012\t\249\234\244\127\225^\147\178/\199r+w\138p\002N\197oD\199\199\152hO\225:na\026sXG\019\031\240\181\243 \137\239\235\186\173\245\203\235\147\203\255\207\023\180\194#\"\1834b\019\1797\211\149\1287\192)\151?Ykj\203v\199\190-\238?\128-\128\138\007\248\255\172'=\161\238\134\003\254o\244\159\031\255\002\240\217o\128\207\030\221\249\240\236\199\141\031K?\250\173\241\245G\163\031~\178\127/z\n\002\230\002;=\001y\204~\142d\030X\197=\167y.[\021\007\0281\228\185\191Y\206Q\188\225\206\218s]3\236\184\189\142\249A\199\236\226\176$g\029\006&S\028f(\254\223|\225\178a\203\142\003w\002B\"b\018\222|\248\146S:c\151\179\025\193\137\248\160\018*L\132(\241\018$J\146!\139V\142\\\005*T\209\169VK\175I\179\022\173:\156\138\005\167\253r\216AO\189\244\204\171Xj\162\183\166\140q\195o;\194\209Ws~\154hK\164\252I\t\187#c\147\177n\218n\155\029\014\235I\nN\208H*\157\165\192\227\011\212U\213\132\028\145\145\190\129\216\208\127\198R\235X'%\163\224\161F\016\127\001\212\002\005\011\017.N\180\024\177\210%K\145*R\190\018\133\138\148)\246\213\139\026\213\169\215\160M\165vn\202\227i\1686:s\213\021w\221s\199\193\175\014\144\157\175\023@\136\188\181\243\243\224P\176e\205\024\024\004r\233\029}\175W\242j\211G?JS\016\175]\203\003;\255`?\223\161|{\229\184\185\226\232=\012\145^;R\139\255\2130B\221\211\174\017!r\226B\1555\b\024lA\002\182\139aA\n\244\193\247?\242\244\170\030E\157\173^\1392;!3\127\252\218\137\138I\239\192g\1357\238\204=\245\166\150vGv\223=\178O_\236sD\154M1I\137\153\208\225\253(\012\145\030b\003t\030t\179M0uSJ!\141\007\127\230\012\137KW\137\1421\200\187^\144\001-\144[\236\131\130\135\142B-\165Z#\226I\138\130\028**\232gQY\184\137\236\136\145A\158\187T\138\212G\246\"#.\145\202m" @@ -250,6 +252,8 @@ module Internal = struct let d_95bcc9f523cb0c335564418b86d5f90f = "wOF2\000\001\000\000\000\000f\160\000\014\000\000\000\000\210X\000\000fG\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006`\000\134T\bZ\t\156\012\017\b\n\130\215$\130\136/\0016\002$\003\136t\011\132>\000\004 \005\136x\007\142E\012\1292\027\173\167\007d^\011\158\187\029\216\241\2542\207~$B\2168\128X\027\182\143D\216\132M*\155\232\255\255\188\164\"c\166\217L\211\r\021\016P\253\185R\t\171P5*\206\130\151\137\137Be\028\178\145\1343'\238.\228\163\200\232\242\012s\021\0314\2134\176\210-\019j\221\251n/\175*\166\142\007?\185\184b\158jq\211\178_\151\241F!!RAQQ\n'\012\147#l\236\"\249!\235\023\227\247\193\136\137\180\227\178M\188\163m?\1631\153\250\175q#\186\1853\254\197\127\254c\134\184\152\160\134\005j<\232\174n/Q\139\014\241\187\226>p\006\182\141\252IN\222\225iN\255\221]r\185\248I\028\b\017\002\193B\004\018\164@\226\016\002$\144\224\197\172\134U\168R*P\170T\196\215U\214u\149\253\214\127u\149\1911\173nk'mg\237~\167\133\224\185\159w\191r\245\188hb#\223\004\135e2\134\198\n\158\255\231\254\219>\231\1907cS\127\250\252\197\002\r4\0128k\165\t&\152\209X%\212\255\190\211>;i\030\2163lxo\017\208\137\031\000|.\144t\246\207\222e\233\202\177S\142\029\192\150\003m\166\029.\160%-\1947\208\160\155\253'!X(!\224\133\154QQ\174G{=\019\127\186\191\237\239\186\204\127\020[\223\188}\168h\186D&\244v;\223(\174\185*\028F \r\022\227\130p\024\135%\000\254\250\166V\191\236_\247.7\b\012\137\133\230\181c\025B\232\000\247L\219\171\219S\194U\231e\024\221\177t\199#\201\137\002l9\192\176\161\001\195\002\241-\218\213\204\219\193~\152\241o~\254Z\246\0121\t\217\147L\211\rb\242\245\245\208\148t\141X\r\209\12717\242J\250\136\169\181\137x\169\136W\142\030\201op\254\193y\019S\127\172\019\014\167w\247v{gk[\183\208\150:TT@\n\140\178\169\030.@\134\011\237=$l\1796(\249\207_\212_\212\234\170\209\153\251\"Dn\251K\134\146\023\020\007\"\162Zs\137\181\237\131\218\028\144\178;\207h\203-\233\233\185\022\192\031 \241\199\206\208\178j\005\016\017O\221\248\023xA\012A\019\004\024\232\n\220M\215L\018\132\244\239O~\189.\171[\179\248[Z\020TmN\148m\148\152\181u\136A\234gg\175\029J\255/\209\140\143#\198\202\199\210\017T~\149\223\255\153j\182\187\208\005\242\"u!\135\215\167\234\\t\206E\233r\246\207\000\139\153Y\128\192, a\023\140K\233\025\\\144\207\004\150\186\003\247\018\t@\204\210\165\152 \136J\160\228\167#\149\"\229\028B\149\155\218\165\155\210E\025S\239\186uW\133\162qk{\254~\159\206\2049\247\167\202\022\200\154\189\200\173\166\n\171\178\n]\129\196\005J`\222{\247\182,\252d(\179DQ\139c\149\226a,\198\132I\254\182lvy\191Qj\151Ht7\146\174[\185\147\215\141=\161\207\bu\247\151\213wQe\201*m\210\136\b\197\1559\\\255z\140\185B\179\241c\247\188\153)\225\t'\028#\178_\246c\025\211\250e{\251\215\238tVQ\216\t$\160\255\026\232U=y\005\184lI1\015\000\206.?A\007\224\207\014\001\176\136\223:\180g\b\204\195\225\251\128\159:\224\249\229Y\227\127\029\191\016Y)\246\134(\254\169\0213\1443\195\012,}\225\000\128\190\219\000\128\194\184R\134\160\130\133C\217h\218\204\254r\185I\031\148O\141\153\182\218a\175\131\142x\223\007\174\240\025\015y\202\027{\022\215\018\252\1837\250E\239\207\202\t&\154\137\153\154\217I\166v\131*\n\197\192&\1820Y\180\189\253\196Wv\213\211Xs\157\244\214n\237\215\135:\175\155\250\004\160\026U\172\202T\165\170\207\148%\134#\176\227\204\029\007.r\200\199O\029M\140a\026s\024`\t\235\216\197^\174p\149\159\248E\205VO\220'\028\011'\195\135\225b\248)6\196\t\233\251\244S\2503\230\239\184\236m\245\031\190}\011P\1683F\222\179\246\225Q\159\202\255\151\139\158\242\149^\235g\253jV\188\191\226\169\222\192\138\\\209\183\177\205\205f\242k\231}:\163s\242\029\185r\186{\143\001\139#O\007o\164\157\169\2443\127\2440\219\229K\242\203'\199\212cW\029\1866\142K\223\165\151\137\239\234y\251e\250\246\235?m\140\206\156|\255\232\145\157+\151\012Ni\194/\243\221\246\2044\204\207\255\254g\127\2517?\249\241\143\026\236\217\177i\2456\185\238Z]z\184\216\223\207\203]\031\137\193\226\252\230\023\207\030|\243\224\148\147>p\194q\239:\228\160\003\246\217k\1435VZn\216R\011-\208k\178nMj\140V*$_\030\189Z\024\243\223\150\2552(\144\191\188rr$y\225[\138)PI\197\235\031\025k\147\226?y\208\188\"\165\242\027\000Mh\243\255\007\030\006OB\138\144\148[\161_\223\244\255]\179\252\139\242]\254^\227\215\204\2394\151\tN\195\216\128/g\128\158|\161p\24630\154c\237&\206\145O\175\137,\157K\210-\249L\246\157\247\004\151\004\2032\234\000\020F\029\018\130\185d>$\130x\241Cr@{\200\141__\210\134&\017\163\0224\222h)W\151\137\184\189\000\019J\196&\181\196\199\139\014U*\140\202|y\215\215\166vt\226\194\210]\196)\162\157\025\204\026b\031\031\028\132\003\235\156\128z\148p\n\231\180\025\016\141H\142\183EK\135\022\252\174\225\204\226\207\174\022T\142gc\n\027\193\179\027\2056\127\005Lu\249b\153\007\199wtA\b\198\165\166\248\198PX}jY\147\222\n\170{\186\172+(}o\1299\242\143i,\017\026\011,\215\196H\2013\148\134\177h\214Z\130\200\152\224\140\224(\016l/\169\207\253Nz2\233\153\189t\198d&P\240\140\151\204\172MF\232\193k\128dsA\135\1626$\015\140Al\169]\234D\174\007\172S\165\132\134\243\190\167!\025R\1767B\201\237\"f\138\1890\\\205\233\015\155\024Qb\235\201w\252\227\226\0199\247\250{\240\210\173\151\137\227F\136\235.mZ\016\243\006.\156\005d\142\022\175.\003\r)\1302\251\029@n\150\164\150\178\170\128`9X\"\202\230\132y\140b\199\1542\1286\149rv\134%kQVs!1\166\199Q>#\130N\030\020\142\181\231\003GR:\006\146\150\0001\160K\185\142\216b\214\156\139)Zk\011\0168\004\165\232S\185`\177\0249ch\163>\250\163\030\030fiH\0069\231\018\133\001\205\236P\237\151\234\198z\240N\188\245_Ys\205\018R<\190I\0245N\r\018J1\139\179\242q\225\160\005\000SG\132$\152\251\132!\\\143\152\141\165\002\218\216\0144T1&U\165\170D\137\"\158z\211\023\192\136\\\021U%@\178\n\019\166\197\234n\240'\159{h\178\133\131\002l\015\129p\005\225\t!)\014\1900\002\241HI@Z\"2\146\144\149\188\216\128\208\255%\133\228\203v\016T\132\015\201\018\153\251\205\189M\199\159{\182\154\021\127\249\180\028\150\216\186\153\235\132\233\241:a\023\204c\1589\022\018\142\162\016J\226P\022FE<\170\018P\147\136P\018\234\146\215\218@\029\176\232\236\141\244\0184r\029j\\\154\028\133C\237\152\021\012uQ\245\187\245w\146;\165\007`\noZ\146\150\229\196\158\191\000s\198K}\178\178\nmlD\220\212\216\235\020>L\140\195\0193R\027\216'\127\145\134\bx\137\188z\nK\172\143\r\149\2002\199\146\187\222\002\2067xp\173\188\149\229\018\005\219\212;e\b\212\152\226\143\017,kd\018\211\168n\214\159I\138\219\162\128*J{\230\b\005\201\164\161R&A1Y\018\159\242\143[z\216\ta\223\141\186\153\170]\028\224\196\181\158L\029\131\192yw\1830\1827n\023+\t\185\022T\216?\200m\005\234\028\195\145\204DP\193\133(\020|\194\232\194\030\198\148\204\133\147p\136\151\175\228\220i\199+\190\233H\155$D.J\196d\018u\175<^Y\028\237\200\187R\001\204\216\ny\166V+\151pr\200\226H\151U\198H\002v\139(\147\180\236\172I8y\199\210\t\149\156a\196\156\t\163Ra\209\025\006o\201gme\018G-\152\241\t\241\161\169\213\211\140D5{\024\005\017\204\003\216\"\000\150\243\200\130r\229\150k\183C\027\150\221q\155\223a\023\000\251\000\245ak:\030\221\241\228\142gw\188\228\012\215\000\184\005\168\239\208\244|\184\231\211=_\238\249\206\025>\001\016\235\143\001z\203\r?\225S\249d;S\ns\029\174T7\130x\231\205t9\182T\146[[_\156\173K\r\139\001\016\232\191\005\000\128\1746a\248)\145\190Z\167~d\192\241\142\030\014\227\004\144?0\014\023\006\130\166{\135X%\204I\022@\196qE\149\197,\231-4\170\139|\004\212M%RR\243\188eU\236YP\142B4\004,\151I8W\155\214F\b\239\248\144\029cO\004W\238eNeY\165r\017\"\195\170\130\\\141\001\132H\204sP\164\214\196\233\144\231\222\017h\025\233P\159K\190\253\166\127\176!\184\233W\239T\194\152Q\223?!\187\026\137\r\221\2186\152\159L\205;>\166\204N\023\226\227\018^k\219\131\170i\247\028Ji\210ST\127@\175\173H.{\198B\016l-_\173\213W\158\186[C\223\173:\195<=\180\142\230&\189\227\135\197\142\164I6^`u{\016\178\1782\218b\201S\154\165\229\135\230\015'\1829OCsm\171<\219\217\191_\234/\147\153\204\155|\160'4j\232\217jp\161t\251\170vuH\r*\209\142\202\1787nd\208\178\205\176n\007-\191\1782\154\214\210D?H\140\189\132\223\025on)\202\211#\198)?\b|\127im\134R\170\151\239G\187\177q`\254\170\127\011\007\213\225\242\211h4\153\159\026FI\207\181]/^\024\196\155\250\186\017\b\177\237F\166I\165NO\2021m\1392\154\025X5\205\244\137n\2303\245p\020U\154$R\212~7\151STJ$\146&\030\t\130\211\211J\189\211\238H\031\1640g\016\157\152\166+\187\021qU\213M\016\"\187z\194\245\025\211\153V\176\004\218\017+\132\206B\186A/\243A\1741\209\133$1\004S\204\004\147V-\199\206<\213%w\162cV\134auc\018\187\139S\151\161\212\144t\133W\176\139\161%}\018\030\197\199\137\031Ez(\193\228\208\247`\220\141\004\tf\r\000\014\199\189MI!\021\198\0151\143A\219\007\175\186\136\220\223\140\018\2100\1678\022\250\178\020\140\184\023\245\160\177\172gP\161|\138P\130\195\130\131\1363\134\020K\021\223\142,\160\031\154LD\000j\237b\028\226<,\163\\_\215Q\001\007Yq#ffk/\155\229Bo\003\220\161\149&]M\024\031\221\026\132hP\192\220\004\216L\026u\208-\133-\149\247l\196j-\227 X\1950\166]\134E\1809\1895\1421\131\139'\144\0271\154a\250\"`\162\236w\147N\19942\234\002\230\016\001p'2\226\229\\\163i!\021{\128\225D\233\255\145.\179`q\233\226\0311u\200\242B\0293Z]m\216\2295b^9\002\180\203\143\025\189\209\161\022o3\001\226\157\142\209\229Ka\\\000\230\140\136\179%\027\169\234J\131k\166}Q\189V\197!\028\212\166\196\133.x^E\204N\154\142\"\140\030ek\196o\149\170&\171-<\232\150\145b:\128Z\166\238\004\204\019\136\252\132)\0038\007\240\205\180!\155\248\012\006o85\207y\206\171\170;|:\179y\b\135X!n\131\146\138u\t\004\007\205$\253\163F\019\182O\172/\231\003\214_\150$\235\233\210\157\132\252\147\014\028\199m=\"\162\162\004\007@\1321j\179\002\219L\188\1559\149k\155\005c1B\029\222B\195\nq\144\029\153|\158\02007r\183|\165@\137\155\020'u\153\017g\153\1627\232\137\172K\241l>\234\197N*g3IN\231 \142\149J\194m\165\022Bp?\221\205\017\198\226\173\200\145\014F\250\012E\254\024\194\255\019\146\248\172Z5Gd\183u\021S\247\225\243~A=\021\173Z\018YH1_S^#^\217X\167&\001\014\012\206\0293\204\160\166\230\017&r\164\171\2274\181qFE\1764\203\172Rb&q/\202\208n\216Z\145\134\208\148\1713\191\148\247\005\243\179\128j\"\149\219\195\160\164\146\181\018\224`\142\"\148\024\196\177\0179\255D\178Zx\029\rA\1550\202\174\007\227\132\205;\152NM\152|\165\182\004\141]\226\131;\160\152\012\141\239\176\165?\151WDV\220\001\134$\152\205\196\164\006\029\238\224wDL\170\169} \152`\160\185\166\215P\172\202\152`12\140\142\215E\207\174\228]\216\166\0038T\197\165\0195mLI\146\028\134\237\002I\2288'N}!\020\0113l)\215\136\223\001:\164\204\017\137\207\202C\239\1687z\163R4\217\023\137\183\244\236A\020\197\240L\205\028\142\131a\130X\170\186\020\197\na\176\216Z\027" + let d_95e6d8b2e4f4e5a25b3f27c86326a4cd = ";\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/\n" + let d_96c4d8e2622ac6552ccf67643b20f09c = "\",\"\\u03a1\"),ie(oe,le,xe,\"T\",\"\\u03a4\"),ie(oe,le,xe,\"X\",\"\\u03a7\"),ie(oe,le,xe,\"\\xac\",\"\\\\neg\",!0),ie(oe,le,xe,\"\\xac\",\"\\\\lnot\"),ie(oe,le,xe,\"\\u22a4\",\"\\\\top\"),ie(oe,le,xe,\"\\u22a5\",\"\\\\bot\"),ie(oe,le,xe,\"\\u2205\",\"\\\\emptyset\"),ie(oe,he,xe,\"\\u2205\",\"\\\\varnothing\"),ie(oe,le,de,\"\\u03b1\",\"\\\\alpha\",!0),ie(oe,le,de,\"\\u03b2\",\"\\\\beta\",!0),ie(oe,le,de,\"\\u03b3\",\"\\\\gamma\",!0),ie(oe,le,de,\"\\u03b4\",\"\\\\delta\",!0),ie(oe,le,de,\"\\u03f5\",\"\\\\epsilon\",!0),ie(oe,le,de,\"\\u03b6\",\"\\\\zeta\",!0),ie(oe,le,de,\"\\u03b7\",\"\\\\eta\",!0),ie(oe,le,de,\"\\u03b8\",\"\\\\theta\",!0),ie(oe,le,de,\"\\u03b9\",\"\\\\iota\",!0),ie(oe,le,de,\"\\u03ba\",\"\\\\kappa\",!0),ie(oe,le,de,\"\\u03bb\",\"\\\\lambda\",!0),ie(oe,le,de,\"\\u03bc\",\"\\\\mu\",!0),ie(oe,le,de,\"\\u03bd\",\"\\\\nu\",!0),ie(oe,le,de,\"\\u03be\",\"\\\\xi\",!0),ie(oe,le,de,\"\\u03bf\",\"\\\\omicron\",!0),ie(oe,le,de,\"\\u03c0\",\"\\\\pi\",!0),ie(oe,le,de,\"\\u03c1\",\"\\\\rho\",!0),ie(oe,le,de,\"\\u03c3\",\"\\\\sigma\",!0),ie(oe,le,de,\"\\u03c4\",\"\\\\tau\",!0),ie(oe,le,de,\"\\u03c5\",\"\\\\upsilon\",!0),ie(oe,le,de,\"\\u03d5\",\"\\\\phi\",!0),ie(oe,le,de,\"\\u03c7\",\"\\\\chi\",!0),ie(oe,le,de,\"\\u03c8\",\"\\\\psi\",!0),ie(oe,le,de,\"\\u03c9\",\"\\\\omega\",!0),ie(oe,le,de,\"\\u03b5\",\"\\\\varepsilon\",!0),ie(oe,le,de,\"\\u03d1\",\"\\\\vartheta\",!0),ie(oe,le,de,\"\\u03d6\",\"\\\\varpi\",!0),ie(oe,le,de,\"\\u03f1\",\"\\\\varrho\",!0),ie(oe,le,de,\"\\u03c2\",\"\\\\varsigma\",!0),ie(oe,le,de,\"\\u03c6\",\"\\\\varphi\",!0),ie(oe,le,ce,\"\\u2217\",\"*\",!0),ie(oe,le,ce,\"+\",\"+\"),ie(oe,le,ce,\"\\u2212\",\"-\",!0),ie(oe,le,ce,\"\\u22c5\",\"\\\\cdot\",!0),ie(oe,le,ce,\"\\u2218\",\"\\\\circ\"),ie(oe,le,ce,\"\\xf7\",\"\\\\div\",!0),ie(oe,le,ce,\"\\xb1\",\"\\\\pm\",!0),ie(oe,le,ce,\"\\xd7\",\"\\\\times\",!0),ie(oe,le,ce,\"\\u2229\",\"\\\\cap\",!0),ie(oe,le,ce,\"\\u222a\",\"\\\\cup\",!0),ie(oe,le,ce,\"\\u2216\",\"\\\\setminus\"),ie(oe,le,ce,\"\\u2227\",\"\\\\land\"),ie(oe,le,ce,\"\\u2228\",\"\\\\lor\"),ie(oe,le,ce,\"\\u2227\",\"\\\\wedge\",!0),ie(oe,le,ce,\"\\u2228\",\"\\\\vee\",!0),ie(oe,le,xe,\"\\u221a\",\"\\\\surd\"),ie(oe,le,ge,\"\\u27e8\",\"\\\\langle\",!0),ie(oe,le,ge,\"\\u2223\",\"\\\\lvert\"),ie(oe,le,ge,\"\\u2225\",\"\\\\lVert\"),ie(oe,le,ue,\"?\",\"?\"),ie(oe,le,ue,\"!\",\"!\"),ie(oe,le,ue,\"\\u27e9\",\"\\\\rangle\",!0),ie(oe,le,ue,\"\\u2223\",\"\\\\rvert\"),ie(oe,le,ue,\"\\u2225\",\"\\\\rVert\"),ie(oe,le,be,\"=\",\"=\"),ie(oe,le,be,\":\",\":\"),ie(oe,le,be,\"\\u2248\",\"\\\\approx\",!0),ie(oe,le,be,\"\\u2245\",\"\\\\cong\",!0),ie(oe,le,be,\"\\u2265\",\"\\\\ge\"),ie(oe,le,be,\"\\u2265\",\"\\\\geq\",!0),ie(oe,le,be,\"\\u2190\",\"\\\\gets\"),ie(oe,le,be,\">\",\"\\\\gt\",!0),ie(oe,le,be,\"\\u2208\",\"\\\\in\",!0),ie(oe,le,be,\"\\ue020\",\"\\\\@not\"),ie(oe,le,be,\"\\u2282\",\"\\\\subset\",!0),ie(oe,le,be,\"\\u2283\",\"\\\\supset\",!0),ie(oe,le,be,\"\\u2286\",\"\\\\subseteq\",!0),ie(oe,le,be,\"\\u2287\",\"\\\\supseteq\",!0),ie(oe,he,be,\"\\u2288\",\"\\\\nsubseteq\",!0),ie(oe,he,be,\"\\u2289\",\"\\\\nsupseteq\",!0),ie(oe,le,be,\"\\u22a8\",\"\\\\models\"),ie(oe,le,be,\"\\u2190\",\"\\\\leftarrow\",!0),ie(oe,le,be,\"\\u2264\",\"\\\\le\"),ie(oe,le,be,\"\\u2264\",\"\\\\leq\",!0),ie(oe,le,be,\"<\",\"\\\\lt\",!0),ie(oe,le,be,\"\\u2192\",\"\\\\rightarrow\",!0),ie(oe,le,be,\"\\u2192\",\"\\\\to\"),ie(oe,he,be,\"\\u2271\",\"\\\\ngeq\",!0),ie(oe,he,be,\"\\u2270\",\"\\\\nleq\",!0),ie(oe,le,ye,\"\\xa0\",\"\\\\ \"),ie(oe,le,ye,\"\\xa0\",\"\\\\space\"),ie(oe,le,ye,\"\\xa0\",\"\\\\nobreakspace\"),ie(se,le,ye,\"\\xa0\",\"\\\\ \"),ie(se,le,ye,\"\\xa0\",\" \"),ie(se,le,ye,\"\\xa0\",\"\\\\space\"),ie(se,le,ye,\"\\xa0\",\"\\\\nobreakspace\"),ie(oe,le,ye,null,\"\\\\nobreak\"),ie(oe,le,ye,null,\"\\\\allowbreak\"),ie(oe,le,ve,\",\",\",\"),ie(oe,le,ve,\";\",\";\"),ie(oe,he,ce,\"\\u22bc\",\"\\\\barwedge\",!0),ie(oe,he,ce,\"\\u22bb\",\"\\\\veebar\",!0),ie(oe,le,ce,\"\\u2299\",\"\\\\odot\",!0),ie(oe,le,ce,\"\\u2295\",\"\\\\oplus\",!0),ie(oe,le,ce,\"\\u2297\",\"\\\\otimes\",!0),ie(oe,le,xe,\"\\u2202\",\"\\\\partial\",!0),ie(oe,le,ce,\"\\u2298\",\"\\\\oslash\",!0),ie(oe,he,ce,\"\\u229a\",\"\\\\circledcirc\",!0),ie(oe,he,ce,\"\\u22a1\",\"\\\\boxdot\",!0),ie(oe,le,ce,\"\\u25b3\",\"\\\\bigtriangleup\"),ie(oe,le,ce,\"\\u25bd\",\"\\\\bigtriangledown\"),ie(oe,le,ce,\"\\u2020\",\"\\\\dagger\"),ie(oe,le,ce,\"\\u22c4\",\"\\\\diamond\"),ie(oe,le,ce,\"\\u22c6\",\"\\\\star\"),ie(oe,le,ce,\"\\u25c3\",\"\\\\triangleleft\"),ie(oe,le,ce,\"\\u25b9\",\"\\\\triangleright\"),ie(oe,le,ge,\"{\",\"\\\\{\"),ie(se,le,xe,\"{\",\"\\\\{\"),ie(se,le,xe,\"{\",\"\\\\textbraceleft\"),ie(oe,le,ue,\"}\",\"\\\\}\"),ie(se,le,xe,\"}\",\"\\\\}\"),ie(se,le,xe,\"}\",\"\\\\textbraceright\"),ie(oe,le,ge,\"{\",\"\\\\lbrace\"),ie(oe,le,ue,\"}\",\"\\\\rbrace\"),ie(oe,le,ge,\"[\",\"\\\\lbrack\",!0),ie(se,le,xe,\"[\",\"\\\\lbrack\",!0),ie(oe,le,ue,\"]\",\"\\\\rbrack\",!0),ie(se,le,xe,\"]\",\"\\\\rbr" let d_97a004cb2bb68cf384863688a3675de3 = "j\239\230\025\005E\016\187\137N\191X\186#RXYJuZw\214\157\209Sc\005\191\131Ia$\157E\236\170\016\243\027\177\165!w\225-\155\226\219\253\220\179\197\138\212n\021\187<\186\150\019\172\214+\029\015\162reK\252,L\028\024\226\228\228\153\163\024\228\130\163\221\212\235\241|z\139\016\203\192\252u\180\212q\t\163!$pj\2141\152T\193\194%\164\167I\158\162\192\005f\018* 2|\017k\232\242\"g#G\209\171\2145\246\127\001\t\204\011\157\213\160\168Ok\179\158F\014U\134N\195\132s\142\172^\165\168a\000\202# X$\208\193\0176e\226i\183dY\180D\145\130\2136\005\225\221\170\146{\142*\n\2002Q:J\145\196:\139\150\176\250\238g\0036R\168\131z\016\143v,\014\181\154\225\209\143\214C]\r\154\137\239\182\1646\137X^\"\159V'\142E\190(`\193Y\225\024?\1747\2050\177\006\139\149#j\\\020\179\230\201A\205\223\197=\007\157\159q\165\234\030\159\017\183\151\018&%K'\203Y\217\029=F\208$H\231\238\160I!\246%N\129\144(\193\004\207\215\147\180\237\016zj6)\172\186\149\180\012\155\027#\2086\190\198\015\201O\128q|o\031(\228\129\018{7x\2080\btr.NRt'\2149\018\018\217J\016\237\191\014I\148\020n\194- \130\224\029\188\141\212\134$U\r\017V\015\138.\243U\146R\130\160\227\202\142\153\136\r:\209h\182A\131T\205\128]\022*\004\000%L\194\182\167vO]\136\025\023?\028\158S\0278T\189\166 N\202\247!\137\186c\181\174\229e6m3\227\243\146\228\180\208)\027p\b\142.\175\190m\175\163b\208\169vF\163\224\185\191\224\212*a\016v3\027\018\253\138\231\133\247\1887^\1842m4\234\220;\237\165?p,\175R\179\130v\166\127i\1740'W\206a\234\242|blq\212\180\029w\250L/\159\22237g\129\141\153}\1842\214\166\242\255\206\145:7+\017U\199\160j\150C\153g.\149\180\030H\003\169#\243\139<\172\129\nM|t`d\018\200\189o\129ohp\193\181\162\216Q\161g\\\025aP\175\173]m\031\249\198\187##vb`6rr\164\136\202\228\179\210|\147\189\247\014:\191J\t\241\212\2013\029\ro\138\142D\243\023_$\168\251w\217\139RX\019\179\1645\254\238\194A\208_\247(n\255\204Z\023\156Z\146B\230$\005\029P\002\164)E\029\131\168\011\177\012\201\018\184\228`\147Em\154Eb\177 \r<\223\205\204\012\223\135000\234\129P\217^\027\253\239?\021\136\160p*\024t\"\229\1600\011\001,\026[^I\230\028\228\192!\218\157\130\021\137\160O\027?$\201\027\236\170L\208%\0155]\232\218\203\223\0174S?4w\023\016\146\146\134\225y\2266Ud\031\142\171\234l40b\223p\182\028\156i\150\201\185@\240Y\171X\024\201r(\171w\026\255g\131\243\146\210\007\012\173\028\151\239P\147\167\178\241?\204\nCH\026G\241\232\242\224\204h\183l\031\177\249C\021\239\204;\237;5\200\236\249u\205\185i7\171\027z\165\028\172\029\023\018?\\\030\183~\226\184\232\181\137\183\198\151!`\223H\224\2523\146 \176\218_\b\019`\248(\003\242d\185B\212\016\214\192\201\253\232\1594I?g\218Y\005\030\242\007\169$\207\178\234u.\251]\132\249\175\134\175\245z\176\238\r\026\220a\018\\\159\205\1855\011\158j\014\024;\201\\\025\132o\197O!#\137 I\018O\129\223\174-\213g\228H\187Y\218\128\020\204 \189\229\248\194\246\184\190\004W\183\153\137\152i\193F\1709\164\187\241eO\012\204f\206\178\237\208\224^\006\242\215}\199\161U\017\162\142\167nF\002\005\156\236\216\230\2503\251g\191pk\178\003CaR[r\246\238\130\r]\247\236,\012|\208\011\194\2436&\162\021\202\140d\160\185x\204B\130\167\145/T\242\137\160\154\153\140\244\244\139Da\214\156\025\216\019\129\149k\250\147\133\017*\226\018C\151nW\168\211\170NTs\195\246\232\194\b>B\2430\251\179C\146;\242K/\175\209\006\130L\223\224lE\215\248R5+\212\005\234_4\210:\138\020\002O:6\233\236\216\236\2387 \237V\215D\219-\187Gj\145Lg\224O\171\019\176\140\226\254<|\164\011\188z\159:\003\203\219J\164\129\171\005\253KS\242\226O\0271\217_*/G\212\157\1470u\131G\174\206\161\219=z8~\244\007\r\217\239%3L\026_\026\217\210\022\249>\232\225\165sc\172(\017;\220\2044\144\248\224\237\235\166\238\237\176\225\127\2371\169\156\204\134\004_?#Q\160\183g\236\154`\015\025U\222\018j:{\251\198Q\243pC\170\0078\1572\127\157\199\b\207u\240\235t\028\015\030@\157\215\133\178\137Q\237\188#}\191\210j\n\163mE\160S\158\017\163o\239\146n\152\213\221\141\246[\157sL1$\207m\138\168\184\182m:r7\233\138\222\251L\168\199\169\210\b=\138s\130\241\192\186\0253\151\200\216b\144\211\238\019\253\199:l\021p,\173\186\186\000\238p\026\\\016R~\003\170|Ap^ @\149?\161\137\169l\239]\215\198\180\175\181\236\017\030\018\196\238\147Dk\140\\xp=\006\253\219\231!-S\223\207\144\023\186I\183^H\029l\217W\232\223.\\^\222\184\218\216\157UL\218\143\012F\143'\1717\218\254\223v~\200E\005\157\178\168\158lG\185\194\225\149!&G3.M\014\127D\142\158_\149(+'&4\222\025W\151\238\157\170\192\007C;c\239\021\017\189Z+\214u\239\219\138\131\198\183\tH\233Pp\190$m\179\238-\238k\143\130\000c[\167\028\146\204\149\255\173\027\166\238D\232\1865\198\177\180\1341\014\231N,\004\206\152\187\rO\152\139MBy9UPp\002\0074\227\029\159\170\229\182\170\024wb\192\144\252\243\011 \011/\144\201\136\215\002\1401\023'B\249[\177\026\n\210\162\130@g6\031\003C7\131\140\187\168uP\168\146\191\223\190\155\201\131*\021\016\132\228\\\196\247\003\215\154=\139\205C-\170\019\186\176\156\bA<&\004]\192S\024).\135@\242\185 H\rWU\189\019\169\1402\t\218\199\221+3\129*c\161\202h\227\023\014\160\199\2461\012\217\229\134\153p7\138OE\021\"\233\176\239\023\014\232-'\206x\157\140\139+*\198\233\020}\0029\142\012M\140j\223/\197XB\238\202\137\146\027\195\206\246\143\253g3\235\t\172\245\031\248\227l1\198N\135J\185\161\226\169\0208\202\218\249rL*\243\2099:sw\188\1581\193\195\136\160\212\243\222m\205\149\018s\247#\212@\153\1479'\215\031L\245\019X\253\031p\183P'G\199\192\178\206l\175\214|(\158JA ie\193\234\214\177\027i\157\012\191\152\208\236l\018\161$\030*\140\135\018J\247\167\016\150O\222\028\ni\178i3\183>\152x\170\141\232U\180\138!\139?\016\221\031\127\190\235-Aw\230o\174\254\007\175\150\031\202\220*o\227\172/R*\202P\191\139\142\029\212\207\211 f7\215z\231Y\156\149\246\012\200\2195W\207\199\202\193\132\168\nF\157U\220\180\185?\006f\148\n\023\207D\021\026s\228\027l\250-\163\236\255\165?\220x\185r.v\214#\152\158\030\237\249\144\157\133\192\024\024\249\245\194\145h\b(\164\206\178\194\028\129\006A\133%\184\166U\022\228\215\255?\154\140\216\2282e\030EY\169\175\187\247\224\195\161\240\rNZ\184\004\139wy\204n\233]\213\196f\226G\206\244\229\t\1460 \214\221\130c\248*\017\017\137e\196V\200m\226\206\0192 \176|\242\139+O\166\195\1831\024C\176(P\022\176.\180\014\235.\192\249V\011\194+F\202\003;\153\149\bK\131\026\195=\190\171{\242\194\155\179\228\151\182wP9z\207\178\184\190iq\030O8\185\171\240F\026\017\165\030\157V\241\211\230|\211\254L\143h*\178\216\196;l\192Vm\019\237\244\181\161n\254\195\179\221NI\208\171i}\004h\198\127\208\140\245\132\012\227\002\154\150\134\177u\1765\023z;\231@\025\180\168\216\221\167\176\241L\225\159\158\156Ae\231\207\211\247\164\195H\161Y8\199\221,\213\183\r\174\131/\183\001\217d\191\162\162\226\250\144\003\187\142\237\242*\198\213\194\180\146\225\162I\191\002\024eF]\004U\006K\167P\188\179\229\017\134\162\157\158vc`\159\030\130\224\137\202I\216\138\018\004\213z\216\215\239\142dS\020\233\162\154\174\005\t\b\014\147L\153&^L3\133\198\175\191\236\243\197\191\156>\235\029l#\154J\134#\173G+\232\163\204`m\209L\145Un0{!\223L\192:lq\161\153~'H\163\163\024C\"\225\1788\206\168\212\171\000\003UvL\197\133\024\218,\b\127\166\192\028P\028\190\232S\238}\247\030kKCn\022\218\208\167\198\204\247\027\200\238[9\"\197\203\179\204\154\155N\r\238\012\181\219\195\031\22316L\203\255]\241\236\237\195U\240\212\146\183\197\154\243\164\183\149\015\251\215W\253F\183\190\169{\220>P\0014bV(\143\018\244\191\002\147\133\146\236\179cQ\242\231Rz\n\174\152uc\147\000\176\201\1281E\204D\184\170\214uTTu\245\230\167\172\137I+\174\200\207Ve\228\217\200\193\193NS\169\006\134r\210\b)\252\248\249\157\155\nT\155\197\180l\226\234\003Es\223\030\197\232K\022\242tU\234\024\188\211\235\017\220lO\004(\220z\254iqYU\150[2F\2286\151\169\175\019L\187\198L8}}\223P|\226\197\161\197\027\203\185\005\238c\162\169\020\004B\226\211\209\176\246\217\167\225kq\135\229;\149S\132\tw\132\140\1968$\255U\022I\236\202z\166+\0292\220\0117\150n\184\1838\182\231x_\147\170mTe\183\214k\203\241\138#_\239,\156\158\031\222xqq\252F\144M\248ZE\142\1862#\163\189>5\184\168\220\229q\178Z\149m\201%\007\213\198\199F%\135Gf\150$-\193c/\185\176\240\026y\186^\211KY\016f\193\142\193\166\154\129\142z\223b0\023\021''f\159\223#@w\207T\162<\150>\157\155\250\015\245'*\197S\153=\173m\019\168\223\\\224\171\227\136\153\208\226>\237jiu\021\029]\184\218g~\246\227\2533\011+\224\239\135\178\203\215v\148\176\242\204a\242\179=\183r3\202\214\149\132\130\207\236/j\232Uy\149cW\tn\174y^\158\155\221\211\162Y3o\027m\024Q\240\217O\155~U\155\250\182\235\248F\166d\235\205\139\027\205\207?\252x\233\250\029mcaMH{h\139\144\248w\194\019NZ~\213\003'\254\158\b\132\147\150\239t\161#j\182\216R\130\220\215\248c,\207\194\2098\134\174\144\166p=9!R>Ke\005\251\146d8MY/\016\007\164\195\175\187\159y\014D\157\215R7\004\234\178h\192\154\160C'\244\185\134\215\139+\t\155kz\137>\230\190\201\156\197\235\143PG{\230\149El\163p\005;\221g\136wJK\136w\221\167\015\204\237\136\173y\229a#\162\248\030K\176\204\160\031\149w\216\230bs\204\030=\233\168\027*\246\205-\143\220J\230\250\179\233\214()}h\184\207\028\152'#\183\229\150=r\169\145\155:f\246\136Q\139f\023\210\199\128l\164 \021\136\202\235\028Pu\215\n\2188\165\183\190\249i\190\250-\223rBcG\197\170\225}\167'\197_\213\204l10\201,\183 ?\197%\139\154\232 \163\154S.0\011" diff --git a/src/loader/ident_env.cppo.ml b/src/loader/ident_env.cppo.ml index bcda19b082..6e5094306b 100644 --- a/src/loader/ident_env.cppo.ml +++ b/src/loader/ident_env.cppo.ml @@ -718,6 +718,9 @@ module Path = struct `Identifier (find_type env id, false) with Not_found -> assert false + let read_value_ident env id : Paths.Path.Value.t = + `Identifier (find_value_identifier env id, false) + let read_class_type_ident env id : Paths.Path.ClassType.t = try `Identifier (find_class_type env id, false) @@ -796,6 +799,18 @@ module Path = struct | Path.Pextra_ty (p,_) -> read_type env p #endif + let read_value env = function + | Path.Pident id -> read_value_ident env id +#if OCAML_VERSION >= (4,8,0) + | Path.Pdot(p, s) -> `Dot(read_module env p, s) +#else + | Path.Pdot(p, s, _) -> `Dot(read_module env p, s) +#endif + | Path.Papply(_, _) -> assert false +#if OCAML_VERSION >= (5,1,0) + | Path.Pextra_ty _ -> assert false +#endif + end module Fragment = struct diff --git a/src/loader/ident_env.cppo.mli b/src/loader/ident_env.cppo.mli index 076421173c..c17f827bf3 100644 --- a/src/loader/ident_env.cppo.mli +++ b/src/loader/ident_env.cppo.mli @@ -40,6 +40,8 @@ module Path : sig val read_type : t -> Path.t -> Paths.Path.Type.t val read_class_type : t -> Path.t -> Paths.Path.ClassType.t + + val read_value : t -> Path.t -> Paths.Path.Value.t end val find_module : t -> Ident.t -> Paths.Path.Module.t diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index c743438788..344f8fab79 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -147,7 +147,7 @@ module UidHashtbl = Shape.Uid.Tbl (* Adds the local definitions found in traverse infos to the [loc_to_id] and [ident_to_id] tables. *) -let populate_local_defs source_id poses loc_to_id ident_to_id = +let populate_local_defs source_id poses loc_to_id ident_to_loc = List.iter (function | Typedtree_traverse.Analysis.Definition id, loc -> @@ -155,11 +155,15 @@ let populate_local_defs source_id poses loc_to_id ident_to_id = Odoc_model.Names.LocalName.make_std (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) in - let identifier = - Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) - in - IdentHashtbl.add ident_to_id id identifier; - LocHashtbl.add loc_to_id loc identifier + (match source_id with + Some source_id -> + let identifier = + Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) + in + LocHashtbl.add loc_to_id loc identifier + | None -> () + ); + IdentHashtbl.add ident_to_loc id loc; | _ -> ()) poses @@ -245,6 +249,7 @@ let anchor_of_identifier id = (* Adds the global definitions, found in the [uid_to_loc], to the [loc_to_id] and [uid_to_id] tables. *) let populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id = + match source_id with None -> () | Some source_id -> let mk_src_id id = let name = Odoc_model.Names.DefName.make_std (anchor_of_identifier id) in (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) @@ -278,23 +283,54 @@ let populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id = | _ -> ())) uid_to_loc +let (>>=) a b = Option.map b a + (* Extract [Typedtree_traverse] occurrence information and turn them into proper source infos *) -let process_occurrences poses uid_to_id ident_to_id = +let process_occurrences env poses loc_to_id ident_to_loc = + let open Odoc_model.Lang.Source_info in + let process p find_in_env = + match p with + | Path.Pident id when IdentHashtbl.mem ident_to_loc id -> ( + match + LocHashtbl.find_opt loc_to_id (IdentHashtbl.find ident_to_loc id) + with + | None -> None + | Some id -> + let documentation = None and implementation = Some (Resolved id) in + Some { documentation; implementation }) + | p -> ( + match find_in_env env p with + | path -> + let documentation = Some path + and implementation = Some (Unresolved path) in + Some { documentation; implementation } + | exception _ -> None) + in List.filter_map (function - | Typedtree_traverse.Analysis.Value (LocalValue uniq), loc -> ( - match IdentHashtbl.find_opt ident_to_id uniq with - | Some anchor -> - Some (Odoc_model.Lang.Source_info.Value anchor, pos_of_loc loc) - | None -> None) - | Value (DefJmp x), loc -> ( - match UidHashtbl.find_opt uid_to_id x with - | Some id -> Some (Value id, pos_of_loc loc) - | None -> None) + | Typedtree_traverse.Analysis.Value p, loc -> + process p Ident_env.Path.read_value >>= fun l -> + (Value l, pos_of_loc loc) + | Module p, loc -> + process p Ident_env.Path.read_module >>= fun l -> + (Module l, pos_of_loc loc) + | ClassType p, loc -> + process p Ident_env.Path.read_class_type >>= fun l -> + (ClassType l, pos_of_loc loc) + | ModuleType p, loc -> + process p Ident_env.Path.read_module_type >>= fun l -> + (ModuleType l, pos_of_loc loc) + | Type p, loc -> + process p Ident_env.Path.read_type >>= fun l -> + (Type l, pos_of_loc loc) + | Constructor _p, loc -> + (* process p Ident_env.Path.read_constructor *) None >>= fun l -> + (Constructor l, pos_of_loc loc) | Definition _, _ -> None) poses + (* Add definition source info from the [loc_to_id] table *) let add_definitions loc_to_id occurrences = LocHashtbl.fold @@ -302,30 +338,31 @@ let add_definitions loc_to_id occurrences = (Odoc_model.Lang.Source_info.Definition id, pos_of_loc loc) :: acc) loc_to_id occurrences -let read_cmt_infos source_id_opt id cmt_info = +let read_cmt_infos source_id_opt id cmt_info ~count_occurrences = match Odoc_model.Compat.shape_of_cmt_infos cmt_info with | Some shape -> ( let uid_to_loc = cmt_info.cmt_uid_to_loc in - match (source_id_opt, cmt_info.cmt_annots) with - | Some source_id, Implementation impl -> + match (source_id_opt, count_occurrences, cmt_info.cmt_annots) with + | (Some _ as source_id), _, Implementation impl + | source_id, true, Implementation impl -> let env = Env.of_structure id impl in let traverse_infos = - Typedtree_traverse.of_cmt env uid_to_loc impl |> List.rev + Typedtree_traverse.of_cmt env impl |> List.rev (* Information are accumulated in a list. We need to have the first info first in the list, to assign anchors with increasing numbers, so that adding some content at the end of a file does not modify the anchors for existing anchors. *) in let loc_to_id = LocHashtbl.create 10 - and ident_to_id = IdentHashtbl.create 10 + and ident_to_loc = IdentHashtbl.create 10 and uid_to_id = UidHashtbl.create 10 in let () = (* populate [loc_to_id], [ident_to_id] and [uid_to_id] *) - populate_local_defs source_id traverse_infos loc_to_id ident_to_id; + populate_local_defs source_id traverse_infos loc_to_id ident_to_loc; populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id in let source_infos = - process_occurrences traverse_infos uid_to_id ident_to_id + process_occurrences env traverse_infos loc_to_id ident_to_loc |> add_definitions loc_to_id in ( Some (shape, Shape.Uid.Tbl.to_map uid_to_id), @@ -334,7 +371,7 @@ let read_cmt_infos source_id_opt id cmt_info = Odoc_model.Lang.Source_info.id = source_id; infos = source_infos; } ) - | _, _ -> (Some (shape, Odoc_model.Compat.empty_map), None)) + | _, _, _ -> (Some (shape, Odoc_model.Compat.empty_map), None)) | None -> (None, None) #else diff --git a/src/loader/implementation.mli b/src/loader/implementation.mli index 49701e6dcc..88acd2030d 100644 --- a/src/loader/implementation.mli +++ b/src/loader/implementation.mli @@ -2,6 +2,7 @@ val read_cmt_infos : Odoc_model.Paths.Identifier.Id.source_page option -> Odoc_model.Paths.Identifier.Id.root_module -> Cmt_format.cmt_infos -> + count_occurrences:bool -> (Odoc_model.Compat.shape * Odoc_model.Paths.Identifier.Id.source_location Odoc_model.Compat.shape_uid_map) diff --git a/src/loader/odoc_loader.ml b/src/loader/odoc_loader.ml index a3f0cb8799..bdb3c177d0 100644 --- a/src/loader/odoc_loader.ml +++ b/src/loader/odoc_loader.ml @@ -42,12 +42,12 @@ exception Not_an_interface exception Make_root_error of string -let read_cmt_infos source_id_opt id ~filename () = +let read_cmt_infos source_id_opt id ~filename ~count_occurrences () = match Cmt_format.read_cmt filename with | exception Cmi_format.Error _ -> raise Corrupted | cmt_info -> ( match cmt_info.cmt_annots with - | Implementation _ -> Implementation.read_cmt_infos source_id_opt id cmt_info + | Implementation _ -> Implementation.read_cmt_infos source_id_opt id cmt_info ~count_occurrences | _ -> raise Not_an_implementation) @@ -99,7 +99,7 @@ let compilation_unit_of_sig ~make_root ~imports ~interface ?sourcefile ~name ~id make_compilation_unit ~make_root ~imports ~interface ?sourcefile ~name ~id ?canonical ?shape_info content -let read_cmti ~make_root ~parent ~filename ~cmt_filename_opt ~source_id_opt () = +let read_cmti ~make_root ~parent ~filename ~cmt_filename_opt ~source_id_opt ~count_occurrences () = let cmt_info = Cmt_format.read_cmt filename in match cmt_info.cmt_annots with | Interface intf -> ( @@ -116,15 +116,16 @@ let read_cmti ~make_root ~parent ~filename ~cmt_filename_opt ~source_id_opt () = let shape_info, source_info = match cmt_filename_opt with | Some cmt_filename -> - read_cmt_infos source_id_opt id ~filename:cmt_filename () - | None -> (None, None) + read_cmt_infos source_id_opt id ~filename:cmt_filename ~count_occurrences () + | None -> + (None, None) in compilation_unit_of_sig ~make_root ~imports:cmt_info.cmt_imports ~interface ~sourcefile ~name ~id ?shape_info ~source_info ?canonical sg) | _ -> raise Not_an_interface -let read_cmt ~make_root ~parent ~filename ~source_id_opt () = +let read_cmt ~make_root ~parent ~filename ~source_id_opt ~count_occurrences () = match Cmt_format.read_cmt filename with | exception Cmi_format.Error (Not_an_interface _) -> raise Not_an_implementation @@ -168,7 +169,7 @@ let read_cmt ~make_root ~parent ~filename ~source_id_opt () = | Implementation impl -> let id, sg, canonical = Cmt.read_implementation parent name impl in let shape_info, source_info = - read_cmt_infos source_id_opt id ~filename () + read_cmt_infos source_id_opt id ~filename ~count_occurrences () in compilation_unit_of_sig ~make_root ~imports ~interface ~sourcefile ~name ~id ?canonical ?shape_info ~source_info sg @@ -199,12 +200,12 @@ let wrap_errors ~filename f = | Not_an_interface -> not_an_interface filename | Make_root_error m -> error_msg filename m) -let read_cmti ~make_root ~parent ~filename ~source_id_opt ~cmt_filename_opt = +let read_cmti ~make_root ~parent ~filename ~source_id_opt ~cmt_filename_opt ~count_occurrences = wrap_errors ~filename - (read_cmti ~make_root ~parent ~filename ~source_id_opt ~cmt_filename_opt) + (read_cmti ~make_root ~parent ~filename ~source_id_opt ~cmt_filename_opt ~count_occurrences) -let read_cmt ~make_root ~parent ~filename ~source_id_opt = - wrap_errors ~filename (read_cmt ~make_root ~parent ~filename ~source_id_opt) +let read_cmt ~make_root ~parent ~filename ~source_id_opt ~count_occurrences = + wrap_errors ~filename (read_cmt ~make_root ~parent ~filename ~source_id_opt ~count_occurrences) let read_cmi ~make_root ~parent ~filename = wrap_errors ~filename (read_cmi ~make_root ~parent ~filename) diff --git a/src/loader/odoc_loader.mli b/src/loader/odoc_loader.mli index d60014f300..db0adc302d 100644 --- a/src/loader/odoc_loader.mli +++ b/src/loader/odoc_loader.mli @@ -19,6 +19,7 @@ val read_cmti : filename:string -> source_id_opt:Identifier.SourcePage.t option -> cmt_filename_opt:string option -> + count_occurrences:bool -> (Lang.Compilation_unit.t, Error.t) result Error.with_warnings val read_cmt : @@ -26,6 +27,7 @@ val read_cmt : parent:Identifier.ContainerPage.t option -> filename:string -> source_id_opt:Identifier.SourcePage.t option -> + count_occurrences:bool -> (Lang.Compilation_unit.t, Error.t) result Error.with_warnings val read_cmi : diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml index 164035bb3b..7baac064f2 100644 --- a/src/loader/typedtree_traverse.ml +++ b/src/loader/typedtree_traverse.ml @@ -1,31 +1,41 @@ #if OCAML_VERSION >= (4, 14, 0) module Analysis = struct - type value_implementation = LocalValue of Ident.t | DefJmp of Shape.Uid.t + type annotation = + | Definition of Ident.t + | Value of Path.t + | Module of Path.t + | ClassType of Path.t + | ModuleType of Path.t + | Type of Path.t + | Constructor of Path.t - type annotation = Definition of Ident.t | Value of value_implementation - - let expr uid_to_loc poses expr = + let expr poses expr = let exp_loc = expr.Typedtree.exp_loc in if exp_loc.loc_ghost then () else match expr.exp_desc with - | Texp_ident (p, _, value_description) -> ( - let implementation = - match - Shape.Uid.Tbl.find_opt uid_to_loc value_description.val_uid - with - | Some _ -> Some (DefJmp value_description.val_uid) - | None -> ( - match p with Pident id -> Some (LocalValue id) | _ -> None) - in - match implementation with - | None -> () - | Some impl -> poses := (Value impl, exp_loc) :: !poses) + | Texp_ident (p, _, _) -> poses := (Value p, exp_loc) :: !poses + | Texp_construct (_, { cstr_res; _ }, _) -> ( + let desc = Types.get_desc cstr_res in + match desc with + | Types.Tconstr (p, _, _) -> + poses := (Constructor p, exp_loc) :: !poses + | _ -> ()) | _ -> () let pat env (type a) poses : a Typedtree.general_pattern -> unit = function | { Typedtree.pat_desc; pat_loc; _ } when not pat_loc.loc_ghost -> + let () = + match pat_desc with + | Typedtree.Tpat_construct (_, { cstr_res; _ }, _, _) -> ( + let desc = Types.get_desc cstr_res in + match desc with + | Types.Tconstr (p, _, _) -> + poses := (Constructor p, pat_loc) :: !poses + | _ -> ()) + | _ -> () + in let maybe_localvalue id loc = match Ident_env.identifier_of_loc env loc with | None -> Some (Definition id, loc) @@ -45,19 +55,73 @@ module Analysis = struct in () | _ -> () + + let module_expr poses mod_expr = + match mod_expr with + | { Typedtree.mod_desc = Tmod_ident (p, _); mod_loc; _ } + when not mod_loc.loc_ghost -> + poses := (Module p, mod_loc) :: !poses + | _ -> () + + let class_type poses cltyp = + match cltyp with + | { Typedtree.cltyp_desc = Tcty_constr (p, _, _); cltyp_loc; _ } + when not cltyp_loc.loc_ghost -> + poses := (ClassType p, cltyp_loc) :: !poses + | _ -> () + + let module_type poses mty_expr = + match mty_expr with + | { Typedtree.mty_desc = Tmty_ident (p, _); mty_loc; _ } + when not mty_loc.loc_ghost -> + poses := (ModuleType p, mty_loc) :: !poses + | _ -> () + + let core_type poses ctyp_expr = + match ctyp_expr with + | { Typedtree.ctyp_desc = Ttyp_constr (p, _, _); ctyp_loc; _ } + when not ctyp_loc.loc_ghost -> + poses := (Type p, ctyp_loc) :: !poses + | _ -> () end -let of_cmt env uid_to_loc structure = +let of_cmt env structure = let poses = ref [] in + let module_expr iterator mod_expr = + Analysis.module_expr poses mod_expr; + Tast_iterator.default_iterator.module_expr iterator mod_expr + in let expr iterator e = - Analysis.expr uid_to_loc poses e; + Analysis.expr poses e; Tast_iterator.default_iterator.expr iterator e in let pat iterator e = Analysis.pat env poses e; Tast_iterator.default_iterator.pat iterator e in - let iterator = { Tast_iterator.default_iterator with expr; pat } in + let typ iterator ctyp_expr = + Analysis.core_type poses ctyp_expr; + Tast_iterator.default_iterator.typ iterator ctyp_expr + in + let module_type iterator mty = + Analysis.module_type poses mty; + Tast_iterator.default_iterator.module_type iterator mty + in + let class_type iterator cl_type = + Analysis.class_type poses cl_type; + Tast_iterator.default_iterator.class_type iterator cl_type + in + let iterator = + { + Tast_iterator.default_iterator with + expr; + pat; + module_expr; + typ; + module_type; + class_type; + } + in iterator.structure iterator structure; !poses diff --git a/src/model/lang.ml b/src/model/lang.ml index 74c5b66023..dd4abf6a68 100644 --- a/src/model/lang.ml +++ b/src/model/lang.ml @@ -18,15 +18,31 @@ open Paths (** {3 Modules} *) module Source_info = struct + type 'a jump_to_impl = + | Unresolved of 'a + | Resolved of Identifier.SourceLocation.t + + type ('doc, 'impl) jump_to = { + documentation : 'doc option; + implementation : 'impl jump_to_impl option; + } + + type 'path jump_1 = ('path, 'path) jump_to + type annotation = | Definition of Paths.Identifier.SourceLocation.t - | Value of Paths.Identifier.SourceLocation.t + | Value of Path.Value.t jump_1 + | Module of Path.Module.t jump_1 + | ClassType of Path.ClassType.t jump_1 + | ModuleType of Path.ModuleType.t jump_1 + | Type of Path.Type.t jump_1 + | Constructor of Path.Constructor.t jump_1 type 'a with_pos = 'a * (int * int) type infos = annotation with_pos list - type t = { id : Identifier.SourcePage.t; infos : infos } + type t = { id : Identifier.SourcePage.t option; infos : infos } end module rec Module : sig diff --git a/src/model/paths.ml b/src/model/paths.ml index 1d9e9c7193..fa90e0d05d 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -132,16 +132,19 @@ module Identifier = struct InstanceVariableName.to_string name :: full_name_aux (parent :> t) | `Label (parent, name) -> LabelName.to_string name :: full_name_aux (parent :> t) + | `SourceDir (parent, name) -> name :: full_name_aux (parent :> t) + | `SourceLocation (parent, name) -> + DefName.to_string name :: full_name_aux (parent :> t) + | `SourceLocationInternal (parent, name) -> + LocalName.to_string name :: full_name_aux (parent :> t) + | `SourceLocationMod name -> full_name_aux (name :> t) + | `SourcePage (parent, name) -> name :: full_name_aux (parent :> t) | `AssetFile (parent, name) -> name :: full_name_aux (parent :> t) - | `SourceDir _ | `SourceLocationMod _ | `SourceLocation _ | `SourcePage _ - | `SourceLocationInternal _ -> - [] let fullname : [< t_pv ] id -> string list = fun n -> List.rev @@ full_name_aux (n :> t) let is_internal : [< t_pv ] id -> bool = fun n -> is_internal (n :> t) - let rec label_parent_aux = let open Id in fun (n : non_src) -> diff --git a/src/model/paths.mli b/src/model/paths.mli index bf0b7b1bab..f52538ba73 100644 --- a/src/model/paths.mli +++ b/src/model/paths.mli @@ -206,8 +206,6 @@ module Identifier : sig val name : [< t_pv ] id -> string - (* val root : [< t_pv ] id -> RootModule.t_pv id option *) - val fullname : [< t_pv ] id -> string list (** The fullname of value [x] in module [M] is [M.x], whereas the regular name is [x]. *) @@ -384,12 +382,6 @@ module rec Path : sig module Value : sig type t = Paths_types.Resolved_path.value - - (* val of_ident : Identifier.Path.Value.t -> t *) - - (* val is_hidden : t -> bool *) - - (* val identifier : t -> Identifier.Path.Type.t *) end module ClassType : sig diff --git a/src/model/paths_types.ml b/src/model/paths_types.ml index c14b5314f4..8c61ca316c 100644 --- a/src/model/paths_types.ml +++ b/src/model/paths_types.ml @@ -352,7 +352,10 @@ module rec Path : sig [ `Resolved of Resolved_path.constructor | `Dot of datatype * string ] (** @canonical Odoc_model.Paths.Path.Constructor.t *) - type value = [ `Resolved of Resolved_path.value | `Dot of module_ * string ] + type value = + [ `Resolved of Resolved_path.value + | `Identifier of Identifier.path_value * bool + | `Dot of module_ * string ] (** @canonical Odoc_model.Paths.Path.Value.t *) type class_type = @@ -410,7 +413,8 @@ and Resolved_path : sig type constructor = [ `Constructor of datatype * ConstructorName.t ] (** @canonical Odoc_model.Paths.Path.Resolved.Constructor.t *) - type value = [ `Value of module_ * ValueName.t ] + type value = + [ `Identifier of Identifier.path_value | `Value of module_ * ValueName.t ] (** @canonical Odoc_model.Paths.Path.Resolved.Value.t *) type class_type = diff --git a/src/model_desc/lang_desc.ml b/src/model_desc/lang_desc.ml index 56c96bc008..491fee961c 100644 --- a/src/model_desc/lang_desc.ml +++ b/src/model_desc/lang_desc.ml @@ -18,7 +18,7 @@ let inline_status = let source_info = let open Lang.Source_info in - Record [ F ("id", (fun t -> t.id), identifier) ] + Record [ F ("id", (fun t -> t.id), Option identifier) ] (** {3 Module} *) diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index 0251f7a5af..8c57b67ab2 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -184,7 +184,7 @@ end = struct let compile hidden directories resolve_fwd_refs dst package_opt parent_name_opt open_modules children input warnings_options - source_parent_file source_name cmt_filename_opt = + source_parent_file source_name cmt_filename_opt count_occurrences = let open Or_error in let resolver = Resolver.create ~important_digests:(not resolve_fwd_refs) ~directories @@ -220,7 +220,7 @@ end = struct source >>= fun source -> Fs.Directory.mkdir_p (Fs.File.dirname output); Compile.compile ~resolver ~parent_cli_spec ~hidden ~children ~output - ~warnings_options ~source ~cmt_filename_opt input + ~warnings_options ~source ~cmt_filename_opt ~count_occurrences input let input = let doc = "Input $(i,.cmti), $(i,.cmt), $(i,.cmi) or $(i,.mld) file." in @@ -293,11 +293,18 @@ end = struct let doc = "Try resolving forward references." in Arg.(value & flag & info ~doc [ "r"; "resolve-fwd-refs" ]) in + let count_occurrences = + let doc = + "Count occurrences in implementation. Useful in search ranking." + in + Arg.(value & flag & info ~doc [ "count-occurrences" ]) + in Term.( const handle_error $ (const compile $ hidden $ odoc_file_directories $ resolve_fwd_refs $ dst $ package_opt $ parent_opt $ open_modules $ children $ input - $ warnings_options $ source_parent_file $ source_name $ source_cmt)) + $ warnings_options $ source_parent_file $ source_name $ source_cmt + $ count_occurrences)) let info ~docs = let man = @@ -1104,6 +1111,30 @@ module Targets = struct end end +module Occurrences = struct + let index directories dst warnings_options = + let dst = Fpath.v dst in + Occurrences.count ~dst ~warnings_options directories + + let cmd = + let dst = + let doc = "Output file path." in + Arg.( + required & opt (some string) None & info ~docs ~docv:"PATH" ~doc [ "o" ]) + in + Term.( + const handle_error + $ (const index $ odoc_file_directories $ dst $ warnings_options)) + + let info ~docs = + let doc = + "Generate a hashtable mapping identifiers to number of occurrences, as \ + computed from the implementations of .odocl files found in the given \ + directories." + in + Term.info "count-occurrences" ~docs ~doc +end + module Odoc_error = struct let errors input = let open Odoc_odoc in @@ -1144,6 +1175,7 @@ let () = Printexc.record_backtrace true; let subcommands = [ + Occurrences.(cmd, info ~docs:section_pipeline); Compile.(cmd, info ~docs:section_pipeline); Odoc_link.(cmd, info ~docs:section_pipeline); Odoc_html.generate ~docs:section_pipeline; diff --git a/src/odoc/compile.ml b/src/odoc/compile.ml index 5429c353bf..51244fdf0a 100644 --- a/src/odoc/compile.ml +++ b/src/odoc/compile.ml @@ -99,16 +99,17 @@ let resolve_imports resolver imports = (** Raises warnings and errors. *) let resolve_and_substitute ~resolver ~make_root ~source_id_opt ~cmt_filename_opt ~hidden (parent : Paths.Identifier.ContainerPage.t option) input_file - input_type = + input_type ~count_occurrences = let filename = Fs.File.to_string input_file in let unit = match input_type with | `Cmti -> Odoc_loader.read_cmti ~make_root ~parent ~filename ~source_id_opt - ~cmt_filename_opt + ~cmt_filename_opt ~count_occurrences |> Error.raise_errors_and_warnings | `Cmt -> Odoc_loader.read_cmt ~make_root ~parent ~filename ~source_id_opt + ~count_occurrences |> Error.raise_errors_and_warnings | `Cmi -> Odoc_loader.read_cmi ~make_root ~parent ~filename @@ -250,7 +251,7 @@ let handle_file_ext ext = Error (`Msg "Unknown extension, expected one of: cmti, cmt, cmi or mld.") let compile ~resolver ~parent_cli_spec ~hidden ~children ~output - ~warnings_options ~source ~cmt_filename_opt input = + ~warnings_options ~source ~cmt_filename_opt ~count_occurrences input = parent resolver parent_cli_spec >>= fun parent_spec -> let ext = Fs.File.get_ext input in if ext = ".mld" then @@ -296,7 +297,7 @@ let compile ~resolver ~parent_cli_spec ~hidden ~children ~output let result = Error.catch_errors_and_warnings (fun () -> resolve_and_substitute ~resolver ~make_root ~hidden ~source_id_opt - ~cmt_filename_opt parent input input_type) + ~cmt_filename_opt ~count_occurrences parent input input_type) in (* Extract warnings to write them into the output file *) let _, warnings = Error.unpack_warnings result in diff --git a/src/odoc/compile.mli b/src/odoc/compile.mli index 602d9d5724..7d2755cbf6 100644 --- a/src/odoc/compile.mli +++ b/src/odoc/compile.mli @@ -43,6 +43,7 @@ val compile : warnings_options:Odoc_model.Error.warnings_options -> source:(Fpath.t * string list) option -> cmt_filename_opt:string option -> + count_occurrences:bool -> Fs.File.t -> (unit, [> msg ]) result (** Produces .odoc files out of [.cm{i,t,ti}] or .mld files. *) diff --git a/src/odoc/html_page.ml b/src/odoc/html_page.ml index b0c790416a..c316899694 100644 --- a/src/odoc/html_page.ml +++ b/src/odoc/html_page.ml @@ -39,7 +39,7 @@ let render { html_config; source = _; assets = _ } page = let source_documents source_info source ~syntax = match (source_info, source) with - | Some { Lang.Source_info.id; infos }, Some src -> ( + | Some { Lang.Source_info.id = Some id; infos }, Some src -> ( let file = match src with | Source.File f -> f @@ -68,7 +68,7 @@ let source_documents source_info source ~syntax = Odoc_document.Renderer.document_of_source ~syntax id syntax_info infos source_code; ]) - | Some { id; _ }, None -> + | Some { id = Some id; _ }, None -> let filename = Paths.Identifier.name id in Error.raise_warning (Error.filename_only @@ -77,14 +77,14 @@ let source_documents source_info source ~syntax = --source-name" filename); [] - | None, Some src -> + | _, Some src -> Error.raise_warning (Error.filename_only "--source argument is invalid on compilation unit that were not \ compiled with --source-parent and --source-name" (Source.to_string src)); [] - | None, None -> [] + | _, None -> [] let list_filter_map f lst = List.rev diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml new file mode 100644 index 0000000000..286f047600 --- /dev/null +++ b/src/odoc/occurrences.ml @@ -0,0 +1,58 @@ +open Or_error + +let handle_file file ~f = + Odoc_file.load file + |> Result.map @@ fun unit' -> + match unit' with + | { Odoc_file.content = Unit_content unit; _ } -> Some (f unit) + | _ -> None + +let fold_dirs ~dirs ~f ~init = + dirs + |> List.fold_left + (fun acc dir -> + acc >>= fun acc -> + Fs.Directory.fold_files_rec_result ~ext:"odocl" + (fun acc file -> + file |> handle_file ~f:(f acc) >>= function + | None -> Ok acc + | Some acc -> Ok acc) + acc dir) + (Ok init) + +module H = Hashtbl.Make (Odoc_model.Paths.Identifier) + +let count ~dst ~warnings_options:_ directories = + let htbl = H.create 100 in + let f () (unit : Odoc_model.Lang.Compilation_unit.t) = + let incr tbl p p' = + let id = Odoc_model.Paths.Path.Resolved.(identifier (p :> t)) in + let old_value = match H.find_opt tbl id with Some n -> n | None -> 0 in + if not Odoc_model.Paths.Path.(is_hidden p') then + H.replace tbl id (old_value + 1) + in + let () = + List.iter + (function + | ( Odoc_model.Lang.Source_info.Module + { documentation = Some (`Resolved p as p'); _ }, + _ ) -> + incr htbl p Odoc_model.Paths.Path.((p' : Module.t :> t)) + | Value { documentation = Some (`Resolved p as p'); _ }, _ -> + incr htbl p Odoc_model.Paths.Path.((p' : Value.t :> t)) + | ClassType { documentation = Some (`Resolved p as p'); _ }, _ -> + incr htbl p Odoc_model.Paths.Path.((p' : ClassType.t :> t)) + | ModuleType { documentation = Some (`Resolved p as p'); _ }, _ -> + incr htbl p Odoc_model.Paths.Path.((p' : ModuleType.t :> t)) + | Type { documentation = Some (`Resolved p as p'); _ }, _ -> + incr htbl p Odoc_model.Paths.Path.((p' : Type.t :> t)) + | _ -> ()) + (match unit.source_info with None -> [] | Some i -> i.infos) + in + () + in + fold_dirs ~dirs:directories ~f ~init:() >>= fun () -> + Fs.Directory.mkdir_p (Fs.File.dirname dst); + let oc = open_out_bin (Fs.File.to_string dst) in + Marshal.to_channel oc htbl []; + Ok () diff --git a/src/xref2/compile.ml b/src/xref2/compile.ml index 7f2312ff17..4aeebe29b3 100644 --- a/src/xref2/compile.ml +++ b/src/xref2/compile.ml @@ -90,7 +90,28 @@ let rec unit env t = and source_info env si = { si with infos = source_info_infos env si.infos } -and source_info_infos _env infos = infos +and source_info_infos env infos = + let open Source_info in + let map_doc f v = + let documentation = + match v.documentation with Some p -> Some (f p) | None -> None + in + { v with documentation } + in + List.map + (function + | v, pos -> + let v = + match v with + | Value v -> Value (map_doc (value_path env) v) + | Module v -> Module (map_doc (module_path env) v) + | ModuleType v -> ModuleType (map_doc (module_type_path env) v) + | Type v -> Type (map_doc (type_path env) v) + | Constructor v -> Constructor (map_doc (constructor_path env) v) + | i -> i + in + (v, pos)) + infos and content env id = let open Compilation_unit in diff --git a/src/xref2/component.ml b/src/xref2/component.ml index 5ccfaa4655..f0fab6a9d5 100644 --- a/src/xref2/component.ml +++ b/src/xref2/component.ml @@ -1060,6 +1060,9 @@ module Fmt = struct | `Value (p, t) -> Format.fprintf ppf "%a.%s" resolved_parent_path p (Odoc_model.Names.ValueName.to_string t) + | `Gpath p -> + Format.fprintf ppf "%a" model_resolved_path + (p :> Odoc_model.Paths.Path.Resolved.t) and resolved_constructor_path : Format.formatter -> Cpath.Resolved.constructor -> unit = @@ -1120,6 +1123,10 @@ module Fmt = struct | `Value (p, t) -> Format.fprintf ppf "%a.%s" resolved_parent_path p (Odoc_model.Names.ValueName.to_string t) + | `Identifier (id, b) -> + Format.fprintf ppf "identifier(%a, %b)" model_identifier + (id :> Odoc_model.Paths.Identifier.t) + b and constructor_path : Format.formatter -> Cpath.constructor -> unit = fun ppf p -> @@ -1872,8 +1879,11 @@ module Of_Lang = struct and resolved_value_path : _ -> Odoc_model.Paths.Path.Resolved.Value.t -> Cpath.Resolved.value = - fun ident_map (`Value (p, name)) -> - `Value (`Module (resolved_module_path ident_map p), name) + fun ident_map p -> + match p with + | `Value (p, name) -> + `Value (`Module (resolved_module_path ident_map p), name) + | `Identifier _ -> `Gpath p and resolved_constructor_path : _ -> @@ -1934,12 +1944,6 @@ module Of_Lang = struct | `Local i -> `Local (i, b)) | `Dot (path', x) -> `Dot (module_path ident_map path', x) - and value_path : _ -> Odoc_model.Paths.Path.Value.t -> Cpath.value = - fun ident_map p -> - match p with - | `Resolved r -> `Resolved (resolved_value_path ident_map r) - | `Dot (path', x) -> `Dot (module_path ident_map path', x) - and datatype : _ -> Odoc_model.Paths.Path.DataType.t -> Cpath.datatype = fun ident_map p -> match p with @@ -1950,6 +1954,13 @@ module Of_Lang = struct | `Local i -> `Local (i, b)) | `Dot (path', x) -> `Dot (module_path ident_map path', x) + and value_path : _ -> Odoc_model.Paths.Path.Value.t -> Cpath.value = + fun ident_map p -> + match p with + | `Resolved r -> `Resolved (resolved_value_path ident_map r) + | `Dot (path', x) -> `Dot (module_path ident_map path', x) + | `Identifier (i, b) -> `Identifier (i, b) + and constructor_path : _ -> Odoc_model.Paths.Path.Constructor.t -> Cpath.constructor = fun ident_map p -> diff --git a/src/xref2/cpath.ml b/src/xref2/cpath.ml index 05891c7111..cd9f5f6ac3 100644 --- a/src/xref2/cpath.ml +++ b/src/xref2/cpath.ml @@ -36,7 +36,8 @@ module rec Resolved : sig | `Class of parent * ClassName.t | `ClassType of parent * ClassTypeName.t ] - and value = [ `Value of parent * ValueName.t ] + and value = + [ `Value of parent * ValueName.t | `Gpath of Path.Resolved.Value.t ] and datatype = [ `Local of Ident.path_datatype @@ -89,7 +90,8 @@ and Cpath : sig and value = [ `Resolved of Resolved.value | `Dot of module_ * string - | `Value of Resolved.parent * ValueName.t ] + | `Value of Resolved.parent * ValueName.t + | `Identifier of Identifier.Value.t * bool ] and datatype = [ `Resolved of Resolved.datatype diff --git a/src/xref2/env.ml b/src/xref2/env.ml index a0cb34a970..ad3dd52c69 100644 --- a/src/xref2/env.ml +++ b/src/xref2/env.ml @@ -361,8 +361,8 @@ let module_of_unit : Lang.Compilation_unit.t -> Component.Module.t = let id = (unit.id :> Paths.Identifier.Module.t) in let locs = match unit.source_info with - | Some src -> Some (Identifier.Mk.source_location_mod src.id) - | None -> None + | Some { id = Some id; _ } -> Some (Identifier.Mk.source_location_mod id) + | _ -> None in match unit.content with | Module s -> diff --git a/src/xref2/errors.ml b/src/xref2/errors.ml index 4ca923a9b7..56b953d785 100644 --- a/src/xref2/errors.ml +++ b/src/xref2/errors.ml @@ -197,7 +197,7 @@ module Tools_error = struct Component.Fmt.model_identifier (m :> Odoc_model.Paths.Identifier.t) | `Lookup_failureC m -> - Format.fprintf fmt "Lookup failure (value): %a" + Format.fprintf fmt "Lookup failure (constructor): %a" Component.Fmt.model_identifier (m :> Odoc_model.Paths.Identifier.t) | `ApplyNotFunctor -> Format.fprintf fmt "Apply module is not a functor" diff --git a/src/xref2/find.ml b/src/xref2/find.ml index 0287f603f3..ba5ec4108e 100644 --- a/src/xref2/find.ml +++ b/src/xref2/find.ml @@ -281,7 +281,10 @@ let module_type_in_sig sg name = let value_in_sig sg name = filter_in_sig sg (function - | Signature.Value (id, m) when N.value id = name -> + | Signature.Value (id, m) + when N.value id = name || N.value id = "(" ^ name ^ ")" -> + (* For operator, the value will have name [()]. We match that even + with name []. *) Some (`FValue (N.typed_value id, Delayed.get m)) | _ -> None) diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index 3a40397c4b..bbe07f8ac5 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -198,9 +198,11 @@ module Path = struct | `ClassType (p, name) -> `ClassType (resolved_parent map p, name) | `Substituted s -> resolved_type map s - and resolved_value map (`Value (p, name) : Cpath.Resolved.value) : + and resolved_value map (p : Cpath.Resolved.value) : Odoc_model.Paths.Path.Resolved.Value.t = - `Value (resolved_parent map p, name) + match p with + | `Value (p, name) -> `Value (resolved_parent map p, name) + | `Gpath y -> y and resolved_datatype map (p : Cpath.Resolved.datatype) : Odoc_model.Paths.Path.Resolved.DataType.t = diff --git a/src/xref2/link.ml b/src/xref2/link.ml index ec9dba822f..0bc640a628 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -403,13 +403,60 @@ and open_ env parent = function let rec unit env t = let open Compilation_unit in let content = - match t.content with - | Module sg -> - let sg = signature env (t.id :> Id.Signature.t) sg in - Module sg - | Pack _ as p -> p + if t.Lang.Compilation_unit.linked || t.hidden then t.content + else + match t.content with + | Module sg -> + let sg = signature env (t.id :> Id.Signature.t) sg in + Module sg + | Pack _ as p -> p in - { t with content; linked = true } + let source_info = + let open Source_info in + match t.source_info with + | Some inf -> + let jump_to v f_impl f_doc = + let documentation = + match v.documentation with Some p -> Some (f_doc p) | None -> None + in + let implementation = + match v.implementation with + | Some (Unresolved p) -> ( + match f_impl p with + | Some x -> Some (Resolved x) + | None -> v.implementation) + | x -> x + in + { documentation; implementation } + in + let infos = + List.map + (fun (i, pos) -> + let info = + match i with + | Value v -> + Value + (jump_to v + (Shape_tools.lookup_value_path env) + (value_path env)) + | Module v -> + Module (jump_to v (fun _ -> None) (module_path env)) + | ModuleType v -> + ModuleType + (jump_to v (fun _ -> None) (module_type_path env)) + | Type v -> Type (jump_to v (fun _ -> None) (type_path env)) + | Constructor v -> + Constructor + (jump_to v (fun _ -> None) (constructor_path env)) + | i -> i + in + (info, pos)) + inf.infos + in + Some { inf with infos } + | None -> None + in + { t with content; linked = true; source_info } and value_ env parent t = let open Value in @@ -1087,8 +1134,7 @@ and type_expression : Env.t -> Id.Signature.t -> _ -> _ = | Package p -> Package (type_expression_package env parent visited p) let link ~filename x y = - Lookup_failures.catch_failures ~filename (fun () -> - if y.Lang.Compilation_unit.linked || y.hidden then y else unit x y) + Lookup_failures.catch_failures ~filename (fun () -> unit x y) let page env page = let () = diff --git a/src/xref2/shape_tools.cppo.ml b/src/xref2/shape_tools.cppo.ml index c702e17b56..5d516dd926 100644 --- a/src/xref2/shape_tools.cppo.ml +++ b/src/xref2/shape_tools.cppo.ml @@ -53,6 +53,49 @@ let rec shape_of_id env : (* Not represented in shapes. *) None +let rec shape_of_module_path env : _ -> Shape.t option = + let proj parent kind name = + let item = Shape.Item.make name kind in + match shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) with + | Some shape -> Some (Shape.proj shape item) + | None -> None + in + fun (path : Odoc_model.Paths.Path.t) -> + match path with + | `Resolved _ -> None + | `Root name -> ( + match Env.lookup_unit name env with + | Some (Env.Found unit) -> ( + match unit.shape_info with + | Some (shape, _) -> Some shape + | None -> None) + | _ -> None) + | `Forward _ -> None + | `Dot (parent, name) -> + proj (parent :> Odoc_model.Paths.Path.t) Kind.Module name + | `Apply (parent, arg) -> + shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) + >>= fun parent -> + shape_of_module_path env (arg :> Odoc_model.Paths.Path.t) >>= fun arg -> + Some (Shape.app parent ~arg) + | `Identifier (id, _) -> + shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) + +let shape_of_value_path env : + Odoc_model.Paths.Path.Value.t -> Shape.t option = + let proj parent kind name = + let item = Shape.Item.make name kind in + match shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) with + | Some shape -> Some (Shape.proj shape item) + | None -> None + in + fun (path : Odoc_model.Paths.Path.Value.t) -> + match path with + | `Resolved _ -> None + | `Dot (parent, name) -> proj (parent :> Odoc_model.Paths.Path.t) Kind.Value name + | `Identifier (id, _) -> shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) + + module MkId = Identifier.Mk let unit_of_uid uid = @@ -95,8 +138,8 @@ let lookup_shape : | Some x -> Some x | None -> ( match unit.source_info with - | Some si -> Some (MkId.source_location_mod si.id) - | None -> None) + | Some {id = Some id ; _} -> Some (MkId.source_location_mod id) + | _ -> None) let lookup_def : @@ -108,6 +151,15 @@ let lookup_def : | None -> None | Some query -> lookup_shape env query +let lookup_value_path : + Env.t -> + Path.Value.t -> + Identifier.SourceLocation.t option + = fun env path -> + match shape_of_value_path env path with + | None -> None + | Some query -> lookup_shape env query + #else type t = unit diff --git a/src/xref2/shape_tools.cppo.mli b/src/xref2/shape_tools.cppo.mli index d9082e06ba..607d50b8dc 100644 --- a/src/xref2/shape_tools.cppo.mli +++ b/src/xref2/shape_tools.cppo.mli @@ -13,3 +13,8 @@ val lookup_def : Env.t -> Identifier.NonSrc.t -> Identifier.SourceLocation.t option + +val lookup_value_path : + Env.t -> + Path.Value.t -> + Identifier.SourceLocation.t option diff --git a/src/xref2/tools.ml b/src/xref2/tools.ml index 90d84806a4..a59437874c 100644 --- a/src/xref2/tools.ml +++ b/src/xref2/tools.ml @@ -878,6 +878,29 @@ and lookup_type_gpath : in res +and lookup_value_gpath : + Env.t -> + Odoc_model.Paths.Path.Resolved.Value.t -> + (Find.value, simple_value_lookup_error) Result.result = + fun env p -> + let do_value p name = + lookup_parent_gpath ~mark_substituted:true env p + |> map_error (fun e -> (e :> simple_value_lookup_error)) + >>= fun (sg, sub) -> + match Find.value_in_sig sg name with + | `FValue (name, t) :: _ -> Ok (`FValue (name, Subst.value sub t)) + | [] -> Error `Find_failure + in + let res = + match p with + | `Identifier ({ iv = `Value _; _ } as i) -> + of_option ~error:(`Lookup_failureV i) (Env.(lookup_by_id s_value) i env) + >>= fun (`Value ({ iv = `Value (_, name); _ }, t)) -> + Ok (`FValue (name, t)) + | `Value (p, id) -> do_value p (ValueName.to_string id) + in + res + and lookup_datatype_gpath : Env.t -> Odoc_model.Paths.Path.Resolved.DataType.t -> @@ -1005,13 +1028,16 @@ and lookup_datatype : and lookup_value : Env.t -> Cpath.Resolved.value -> - (Find.value, simple_value_lookup_error) Result.result = - fun env (`Value (p, id)) -> - lookup_parent ~mark_substituted:true env p - |> map_error (fun e -> (e :> simple_value_lookup_error)) - >>= fun (sg, sub) -> - handle_value_lookup env (ValueName.to_string id) p sg - >>= fun (_, `FValue (name, c)) -> Ok (`FValue (name, Subst.value sub c)) + (_, simple_value_lookup_error) Result.result = + fun env p -> + match p with + | `Value (p, id) -> + lookup_parent ~mark_substituted:true env p + |> map_error (fun e -> (e :> simple_value_lookup_error)) + >>= fun (sg, sub) -> + handle_value_lookup env (ValueName.to_string id) p sg + >>= fun (_, `FValue (name, c)) -> Ok (`FValue (name, Subst.value sub c)) + | `Gpath p -> lookup_value_gpath env p and lookup_constructor : Env.t -> @@ -1357,6 +1383,9 @@ and resolve_value : Env.t -> Cpath.value -> resolve_value_result = in of_option ~error:`Find_failure result | `Resolved r -> lookup_value env r >>= fun t -> Ok (r, t) + | `Identifier (i, _) -> + let i' = `Identifier i in + lookup_value env (`Gpath i') >>= fun t -> Ok (`Gpath i', t) in result @@ -1808,7 +1837,10 @@ and reresolve_datatype : result and reresolve_value : Env.t -> Cpath.Resolved.value -> Cpath.Resolved.value = - fun env (`Value (p, n)) -> `Value (reresolve_parent env p, n) + fun env p -> + match p with + | `Value (p, n) -> `Value (reresolve_parent env p, n) + | `Gpath _ -> p and reresolve_constructor : Env.t -> Cpath.Resolved.constructor -> Cpath.Resolved.constructor = diff --git a/test/occurrences/double_wrapped.t/a.ml b/test/occurrences/double_wrapped.t/a.ml new file mode 100644 index 0000000000..0a13bbe074 --- /dev/null +++ b/test/occurrences/double_wrapped.t/a.ml @@ -0,0 +1,7 @@ +let x = 1 + +type t = string + +module type M = sig end + +let (||>) x y = x + y diff --git a/test/occurrences/double_wrapped.t/b.ml b/test/occurrences/double_wrapped.t/b.ml new file mode 100644 index 0000000000..9c65111cd5 --- /dev/null +++ b/test/occurrences/double_wrapped.t/b.ml @@ -0,0 +1,13 @@ +module Y = A + +module Z = C + +let y = Y.x + A.x + Z.y + C.y + +let (_ : A.t) = "string" + +module M : A.M = struct end + +module type Y = A.M + +let _ = let open A in 1 ||> 2 diff --git a/test/occurrences/double_wrapped.t/c.ml b/test/occurrences/double_wrapped.t/c.ml new file mode 100644 index 0000000000..b0ae315a86 --- /dev/null +++ b/test/occurrences/double_wrapped.t/c.ml @@ -0,0 +1,3 @@ +module Y = A + +let y = Y.x + A.x diff --git a/test/occurrences/double_wrapped.t/main.ml b/test/occurrences/double_wrapped.t/main.ml new file mode 100644 index 0000000000..25a40aaa6e --- /dev/null +++ b/test/occurrences/double_wrapped.t/main.ml @@ -0,0 +1,5 @@ +(** Handwritten top-level module *) + +module A = A + +module B = B diff --git a/test/occurrences/double_wrapped.t/main__.ml b/test/occurrences/double_wrapped.t/main__.ml new file mode 100644 index 0000000000..59f553e2ae --- /dev/null +++ b/test/occurrences/double_wrapped.t/main__.ml @@ -0,0 +1,10 @@ +(** Would be generated by dune *) + +module A = Main__A +(** @canonical Main.A *) + +module B = Main__B +(** @canonical Main.B *) + +module C = Main__C +(** @canonical Main.C *) diff --git a/test/occurrences/double_wrapped.t/root.mld b/test/occurrences/double_wrapped.t/root.mld new file mode 100644 index 0000000000..54f377d3e8 --- /dev/null +++ b/test/occurrences/double_wrapped.t/root.mld @@ -0,0 +1 @@ +{0 Root} diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t new file mode 100644 index 0000000000..48a9a5f247 --- /dev/null +++ b/test/occurrences/double_wrapped.t/run.t @@ -0,0 +1,59 @@ +This test simulates the conditions when a dune user write a toplevel module. + +The module C is not exposed in the handwritten toplevel module. +The module A and B are exposed. +The module B depends on both B and C, the module C only depends on A. + + $ ocamlc -c -o main__.cmo main__.ml -bin-annot -w -49 -no-alias-deps -I . + $ ocamlc -c -open Main__ -o main__A.cmo a.ml -bin-annot -I . + $ ocamlc -c -open Main__ -o main__C.cmo c.ml -bin-annot -I . + $ ocamlc -c -open Main__ -o main__B.cmo b.ml -bin-annot -I . + $ ocamlc -c -open Main__ main.ml -bin-annot -I . + +Passing the count-occurrences flag to odoc compile makes it collect the +occurrences information. + + + $ odoc compile --count-occurrences -I . main__A.cmt + $ odoc compile --count-occurrences -I . main__C.cmt + $ odoc compile --count-occurrences -I . main__B.cmt + $ odoc compile --count-occurrences -I . main__.cmt + $ odoc compile --count-occurrences -I . main.cmt + + $ odoc link -I . main.odoc + $ odoc link -I . main__A.odoc + $ odoc link -I . main__B.odoc + File "main__B.odoc": + Warning: Failed to lookup value identifier((root Main__B).Z, false).y Parent_module: Lookup failure (module): (root Main__B).Z + File "main__B.odoc": + Warning: Failed to lookup value identifier((root Main__B).Y, false).x Parent_module: Lookup failure (module): (root Main__B).Y + $ odoc link -I . main__C.odoc + File "main__C.odoc": + Warning: Failed to lookup value identifier((root Main__C).Y, false).x Parent_module: Lookup failure (module): (root Main__C).Y + $ odoc link -I . main__.odoc + +The count occurrences command outputs a marshalled hashtable, whose keys are +odoc identifiers, and whose values are integers corresponding to the number of +uses. + + $ odoc count-occurrences -I . -o occurrences.txt + + $ du -h occurrences.txt + 4.0K occurrences.txt + +The occurrences_print executable, available only for testing, unmarshal the file +and prints the number of occurrences in a readable format. + +Uses of A and B are counted correctly, with the path rewritten correctly. +Uses of C are not counted, since the canonical destination (generated by dune) does not exist. +Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. +Uses of values Main__.C.y and Main__.A.x are not rewritten since we use references instead of paths. + + $ occurrences_print occurrences.txt | sort + Main.A was used 4 times + Main.A.(||>) was used 1 times + Main.A.M was used 2 times + Main.A.t was used 1 times + Main.A.x was used 2 times + Main.B was used 1 times + string was used 1 times diff --git a/test/occurrences/dune b/test/occurrences/dune new file mode 100644 index 0000000000..7ce8e1acbc --- /dev/null +++ b/test/occurrences/dune @@ -0,0 +1,11 @@ +; Tests related to linking to source code + +(env + (_ + (binaries + (../odoc_print/occurrences_print.exe as occurrences_print)))) + +(cram + (enabled_if + (>= %{ocaml_version} 4.14.1)) + (deps %{bin:odoc} %{bin:occurrences_print})) diff --git a/test/occurrences/source.t/a.ml b/test/occurrences/source.t/a.ml new file mode 100644 index 0000000000..e09e5d02a3 --- /dev/null +++ b/test/occurrences/source.t/a.ml @@ -0,0 +1 @@ +let a = B.b diff --git a/test/occurrences/source.t/b.ml b/test/occurrences/source.t/b.ml new file mode 100644 index 0000000000..56d2d5273c --- /dev/null +++ b/test/occurrences/source.t/b.ml @@ -0,0 +1 @@ +let b = 3 diff --git a/test/occurrences/source.t/root.mld b/test/occurrences/source.t/root.mld new file mode 100644 index 0000000000..54f377d3e8 --- /dev/null +++ b/test/occurrences/source.t/root.mld @@ -0,0 +1 @@ +{0 Root} diff --git a/test/occurrences/source.t/run.t b/test/occurrences/source.t/run.t new file mode 100644 index 0000000000..9c0da5e49f --- /dev/null +++ b/test/occurrences/source.t/run.t @@ -0,0 +1,38 @@ +When both source rendering and occurrence counting are enabled, the occurrences information are used to generate "jump to documentation" links. + +This test tests this. + +Files containing some values: + + $ cat a.ml | head -n 3 + let a = B.b + + $ cat b.ml | head -n 3 + let b = 3 + +Source pages require a parent: + + $ odoc compile -c module-a -c module-b -c src-source root.mld + +Compile the modules: + + $ ocamlc -c b.ml -bin-annot + $ ocamlc -c a.ml -I . -bin-annot + +Compile the pages with the source and occurrences options + + $ printf "a.ml\nb.ml\n" > source_tree.map + $ odoc source-tree -I . --parent page-root -o src-source.odoc source_tree.map + $ odoc compile --count-occurrences -I . --source-name b.ml --source-parent-file src-source.odoc b.cmt + $ odoc compile --count-occurrences -I . --source-name a.ml --source-parent-file src-source.odoc a.cmt + $ odoc link -I . b.odoc + $ odoc link -I . a.odoc + $ odoc html-generate --source b.ml --indent -o html b.odocl + $ odoc html-generate --source a.ml --indent -o html a.odocl + $ odoc support-files -o html + +The source for `a` contains a link to the documentation of `B.b`, as it is used in the implementation: + + $ cat html/root/source/a.ml.html | tr '> ' '\n\n' | grep 'href' | grep val-b + href="b.ml.html#val-b" + href="../../B/index.html#val-b" diff --git a/test/odoc_print/dune b/test/odoc_print/dune index 2ff497d279..808b543f1a 100644 --- a/test/odoc_print/dune +++ b/test/odoc_print/dune @@ -6,9 +6,9 @@ (executable (name odoc_print) (modules odoc_print) - (libraries - odoc_odoc - cmdliner - type_desc_to_yojson - odoc_model_desc - compatcmdliner)) + (libraries odoc_odoc type_desc_to_yojson odoc_model_desc compatcmdliner)) + +(executable + (name occurrences_print) + (modules occurrences_print) + (libraries odoc_model_desc compatcmdliner)) diff --git a/test/odoc_print/occurrences_print.ml b/test/odoc_print/occurrences_print.ml new file mode 100644 index 0000000000..86d39fade3 --- /dev/null +++ b/test/odoc_print/occurrences_print.ml @@ -0,0 +1,27 @@ +module H = Hashtbl.Make (Odoc_model.Paths.Identifier) + +let run inp = + let ic = open_in_bin inp in + let htbl = Marshal.from_channel ic in + H.iter + (fun id occ -> + let id = String.concat "." (Odoc_model.Paths.Identifier.fullname id) in + Format.printf "%s was used %d times\n" id occ) + htbl + +open Compatcmdliner + +let a_inp = + let doc = "Input file." in + Arg.(required & pos 0 (some file) None & info ~doc ~docv:"PATH" []) + +let term = + let doc = + "Print the content of occurrences files into a text format. For tests" + in + Term.(const run $ a_inp, info "occurrences_print" ~doc) + +let () = + match Term.eval term with + | `Ok () -> () + | (`Version | `Help | `Error _) as x -> Term.exit x diff --git a/test/sources/functor.t/run.t b/test/sources/functor.t/run.t index 4bca693672..1b41b151bd 100644 --- a/test/sources/functor.t/run.t +++ b/test/sources/functor.t/run.t @@ -12,8 +12,16 @@ Verify the behavior on functors. $ odoc compile --source-name a.ml --source-parent-file src-source.odoc -I . a.cmt $ odoc compile --source-name b.ml --source-parent-file src-source.odoc -I . b.cmt $ odoc link -I . s.odoc + File "s.odoc": + Warning: Failed to lookup type identifier((root S).S.t, false) Lookup failure (type): (root S).S.t $ odoc link -I . a.odoc + File "a.odoc": + Warning: Failed to lookup value identifier((param (root A).F S), false).x Parent_module: Lookup failure (module): (param (root A).F S) + File "a.odoc": + Warning: Failed to lookup type identifier((param (root A).F S), false).t Parent_module: Lookup failure (module): (param (root A).F S) $ odoc link -I . b.odoc + File "b.odoc": + Warning: Failed to resolve module path identifier((root B).S, false) Lookup failure (module): (root B).S $ odoc html-generate --source s.ml --indent -o html s.odocl $ odoc html-generate --source a.ml --indent -o html a.odocl $ odoc html-generate --source b.ml --indent -o html b.odocl diff --git a/test/sources/lookup_def.t/run.t b/test/sources/lookup_def.t/run.t index f6c30e1045..944b6741fd 100644 --- a/test/sources/lookup_def.t/run.t +++ b/test/sources/lookup_def.t/run.t @@ -8,6 +8,8 @@ Compile the modules: $ ocamlc -c a.mli a.ml -bin-annot $ odoc compile --cmt a.cmt --source-name a.ml --source-parent-file src-source.odoc -I . a.cmti $ odoc link a.odoc + File "a.odoc": + Warning: Failed to resolve module type path identifier((root A).N.S, false) Lookup failure (module type): (root A).N.S Show the locations: diff --git a/test/sources/recursive_module.t/run.t b/test/sources/recursive_module.t/run.t index aba686595a..0f8a5517ba 100644 --- a/test/sources/recursive_module.t/run.t +++ b/test/sources/recursive_module.t/run.t @@ -8,6 +8,14 @@ Checking that source links exists inside recursive modules. $ ocamlc -c main.ml -bin-annot -I . $ odoc compile --source-name main.ml --source-parent-file src-source.odoc -I . main.cmt $ odoc link -I . main.odoc + File "main.odoc": + Warning: Failed to lookup type identifier((root Main).A, false).t Parent_module: Lookup failure (module): (root Main).A + File "main.odoc": + Warning: Failed to resolve module path identifier((root Main).B, false) Lookup failure (module): (root Main).B + File "main.odoc": + Warning: Failed to lookup type identifier((root Main).B, false).t Parent_module: Lookup failure (module): (root Main).B + File "main.odoc": + Warning: Failed to resolve module path identifier((root Main).A, false) Lookup failure (module): (root Main).A $ odoc html-generate --source main.ml --indent -o html main.odocl Both modules should contain source links diff --git a/test/sources/source.t/run.t b/test/sources/source.t/run.t index f350b1b810..eb8eec5f03 100644 --- a/test/sources/source.t/run.t +++ b/test/sources/source.t/run.t @@ -88,6 +88,30 @@ Now, compile the pages with the --source option: $ odoc compile -I . --source-name a.ml --source-parent-file src-source.odoc a.cmt $ odoc link -I . a.odoc + File "a.odoc": + Warning: Failed to resolve module path identifier((root A).F, false) Lookup failure (module): (root A).F + File "a.odoc": + Warning: Failed to resolve module path identifier((param (root A).F M), false).A Parent_module: Lookup failure (module): (param (root A).F M) + File "a.odoc": + Warning: Failed to lookup type identifier((root A).a1, false) Lookup failure (type): (root A).a1 + File "a.odoc": + Warning: Failed to resolve module type path identifier((root A).T, false) Lookup failure (module type): (root A).T + File "a.odoc": + Warning: Failed to resolve module path identifier((root A).A, false) Lookup failure (module): (root A).A + File "a.odoc": + Warning: Failed to lookup value identifier((root A).y, false) Lookup failure (value): (root A).y + File "a.odoc": + Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 + File "a.odoc": + Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 + File "a.odoc": + Warning: Failed to lookup value identifier((root A).y, false) Lookup failure (value): (root A).y + File "a.odoc": + Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 + File "a.odoc": + Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 + File "a.odoc": + Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 $ odoc link -I . page-root.odoc $ odoc link -I . src-source.odoc $ odoc html-generate --indent -o html src-source.odocl @@ -312,4 +336,3 @@ Ids generated in the source code: id="module-FF2" id="module-FF2.argument-1-A.module-E" id="module-FF2.argument-2-A.module-F" - From b70e3f93c20630f253f40ae81c2193bca9be3b05 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 19 Oct 2023 08:46:58 +0200 Subject: [PATCH 13/35] Occurrence: change datastructure to capture more information Signed-off-by: Paul-Elliot --- src/odoc/occurrences.ml | 101 +++++++++++++++++++++++- test/occurrences/double_wrapped.t/run.t | 15 ++-- test/odoc_print/dune | 2 +- test/odoc_print/occurrences_print.ml | 11 ++- 4 files changed, 114 insertions(+), 15 deletions(-) diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index 286f047600..ab57e32acf 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -22,14 +22,109 @@ let fold_dirs ~dirs ~f ~init = module H = Hashtbl.Make (Odoc_model.Paths.Identifier) +module Occtbl : sig + type item = { direct : int; indirect : int; sub : item H.t } + type t = item H.t + type key = Odoc_model.Paths.Identifier.t + val v : unit -> t + + val add : t -> key -> unit + + val iter : (key -> item -> unit) -> t -> unit + + val get : t -> key -> item option +end = struct + type item = { direct : int; indirect : int; sub : item H.t } + type t = item H.t + type key = Odoc_model.Paths.Identifier.t + + let v_item () = { direct = 0; indirect = 0; sub = H.create 0 } + + let v () = H.create 0 + + let add tbl id = + let rec add ?(kind = `Indirect) id = + let incr htbl id = + let { direct; indirect; sub } = + match H.find_opt htbl id with Some n -> n | None -> v_item () + in + let direct, indirect = + match kind with + | `Direct -> (direct + 1, indirect) + | `Indirect -> (direct, indirect + 1) + in + H.replace htbl id { direct; indirect; sub }; + sub + in + let do_ parent = + let htbl = add (parent :> key) in + incr htbl id + in + match id.iv with + | `InstanceVariable (parent, _) -> do_ parent + | `Parameter (parent, _) -> do_ parent + | `Module (parent, _) -> do_ parent + | `ModuleType (parent, _) -> do_ parent + | `Method (parent, _) -> do_ parent + | `Field (parent, _) -> do_ parent + | `Extension (parent, _) -> do_ parent + | `Type (parent, _) -> do_ parent + | `CoreType _ -> incr tbl id + | `Constructor (parent, _) -> do_ parent + | `Exception (parent, _) -> do_ parent + | `ExtensionDecl (parent, _, _) -> do_ parent + | `Class (parent, _) -> do_ parent + | `Value (parent, _) -> do_ parent + | `ClassType (parent, _) -> do_ parent + | `Root _ -> incr tbl id + | `SourcePage _ | `Page _ | `LeafPage _ | `SourceLocation _ + | `CoreException _ | `Label _ | `SourceLocationMod _ | `Result _ + | `AssetFile _ | `SourceDir _ | `SourceLocationInternal _ -> + assert false + in + let _htbl = add ~kind:`Direct id in + () + + let rec get t id = + let ( >>= ) = Option.bind in + let do_ parent = + get t (parent :> key) >>= fun { sub; _ } -> H.find_opt sub id + in + match id.iv with + | `InstanceVariable (parent, _) -> do_ parent + | `Parameter (parent, _) -> do_ parent + | `Module (parent, _) -> do_ parent + | `ModuleType (parent, _) -> do_ parent + | `Method (parent, _) -> do_ parent + | `Field (parent, _) -> do_ parent + | `Extension (parent, _) -> do_ parent + | `ExtensionDecl (parent, _, _) -> do_ parent + | `Type (parent, _) -> do_ parent + | `Constructor (parent, _) -> do_ parent + | `Exception (parent, _) -> do_ parent + | `Class (parent, _) -> do_ parent + | `Value (parent, _) -> do_ parent + | `ClassType (parent, _) -> do_ parent + | `Root _ -> H.find_opt t id + | `SourcePage _ | `Page _ | `LeafPage _ | `CoreType _ | `SourceLocation _ + | `CoreException _ | `Label _ | `SourceLocationMod _ | `Result _ + | `AssetFile _ | `SourceDir _ | `SourceLocationInternal _ -> + assert false + + let rec iter f tbl = + H.iter + (fun id v -> + iter f v.sub; + f id v) + tbl +end + let count ~dst ~warnings_options:_ directories = let htbl = H.create 100 in let f () (unit : Odoc_model.Lang.Compilation_unit.t) = let incr tbl p p' = let id = Odoc_model.Paths.Path.Resolved.(identifier (p :> t)) in - let old_value = match H.find_opt tbl id with Some n -> n | None -> 0 in - if not Odoc_model.Paths.Path.(is_hidden p') then - H.replace tbl id (old_value + 1) + if not Odoc_model.Paths.Path.(is_hidden p') then Occtbl.add tbl id in let () = List.iter diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index 48a9a5f247..d3ff37f904 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -50,10 +50,11 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc Uses of values Main__.C.y and Main__.A.x are not rewritten since we use references instead of paths. $ occurrences_print occurrences.txt | sort - Main.A was used 4 times - Main.A.(||>) was used 1 times - Main.A.M was used 2 times - Main.A.t was used 1 times - Main.A.x was used 2 times - Main.B was used 1 times - string was used 1 times + Main was used directly 0 times and indirectly 11 times + Main.A was used directly 4 times and indirectly 6 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times + Main.A.x was used directly 2 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times diff --git a/test/odoc_print/dune b/test/odoc_print/dune index 808b543f1a..af9fe88cde 100644 --- a/test/odoc_print/dune +++ b/test/odoc_print/dune @@ -11,4 +11,4 @@ (executable (name occurrences_print) (modules occurrences_print) - (libraries odoc_model_desc compatcmdliner)) + (libraries odoc_model_desc compatcmdliner odoc_odoc)) diff --git a/test/odoc_print/occurrences_print.ml b/test/odoc_print/occurrences_print.ml index 86d39fade3..7035bf90f8 100644 --- a/test/odoc_print/occurrences_print.ml +++ b/test/odoc_print/occurrences_print.ml @@ -2,11 +2,14 @@ module H = Hashtbl.Make (Odoc_model.Paths.Identifier) let run inp = let ic = open_in_bin inp in - let htbl = Marshal.from_channel ic in - H.iter - (fun id occ -> + let htbl : Odoc_odoc.Occurrences.Occtbl.item Odoc_odoc.Occurrences.H.t = + Marshal.from_channel ic + in + Odoc_odoc.Occurrences.Occtbl.iter + (fun id { Odoc_odoc.Occurrences.Occtbl.direct; indirect; _ } -> let id = String.concat "." (Odoc_model.Paths.Identifier.fullname id) in - Format.printf "%s was used %d times\n" id occ) + Format.printf "%s was used directly %d times and indirectly %d times\n" id + direct indirect) htbl open Compatcmdliner From e47ecadc8a8c7de2184578611c4c336d2aec1d7e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 24 Oct 2023 13:31:49 +0200 Subject: [PATCH 14/35] Occurrences: add changelog Signed-off-by: Paul-Elliot --- CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index eda0c898aa..2731a0af97 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,6 +16,8 @@ Tags: - Add support for search (@panglesd, @EmileTrotignon, #972) - Allow to omit parent type in constructor reference (@panglesd, @EmileTrotignon, #933) +- Add jumps to documentation in rendered source code, and a `count-occurrences` + flag and command to count occurrences of every identifiers (@panglesd, #976) ### Fixed From 3af1d4c326fba83557d26e5c3f9336271f68477e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 11:37:36 +0100 Subject: [PATCH 15/35] remove duplicated function Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 8 +------- src/loader/typedtree_traverse.ml | 3 +++ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 344f8fab79..88f3136c67 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -53,18 +53,12 @@ module Env = struct match item.str_desc with | Tstr_module mb -> module_binding env parent mb | Tstr_recmodule mbs -> module_bindings env parent mbs - | Tstr_modtype mtd -> module_type_decl env parent mtd + | Tstr_modtype mtd -> module_type_declaration env parent mtd | Tstr_open _ | Tstr_value _ | Tstr_class _ | Tstr_eval _ | Tstr_class_type _ | Tstr_include _ | Tstr_attribute _ | Tstr_primitive _ | Tstr_type _ | Tstr_typext _ | Tstr_exception _ -> () - and module_type_decl env _parent mtd = - let id = Ident_env.find_module_type env mtd.mtd_id in - match mtd.mtd_type with - | None -> () - | Some mty -> module_type env (id :> Identifier.Signature.t) mty - and module_type env (parent : Identifier.Signature.t) mty = match mty.mty_desc with | Tmty_signature sg -> signature env (parent : Identifier.Signature.t) sg diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml index 7baac064f2..9c64a1d911 100644 --- a/src/loader/typedtree_traverse.ml +++ b/src/loader/typedtree_traverse.ml @@ -56,6 +56,9 @@ module Analysis = struct () | _ -> () + (* Add module_binding equivalent of pat *) + + let module_expr poses mod_expr = match mod_expr with | { Typedtree.mod_desc = Tmod_ident (p, _); mod_loc; _ } From ff735ea81b6dc2d8b52879f4a3e5ba6447375b0b Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 14:16:11 +0100 Subject: [PATCH 16/35] Do not report resolution warning for occurrences Signed-off-by: Paul-Elliot --- src/xref2/link.ml | 95 ++++++++++++++----------- test/occurrences/double_wrapped.t/run.t | 6 -- test/sources/functor.t/run.t | 8 --- test/sources/lookup_def.t/run.t | 2 - test/sources/recursive_module.t/run.t | 8 --- test/sources/source.t/run.t | 24 ------- 6 files changed, 55 insertions(+), 88 deletions(-) diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 0bc640a628..16e08b177c 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -135,8 +135,9 @@ and should_resolve_constructor : Paths.Path.Constructor.t -> bool = | `Resolved p -> should_reresolve (p :> Paths.Path.Resolved.t) | _ -> true -let type_path : Env.t -> Paths.Path.Type.t -> Paths.Path.Type.t = - fun env p -> +let type_path : + ?report_errors:bool -> Env.t -> Paths.Path.Type.t -> Paths.Path.Type.t = + fun ?(report_errors = true) env p -> if not (should_resolve (p :> Paths.Path.t)) then p else let cp = Component.Of_Lang.(type_path (empty ()) p) in @@ -150,11 +151,13 @@ let type_path : Env.t -> Paths.Path.Type.t -> Paths.Path.Type.t = let result = Tools.reresolve_type env p' in `Resolved Lang_of.(Path.resolved_type (empty ()) result) | Error e -> - Errors.report ~what:(`Type_path cp) ~tools_error:e `Lookup; + if report_errors then + Errors.report ~what:(`Type_path cp) ~tools_error:e `Lookup; p) -let value_path : Env.t -> Paths.Path.Value.t -> Paths.Path.Value.t = - fun env p -> +let value_path : + ?report_errors:bool -> Env.t -> Paths.Path.Value.t -> Paths.Path.Value.t = + fun ?(report_errors = true) env p -> if not (should_resolve (p :> Paths.Path.t)) then p else let cp = Component.Of_Lang.(value_path (empty ()) p) in @@ -168,36 +171,41 @@ let value_path : Env.t -> Paths.Path.Value.t -> Paths.Path.Value.t = let result = Tools.reresolve_value env p' in `Resolved Lang_of.(Path.resolved_value (empty ()) result) | Error e -> - Errors.report ~what:(`Value_path cp) ~tools_error:e `Lookup; + if report_errors then + Errors.report ~what:(`Value_path cp) ~tools_error:e `Lookup; p) let constructor_path : - Env.t -> Paths.Path.Constructor.t -> Paths.Path.Constructor.t = - fun env p -> + ?report_errors:bool -> + Env.t -> + Paths.Path.Constructor.t -> + Paths.Path.Constructor.t = + fun ?(report_errors = true) env p -> + (* if not (should_resolve (p : Paths.Path.Constructor.t :> Paths.Path.t)) then p *) + (* else *) if not (should_resolve_constructor p) then p else - let cp = Component.Of_Lang.(constructor_path (empty ()) p) in - match cp with - | `Resolved p -> - let result = Tools.reresolve_constructor env p in - `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) - | _ -> ( - match Tools.resolve_constructor_path env cp with - | Ok p' -> - let result = Tools.reresolve_constructor env p' in - `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) - | Error e -> + let cp = Component.Of_Lang.(constructor_path (empty ()) p) in + match cp with + | `Resolved p -> + let result = Tools.reresolve_constructor env p in + `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) + | _ -> ( + match Tools.resolve_constructor_path env cp with + | Ok p' -> + let result = Tools.reresolve_constructor env p' in + `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) + | Error e -> + if report_errors then Errors.report ~what:(`Constructor_path cp) ~tools_error:e `Lookup; - p) - -let () = - (* Until those are used *) - ignore value_path; - ignore constructor_path + p) -let class_type_path : Env.t -> Paths.Path.ClassType.t -> Paths.Path.ClassType.t - = - fun env p -> +let class_type_path : + ?report_errors:bool -> + Env.t -> + Paths.Path.ClassType.t -> + Paths.Path.ClassType.t = + fun ?(report_errors = true) env p -> if not (should_resolve (p :> Paths.Path.t)) then p else let cp = Component.Of_Lang.(class_type_path (empty ()) p) in @@ -211,12 +219,16 @@ let class_type_path : Env.t -> Paths.Path.ClassType.t -> Paths.Path.ClassType.t let result = Tools.reresolve_class_type env p' in `Resolved Lang_of.(Path.resolved_class_type (empty ()) result) | Error e -> - Errors.report ~what:(`Class_type_path cp) ~tools_error:e `Lookup; + if report_errors then + Errors.report ~what:(`Class_type_path cp) ~tools_error:e `Lookup; p) and module_type_path : - Env.t -> Paths.Path.ModuleType.t -> Paths.Path.ModuleType.t = - fun env p -> + ?report_errors:bool -> + Env.t -> + Paths.Path.ModuleType.t -> + Paths.Path.ModuleType.t = + fun ?(report_errors = true) env p -> if not (should_resolve (p :> Paths.Path.t)) then p else let cp = Component.Of_Lang.(module_type_path (empty ()) p) in @@ -230,11 +242,13 @@ and module_type_path : let result = Tools.reresolve_module_type env p' in `Resolved Lang_of.(Path.resolved_module_type (empty ()) result) | Error e -> - Errors.report ~what:(`Module_type_path cp) ~tools_error:e `Resolve; + if report_errors then + Errors.report ~what:(`Module_type_path cp) ~tools_error:e `Resolve; p) -and module_path : Env.t -> Paths.Path.Module.t -> Paths.Path.Module.t = - fun env p -> +and module_path : + ?report_errors:bool -> Env.t -> Paths.Path.Module.t -> Paths.Path.Module.t = + fun ?(report_errors = true) env p -> if not (should_resolve (p :> Paths.Path.t)) then p else let cp = Component.Of_Lang.(module_path (empty ()) p) in @@ -249,7 +263,8 @@ and module_path : Env.t -> Paths.Path.Module.t -> Paths.Path.Module.t = `Resolved Lang_of.(Path.resolved_module (empty ()) result) | Error _ when is_forward p -> p | Error e -> - Errors.report ~what:(`Module_path cp) ~tools_error:e `Resolve; + if report_errors then + Errors.report ~what:(`Module_path cp) ~tools_error:e `Resolve; p) let rec comment_inline_element : @@ -438,16 +453,16 @@ let rec unit env t = Value (jump_to v (Shape_tools.lookup_value_path env) - (value_path env)) + (value_path ~report_errors:false env)) | Module v -> - Module (jump_to v (fun _ -> None) (module_path env)) + Module (jump_to v (fun _ -> None) (module_path ~report_errors:false env)) | ModuleType v -> ModuleType - (jump_to v (fun _ -> None) (module_type_path env)) - | Type v -> Type (jump_to v (fun _ -> None) (type_path env)) + (jump_to v (fun _ -> None) (module_type_path ~report_errors:false env)) + | Type v -> Type (jump_to v (fun _ -> None) (type_path ~report_errors:false env)) | Constructor v -> Constructor - (jump_to v (fun _ -> None) (constructor_path env)) + (jump_to v (fun _ -> None) (constructor_path ~report_errors:false env)) | i -> i in (info, pos)) diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index d3ff37f904..e87a140d68 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -23,13 +23,7 @@ occurrences information. $ odoc link -I . main.odoc $ odoc link -I . main__A.odoc $ odoc link -I . main__B.odoc - File "main__B.odoc": - Warning: Failed to lookup value identifier((root Main__B).Z, false).y Parent_module: Lookup failure (module): (root Main__B).Z - File "main__B.odoc": - Warning: Failed to lookup value identifier((root Main__B).Y, false).x Parent_module: Lookup failure (module): (root Main__B).Y $ odoc link -I . main__C.odoc - File "main__C.odoc": - Warning: Failed to lookup value identifier((root Main__C).Y, false).x Parent_module: Lookup failure (module): (root Main__C).Y $ odoc link -I . main__.odoc The count occurrences command outputs a marshalled hashtable, whose keys are diff --git a/test/sources/functor.t/run.t b/test/sources/functor.t/run.t index 1b41b151bd..4bca693672 100644 --- a/test/sources/functor.t/run.t +++ b/test/sources/functor.t/run.t @@ -12,16 +12,8 @@ Verify the behavior on functors. $ odoc compile --source-name a.ml --source-parent-file src-source.odoc -I . a.cmt $ odoc compile --source-name b.ml --source-parent-file src-source.odoc -I . b.cmt $ odoc link -I . s.odoc - File "s.odoc": - Warning: Failed to lookup type identifier((root S).S.t, false) Lookup failure (type): (root S).S.t $ odoc link -I . a.odoc - File "a.odoc": - Warning: Failed to lookup value identifier((param (root A).F S), false).x Parent_module: Lookup failure (module): (param (root A).F S) - File "a.odoc": - Warning: Failed to lookup type identifier((param (root A).F S), false).t Parent_module: Lookup failure (module): (param (root A).F S) $ odoc link -I . b.odoc - File "b.odoc": - Warning: Failed to resolve module path identifier((root B).S, false) Lookup failure (module): (root B).S $ odoc html-generate --source s.ml --indent -o html s.odocl $ odoc html-generate --source a.ml --indent -o html a.odocl $ odoc html-generate --source b.ml --indent -o html b.odocl diff --git a/test/sources/lookup_def.t/run.t b/test/sources/lookup_def.t/run.t index 944b6741fd..f6c30e1045 100644 --- a/test/sources/lookup_def.t/run.t +++ b/test/sources/lookup_def.t/run.t @@ -8,8 +8,6 @@ Compile the modules: $ ocamlc -c a.mli a.ml -bin-annot $ odoc compile --cmt a.cmt --source-name a.ml --source-parent-file src-source.odoc -I . a.cmti $ odoc link a.odoc - File "a.odoc": - Warning: Failed to resolve module type path identifier((root A).N.S, false) Lookup failure (module type): (root A).N.S Show the locations: diff --git a/test/sources/recursive_module.t/run.t b/test/sources/recursive_module.t/run.t index 0f8a5517ba..aba686595a 100644 --- a/test/sources/recursive_module.t/run.t +++ b/test/sources/recursive_module.t/run.t @@ -8,14 +8,6 @@ Checking that source links exists inside recursive modules. $ ocamlc -c main.ml -bin-annot -I . $ odoc compile --source-name main.ml --source-parent-file src-source.odoc -I . main.cmt $ odoc link -I . main.odoc - File "main.odoc": - Warning: Failed to lookup type identifier((root Main).A, false).t Parent_module: Lookup failure (module): (root Main).A - File "main.odoc": - Warning: Failed to resolve module path identifier((root Main).B, false) Lookup failure (module): (root Main).B - File "main.odoc": - Warning: Failed to lookup type identifier((root Main).B, false).t Parent_module: Lookup failure (module): (root Main).B - File "main.odoc": - Warning: Failed to resolve module path identifier((root Main).A, false) Lookup failure (module): (root Main).A $ odoc html-generate --source main.ml --indent -o html main.odocl Both modules should contain source links diff --git a/test/sources/source.t/run.t b/test/sources/source.t/run.t index eb8eec5f03..ccd15b178e 100644 --- a/test/sources/source.t/run.t +++ b/test/sources/source.t/run.t @@ -88,30 +88,6 @@ Now, compile the pages with the --source option: $ odoc compile -I . --source-name a.ml --source-parent-file src-source.odoc a.cmt $ odoc link -I . a.odoc - File "a.odoc": - Warning: Failed to resolve module path identifier((root A).F, false) Lookup failure (module): (root A).F - File "a.odoc": - Warning: Failed to resolve module path identifier((param (root A).F M), false).A Parent_module: Lookup failure (module): (param (root A).F M) - File "a.odoc": - Warning: Failed to lookup type identifier((root A).a1, false) Lookup failure (type): (root A).a1 - File "a.odoc": - Warning: Failed to resolve module type path identifier((root A).T, false) Lookup failure (module type): (root A).T - File "a.odoc": - Warning: Failed to resolve module path identifier((root A).A, false) Lookup failure (module): (root A).A - File "a.odoc": - Warning: Failed to lookup value identifier((root A).y, false) Lookup failure (value): (root A).y - File "a.odoc": - Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 - File "a.odoc": - Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 - File "a.odoc": - Warning: Failed to lookup value identifier((root A).y, false) Lookup failure (value): (root A).y - File "a.odoc": - Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 - File "a.odoc": - Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 - File "a.odoc": - Warning: Failed to lookup value identifier((root A).{x}2, false) Lookup failure (value): (root A).{x}2 $ odoc link -I . page-root.odoc $ odoc link -I . src-source.odoc $ odoc html-generate --indent -o html src-source.odocl From 164cc199e71510fcce914267f2347e57feab950e Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 14:34:35 +0100 Subject: [PATCH 17/35] Occurrences: Rename Definition to LocalDefinition when applicable Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 20 ++++++++++---------- src/loader/typedtree_traverse.ml | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 88f3136c67..4dbece1fa8 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -141,10 +141,10 @@ module UidHashtbl = Shape.Uid.Tbl (* Adds the local definitions found in traverse infos to the [loc_to_id] and [ident_to_id] tables. *) -let populate_local_defs source_id poses loc_to_id ident_to_loc = +let populate_local_defs source_id poses loc_to_id local_ident_to_loc = List.iter (function - | Typedtree_traverse.Analysis.Definition id, loc -> + | Typedtree_traverse.Analysis.LocalDefinition id, loc -> let name = Odoc_model.Names.LocalName.make_std (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) @@ -157,7 +157,7 @@ let populate_local_defs source_id poses loc_to_id ident_to_loc = LocHashtbl.add loc_to_id loc identifier | None -> () ); - IdentHashtbl.add ident_to_loc id loc; + IdentHashtbl.add local_ident_to_loc id loc; | _ -> ()) poses @@ -281,13 +281,13 @@ let (>>=) a b = Option.map b a (* Extract [Typedtree_traverse] occurrence information and turn them into proper source infos *) -let process_occurrences env poses loc_to_id ident_to_loc = +let process_occurrences env poses loc_to_id local_ident_to_loc = let open Odoc_model.Lang.Source_info in let process p find_in_env = match p with - | Path.Pident id when IdentHashtbl.mem ident_to_loc id -> ( + | Path.Pident id when IdentHashtbl.mem local_ident_to_loc id -> ( match - LocHashtbl.find_opt loc_to_id (IdentHashtbl.find ident_to_loc id) + LocHashtbl.find_opt loc_to_id (IdentHashtbl.find local_ident_to_loc id) with | None -> None | Some id -> @@ -321,7 +321,7 @@ let process_occurrences env poses loc_to_id ident_to_loc = | Constructor _p, loc -> (* process p Ident_env.Path.read_constructor *) None >>= fun l -> (Constructor l, pos_of_loc loc) - | Definition _, _ -> None) + | LocalDefinition _, _ -> None) poses @@ -348,15 +348,15 @@ let read_cmt_infos source_id_opt id cmt_info ~count_occurrences = not modify the anchors for existing anchors. *) in let loc_to_id = LocHashtbl.create 10 - and ident_to_loc = IdentHashtbl.create 10 + and local_ident_to_loc = IdentHashtbl.create 10 and uid_to_id = UidHashtbl.create 10 in let () = (* populate [loc_to_id], [ident_to_id] and [uid_to_id] *) - populate_local_defs source_id traverse_infos loc_to_id ident_to_loc; + populate_local_defs source_id traverse_infos loc_to_id local_ident_to_loc; populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id in let source_infos = - process_occurrences env traverse_infos loc_to_id ident_to_loc + process_occurrences env traverse_infos loc_to_id local_ident_to_loc |> add_definitions loc_to_id in ( Some (shape, Shape.Uid.Tbl.to_map uid_to_id), diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml index 9c64a1d911..1a04257db6 100644 --- a/src/loader/typedtree_traverse.ml +++ b/src/loader/typedtree_traverse.ml @@ -2,7 +2,7 @@ module Analysis = struct type annotation = - | Definition of Ident.t + | LocalDefinition of Ident.t | Value of Path.t | Module of Path.t | ClassType of Path.t @@ -38,7 +38,7 @@ module Analysis = struct in let maybe_localvalue id loc = match Ident_env.identifier_of_loc env loc with - | None -> Some (Definition id, loc) + | None -> Some (LocalDefinition id, loc) | Some _ -> None in let () = From 6229d9ab565c3aa3c023eabb11adc3e7cd905916 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 14:56:18 +0100 Subject: [PATCH 18/35] Occurrences: remove duplicated source infos Some subnodes of hidden nodes were generating twice the infos Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 46 +++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 4dbece1fa8..910b13a30f 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -137,6 +137,12 @@ module IdentHashtbl = Hashtbl.Make (struct let hash = Hashtbl.hash end) +module AnnotHashtbl = Hashtbl.Make (struct + type t = Odoc_model.Lang.Source_info.annotation Odoc_model.Lang.Source_info.with_pos + let equal l1 l2 = l1 = l2 + let hash = Hashtbl.hash +end) + module UidHashtbl = Shape.Uid.Tbl (* Adds the local definitions found in traverse infos to the [loc_to_id] and @@ -277,17 +283,18 @@ let populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id = | _ -> ())) uid_to_loc -let (>>=) a b = Option.map b a - (* Extract [Typedtree_traverse] occurrence information and turn them into proper source infos *) let process_occurrences env poses loc_to_id local_ident_to_loc = let open Odoc_model.Lang.Source_info in + (* Ensure source infos are not repeated by putting them in a Set (a unit hashtbl) *) + let occ_tbl = AnnotHashtbl.create 100 in let process p find_in_env = match p with | Path.Pident id when IdentHashtbl.mem local_ident_to_loc id -> ( match - LocHashtbl.find_opt loc_to_id (IdentHashtbl.find local_ident_to_loc id) + LocHashtbl.find_opt loc_to_id + (IdentHashtbl.find local_ident_to_loc id) with | None -> None | Some id -> @@ -301,29 +308,30 @@ let process_occurrences env poses loc_to_id local_ident_to_loc = Some { documentation; implementation } | exception _ -> None) in - List.filter_map + List.iter (function | Typedtree_traverse.Analysis.Value p, loc -> - process p Ident_env.Path.read_value >>= fun l -> - (Value l, pos_of_loc loc) + process p Ident_env.Path.read_value |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Value l, pos_of_loc loc) () | Module p, loc -> - process p Ident_env.Path.read_module >>= fun l -> - (Module l, pos_of_loc loc) + process p Ident_env.Path.read_module |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Module l, pos_of_loc loc) () | ClassType p, loc -> - process p Ident_env.Path.read_class_type >>= fun l -> - (ClassType l, pos_of_loc loc) + process p Ident_env.Path.read_class_type |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (ClassType l, pos_of_loc loc) () | ModuleType p, loc -> - process p Ident_env.Path.read_module_type >>= fun l -> - (ModuleType l, pos_of_loc loc) + process p Ident_env.Path.read_module_type |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (ModuleType l, pos_of_loc loc) () | Type p, loc -> - process p Ident_env.Path.read_type >>= fun l -> - (Type l, pos_of_loc loc) + process p Ident_env.Path.read_type |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Type l, pos_of_loc loc) () | Constructor _p, loc -> - (* process p Ident_env.Path.read_constructor *) None >>= fun l -> - (Constructor l, pos_of_loc loc) - | LocalDefinition _, _ -> None) - poses - + (* process p Ident_env.Path.read_constructor *) + None |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Constructor l, pos_of_loc loc) () + | LocalDefinition _, _ -> ()) + poses; + AnnotHashtbl.fold (fun k () acc -> k :: acc) occ_tbl [] (* Add definition source info from the [loc_to_id] table *) let add_definitions loc_to_id occurrences = From 2f61d549a4892522686236bbde3db0c904a009a4 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 16:25:54 +0100 Subject: [PATCH 19/35] Occurrence: collect local module definitions Signed-off-by: Paul-Elliot --- src/loader/typedtree_traverse.ml | 13 ++++++-- src/odoc/occurrences.ml | 2 +- src/xref2/link.ml | 52 +++++++++++++++++++++----------- 3 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/loader/typedtree_traverse.ml b/src/loader/typedtree_traverse.ml index 1a04257db6..8b5a96a97f 100644 --- a/src/loader/typedtree_traverse.ml +++ b/src/loader/typedtree_traverse.ml @@ -56,8 +56,12 @@ module Analysis = struct () | _ -> () - (* Add module_binding equivalent of pat *) - + let module_binding env poses = function + | { Typedtree.mb_id = Some id; mb_loc; _ } when not mb_loc.loc_ghost -> ( + match Ident_env.identifier_of_loc env mb_loc with + | None -> poses := (LocalDefinition id, mb_loc) :: !poses + | Some _ -> ()) + | _ -> () let module_expr poses mod_expr = match mod_expr with @@ -114,6 +118,10 @@ let of_cmt env structure = Analysis.class_type poses cl_type; Tast_iterator.default_iterator.class_type iterator cl_type in + let module_binding iterator mb = + Analysis.module_binding env poses mb; + Tast_iterator.default_iterator.module_binding iterator mb + in let iterator = { Tast_iterator.default_iterator with @@ -123,6 +131,7 @@ let of_cmt env structure = typ; module_type; class_type; + module_binding; } in iterator.structure iterator structure; diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index ab57e32acf..e36fb1dbbb 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -77,7 +77,7 @@ end = struct | `Value (parent, _) -> do_ parent | `ClassType (parent, _) -> do_ parent | `Root _ -> incr tbl id - | `SourcePage _ | `Page _ | `LeafPage _ | `SourceLocation _ + | `SourcePage _ | `Page _ | `LeafPage _ | `SourceLocation _ | `CoreException _ | `Label _ | `SourceLocationMod _ | `Result _ | `AssetFile _ | `SourceDir _ | `SourceLocationInternal _ -> assert false diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 16e08b177c..1199fc0e2f 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -185,20 +185,20 @@ let constructor_path : (* else *) if not (should_resolve_constructor p) then p else - let cp = Component.Of_Lang.(constructor_path (empty ()) p) in - match cp with - | `Resolved p -> - let result = Tools.reresolve_constructor env p in - `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) - | _ -> ( - match Tools.resolve_constructor_path env cp with - | Ok p' -> - let result = Tools.reresolve_constructor env p' in - `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) - | Error e -> - if report_errors then - Errors.report ~what:(`Constructor_path cp) ~tools_error:e `Lookup; - p) + let cp = Component.Of_Lang.(constructor_path (empty ()) p) in + match cp with + | `Resolved p -> + let result = Tools.reresolve_constructor env p in + `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) + | _ -> ( + match Tools.resolve_constructor_path env cp with + | Ok p' -> + let result = Tools.reresolve_constructor env p' in + `Resolved Lang_of.(Path.resolved_constructor (empty ()) result) + | Error e -> + if report_errors then + Errors.report ~what:(`Constructor_path cp) ~tools_error:e `Lookup; + p) let class_type_path : ?report_errors:bool -> @@ -427,6 +427,11 @@ let rec unit env t = | Pack _ as p -> p in let source_info = + let env = + match t.content with + | Module sg -> Env.open_signature sg env |> Env.add_docs sg.doc + | Pack _ -> env + in let open Source_info in match t.source_info with | Some inf -> @@ -455,14 +460,25 @@ let rec unit env t = (Shape_tools.lookup_value_path env) (value_path ~report_errors:false env)) | Module v -> - Module (jump_to v (fun _ -> None) (module_path ~report_errors:false env)) + Module + (jump_to v + (fun _ -> None) + (module_path ~report_errors:false env)) | ModuleType v -> ModuleType - (jump_to v (fun _ -> None) (module_type_path ~report_errors:false env)) - | Type v -> Type (jump_to v (fun _ -> None) (type_path ~report_errors:false env)) + (jump_to v + (fun _ -> None) + (module_type_path ~report_errors:false env)) + | Type v -> + Type + (jump_to v + (fun _ -> None) + (type_path ~report_errors:false env)) | Constructor v -> Constructor - (jump_to v (fun _ -> None) (constructor_path ~report_errors:false env)) + (jump_to v + (fun _ -> None) + (constructor_path ~report_errors:false env)) | i -> i in (info, pos)) From 094eb94a8362be4f62cbb7bb0237b5abab85dec7 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Thu, 2 Nov 2023 17:17:19 +0100 Subject: [PATCH 20/35] Render source code: Add jump to implementation for modules Signed-off-by: Paul-Elliot --- src/xref2/link.ml | 2 +- src/xref2/shape_tools.cppo.ml | 24 +++++++++++++++++------- src/xref2/shape_tools.cppo.mli | 5 +++++ test/sources/source.t/run.t | 2 +- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 1199fc0e2f..66e2e60ee3 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -462,7 +462,7 @@ let rec unit env t = | Module v -> Module (jump_to v - (fun _ -> None) + (Shape_tools.lookup_module_path env) (module_path ~report_errors:false env)) | ModuleType v -> ModuleType diff --git a/src/xref2/shape_tools.cppo.ml b/src/xref2/shape_tools.cppo.ml index 5d516dd926..a6bf903791 100644 --- a/src/xref2/shape_tools.cppo.ml +++ b/src/xref2/shape_tools.cppo.ml @@ -56,11 +56,11 @@ let rec shape_of_id env : let rec shape_of_module_path env : _ -> Shape.t option = let proj parent kind name = let item = Shape.Item.make name kind in - match shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) with + match shape_of_module_path env (parent :> Odoc_model.Paths.Path.Module.t) with | Some shape -> Some (Shape.proj shape item) | None -> None in - fun (path : Odoc_model.Paths.Path.t) -> + fun (path : Odoc_model.Paths.Path.Module.t) -> match path with | `Resolved _ -> None | `Root name -> ( @@ -72,11 +72,11 @@ let rec shape_of_module_path env : _ -> Shape.t option = | _ -> None) | `Forward _ -> None | `Dot (parent, name) -> - proj (parent :> Odoc_model.Paths.Path.t) Kind.Module name + proj (parent :> Odoc_model.Paths.Path.Module.t) Kind.Module name | `Apply (parent, arg) -> - shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) + shape_of_module_path env (parent :> Odoc_model.Paths.Path.Module.t) >>= fun parent -> - shape_of_module_path env (arg :> Odoc_model.Paths.Path.t) >>= fun arg -> + shape_of_module_path env (arg :> Odoc_model.Paths.Path.Module.t) >>= fun arg -> Some (Shape.app parent ~arg) | `Identifier (id, _) -> shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) @@ -85,14 +85,14 @@ let shape_of_value_path env : Odoc_model.Paths.Path.Value.t -> Shape.t option = let proj parent kind name = let item = Shape.Item.make name kind in - match shape_of_module_path env (parent :> Odoc_model.Paths.Path.t) with + match shape_of_module_path env parent with | Some shape -> Some (Shape.proj shape item) | None -> None in fun (path : Odoc_model.Paths.Path.Value.t) -> match path with | `Resolved _ -> None - | `Dot (parent, name) -> proj (parent :> Odoc_model.Paths.Path.t) Kind.Value name + | `Dot (parent, name) -> proj parent Kind.Value name | `Identifier (id, _) -> shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) @@ -160,6 +160,16 @@ let lookup_value_path : | None -> None | Some query -> lookup_shape env query + +let lookup_module_path : + Env.t -> + Path.Module.t -> + Identifier.SourceLocation.t option + = fun env path -> + match shape_of_module_path env path with + | None -> None + | Some query -> lookup_shape env query + #else type t = unit diff --git a/src/xref2/shape_tools.cppo.mli b/src/xref2/shape_tools.cppo.mli index 607d50b8dc..40caf7b433 100644 --- a/src/xref2/shape_tools.cppo.mli +++ b/src/xref2/shape_tools.cppo.mli @@ -18,3 +18,8 @@ val lookup_value_path : Env.t -> Path.Value.t -> Identifier.SourceLocation.t option + +val lookup_module_path : + Env.t -> + Path.Module.t -> + Identifier.SourceLocation.t option diff --git a/test/sources/source.t/run.t b/test/sources/source.t/run.t index ccd15b178e..9adb34e60c 100644 --- a/test/sources/source.t/run.t +++ b/test/sources/source.t/run.t @@ -307,7 +307,7 @@ Ids generated in the source code: id="module-F.argument-1-M.module-A" id="module-F.module-B" id="module-FM" - id="def_3" + id="local_A_3" id="module-FF" id="module-FF2" id="module-FF2.argument-1-A.module-E" From bca725928ea617b13383f202f28fcf413d5872d2 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 00:12:06 +0100 Subject: [PATCH 21/35] Occurrences: style improvements Signed-off-by: Paul-Elliot --- src/document/generator.ml | 15 +++++++-------- src/xref2/link.ml | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/document/generator.ml b/src/document/generator.ml index bb411cacfb..338d3a4579 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -252,7 +252,7 @@ module Make (Syntax : SYNTAX) = struct let path id = Url.Path.from_identifier id let url id = Url.from_path (path id) - let to_link documentation implementation = + let to_link {Lang.Source_info.documentation; implementation} = let documentation = let open Paths.Path.Resolved in match documentation with @@ -281,13 +281,12 @@ module Make (Syntax : SYNTAX) = struct | `SourceLocationInternal (_, local) -> Some (Anchor (LocalName.to_string local)) | _ -> None) - | Module { documentation; _ } -> to_link documentation None - | ModuleType { documentation; _ } -> to_link documentation None - | Type { documentation; _ } -> to_link documentation None - | ClassType { documentation; _ } -> to_link documentation None - | Value { documentation; implementation } -> - to_link documentation implementation - | Constructor { documentation; _ } -> to_link documentation None + | Module v -> to_link v + | ModuleType v -> to_link v + | Type v -> to_link v + | ClassType v -> to_link v + | Value v -> to_link v + | Constructor v -> to_link v let source id syntax_info infos source_code = let url = path id in diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 66e2e60ee3..2f8472a994 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -429,7 +429,7 @@ let rec unit env t = let source_info = let env = match t.content with - | Module sg -> Env.open_signature sg env |> Env.add_docs sg.doc + | Module sg -> Env.open_signature sg env | Pack _ -> env in let open Source_info in From f42e58dc87483fdda461e4d9d0197e61a9208b32 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 00:24:10 +0100 Subject: [PATCH 22/35] Occurrences: add a command to aggregate occurrence tables Signed-off-by: Paul-Elliot --- src/odoc/bin/main.ml | 88 +++++++++++++++++++------ src/odoc/occurrences.ml | 55 +++++++++++++++- test/occurrences/double_wrapped.t/run.t | 74 +++++++++++++++++++-- test/odoc_print/occurrences_print.ml | 2 +- 4 files changed, 192 insertions(+), 27 deletions(-) diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index 8c57b67ab2..83cba0decf 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -1112,27 +1112,74 @@ module Targets = struct end module Occurrences = struct - let index directories dst warnings_options = - let dst = Fpath.v dst in - Occurrences.count ~dst ~warnings_options directories + module Count = struct + let index directories dst warnings_options = + let dst = Fpath.v dst in + Occurrences.count ~dst ~warnings_options directories - let cmd = - let dst = - let doc = "Output file path." in - Arg.( - required & opt (some string) None & info ~docs ~docv:"PATH" ~doc [ "o" ]) - in - Term.( - const handle_error - $ (const index $ odoc_file_directories $ dst $ warnings_options)) + let cmd = + let dst = + let doc = "Output file path." in + Arg.( + required + & opt (some string) None + & info ~docs ~docv:"PATH" ~doc [ "o" ]) + in + Term.( + const handle_error + $ (const index $ odoc_file_directories $ dst $ warnings_options)) - let info ~docs = - let doc = - "Generate a hashtable mapping identifiers to number of occurrences, as \ - computed from the implementations of .odocl files found in the given \ - directories." - in - Term.info "count-occurrences" ~docs ~doc + let info ~docs = + let doc = + "Generate a hashtable mapping identifiers to number of occurrences, as \ + computed from the implementations of .odocl files found in the given \ + directories." + in + Term.info "count-occurrences" ~docs ~doc + end + module Aggregate = struct + let index dst files file_list warnings_options = + match (files, file_list) with + | [], [] -> + Error + (`Msg + "At least one of --file-list or a path to a file must be passed \ + to odoc aggregate-occurrences") + | _ -> + let dst = Fpath.v dst in + Occurrences.aggregate ~dst ~warnings_options files file_list + + let cmd = + let dst = + let doc = "Output file path." in + Arg.( + required + & opt (some string) None + & info ~docs ~docv:"PATH" ~doc [ "o" ]) + in + let inputs_in_file = + let doc = + "Input text file containing a line-separated list of paths to files \ + created with count-occurrences." + in + Arg.( + value & opt_all convert_fpath [] + & info ~doc ~docv:"FILE" [ "file-list" ]) + in + let inputs = + let doc = "file created with count-occurrences" in + Arg.(value & pos_all convert_fpath [] & info ~doc ~docv:"FILE" []) + in + Term.( + const handle_error + $ (const index $ dst $ inputs $ inputs_in_file $ warnings_options)) + + let info ~docs = + let doc = + "Aggregate hashtables created with odoc count-occurrences." + in + Term.info "aggregate-occurrences" ~docs ~doc + end end module Odoc_error = struct @@ -1175,7 +1222,8 @@ let () = Printexc.record_backtrace true; let subcommands = [ - Occurrences.(cmd, info ~docs:section_pipeline); + Occurrences.Count.(cmd, info ~docs:section_pipeline); + Occurrences.Aggregate.(cmd, info ~docs:section_pipeline); Compile.(cmd, info ~docs:section_pipeline); Odoc_link.(cmd, info ~docs:section_pipeline); Odoc_html.generate ~docs:section_pipeline; diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index e36fb1dbbb..8d0f4d9ee0 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -142,7 +142,10 @@ let count ~dst ~warnings_options:_ directories = | Type { documentation = Some (`Resolved p as p'); _ }, _ -> incr htbl p Odoc_model.Paths.Path.((p' : Type.t :> t)) | _ -> ()) - (match unit.source_info with None -> [] | Some i -> i.infos) + (match unit.source_info with + | None -> [] + | Some i -> + i.infos) in () in @@ -151,3 +154,53 @@ let count ~dst ~warnings_options:_ directories = let oc = open_out_bin (Fs.File.to_string dst) in Marshal.to_channel oc htbl []; Ok () + +open Astring +open Or_error + +let parse_input_file input = + let is_sep = function '\n' | '\r' -> true | _ -> false in + Fs.File.read input >>= fun content -> + let files = + String.fields ~empty:false ~is_sep content |> List.rev_map Fs.File.of_string + in + Ok files + +let parse_input_files input = + List.fold_left + (fun acc file -> + acc >>= fun acc -> + parse_input_file file >>= fun files -> Ok (files :: acc)) + (Ok []) input + >>= fun files -> Ok (List.concat files) + +let aggregate files file_list ~warnings_options:_ ~dst = + parse_input_files file_list >>= fun new_files -> + let files = files @ new_files in + let from_file file : Occtbl.t = + let ic = open_in_bin (Fs.File.to_string file) in + Marshal.from_channel ic + in + let rec loop n f = + if n > 0 then ( + f (); + loop (n - 1) f) + else () + in + let occtbl = + match files with + | [] -> H.create 0 + | file1 :: files -> + let acc = from_file file1 in + List.iter + (fun file -> + Occtbl.iter + (fun id { direct; _ } -> + loop direct (fun () -> Occtbl.add acc id)) + (from_file file)) + files; + acc + in + let oc = open_out_bin (Fs.File.to_string dst) in + Marshal.to_channel oc occtbl []; + Ok () diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index e87a140d68..b29ba69aaa 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -13,7 +13,6 @@ The module B depends on both B and C, the module C only depends on A. Passing the count-occurrences flag to odoc compile makes it collect the occurrences information. - $ odoc compile --count-occurrences -I . main__A.cmt $ odoc compile --count-occurrences -I . main__C.cmt $ odoc compile --count-occurrences -I . main__B.cmt @@ -26,11 +25,34 @@ occurrences information. $ odoc link -I . main__C.odoc $ odoc link -I . main__.odoc + $ odoc html-generate -o html main.odocl + $ odoc html-generate -o html main__A.odocl + $ odoc html-generate -o html main__B.odocl + $ odoc html-generate -o html main__C.odocl + $ odoc html-generate -o html main__.odocl + The count occurrences command outputs a marshalled hashtable, whose keys are odoc identifiers, and whose values are integers corresponding to the number of -uses. +uses. We can later aggregate those hashtables, so we create the full hashtable, +and a hashtable for each compilation unit. + + $ mkdir dir1 + $ mkdir dir2 + $ mkdir dir3 + $ mkdir dir4 + $ mkdir dir5 + $ mv main.odocl dir1 + $ mv main__.odocl dir2 + $ mv main__A.odocl dir3 + $ mv main__B.odocl dir4 + $ mv main__C.odocl dir5 $ odoc count-occurrences -I . -o occurrences.txt + $ odoc count-occurrences -I dir1 -o occurrences1.txt + $ odoc count-occurrences -I dir2 -o occurrences2.txt + $ odoc count-occurrences -I dir3 -o occurrences3.txt + $ odoc count-occurrences -I dir4 -o occurrences4.txt + $ odoc count-occurrences -I dir5 -o occurrences5.txt $ du -h occurrences.txt 4.0K occurrences.txt @@ -38,10 +60,10 @@ uses. The occurrences_print executable, available only for testing, unmarshal the file and prints the number of occurrences in a readable format. -Uses of A and B are counted correctly, with the path rewritten correctly. -Uses of C are not counted, since the canonical destination (generated by dune) does not exist. +Uses of A are: 2 times in b.ml, 1 time in c.ml, 1 time in main.ml +Uses of B are: 1 time in main.ml +Uses of C are not counted, since the canonical destination (Main.C, generated by dune) does not exist. Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. -Uses of values Main__.C.y and Main__.A.x are not rewritten since we use references instead of paths. $ occurrences_print occurrences.txt | sort Main was used directly 0 times and indirectly 11 times @@ -52,3 +74,45 @@ Uses of values Main__.C.y and Main__.A.x are not rewritten since we use referenc Main.A.x was used directly 2 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times + + $ occurrences_print occurrences1.txt | sort + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 1 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times + + $ occurrences_print occurrences2.txt | sort + + $ occurrences_print occurrences3.txt | sort + string was used directly 1 times and indirectly 0 times + + $ occurrences_print occurrences4.txt | sort + Main was used directly 0 times and indirectly 7 times + Main.A was used directly 2 times and indirectly 5 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times + Main.A.x was used directly 1 times and indirectly 0 times + + $ occurrences_print occurrences5.txt | sort + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 1 times and indirectly 1 times + Main.A.x was used directly 1 times and indirectly 0 times + +Now we can merge both files + + $ cat > files.map << EOF + > occurrences3.txt + > occurrences4.txt + > occurrences5.txt + > EOF + $ odoc aggregate-occurrences occurrences1.txt occurrences2.txt --file-list files.map -o aggregated.txt + + $ occurrences_print aggregated.txt | sort + Main was used directly 0 times and indirectly 11 times + Main.A was used directly 4 times and indirectly 6 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times + Main.A.x was used directly 2 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times diff --git a/test/odoc_print/occurrences_print.ml b/test/odoc_print/occurrences_print.ml index 7035bf90f8..8568d507fe 100644 --- a/test/odoc_print/occurrences_print.ml +++ b/test/odoc_print/occurrences_print.ml @@ -2,7 +2,7 @@ module H = Hashtbl.Make (Odoc_model.Paths.Identifier) let run inp = let ic = open_in_bin inp in - let htbl : Odoc_odoc.Occurrences.Occtbl.item Odoc_odoc.Occurrences.H.t = + let htbl : Odoc_odoc.Occurrences.Occtbl.t = Marshal.from_channel ic in Odoc_odoc.Occurrences.Occtbl.iter From 0141cec232a08872a0c6f21efc5dd2dcb59a1f4a Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 10:12:44 +0100 Subject: [PATCH 23/35] fmt Signed-off-by: Paul-Elliot --- src/document/generator.ml | 2 +- src/odoc/bin/main.ml | 4 +- src/odoc/occurrences.ml | 5 +- src/odoc/odoc_link.ml | 8 +- src/xref2/link.ml | 106 ++++++++++++++++++++++-- test/occurrences/double_wrapped.t/run.t | 33 +++++--- test/odoc_print/occurrences_print.ml | 4 +- 7 files changed, 127 insertions(+), 35 deletions(-) diff --git a/src/document/generator.ml b/src/document/generator.ml index 338d3a4579..cdba1ffae0 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -252,7 +252,7 @@ module Make (Syntax : SYNTAX) = struct let path id = Url.Path.from_identifier id let url id = Url.from_path (path id) - let to_link {Lang.Source_info.documentation; implementation} = + let to_link { Lang.Source_info.documentation; implementation } = let documentation = let open Paths.Path.Resolved in match documentation with diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index 83cba0decf..b141487a6d 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -1175,9 +1175,7 @@ module Occurrences = struct $ (const index $ dst $ inputs $ inputs_in_file $ warnings_options)) let info ~docs = - let doc = - "Aggregate hashtables created with odoc count-occurrences." - in + let doc = "Aggregate hashtables created with odoc count-occurrences." in Term.info "aggregate-occurrences" ~docs ~doc end end diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index 8d0f4d9ee0..b88a69086b 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -142,10 +142,7 @@ let count ~dst ~warnings_options:_ directories = | Type { documentation = Some (`Resolved p as p'); _ }, _ -> incr htbl p Odoc_model.Paths.Path.((p' : Type.t :> t)) | _ -> ()) - (match unit.source_info with - | None -> [] - | Some i -> - i.infos) + (match unit.source_info with None -> [] | Some i -> i.infos) in () in diff --git a/src/odoc/odoc_link.ml b/src/odoc/odoc_link.ml index 5762db39f3..5eed7dea36 100644 --- a/src/odoc/odoc_link.ml +++ b/src/odoc/odoc_link.ml @@ -8,13 +8,7 @@ let link_unit ~resolver ~filename m = let open Odoc_model in let open Lang.Compilation_unit in let m = - if Root.Odoc_file.hidden m.root.file then - { - m with - content = Module { items = []; compiled = false; doc = [] }; - expansion = None; - } - else m + if Root.Odoc_file.hidden m.root.file then { m with expansion = None } else m in let env = Resolver.build_link_env_for_unit resolver m in Odoc_xref2.Link.link ~filename env m diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 2f8472a994..d759b5b5cf 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -415,6 +415,106 @@ and open_ env parent = function | { Odoc_model__Lang.Open.doc; _ } as open_ -> { open_ with doc = comment_docs env parent doc } +module Build_env = struct + let rec unit env t = + let open Compilation_unit in + match t.content with + | Module sg -> + let env = signature env sg in + env + | Pack _ -> env + + and signature env s = + let env = Env.open_signature s env in + signature_items env s.items + + and simple_expansion : Env.t -> ModuleType.simple_expansion -> Env.t = + fun env m -> + match m with + | Signature sg -> signature env sg + | Functor (arg, sg) -> + let env = Env.add_functor_parameter arg env in + let env = functor_argument env arg in + simple_expansion env sg + + and functor_argument env a = + match a with + | FunctorParameter.Unit -> env + | Named arg -> functor_parameter_parameter env arg + + and functor_parameter_parameter : Env.t -> FunctorParameter.parameter -> Env.t + = + fun env a -> module_type_expr env a.expr + + and module_type_expr : Env.t -> ModuleType.expr -> Env.t = + fun env expr -> + let open ModuleType in + match expr with + | Signature s -> signature env s + | Path { p_path = _; p_expansion = Some p_expansion } -> + simple_expansion env p_expansion + | Path { p_path = _; p_expansion = None } -> env + | With _ -> env + | Functor (arg, res) -> + let env = functor_argument env arg in + let env = Env.add_functor_parameter arg env in + let env = module_type_expr env res in + env + | TypeOf { t_expansion = None; _ } -> env + | TypeOf { t_expansion = Some exp; _ } -> simple_expansion env exp + + and signature_items : Env.t -> Signature.item list -> Env.t = + fun env s -> + let open Signature in + List.fold_left + (fun env item -> + match item with + | Module (_, m) -> module_ env m + | ModuleSubstitution m -> Env.open_module_substitution m env + | Type _ -> env + | TypeSubstitution t -> Env.open_type_substitution t env + | ModuleType mt -> module_type env mt + | ModuleTypeSubstitution mts -> + let env = Env.open_module_type_substitution mts env in + module_type_substitution env mts + | Value _ -> env + | Comment _ -> env + | TypExt _ -> env + | Exception _ -> env + | Class _ -> env (* TODO *) + | ClassType _ -> env + | Include i -> include_ env i + | Open _ -> env) + env s + + and module_type_substitution : Env.t -> ModuleTypeSubstitution.t -> Env.t = + fun env m -> module_type_expr env m.manifest + + and include_ : Env.t -> Include.t -> Env.t = + fun env i -> + let open Include in + signature_items env i.expansion.content.items + + and module_type : Env.t -> ModuleType.t -> Env.t = + fun env m -> + match m.expr with None -> env | Some expr -> module_type_expr env expr + + and module_ : Env.t -> Module.t -> Env.t = + fun env m -> + let open Module in + let env = module_decl env m.type_ in + match m.type_ with + | Alias (`Resolved _, Some exp) -> simple_expansion env exp + | Alias _ | ModuleType _ -> env + + and module_decl : Env.t -> Module.decl -> Env.t = + fun env decl -> + let open Module in + match decl with + | ModuleType expr -> module_type_expr env expr + | Alias (_, None) -> env + | Alias (_, Some e) -> simple_expansion env e +end let rec unit env t = let open Compilation_unit in let content = @@ -427,11 +527,7 @@ let rec unit env t = | Pack _ as p -> p in let source_info = - let env = - match t.content with - | Module sg -> Env.open_signature sg env - | Pack _ -> env - in + let env = Build_env.unit env t in let open Source_info in match t.source_info with | Some inf -> diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index b29ba69aaa..40b4ed1726 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -66,13 +66,16 @@ Uses of C are not counted, since the canonical destination (Main.C, generated by Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 11 times - Main.A was used directly 4 times and indirectly 6 times + Main was used directly 0 times and indirectly 13 times + Main.A was used directly 4 times and indirectly 8 times Main.A.(||>) was used directly 1 times and indirectly 0 times Main.A.M was used directly 2 times and indirectly 0 times Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 2 times and indirectly 0 times + Main.A.x was used directly 4 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times + Main__B was used directly 0 times and indirectly 1 times + Main__B.Z was used directly 0 times and indirectly 1 times + Main__B.Z.y was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times $ occurrences_print occurrences1.txt | sort @@ -86,17 +89,20 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc string was used directly 1 times and indirectly 0 times $ occurrences_print occurrences4.txt | sort - Main was used directly 0 times and indirectly 7 times - Main.A was used directly 2 times and indirectly 5 times + Main was used directly 0 times and indirectly 8 times + Main.A was used directly 2 times and indirectly 6 times Main.A.(||>) was used directly 1 times and indirectly 0 times Main.A.M was used directly 2 times and indirectly 0 times Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 1 times and indirectly 0 times + Main.A.x was used directly 2 times and indirectly 0 times + Main__B was used directly 0 times and indirectly 1 times + Main__B.Z was used directly 0 times and indirectly 1 times + Main__B.Z.y was used directly 1 times and indirectly 0 times $ occurrences_print occurrences5.txt | sort - Main was used directly 0 times and indirectly 2 times - Main.A was used directly 1 times and indirectly 1 times - Main.A.x was used directly 1 times and indirectly 0 times + Main was used directly 0 times and indirectly 3 times + Main.A was used directly 1 times and indirectly 2 times + Main.A.x was used directly 2 times and indirectly 0 times Now we can merge both files @@ -108,11 +114,14 @@ Now we can merge both files $ odoc aggregate-occurrences occurrences1.txt occurrences2.txt --file-list files.map -o aggregated.txt $ occurrences_print aggregated.txt | sort - Main was used directly 0 times and indirectly 11 times - Main.A was used directly 4 times and indirectly 6 times + Main was used directly 0 times and indirectly 13 times + Main.A was used directly 4 times and indirectly 8 times Main.A.(||>) was used directly 1 times and indirectly 0 times Main.A.M was used directly 2 times and indirectly 0 times Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 2 times and indirectly 0 times + Main.A.x was used directly 4 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times + Main__B was used directly 0 times and indirectly 1 times + Main__B.Z was used directly 0 times and indirectly 1 times + Main__B.Z.y was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times diff --git a/test/odoc_print/occurrences_print.ml b/test/odoc_print/occurrences_print.ml index 8568d507fe..eb2f8c4284 100644 --- a/test/odoc_print/occurrences_print.ml +++ b/test/odoc_print/occurrences_print.ml @@ -2,9 +2,7 @@ module H = Hashtbl.Make (Odoc_model.Paths.Identifier) let run inp = let ic = open_in_bin inp in - let htbl : Odoc_odoc.Occurrences.Occtbl.t = - Marshal.from_channel ic - in + let htbl : Odoc_odoc.Occurrences.Occtbl.t = Marshal.from_channel ic in Odoc_odoc.Occurrences.Occtbl.iter (fun id { Odoc_odoc.Occurrences.Occtbl.direct; indirect; _ } -> let id = String.concat "." (Odoc_model.Paths.Identifier.fullname id) in From f1884c50d873e908d55a794977d5a482fabc695c Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 10:13:07 +0100 Subject: [PATCH 24/35] Occurrences: detection of hidden modules should be more efficient We consider as internal children of internal modules, and double underscored roots. Signed-off-by: Paul-Elliot --- src/model/paths.ml | 54 ++++++++++++++++++++----- test/occurrences/double_wrapped.t/run.t | 10 +---- 2 files changed, 44 insertions(+), 20 deletions(-) diff --git a/src/model/paths.ml b/src/model/paths.ml index fa90e0d05d..47225b09fa 100644 --- a/src/model/paths.ml +++ b/src/model/paths.ml @@ -19,6 +19,15 @@ module Ocaml_env = Env open Names +let contains_double_underscore s = + let len = String.length s in + let rec aux i = + if i > len - 2 then false + else if s.[i] = '_' && s.[i + 1] = '_' then true + else aux (i + 1) + in + aux 0 + module Identifier = struct type 'a id = 'a Paths_types.id = { iv : 'a; ihash : int; ikey : string } @@ -66,7 +75,9 @@ module Identifier = struct let rec is_internal : t -> bool = fun x -> match x.iv with - | `Root (_, name) -> ModuleName.is_internal name + | `Root (_, name) -> + ModuleName.is_internal name + || contains_double_underscore (ModuleName.to_string name) | `Page (_, _) -> false | `LeafPage (_, _) -> false | `Module (_, name) -> ModuleName.is_internal name @@ -91,6 +102,36 @@ module Identifier = struct | `SourceLocationInternal _ | `AssetFile _ -> false + let rec is_internal_rec : t -> bool = + fun x -> + is_internal x + || + match x.iv with + | `Root (_, name) -> ModuleName.is_internal name + | `Page (_, _) -> false + | `LeafPage (_, _) -> false + | `Module (parent, _) -> is_internal_rec (parent :> t) + | `Parameter (parent, _) -> is_internal_rec (parent :> t) + | `Result x -> is_internal_rec (x :> t) + | `ModuleType (parent, _) -> is_internal_rec (parent :> t) + | `Type (parent, _) -> is_internal_rec (parent :> t) + | `CoreType name -> TypeName.is_internal name + | `Constructor (parent, _) -> is_internal (parent :> t) + | `Field (parent, _) -> is_internal (parent :> t) + | `Extension (parent, _) -> is_internal (parent :> t) + | `ExtensionDecl (parent, _, _) -> is_internal (parent :> t) + | `Exception (parent, _) -> is_internal (parent :> t) + | `CoreException _ -> false + | `Value (parent, _) -> is_internal_rec (parent :> t) + | `Class (parent, _) -> is_internal_rec (parent :> t) + | `ClassType (parent, _) -> is_internal_rec (parent :> t) + | `Method (parent, _) -> is_internal (parent :> t) + | `InstanceVariable (parent, _) -> is_internal (parent :> t) + | `Label (parent, _) -> is_internal (parent :> t) + | `SourceDir _ | `SourceLocationMod _ | `SourceLocation _ | `SourcePage _ + | `SourceLocationInternal _ | `AssetFile _ -> + false + let name : [< t_pv ] id -> string = fun n -> name_aux (n :> t) let rec full_name_aux : t -> string list = @@ -671,7 +712,7 @@ module Path = struct | `Identifier { iv = `Module (_, m); _ } when Names.ModuleName.is_internal m -> true - | `Identifier _ -> false + | `Identifier i -> Identifier.is_internal_rec i | `Canonical (_, `Resolved _) -> false | `Canonical (x, _) -> (not weak_canonical_test) && inner (x : module_ :> any) @@ -708,15 +749,6 @@ module Path = struct in inner x - and contains_double_underscore s = - let len = String.length s in - let rec aux i = - if i > len - 2 then false - else if s.[i] = '_' && s.[i + 1] = '_' then true - else aux (i + 1) - in - aux 0 - and is_path_hidden : Paths_types.Path.any -> bool = let open Paths_types.Path in function diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index 40b4ed1726..c940324781 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -63,6 +63,7 @@ and prints the number of occurrences in a readable format. Uses of A are: 2 times in b.ml, 1 time in c.ml, 1 time in main.ml Uses of B are: 1 time in main.ml Uses of C are not counted, since the canonical destination (Main.C, generated by dune) does not exist. +Uses of B.Z are not counted since they go to a hidden module. Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. $ occurrences_print occurrences.txt | sort @@ -73,9 +74,6 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 4 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times - Main__B was used directly 0 times and indirectly 1 times - Main__B.Z was used directly 0 times and indirectly 1 times - Main__B.Z.y was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times $ occurrences_print occurrences1.txt | sort @@ -95,9 +93,6 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc Main.A.M was used directly 2 times and indirectly 0 times Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 2 times and indirectly 0 times - Main__B was used directly 0 times and indirectly 1 times - Main__B.Z was used directly 0 times and indirectly 1 times - Main__B.Z.y was used directly 1 times and indirectly 0 times $ occurrences_print occurrences5.txt | sort Main was used directly 0 times and indirectly 3 times @@ -121,7 +116,4 @@ Now we can merge both files Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 4 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times - Main__B was used directly 0 times and indirectly 1 times - Main__B.Z was used directly 0 times and indirectly 1 times - Main__B.Z.y was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times From 00cb6b58b47a8537636b21349591cec2ff1e56f7 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 11:47:25 +0100 Subject: [PATCH 25/35] Occurrences: control which occurrences are counted Persistent and hidden occurrences can be counted, or not. Signed-off-by: Paul-Elliot --- src/document/generator.ml | 2 +- src/loader/implementation.ml | 10 +- src/model/lang.ml | 4 +- src/odoc/bin/main.ml | 20 +++- src/odoc/occurrences.ml | 31 +++--- src/xref2/compile.ml | 4 +- src/xref2/link.ml | 4 +- test/occurrences/double_wrapped.t/run.t | 133 ++++++++++++++---------- 8 files changed, 129 insertions(+), 79 deletions(-) diff --git a/src/document/generator.ml b/src/document/generator.ml index cdba1ffae0..1c5b72e5e7 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -256,7 +256,7 @@ module Make (Syntax : SYNTAX) = struct let documentation = let open Paths.Path.Resolved in match documentation with - | Some (`Resolved p) when not (is_hidden (p :> t)) -> ( + | Some (`Resolved p, _) when not (is_hidden (p :> t)) -> ( let id = identifier (p :> t) in match Url.from_identifier ~stop_before:false id with | Ok link -> Some link diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 910b13a30f..58ad71bf7a 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -1,6 +1,12 @@ #if OCAML_VERSION >= (4, 14, 0) -(* open Odoc_model.Lang.Source_info *) +let rec is_persistent : Path.t -> bool = function + | Path.Pident id -> Ident.persistent id + | Path.Pdot(p, _) -> is_persistent p + | Path.Papply(p, _) -> is_persistent p +#if OCAML_VERSION >= (5,1,0) + | Path.Pextra_ty -> assert false +#endif let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum) @@ -303,7 +309,7 @@ let process_occurrences env poses loc_to_id local_ident_to_loc = | p -> ( match find_in_env env p with | path -> - let documentation = Some path + let documentation = Some (path, is_persistent p) and implementation = Some (Unresolved path) in Some { documentation; implementation } | exception _ -> None) diff --git a/src/model/lang.ml b/src/model/lang.ml index dd4abf6a68..c6ba7edab1 100644 --- a/src/model/lang.ml +++ b/src/model/lang.ml @@ -23,7 +23,9 @@ module Source_info = struct | Resolved of Identifier.SourceLocation.t type ('doc, 'impl) jump_to = { - documentation : 'doc option; + documentation : ('doc * bool) option; + (* The boolean indicate if the path is "persistent": from the same + compilation unit. *) implementation : 'impl jump_to_impl option; } diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index b141487a6d..a998aa3efc 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -1113,9 +1113,11 @@ end module Occurrences = struct module Count = struct - let index directories dst warnings_options = + let count directories dst warnings_options include_hidden include_persistent + = let dst = Fpath.v dst in - Occurrences.count ~dst ~warnings_options directories + Occurrences.count ~dst ~warnings_options directories include_hidden + include_persistent let cmd = let dst = @@ -1125,9 +1127,21 @@ module Occurrences = struct & opt (some string) None & info ~docs ~docv:"PATH" ~doc [ "o" ]) in + let include_hidden = + let doc = "Include hidden identifiers in the table" in + Arg.(value & flag & info ~docs ~doc [ "include-hidden" ]) + in + let include_persistent = + let doc = + "Include persistent identifiers in the table: occurrences of in ids \ + intheir own implementation." + in + Arg.(value & flag & info ~docs ~doc [ "include-persistent" ]) + in Term.( const handle_error - $ (const index $ odoc_file_directories $ dst $ warnings_options)) + $ (const count $ odoc_file_directories $ dst $ warnings_options + $ include_hidden $ include_persistent)) let info ~docs = let doc = diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index b88a69086b..36ea9f1026 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -119,28 +119,31 @@ end = struct tbl end -let count ~dst ~warnings_options:_ directories = +let count ~dst ~warnings_options:_ directories include_hidden include_persistent = let htbl = H.create 100 in let f () (unit : Odoc_model.Lang.Compilation_unit.t) = - let incr tbl p p' = - let id = Odoc_model.Paths.Path.Resolved.(identifier (p :> t)) in - if not Odoc_model.Paths.Path.(is_hidden p') then Occtbl.add tbl id + let incr tbl p persistent = + let p = (p :> Odoc_model.Paths.Path.Resolved.t) in + let id = Odoc_model.Paths.Path.Resolved.identifier p in + if not (Odoc_model.Paths.Path.Resolved.is_hidden p) || include_hidden then + if not persistent || include_persistent then + Occtbl.add tbl id in let () = List.iter (function | ( Odoc_model.Lang.Source_info.Module - { documentation = Some (`Resolved p as p'); _ }, + { documentation = Some (`Resolved p, persistent); _ }, _ ) -> - incr htbl p Odoc_model.Paths.Path.((p' : Module.t :> t)) - | Value { documentation = Some (`Resolved p as p'); _ }, _ -> - incr htbl p Odoc_model.Paths.Path.((p' : Value.t :> t)) - | ClassType { documentation = Some (`Resolved p as p'); _ }, _ -> - incr htbl p Odoc_model.Paths.Path.((p' : ClassType.t :> t)) - | ModuleType { documentation = Some (`Resolved p as p'); _ }, _ -> - incr htbl p Odoc_model.Paths.Path.((p' : ModuleType.t :> t)) - | Type { documentation = Some (`Resolved p as p'); _ }, _ -> - incr htbl p Odoc_model.Paths.Path.((p' : Type.t :> t)) + incr htbl p persistent + | Value { documentation = Some (`Resolved p, persistent); _ }, _ -> + incr htbl p persistent + | ClassType { documentation = Some (`Resolved p, persistent); _ }, _ -> + incr htbl p persistent + | ModuleType { documentation = Some (`Resolved p, persistent); _ }, _ -> + incr htbl p persistent + | Type { documentation = Some (`Resolved p, persistent); _ }, _ -> + incr htbl p persistent | _ -> ()) (match unit.source_info with None -> [] | Some i -> i.infos) in diff --git a/src/xref2/compile.ml b/src/xref2/compile.ml index 4aeebe29b3..4b257bfd5d 100644 --- a/src/xref2/compile.ml +++ b/src/xref2/compile.ml @@ -94,7 +94,9 @@ and source_info_infos env infos = let open Source_info in let map_doc f v = let documentation = - match v.documentation with Some p -> Some (f p) | None -> None + match v.documentation with + | Some (p, persistent) -> Some (f p, persistent) + | None -> None in { v with documentation } in diff --git a/src/xref2/link.ml b/src/xref2/link.ml index d759b5b5cf..7dbf5ecbe7 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -533,7 +533,9 @@ let rec unit env t = | Some inf -> let jump_to v f_impl f_doc = let documentation = - match v.documentation with Some p -> Some (f_doc p) | None -> None + match v.documentation with + | Some (p, persistent) -> Some (f_doc p, persistent) + | None -> None in let implementation = match v.implementation with diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index c940324781..989c66ad13 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -25,37 +25,27 @@ occurrences information. $ odoc link -I . main__C.odoc $ odoc link -I . main__.odoc - $ odoc html-generate -o html main.odocl - $ odoc html-generate -o html main__A.odocl - $ odoc html-generate -o html main__B.odocl - $ odoc html-generate -o html main__C.odocl - $ odoc html-generate -o html main__.odocl - The count occurrences command outputs a marshalled hashtable, whose keys are odoc identifiers, and whose values are integers corresponding to the number of uses. We can later aggregate those hashtables, so we create the full hashtable, and a hashtable for each compilation unit. - $ mkdir dir1 - $ mkdir dir2 - $ mkdir dir3 - $ mkdir dir4 - $ mkdir dir5 - - $ mv main.odocl dir1 - $ mv main__.odocl dir2 - $ mv main__A.odocl dir3 - $ mv main__B.odocl dir4 - $ mv main__C.odocl dir5 - $ odoc count-occurrences -I . -o occurrences.txt - $ odoc count-occurrences -I dir1 -o occurrences1.txt - $ odoc count-occurrences -I dir2 -o occurrences2.txt - $ odoc count-occurrences -I dir3 -o occurrences3.txt - $ odoc count-occurrences -I dir4 -o occurrences4.txt - $ odoc count-occurrences -I dir5 -o occurrences5.txt - - $ du -h occurrences.txt - 4.0K occurrences.txt + $ mkdir main + $ mkdir main__ + $ mkdir main__A + $ mkdir main__B + $ mkdir main__C + + $ mv main.odocl main + $ mv main__.odocl main__ + $ mv main__A.odocl main__A + $ mv main__B.odocl main__B + $ mv main__C.odocl main__C + $ odoc count-occurrences -I main -o main.occ + $ odoc count-occurrences -I main__ -o main__.occ + $ odoc count-occurrences -I main__A -o main__A.occ + $ odoc count-occurrences -I main__B -o main__B.occ + $ odoc count-occurrences -I main__C -o main__C.occ The occurrences_print executable, available only for testing, unmarshal the file and prints the number of occurrences in a readable format. @@ -66,49 +56,72 @@ Uses of C are not counted, since the canonical destination (Main.C, generated by Uses of B.Z are not counted since they go to a hidden module. Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. - $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 13 times - Main.A was used directly 4 times and indirectly 8 times - Main.A.(||>) was used directly 1 times and indirectly 0 times - Main.A.M was used directly 2 times and indirectly 0 times - Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 4 times and indirectly 0 times - Main.B was used directly 1 times and indirectly 0 times + $ occurrences_print main.occ | sort + + $ occurrences_print main__.occ | sort + + $ occurrences_print main__A.occ | sort string was used directly 1 times and indirectly 0 times - $ occurrences_print occurrences1.txt | sort + $ occurrences_print main__B.occ | sort + Main was used directly 0 times and indirectly 1 times + Main.A was used directly 0 times and indirectly 1 times + Main.A.x was used directly 1 times and indirectly 0 times + + $ occurrences_print main__C.occ | sort + Main was used directly 0 times and indirectly 1 times + Main.A was used directly 0 times and indirectly 1 times + Main.A.x was used directly 1 times and indirectly 0 times + +Now we can merge both files + + $ cat > files.map << EOF + > main__A.occ + > main__B.occ + > main__C.occ + > EOF + $ odoc aggregate-occurrences main.occ main__.occ --file-list files.map -o aggregated.txt + + $ occurrences_print aggregated.txt | sort Main was used directly 0 times and indirectly 2 times - Main.A was used directly 1 times and indirectly 0 times - Main.B was used directly 1 times and indirectly 0 times + Main.A was used directly 0 times and indirectly 2 times + Main.A.x was used directly 2 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times - $ occurrences_print occurrences2.txt | sort +Compare with the one created directly with all occurrences: - $ occurrences_print occurrences3.txt | sort + $ odoc count-occurrences -I . -o occurrences.txt + $ occurrences_print occurrences.txt | sort + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 0 times and indirectly 2 times + Main.A.x was used directly 2 times and indirectly 0 times string was used directly 1 times and indirectly 0 times - $ occurrences_print occurrences4.txt | sort - Main was used directly 0 times and indirectly 8 times - Main.A was used directly 2 times and indirectly 6 times +We can also include persistent ids, and hidden ids: + + $ odoc count-occurrences -I . -o occurrences.txt --include-persistent + $ occurrences_print occurrences.txt | sort + Main was used directly 0 times and indirectly 13 times + Main.A was used directly 4 times and indirectly 8 times Main.A.(||>) was used directly 1 times and indirectly 0 times Main.A.M was used directly 2 times and indirectly 0 times Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 2 times and indirectly 0 times + Main.A.x was used directly 4 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times - $ occurrences_print occurrences5.txt | sort - Main was used directly 0 times and indirectly 3 times - Main.A was used directly 1 times and indirectly 2 times + $ odoc count-occurrences -I . -o occurrences.txt --include-hidden + $ occurrences_print occurrences.txt | sort + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 0 times and indirectly 2 times Main.A.x was used directly 2 times and indirectly 0 times + Main__B was used directly 0 times and indirectly 1 times + Main__B.Z was used directly 0 times and indirectly 1 times + Main__B.Z.y was used directly 1 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times -Now we can merge both files - - $ cat > files.map << EOF - > occurrences3.txt - > occurrences4.txt - > occurrences5.txt - > EOF - $ odoc aggregate-occurrences occurrences1.txt occurrences2.txt --file-list files.map -o aggregated.txt - - $ occurrences_print aggregated.txt | sort + $ odoc count-occurrences -I . -o occurrences.txt --include-persistent --include-hidden + $ occurrences_print occurrences.txt | sort Main was used directly 0 times and indirectly 13 times Main.A was used directly 4 times and indirectly 8 times Main.A.(||>) was used directly 1 times and indirectly 0 times @@ -116,4 +129,12 @@ Now we can merge both files Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 4 times and indirectly 0 times Main.B was used directly 1 times and indirectly 0 times + Main__ was used directly 0 times and indirectly 2 times + Main__.C was used directly 1 times and indirectly 1 times + Main__.C.y was used directly 1 times and indirectly 0 times + Main__A was used directly 1 times and indirectly 0 times + Main__B was used directly 1 times and indirectly 1 times + Main__B.Z was used directly 0 times and indirectly 1 times + Main__B.Z.y was used directly 1 times and indirectly 0 times + Main__C was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times From 025f687ea7f2ec17265cc5619fc7e45c73538f30 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 11:51:20 +0100 Subject: [PATCH 26/35] Occurrences: remove unused test Signed-off-by: Paul-Elliot --- test/occurrences/source.t/a.ml | 1 - test/occurrences/source.t/b.ml | 1 - test/occurrences/source.t/root.mld | 1 - test/occurrences/source.t/run.t | 38 ------------------------------ 4 files changed, 41 deletions(-) delete mode 100644 test/occurrences/source.t/a.ml delete mode 100644 test/occurrences/source.t/b.ml delete mode 100644 test/occurrences/source.t/root.mld delete mode 100644 test/occurrences/source.t/run.t diff --git a/test/occurrences/source.t/a.ml b/test/occurrences/source.t/a.ml deleted file mode 100644 index e09e5d02a3..0000000000 --- a/test/occurrences/source.t/a.ml +++ /dev/null @@ -1 +0,0 @@ -let a = B.b diff --git a/test/occurrences/source.t/b.ml b/test/occurrences/source.t/b.ml deleted file mode 100644 index 56d2d5273c..0000000000 --- a/test/occurrences/source.t/b.ml +++ /dev/null @@ -1 +0,0 @@ -let b = 3 diff --git a/test/occurrences/source.t/root.mld b/test/occurrences/source.t/root.mld deleted file mode 100644 index 54f377d3e8..0000000000 --- a/test/occurrences/source.t/root.mld +++ /dev/null @@ -1 +0,0 @@ -{0 Root} diff --git a/test/occurrences/source.t/run.t b/test/occurrences/source.t/run.t deleted file mode 100644 index 9c0da5e49f..0000000000 --- a/test/occurrences/source.t/run.t +++ /dev/null @@ -1,38 +0,0 @@ -When both source rendering and occurrence counting are enabled, the occurrences information are used to generate "jump to documentation" links. - -This test tests this. - -Files containing some values: - - $ cat a.ml | head -n 3 - let a = B.b - - $ cat b.ml | head -n 3 - let b = 3 - -Source pages require a parent: - - $ odoc compile -c module-a -c module-b -c src-source root.mld - -Compile the modules: - - $ ocamlc -c b.ml -bin-annot - $ ocamlc -c a.ml -I . -bin-annot - -Compile the pages with the source and occurrences options - - $ printf "a.ml\nb.ml\n" > source_tree.map - $ odoc source-tree -I . --parent page-root -o src-source.odoc source_tree.map - $ odoc compile --count-occurrences -I . --source-name b.ml --source-parent-file src-source.odoc b.cmt - $ odoc compile --count-occurrences -I . --source-name a.ml --source-parent-file src-source.odoc a.cmt - $ odoc link -I . b.odoc - $ odoc link -I . a.odoc - $ odoc html-generate --source b.ml --indent -o html b.odocl - $ odoc html-generate --source a.ml --indent -o html a.odocl - $ odoc support-files -o html - -The source for `a` contains a link to the documentation of `B.b`, as it is used in the implementation: - - $ cat html/root/source/a.ml.html | tr '> ' '\n\n' | grep 'href' | grep val-b - href="b.ml.html#val-b" - href="../../B/index.html#val-b" From 3224ef20c78c30de01fec29be3343486b0116266 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 12:32:46 +0100 Subject: [PATCH 27/35] Occurrences: compatibility with different OCaml versions and fmt Signed-off-by: Paul-Elliot --- src/loader/cmt.ml | 6 +++--- src/loader/implementation.ml | 4 ++-- src/odoc/occurrences.ml | 14 ++++++++------ src/xref2/shape_tools.cppo.ml | 4 ++++ 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/loader/cmt.ml b/src/loader/cmt.ml index 682333588a..9b06dbaa87 100644 --- a/src/loader/cmt.ml +++ b/src/loader/cmt.ml @@ -382,16 +382,16 @@ let rec read_module_expr env parent label_parent mexpr = Functor (f_parameter, res) #else | Tmod_functor(id, _, arg, res) -> - let new_env = Env.add_parameter parent id (ModuleName.of_ident id) env in + let () = Env.add_parameter parent id (ModuleName.of_ident id) env in let f_parameter = match arg with | None -> FunctorParameter.Unit | Some arg -> - let id = Env.find_parameter_identifier new_env id in + let id = Env.find_parameter_identifier env id in let arg = Cmti.read_module_type env (id :> Identifier.Signature.t) label_parent arg in Named { FunctorParameter. id; expr = arg; } in - let res = read_module_expr new_env (Identifier.Mk.result parent) label_parent res in + let res = read_module_expr env (Identifier.Mk.result parent) label_parent res in Functor(f_parameter, res) #endif | Tmod_apply _ -> diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 58ad71bf7a..5e6782c011 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -5,7 +5,7 @@ let rec is_persistent : Path.t -> bool = function | Path.Pdot(p, _) -> is_persistent p | Path.Papply(p, _) -> is_persistent p #if OCAML_VERSION >= (5,1,0) - | Path.Pextra_ty -> assert false + | Path.Pextra_ty _ -> assert false #endif let pos_of_loc loc = (loc.Location.loc_start.pos_cnum, loc.loc_end.pos_cnum) @@ -384,7 +384,7 @@ let read_cmt_infos source_id_opt id cmt_info ~count_occurrences = #else -let read_cmt_infos _source_id_opt _id _cmt_info = +let read_cmt_infos _source_id_opt _id _cmt_info ~count_occurrences:_ = (None, None) #endif diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index 36ea9f1026..2a23478be0 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -119,15 +119,15 @@ end = struct tbl end -let count ~dst ~warnings_options:_ directories include_hidden include_persistent = +let count ~dst ~warnings_options:_ directories include_hidden include_persistent + = let htbl = H.create 100 in let f () (unit : Odoc_model.Lang.Compilation_unit.t) = let incr tbl p persistent = let p = (p :> Odoc_model.Paths.Path.Resolved.t) in let id = Odoc_model.Paths.Path.Resolved.identifier p in - if not (Odoc_model.Paths.Path.Resolved.is_hidden p) || include_hidden then - if not persistent || include_persistent then - Occtbl.add tbl id + if (not (Odoc_model.Paths.Path.Resolved.is_hidden p)) || include_hidden + then if (not persistent) || include_persistent then Occtbl.add tbl id in let () = List.iter @@ -138,9 +138,11 @@ let count ~dst ~warnings_options:_ directories include_hidden include_persistent incr htbl p persistent | Value { documentation = Some (`Resolved p, persistent); _ }, _ -> incr htbl p persistent - | ClassType { documentation = Some (`Resolved p, persistent); _ }, _ -> + | ClassType { documentation = Some (`Resolved p, persistent); _ }, _ + -> incr htbl p persistent - | ModuleType { documentation = Some (`Resolved p, persistent); _ }, _ -> + | ModuleType { documentation = Some (`Resolved p, persistent); _ }, _ + -> incr htbl p persistent | Type { documentation = Some (`Resolved p, persistent); _ }, _ -> incr htbl p persistent diff --git a/src/xref2/shape_tools.cppo.ml b/src/xref2/shape_tools.cppo.ml index a6bf903791..f4feb5970f 100644 --- a/src/xref2/shape_tools.cppo.ml +++ b/src/xref2/shape_tools.cppo.ml @@ -176,4 +176,8 @@ type t = unit let lookup_def _ _id = None +let lookup_value_path _ _id = None + +let lookup_module_path _ _id = None + #endif From 213dcd154a24016f78d93cc893e5da0db969b3dc Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 16:52:07 +0100 Subject: [PATCH 28/35] fmt Signed-off-by: Paul-Elliot --- src/loader/implementation.ml | 117 +++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 52 deletions(-) diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 5e6782c011..7fc5941679 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -144,7 +144,8 @@ module IdentHashtbl = Hashtbl.Make (struct end) module AnnotHashtbl = Hashtbl.Make (struct - type t = Odoc_model.Lang.Source_info.annotation Odoc_model.Lang.Source_info.with_pos + type t = + Odoc_model.Lang.Source_info.annotation Odoc_model.Lang.Source_info.with_pos let equal l1 l2 = l1 = l2 let hash = Hashtbl.hash end) @@ -162,14 +163,14 @@ let populate_local_defs source_id poses loc_to_id local_ident_to_loc = (Printf.sprintf "local_%s_%d" (Ident.name id) (counter ())) in (match source_id with - Some source_id -> + | Some source_id -> let identifier = - Odoc_model.Paths.Identifier.Mk.source_location_int (source_id, name) + Odoc_model.Paths.Identifier.Mk.source_location_int + (source_id, name) in LocHashtbl.add loc_to_id loc identifier - | None -> () - ); - IdentHashtbl.add local_ident_to_loc id loc; + | None -> ()); + IdentHashtbl.add local_ident_to_loc id loc | _ -> ()) poses @@ -255,39 +256,44 @@ let anchor_of_identifier id = (* Adds the global definitions, found in the [uid_to_loc], to the [loc_to_id] and [uid_to_id] tables. *) let populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id = - match source_id with None -> () | Some source_id -> - let mk_src_id id = - let name = Odoc_model.Names.DefName.make_std (anchor_of_identifier id) in - (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) - :> Odoc_model.Paths.Identifier.SourceLocation.t) - in - let () = - Ident_env.iter_located_identifier env @@ fun loc id -> - LocHashtbl.add loc_to_id loc (mk_src_id id) - in - let mk_src_id () = - let name = - Odoc_model.Names.DefName.make_std (Printf.sprintf "def_%d" (counter ())) - in - (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) - :> Odoc_model.Paths.Identifier.SourceLocation.t) - in - Shape.Uid.Tbl.iter - (fun uid loc -> - if loc.Location.loc_ghost then () - else - match LocHashtbl.find_opt loc_to_id loc with - | Some id -> UidHashtbl.add uid_to_id uid id - | None -> ( - (* In case there is no entry for the location of the uid, we add one. *) - match uid with - | Item _ -> - let id = mk_src_id () in - LocHashtbl.add loc_to_id loc id; - UidHashtbl.add uid_to_id uid id - | Compilation_unit _ -> () - | _ -> ())) - uid_to_loc + match source_id with + | None -> () + | Some source_id -> + let mk_src_id id = + let name = + Odoc_model.Names.DefName.make_std (anchor_of_identifier id) + in + (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) + :> Odoc_model.Paths.Identifier.SourceLocation.t) + in + let () = + Ident_env.iter_located_identifier env @@ fun loc id -> + LocHashtbl.add loc_to_id loc (mk_src_id id) + in + let mk_src_id () = + let name = + Odoc_model.Names.DefName.make_std + (Printf.sprintf "def_%d" (counter ())) + in + (Odoc_model.Paths.Identifier.Mk.source_location (source_id, name) + :> Odoc_model.Paths.Identifier.SourceLocation.t) + in + Shape.Uid.Tbl.iter + (fun uid loc -> + if loc.Location.loc_ghost then () + else + match LocHashtbl.find_opt loc_to_id loc with + | Some id -> UidHashtbl.add uid_to_id uid id + | None -> ( + (* In case there is no entry for the location of the uid, we add one. *) + match uid with + | Item _ -> + let id = mk_src_id () in + LocHashtbl.add loc_to_id loc id; + UidHashtbl.add uid_to_id uid id + | Compilation_unit _ -> () + | _ -> ())) + uid_to_loc (* Extract [Typedtree_traverse] occurrence information and turn them into proper source infos *) @@ -317,24 +323,30 @@ let process_occurrences env poses loc_to_id local_ident_to_loc = List.iter (function | Typedtree_traverse.Analysis.Value p, loc -> - process p Ident_env.Path.read_value |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (Value l, pos_of_loc loc) () + process p Ident_env.Path.read_value + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Value l, pos_of_loc loc) () | Module p, loc -> - process p Ident_env.Path.read_module |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (Module l, pos_of_loc loc) () + process p Ident_env.Path.read_module + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Module l, pos_of_loc loc) () | ClassType p, loc -> - process p Ident_env.Path.read_class_type |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (ClassType l, pos_of_loc loc) () + process p Ident_env.Path.read_class_type + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (ClassType l, pos_of_loc loc) () | ModuleType p, loc -> - process p Ident_env.Path.read_module_type |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (ModuleType l, pos_of_loc loc) () + process p Ident_env.Path.read_module_type + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (ModuleType l, pos_of_loc loc) () | Type p, loc -> - process p Ident_env.Path.read_type |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (Type l, pos_of_loc loc) () + process p Ident_env.Path.read_type + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Type l, pos_of_loc loc) () | Constructor _p, loc -> (* process p Ident_env.Path.read_constructor *) - None |> Option.iter @@ fun l -> - AnnotHashtbl.replace occ_tbl (Constructor l, pos_of_loc loc) () + None + |> Option.iter @@ fun l -> + AnnotHashtbl.replace occ_tbl (Constructor l, pos_of_loc loc) () | LocalDefinition _, _ -> ()) poses; AnnotHashtbl.fold (fun k () acc -> k :: acc) occ_tbl [] @@ -366,7 +378,8 @@ let read_cmt_infos source_id_opt id cmt_info ~count_occurrences = and uid_to_id = UidHashtbl.create 10 in let () = (* populate [loc_to_id], [ident_to_id] and [uid_to_id] *) - populate_local_defs source_id traverse_infos loc_to_id local_ident_to_loc; + populate_local_defs source_id traverse_infos loc_to_id + local_ident_to_loc; populate_global_defs env source_id loc_to_id uid_to_loc uid_to_id in let source_infos = From b0da38ad5a81c9c52707e76672db5707ea599928 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 16:52:30 +0100 Subject: [PATCH 29/35] Occurrences: change option from -include-persistent to -include-own We always want to include persistents, the question is whether we want to include the non-persistent ident! Signed-off-by: Paul-Elliot --- src/odoc/bin/main.ml | 13 +++-- src/odoc/occurrences.ml | 4 +- test/occurrences/double_wrapped.t/run.t | 66 ++++++++++++++++++------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index a998aa3efc..539457f406 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -1113,11 +1113,11 @@ end module Occurrences = struct module Count = struct - let count directories dst warnings_options include_hidden include_persistent + let count directories dst warnings_options include_hidden include_own = let dst = Fpath.v dst in Occurrences.count ~dst ~warnings_options directories include_hidden - include_persistent + include_own let cmd = let dst = @@ -1131,17 +1131,16 @@ module Occurrences = struct let doc = "Include hidden identifiers in the table" in Arg.(value & flag & info ~docs ~doc [ "include-hidden" ]) in - let include_persistent = + let include_own = let doc = - "Include persistent identifiers in the table: occurrences of in ids \ - intheir own implementation." + "Include identifiers from the compilation in the table." in - Arg.(value & flag & info ~docs ~doc [ "include-persistent" ]) + Arg.(value & flag & info ~docs ~doc [ "include-own" ]) in Term.( const handle_error $ (const count $ odoc_file_directories $ dst $ warnings_options - $ include_hidden $ include_persistent)) + $ include_hidden $ include_own)) let info ~docs = let doc = diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index 2a23478be0..48b38ebb80 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -119,7 +119,7 @@ end = struct tbl end -let count ~dst ~warnings_options:_ directories include_hidden include_persistent +let count ~dst ~warnings_options:_ directories include_hidden include_own = let htbl = H.create 100 in let f () (unit : Odoc_model.Lang.Compilation_unit.t) = @@ -127,7 +127,7 @@ let count ~dst ~warnings_options:_ directories include_hidden include_persistent let p = (p :> Odoc_model.Paths.Path.Resolved.t) in let id = Odoc_model.Paths.Path.Resolved.identifier p in if (not (Odoc_model.Paths.Path.Resolved.is_hidden p)) || include_hidden - then if (not persistent) || include_persistent then Occtbl.add tbl id + then if persistent || include_own then Occtbl.add tbl id in let () = List.iter diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index 989c66ad13..0aacfb0a2d 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -57,20 +57,25 @@ Uses of B.Z are not counted since they go to a hidden module. Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "local" module. $ occurrences_print main.occ | sort + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 1 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times $ occurrences_print main__.occ | sort $ occurrences_print main__A.occ | sort - string was used directly 1 times and indirectly 0 times $ occurrences_print main__B.occ | sort - Main was used directly 0 times and indirectly 1 times - Main.A was used directly 0 times and indirectly 1 times + Main was used directly 0 times and indirectly 7 times + Main.A was used directly 2 times and indirectly 5 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 1 times and indirectly 0 times $ occurrences_print main__C.occ | sort - Main was used directly 0 times and indirectly 1 times - Main.A was used directly 0 times and indirectly 1 times + Main was used directly 0 times and indirectly 2 times + Main.A was used directly 1 times and indirectly 1 times Main.A.x was used directly 1 times and indirectly 0 times Now we can merge both files @@ -83,23 +88,40 @@ Now we can merge both files $ odoc aggregate-occurrences main.occ main__.occ --file-list files.map -o aggregated.txt $ occurrences_print aggregated.txt | sort - Main was used directly 0 times and indirectly 2 times - Main.A was used directly 0 times and indirectly 2 times + Main was used directly 0 times and indirectly 11 times + Main.A was used directly 4 times and indirectly 6 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 2 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times Compare with the one created directly with all occurrences: $ odoc count-occurrences -I . -o occurrences.txt $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 2 times - Main.A was used directly 0 times and indirectly 2 times + Main was used directly 0 times and indirectly 11 times + Main.A was used directly 4 times and indirectly 6 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 2 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times We can also include persistent ids, and hidden ids: - $ odoc count-occurrences -I . -o occurrences.txt --include-persistent + $ odoc count-occurrences -I main__A -o occurrences.txt --include-own + $ occurrences_print occurrences.txt | sort + string was used directly 1 times and indirectly 0 times + + $ odoc count-occurrences -I main__A -o occurrences.txt --include-hidden + $ occurrences_print occurrences.txt | sort + + $ odoc count-occurrences -I main__A -o occurrences.txt --include-own --include-hidden + $ occurrences_print occurrences.txt | sort + string was used directly 1 times and indirectly 0 times + + $ odoc count-occurrences -I . -o occurrences.txt --include-own $ occurrences_print occurrences.txt | sort Main was used directly 0 times and indirectly 13 times Main.A was used directly 4 times and indirectly 8 times @@ -112,15 +134,21 @@ We can also include persistent ids, and hidden ids: $ odoc count-occurrences -I . -o occurrences.txt --include-hidden $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 2 times - Main.A was used directly 0 times and indirectly 2 times + Main was used directly 0 times and indirectly 11 times + Main.A was used directly 4 times and indirectly 6 times + Main.A.(||>) was used directly 1 times and indirectly 0 times + Main.A.M was used directly 2 times and indirectly 0 times + Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 2 times and indirectly 0 times - Main__B was used directly 0 times and indirectly 1 times - Main__B.Z was used directly 0 times and indirectly 1 times - Main__B.Z.y was used directly 1 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times + Main.B was used directly 1 times and indirectly 0 times + Main__ was used directly 0 times and indirectly 2 times + Main__.C was used directly 1 times and indirectly 1 times + Main__.C.y was used directly 1 times and indirectly 0 times + Main__A was used directly 1 times and indirectly 0 times + Main__B was used directly 1 times and indirectly 0 times + Main__C was used directly 1 times and indirectly 0 times - $ odoc count-occurrences -I . -o occurrences.txt --include-persistent --include-hidden + $ odoc count-occurrences -I . -o occurrences.txt --include-own --include-hidden $ occurrences_print occurrences.txt | sort Main was used directly 0 times and indirectly 13 times Main.A was used directly 4 times and indirectly 8 times From e098649193188aa9d1cfa60d139ece291df68e93 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 18:09:53 +0100 Subject: [PATCH 30/35] Occurrences: add shapes for other nodes, improve test Signed-off-by: Paul-Elliot --- src/xref2/link.ml | 9 ++++-- src/xref2/shape_tools.cppo.ml | 40 ++++++++++++++----------- src/xref2/shape_tools.cppo.mli | 16 ++++++++++ test/occurrences/double_wrapped.t/a.ml | 2 ++ test/occurrences/double_wrapped.t/run.t | 27 ++++++++++++++++- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 7dbf5ecbe7..0fd8c37ca9 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -565,18 +565,23 @@ let rec unit env t = | ModuleType v -> ModuleType (jump_to v - (fun _ -> None) + (Shape_tools.lookup_module_type_path env) (module_type_path ~report_errors:false env)) | Type v -> Type (jump_to v - (fun _ -> None) + (Shape_tools.lookup_type_path env) (type_path ~report_errors:false env)) | Constructor v -> Constructor (jump_to v (fun _ -> None) (constructor_path ~report_errors:false env)) + | ClassType v -> + ClassType + (jump_to v + (Shape_tools.lookup_class_type_path env) + (class_type_path ~report_errors:false env)) | i -> i in (info, pos)) diff --git a/src/xref2/shape_tools.cppo.ml b/src/xref2/shape_tools.cppo.ml index f4feb5970f..7d2a351c32 100644 --- a/src/xref2/shape_tools.cppo.ml +++ b/src/xref2/shape_tools.cppo.ml @@ -81,21 +81,20 @@ let rec shape_of_module_path env : _ -> Shape.t option = | `Identifier (id, _) -> shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) -let shape_of_value_path env : - Odoc_model.Paths.Path.Value.t -> Shape.t option = +let shape_of_kind_path env kind : + _ -> Shape.t option = let proj parent kind name = let item = Shape.Item.make name kind in match shape_of_module_path env parent with | Some shape -> Some (Shape.proj shape item) | None -> None in - fun (path : Odoc_model.Paths.Path.Value.t) -> + fun path -> match path with | `Resolved _ -> None - | `Dot (parent, name) -> proj parent Kind.Value name + | `Dot (parent, name) -> proj parent kind name | `Identifier (id, _) -> shape_of_id env (id :> Odoc_model.Paths.Identifier.NonSrc.t) - module MkId = Identifier.Mk let unit_of_uid uid = @@ -151,25 +150,24 @@ let lookup_def : | None -> None | Some query -> lookup_shape env query -let lookup_value_path : - Env.t -> - Path.Value.t -> - Identifier.SourceLocation.t option - = fun env path -> - match shape_of_value_path env path with +let lookup_module_path = fun env path -> + match shape_of_module_path env path with | None -> None | Some query -> lookup_shape env query - -let lookup_module_path : - Env.t -> - Path.Module.t -> - Identifier.SourceLocation.t option - = fun env path -> - match shape_of_module_path env path with +let lookup_kind_path = fun kind env path -> + match shape_of_kind_path env kind path with | None -> None | Some query -> lookup_shape env query +let lookup_value_path = lookup_kind_path Kind.Value + +let lookup_type_path = lookup_kind_path Kind.Type + +let lookup_module_type_path = lookup_kind_path Kind.Module_type + +let lookup_class_type_path = lookup_kind_path Kind.Class_type + #else type t = unit @@ -180,4 +178,10 @@ let lookup_value_path _ _id = None let lookup_module_path _ _id = None +let lookup_type_path _ _id = None + +let lookup_module_type_path _ _id = None + +let lookup_class_type_path _ _id = None + #endif diff --git a/src/xref2/shape_tools.cppo.mli b/src/xref2/shape_tools.cppo.mli index 40caf7b433..adfddc5d2c 100644 --- a/src/xref2/shape_tools.cppo.mli +++ b/src/xref2/shape_tools.cppo.mli @@ -19,7 +19,23 @@ val lookup_value_path : Path.Value.t -> Identifier.SourceLocation.t option +val lookup_type_path : + Env.t -> + Path.Type.t -> + Identifier.SourceLocation.t option + val lookup_module_path : Env.t -> Path.Module.t -> Identifier.SourceLocation.t option + +val lookup_module_type_path : + Env.t -> + Path.ModuleType.t -> + Identifier.SourceLocation.t option + +val lookup_class_type_path : + Env.t -> + Path.ClassType.t -> + Identifier.SourceLocation.t option + diff --git a/test/occurrences/double_wrapped.t/a.ml b/test/occurrences/double_wrapped.t/a.ml index 0a13bbe074..aa8464151f 100644 --- a/test/occurrences/double_wrapped.t/a.ml +++ b/test/occurrences/double_wrapped.t/a.ml @@ -5,3 +5,5 @@ type t = string module type M = sig end let (||>) x y = x + y + +let _ = x + x diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index 0aacfb0a2d..a0660c6c29 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -119,6 +119,8 @@ We can also include persistent ids, and hidden ids: $ odoc count-occurrences -I main__A -o occurrences.txt --include-own --include-hidden $ occurrences_print occurrences.txt | sort + Main__A was used directly 0 times and indirectly 2 times + Main__A.x was used directly 2 times and indirectly 0 times string was used directly 1 times and indirectly 0 times $ odoc count-occurrences -I . -o occurrences.txt --include-own @@ -160,9 +162,32 @@ We can also include persistent ids, and hidden ids: Main__ was used directly 0 times and indirectly 2 times Main__.C was used directly 1 times and indirectly 1 times Main__.C.y was used directly 1 times and indirectly 0 times - Main__A was used directly 1 times and indirectly 0 times + Main__A was used directly 1 times and indirectly 2 times + Main__A.x was used directly 2 times and indirectly 0 times Main__B was used directly 1 times and indirectly 1 times Main__B.Z was used directly 0 times and indirectly 1 times Main__B.Z.y was used directly 1 times and indirectly 0 times Main__C was used directly 1 times and indirectly 0 times string was used directly 1 times and indirectly 0 times + + +REMARKS! + + $ odoc count-occurrences -I main__B -o b_only_persistent.occ + $ odoc count-occurrences -I main__B -o b_with_own.occ --include-own + $ occurrences_print b_only_persistent.occ | sort > only_persistent + $ occurrences_print b_with_own.occ | sort > with_own + $ diff only_persistent with_own | grep Main.A.x + < Main.A.x was used directly 1 times and indirectly 0 times + > Main.A.x was used directly 2 times and indirectly 0 times + +This is because the persistent Y.x is resolved into Main.A.x. So maybe relying +on Ident.persistent is not the good way of knowing if it is persistent or not? + + $ odoc count-occurrences -I main__A -o a_with_own_and_hidden.occ --include-own --include-hidden + $ occurrences_print a_with_own_and_hidden.occ | sort + Main__A was used directly 0 times and indirectly 2 times + Main__A.x was used directly 2 times and indirectly 0 times + string was used directly 1 times and indirectly 0 times + +That's a problem: it should be Main.A and Main.A.x From 07c3dd95cb3dc282e5ec7a475e389003314eb636 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Fri, 3 Nov 2023 18:40:12 +0100 Subject: [PATCH 31/35] loader compatibility code Signed-off-by: Paul-Elliot --- src/loader/cmti.ml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 870cd18f69..436f6a6fdc 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -531,16 +531,16 @@ and read_module_type env parent label_parent mty = Functor (f_parameter, res) #else | Tmty_functor(id, _, arg, res) -> - let new_env = Env.add_parameter parent id (ModuleName.of_ident id) env in + let () = Env.add_parameter parent id (ModuleName.of_ident id) env in let f_parameter = match arg with | None -> Odoc_model.Lang.FunctorParameter.Unit | Some arg -> - let id = Ident_env.find_parameter_identifier new_env id in + let id = Ident_env.find_parameter_identifier env id in let arg = read_module_type env (id :> Identifier.Signature.t) label_parent arg in Named { FunctorParameter. id; expr = arg } in - let res = read_module_type new_env (Identifier.Mk.result parent) label_parent res in + let res = read_module_type () (Identifier.Mk.result parent) label_parent res in Functor( f_parameter, res) #endif | Tmty_with(body, subs) -> ( From cc6e2d70d42df416245f3eff2426b401b749104c Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 5 Dec 2023 12:08:31 +0100 Subject: [PATCH 32/35] Promote support files after rebase Signed-off-by: Paul-Elliot --- .../odoc_html_support_files.ml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/html_support_files/odoc_html_support_files.ml b/src/html_support_files/odoc_html_support_files.ml index 54812d8baf..7c48414c81 100644 --- a/src/html_support_files/odoc_html_support_files.ml +++ b/src/html_support_files/odoc_html_support_files.ml @@ -128,8 +128,6 @@ module Internal = struct let d_4a0d6b1f3fe23870dc64a5c9998fab74 = "wOF2\000\001\000\000\000\000?\020\000\017\000\000\000\000\134\224\000\000>\178\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\026\028\027\030\028\136$\006`\000\132|\b\129\018\t\151\023\017\b\n\129\201h\129\172t\011\132\026\000\0016\002$\003\135B\004 \005\131T\007\137\028\012\129 \027*u\005\227\152%\224<\000\129\146\245\0192\138`\227\000\146\024\188\027E\176q\128`\191\029\221\252\127=n\012\017\236\136V\181\014%$\184\218T\228\158\166U(Wg\163{\147a:=eRp1\147J^\223\209\2050\133\133\228d\197\175\140\135\219wT\007\025\238^\197\219\016\196\021\023\132\127`{b\209\027R\240Ew\255\224A\173@\130\006%\186\244\193\195\239\004\165\168OFR\248\156\191\220\248\232\b\141}\146\011U,[\247\236\127&$\225\016\158\194\135\168\192\168\168q\022\148@HT\242_\b\159\212\237\146\029\149\193\145n!\232\169J\228\014\192\220\028\130\003F\245\"a\209l\205\130U\177J6bT\140L\005\251\162\024\137\141\145`\005f\222G\164\149\015\255+U}\239\253\191\187\000I\145\162U\154{\191\177\164\168\204\144^\151\170\225\192p\131\145V\024\235\152\243\197\247SB\004\141\177f\015\151\012\161\019E\155y\018Mb\157\140GR\164v\154\254\031<\212^\219\219\250kK\178I\255\185\163\021\133\208\027\154\187u\224\016\150A6\165\025\020H\135D!T\243\159t\234\251\167\147-\019\004\248\146\179\212T\186 +>;\132\176g,\224\180u\0243v\157\218\006\247\223\007\248\1919\255\243^\0250\177$#H\182c;y\196gF\003\152\161v\213.\187\236~\247?\031\234\210S\203\167t\011\179?\192,\217\133u\r\001?C${-lc\136\245\249\159\181\026\"\030\228\135\015\222\221k\214X\198V%A\1471l\214\228p\164r;\189\244:\000!\142e.\212<\000\202\031)S)\006B\185\253\159\174\223\223I6\200\189\025^EoEIQA\143\143DX\194{\001\1949\193e\13429\180n\203\195\190\152U\201\006\241|\207W\249{S\205\246\191]\174\004R\014\132\194\012\229\172\211\197\216\175\194\217\2449\151v\229\162s\251\241\255_\252\221\191X`\177K\222-\022:\029\024\164#A\209\002\b\158D\018\180\006\1297\179\1608\030E\135\016%9\209\174HP\129\162\018%9\166Xt\030W\149K\183eJ\157{\023U\239\162\247\024\250\246\139\213y\243\023\148m\1916c6\029\026\014-El^\185\028\rY\196\146|\239O\200\131\140\229\230i\150\001s\171\237_/\219l6Hjt\168\006\011{a\137\183g\246\134\211{\127\179\255C\023\186\166\215K\144\208\000\145\153\136B{\191\158\\\004\001k\128\017;\019U\014\185\234\1730ijA\026\182\r\155?\157YA\020:S`#`\197\202\155\133\130\231u\238\188\228\229\014\241\166\177\207\156N\011X5\227-\222-\243\231\164+\225\238\185\165\150\186\133\209\173T`u\006\028\243\166$%\219\\\170L\022\233\163:\014B r\138\203\178\019\004\150}Y6\002\178`.\203\138_&\244eY\240\017\131\186,\197K\020\242\178\004\015\017\136Kb\220\132\193\1836\b\023\025\175,\243\247U\002{\146z\127K\167\210\031\163\240 \232%\030\211\142o(]N\148AR\196\"\252'\191\145\159=\"\252u\153s\251\132_.\001\128\216e$\131Ld,\179\202,2\0056,Y\201\137\011w\150\003_\201wI\241\219\193\183\019\127\145g,?}g\141DHa\154\1381E\241\202\012\194G\169M\187\014\157\186t\235\209\171O?\132\023\165\"_\208Z\131\134\012\0271j\204\184\t\147(\170bD\214,\194@v\245\133\154eAT\020\174\138\201\243\003\130\180*\208u\238\023\020F\215\207\1536`H\155~ \005\233U\005\195\003&A\212\196\245\166Y\137\023K*4r\137[\175\162\023\238\189p\204]\130\151\147\031u\204\175~\243;\128rU\143\127\157\143\187\232\015\127\250K\024>\021*U\169V\163V\157z\r\026\029v\196=?\2489: \172pB\004\132\247c;.\196DV6!\134@5\133\139\240:d\201\203L\201\246\160$\152\011\167`\136\221\197\220\b[\253\137\190\211<\159\1702\239\162\178\b\203\212\222\194\203\141/`6\200S\222\r\128\171\188\174{0\"\004\144\014\155tS\031\194S\160\149\179\030m\022\2428/\238?\211\185\225\007\128\251\148F\191\001\240\012 \189\153\006,6\161X\185'\028\nG\148w\031\217CH\017\196\197\209\195\215\239\1274\208\1503\185Zn\151\187#\\\200=Q)jE\131pD\191(\200g\203/\247\138\245\191\251\174A\176\161\228\031\243\0207|\157<\186<\155g\213\214\149\187\162\\T\175\177\239\011\165\127\000p\r\000-\001\134\149LSK\149\027\000\171\143\193\234\193\247\196+\255za\1925\223\185\234e\000\254\253b\187\025\191}\239\185\221\254\216\166\2209K4k\181\133\029\011V\156\216p\224\194KD\178\020\169`\192 \160\018e#\192\194!\193\251\017\017\023\011\027\135\016U\136\156\132\148\146\140\130\138\150Y\001#\019/'\0237\189R\149\202\148\171V\225KU\218\181h\213\166G\157^d5.\187\228\182;na\198\147ANrW\029\144^\000}\184#\231x\172~Q\150X\189\028\165\127:\"\2250\193O\188\021\128V`\217\240\203\020\020\001\171\186`\136\134\014\016_\028B`\249\163Fg\021\0267m\157\252\170\006\179\221\161\005\011\199\021.\011)\129M@s>\003A[\021\131\020\196A=\006ST%\188\155\193\157\143Y#\133u\161R\152\252\164%K\2257\b\011\227Z\1947\130\208+n\234\2214\020\182\029\174\138\198\166V\199\002\169U\180b\209{\014\213\201\127i\n\0206lO\b\169\b\139R7\234\2544\176\198\024\001\242\140a`A\215\140\137a(*\016\184\237\170\004S\143k\152R! \149\144\210\128\014bp\197\146%U\131y\164h\195\198''\015\198A\1921\233\202\129\167\201\159\167\247\135^h5mpgB\219q\225&\141f3N\249S\218\011\225\022\211\029\209\163M\133\160~\157\129\005\007\005\244 f\152\000\215\227\192\142\234\1988\014\030L7\248AEf\230Gt\229\128\227\136\021Y}\223\026pm>9\146\165\178`\004\186\160^\201p\163Py\248ca\154\020y<\200\128\219\182\238\247\242\144\170\177rP\021\207\205\016U\240#\132\173nKb\249Q&\018\025 \137\220\028\160j\138\162\196\165\169\179H\216(j)X\154WR\015\137\169\192X\017'\178\142\024q\021l\"\227\232\193\001\"OO*#!uX\130\024\222\251\018\138\144\012\202\016:\2248\246\242pR\215V\247\001g\152\131x\170\164\026\154\214\129\159\228\205\147O\205\167\188\165\167z\221\019zhj\153\0202\200\153\011\167U@B\207\232\137{\004\232P!\225\025\151\178\204V!\186\130\216\016P)\019\012{\017!|6x3\237\191\156\0319\229J\254\024\173\197\004\002\177\b\209M\174AT\151\016\131H\191\194\197\026\203%\014\193\012z2`\2155\003Y\248e\178\170\138aM5B\002\217\026\154C\\KGX\015]q\145Qiz\195\138\133Dl^qR\247rM\018\154)\251\250e\225\200*\227\227\248\221\171wz\225\163\017z\189qG\230#\244y^\136\020.\187\243\189\135wc\226\181\216EF.=\248l\183\006\144\136\2490\014\190\199\133\031;\199A\030\168\169o<\214\179\011\1430T\228|\148\202\208\t\249\014\185\212\195\220\140\004\159\145\135\140\167\022\250\170~\217\144$q[\2396\242\168\151P\176\002\163\132z\\\248#\024\r\137\205\250\141\209\0250\201\1911\1610\166\164\134\001;\251C\157p\227\231\2552I\153\253\220\177\024\241aPQ\200T\253\005\162\183@\227\162\210=]\241E|\224\234Z\1894\216\163\143\234\184\192\250\004\226\190M\197(\248\207\141\023\171F\"\221<\027\254\158\218\017\004\132\181pN\196\018\169\176\1996p\186\142\196\159\005\147\146\179gfRuV\250\239\130\244\031\140\196a\030\224\182\128?\2279\202\t6\225\250\243\208\176\164\218\184\232=\231\153\028\146\0188z\200F\004\1743=\200\234c\206\184\245]\202i\t.\165>\199(\248\161^LaB\137\212\020\132\127\178\227\232\205q#\209\189\030\193:\225\179\204g\028\150\183G\005L\175\030\191\237 fC\218\173UL\247Ae(\236~\1747\250\183&9\174\150\180|Q\248\225L\131\175\r\194\186\225\214);\197\181\017\140\014u\020Ed`Ai\174X'\247F\164j.\152\134\158v\238\136i\154\"`\130\183i\171\241\151\222\248j\229/&$\129[\222I/\167'\187,j!\239\161\026\167\146\154ro\219\200{}\246\014&\175\244\235zH[\184\160\158A\196p\244OZ2TL}\1499\144\140\217\024\002g\136\177\189.9\174YRG\199\217'\177\000\128\004:&A\031\2507\157\023\248\242\248\023)\156]\004C\201\031\232\217:\200\156y\127:\225,\029w\221\141\242|\024Q\027#\255#`\162F\220e1\1901]\175\131\174}O\185&\007=\253\255\235\140\150W,\222\211f\2187\022\201\229?\150w\2327\130\169\141\254D\166\2370\\\134kJ\r-[\184\231w\211S\177n\n\180\030\232\252a\168G\211\215\194\180\228W\253\173\t\2017\025i\219>n\140Gv\192b2C=\168j%\017z\134\0003\177\202\006\179g\248\141\233\173h\2517\143w\178\237\191\231\232\223B\174Al\221q\154\172H\194pW\007\019\239W\141\004<\245\163Z\025_\199\192c\216b\215\251\203\030\175\203u\213J\155\198\192~V\230z\138=UF\137\168u\\\019q\174\227\156\169\174\146+k\2482:\025\245\229\1715\bW\149\154+\172\237\021{\188\230\004j\224\184\133\179h\225\\\200\026P\169?\001j\r\173C\018w\188\167%\144\139\149=\\\012}\026\011)\155\167\240D\242\020\133\236\137\197\192\190\004,\241TV\226\004\157\2454K\206\173]zi\223u>x\029\248!(\177/\149\183\131w2\133\183\130ghH|\016\186\165\235\1405cW\198\217\159JFUgd\031O\191\140\217\144\200;\143^\181\006\179\178\246\194i\007\2378M\145\157Y\209t\029\148U\243$\184\191\254rY\146\243X\253Mt\029\151\230\200Z#\222\243\171g\221\203r\226q\169\215\239\240\180\215:\197\139\211M\r\2046\137\190\168\133\207\254\170\132M\213c\254y\026\022\170F\151\163c\239\251q\\\137\007K\150\019\"\183\170v\129\1602\018\234\243(\215W\163\233P\007\200'\207\249K\249\229\021f\185c\160m\167P}j\165 \184Tf.\200\139\214b\188YQQE\170\172:\217\201\199\229l(Q\191\204\189Jb\178K`\183\217\144\031_C;\154B\021\188\197\153\230N^CN<\244\204\130\024\011~\167\028\129\239\232\252\007\189J\238\\&\210\023\182rY\005%u\167\208r\165\177\178\139\165\023O\186\217\167\241E/\252\204\015\219E\225\198\158\181\141F\241\158\137h\1577\154\234XmI\020\155\133M`gW%\236$QR\223qG-\159\214\127\186\030\202\175\153\025L\187\179\189\206\1949\216\209\2362\190\132^\189Y\1973\23053\217o\023\195C\143\138\150?b\228mx\199$\219R\221\174\1860Y\231\151\213\210y~\133\1383\214\2364\018^\159\028\133\214\208^\175\166\200\132\229)\196\028]\250\159\014\179F#\019T\2409\241\212\182?\248\"V\147\182Z_\155F9\234\219\005Z\237\243\"ey:\r\254\237\221\017\239\141ZE\243S\245Q_\196&\253\161\201! B\251\139X\226\1384y\189tD\174\214\244\195[\154\024\141\169vyc\141T[\128\235xB\168LQ1\219-\160\022K0\213\210Q\235\179\203I\028\223j\234\232\251\170:\174\252>t\253\248\186Az#\252:+RNP\177\020t`t\237\029\r\134\224\172l\243\219$\011\235\235\1558mRuq=\203'\225\208\245\152\175\222\132\245\190\136\150*\197\185E\236\225y\154\031\n\176o\005s\165\131x\244|\253\167\011\150\164\192\231=|\166\251\031\136\0302\175\135pB-O\t\149@\149\252\189\249\1767\132\250z\t\251\233\145\193U'7\169\249\018\173OW\\\251\245\201\140\255\029Y\173 \147)H\021\2517\178n\161\254\211\189b\221\221Y\201\254\140\180O -\015\184B\153H\152\133rz\231\193\002\224\003\180D)\202-b\143\204\211\253P\128\020-i\134^\002\225\155\219\187F*\201t\208+\163x\236\188\0302\181\210\189\194\193\166S_n\253\215\205*\155~I%\189\217\003F\179\134\222\180\209]N\196\006\201 \001\221\252\210Q\141\242\tX\253\247\127G\021A\190\1512\173*\\\216U\004\187\t?\2462\214\149~\185E\220\213\211h\231\239\025\175k\136\198{\234\139;6?^\223`\233\228nKr\177,X5o\187\139%\197\217\127\127\151\224\019\216\249\011\237Y3l\172\158\022$\127`\029\193/\1945\1960\167\247\235\187p\240)\189\212X\208@\165\188\177\222#\141\024\197\198\130h\025\249\137\025mZ!\231\197\178\155\213\1872W\251*Q\159{x\190\026M\172\135g\145[\226\r\241\158F\187`\207H]\132\239\160,\025\028q\137\007K\145\019~lr\nKs6\148p\132.\160\242\133[\029w\186\131\229\026n\238l\000{\171\0062#\212\150;\173\142\198\176\139wh\1609\196\153-yv\143X \019\234\139\162f\006\024\251\031\244*!j\250k*\213\205ws\014\0145G\152\179\197\207.\136S\134./\136\177\153\015\141\b\156\227^\136\225\132\187%wn4\149\229\027pd\187\167\189\214-Y\156ih\136\135\1855\215\230\193k\194r\193\141\166K\244\197-|\246_0\239N\2281\242\174\203\2242Qy\158\006\245\171!\255\nXQ{\212, o\024B[\149*\231\003Y6\028\165\205\006\225\240\163\200\028\149I\204d:\154\232fu'\149c\182}n\197\239\205\131\172\158\251~T\158L+\1602\141ue\026o\168\233\242\205M\170\0312\026&\227m\149A\139\148\232\016\205\173\203\134n\156{\178\255\025\018\157\234\011\011\r\232\0316\242\235\023\138\b\148b\216\155o\254\157\137\241X\243\225\248\248\226\156\163yfP\155\252\221T\187\194!\255N\237x\227\156\021\192^\r\005m\196\227#?\153\160h\189\201\164\207\198\162~\209\131Z\172\136\248\004\b2~-\162%\234\169\003\203\213\018\b\138\189v\158V\003]#UA\168\028G\153}^\015\153\\i\214\007\252mh\2007\144\235>\2001\204\158\185=r\026\003\186\004\185\n\154\236\159\188\134\129,\172\\X\191\176+c\161w\193\144\014\217\245\247\168\220\019\178\251]\247\207\\\145u\254~\130~\210\127R'Z\145\252\220\183\233\171Z\141@3\245\019\174\019r\016u\250\192\233\131\178\023 \160b \169\t\214\179\027\212\150J\186\004\238\214GxVpx\254\170\030\211\169\236/\026S\155\138\254\159Us_(\196\180\231L\176C\141l\210\162Z\131\156F5E\216P\245O\249(\130S\027.!\188\197\158Af\143\213\006\020\163\227\025\174 tK\1981\150B\028?&W]\195jZ\206j}\192\019\254\203\207t\142\250\209G\193\136;\148\019\030\2223(\200~\131\213\134\182\128\156\193\213)\249v\143\006\146\149J\166$l\143\227\138W\243r2\138\153\170\028h\213`%\136\208\195$R@\208\153UEk\248{/\149z\229\127\189\245\151\221\025\2187S`\230!\145\1595e\246m\203\236\187?\185/\232u\026\132\177f\153\214SS\229x\186^:N\029\177J\166fQ\136>\153\146\1375\131\251\246\131\007\190\212>\025E\163Y7\131\156\172\194\248.\028\190\190\002\134u\165Wn\007E\191\155\247\239X\157Jr\205\135Y\233M\2434\159\254\203\011\1477\240\031\213\0154\143\215\183Nm\018\192U\174k\030\171\207\239\202\020\244.9!\237\162!W\226\127B\031\147v\210lg\015\249\014\237\214%\205{X\029?\2078\131\023\252\020\154\149\201\"\215Nm\024\011\131\147\156G\156\207\232\2161:1Zf\"\162'P\232\011L\151\149\029\231\234\\\163\023\162^\173@\239\181\228\238\208\169%\028a\243\1606`hbg\249M\007N\227\216J\005\031\247\001\157\143h\198\242\r\004D\r\006\171,\161(+\171bDEgn\178\184\220\144\189u7tk!(\239\215k\195\244\135k;K\247O\230\238\175\248\156\241#t\211\167\250rO\176R\"\026\024u\133\r\017\182\196o\005\233%J\151\196e\202]\187\177\145\222\252\216\226\210\019\201A\183\132;\209W]\221\209<\212\213\235xeaL\131\231\172\210\171\163\241\156>\168[)\176\018\"\140f)\241cX\241\198\153\154R~\146\166\236\167C\160F\133n\154Z\154.\004\015\019e\147k\196\234\240\136\192\173\175/\227\216\217[U\182gx0\138`\nq\002\134O@\192\193\170g\193\245\019C\r\130W'\2316\133\162c\195Q\193kS\243\154\248]\162\225\226K\022\225sp\170x]\209E\187\240\005\152}m\207\b\184\231Jf\207\001\254\194n\023\167\233\231\153\025\245\216r:\149jg\178hu\027\183N6\021'9\143x2\163c\231\208\214\245\\\015\t\219\131\197\202Q\024\183%\210\182\2215\176\028\192\211u\020\169\165\198\146\187\211T.\019\202\155\199U\129\242\024G\225/\207p\n\140*\129\181^\129h.\019\n\228\004\248\199\165\006\141T\227i\172\154\238\204J\182\140\171\161\182\249VU\144\145\247\215\179\195>ol\170\192\159\156\204;Ya\002\027#\001\163\241\255\210%I@\2342\229n\184\213\184\130i\222\139h\255={\014\192\141\171\170\169P\tG&*\026\215-\189\144\020\244\2029S}>_K\203p|\192\246\206\222\137M\158YE%\143\206s\133\161>\170\166\004\143i/\235V\016>\132s\217\201a\b\190\130\195\156\196i+\130\211,>\028qe\175\186\152\022\014\135\023\233W\006u\017*\2197\139\212\225oSk\209*2\157\021l\147:\170;\\F\190\208\165D\142~\193!*\177\193\237\143\222\163\224P\004\228o\129\162\012\029\253\240\198[\141\006\135{\183\180\250\210r\233\218\250\027\015\2373\188$-\195%\155k\017\158g,ez*\193\205W\240\134\214:\170%?\163j5\"zH\230\144\011\190q\193\207\234]6\019e\157W\175\208\021\173F\202@\213\255>\160\186K\1994\184\226l\002nL\141+\129Z\248\135\005\135c$N\144G0\029\244Hs\207\234\2294\"E\173\021\0258\167\242<\216\212\248\206\171^\131\197\134\129\216\161y*\141\140\171+\247;\242\207\234x\020\194D\209v\"\129\196P\184\208\1720M\165\226\173\241qj\135\231\220/\193\231[\242K\136\249H\018\229>U\199\247v\212\156HwQ\210\226[R\029\183RM\011\233U\232\161\015\180\b\191'\221\223cv\030\000\026\252h\234i\014\139a\173$\011|t\181\134\251*\025\181\015G\196\023\190g\129\127\145\127\014^t\131\195\162\217\157e,\163\222n0\241G\027L\026\225&\154b\016\134J\186:\203\023\251\2027\184\156\031 \197\175k!\197\169\214\230\198\195\169\166\231kkq\215\153gR]\024\193C\024\018\247\158\027-2\216\165tK\000\141\228 \251\140h\142\210\204\161 \157\143\251F\175\229\129\127\209^j\017A\176\132d\185W\030$2S\255\007\005z9\223[r\214b\144N\156~lw\001\168\175\019\236\165\183Z\246\021Q\223a\211i&\023\137\165z\017\131\190\163\000\023`s\138%\00460=\161\195\215\163\248\222\155\149]r\251M\020\155\186\022\233\n\191n\205\152\167\191\000\220\1460JZ\004||-\163\253p\146\017J\184\147\012\184\1477\155\239\012\199-\180\001\235`\141\165\189n:\143\215\223#Z5k\019avTB\204\186D\003\236\029\217\000\003\204\027\001X\223\184\165\198\239!\160\030\161\t\235\137\176?\222S(X$\130V\141'\178-a\255\234k4x\002\0288\229\208Ce>\245\172}\214\163\188\240\184+q\003\177\132\254\031a\233\136ui(\147\194\2546\159\174\231z\149\249\136W\142\216\174\180S\174h\024w\248\160<\rnv\228\"\161\2100v\150\187\172U1\239\2402*Y\212\232\168!\181d$\203Mv\237\142\215\214\206\253I\011\165\223\176\236M\203&\183\130\129U\214\031\253\163\017\149i79\187'\191\140\178\186\252j\023<\247\181b\137L\236\177F\162\027\231^\155\182\127\128\243w\207\215\171\023\222\n9d,\172\178\226\232\nmW\001\200~rv_\030\133\188&\235\2338<\247\213\018\201\191\030k\164ac\165c/4w\019?\151\r\180\223K\031\135\231:F\198\016\128\128-\224\254\239\178\250q\172{*\246\211|P\158\022\203\127<\196j\228\028WW\134\n@\185Z\204\250\145\139\132\200p\150\155\226;\199C\240\185y\201\244&I(+\184>8\221r\226:\021\140,\188\182&-\175\001\147V\212\224W(s\138\242/\"A\178\249\240\172a,\174\186\220\167\143\162\014\161*\132%X\239\218\147\148,T\193\r\206Cs3\203c\161'b\224\1745)\161\139\248\220C\220\148\248\139k\192\150,\127\238\199\241y\015r\026\006Cy\007|\184\029xC\131\136\160e6!'mC\162G\237\151\170\154\000\160\237\153\204\193\200)\219\160\248Q,\225m\168\214\232\195\225\220\207\133\210\157\004C\147\b\016r\127\224\216\131\208\028\191O\139\199iJ\219\245\157\206\171\1740\128\017?pt9<\145\207\175-\197)\241\177\195\214\001\128\192\172\191Y}\159\128\251`\159\233\171]\165\127OA\001\216~\133G\146l\254Q\198s\017\247y\243\1420\0048FZxW\024z\253\029\143l\225\185A\143\000\241\135;\153\188\207\138=\1796\217\190e-F\142;%\189\166\215\200\207L\005\233zx~fl\224\184M\152\191nJ.\145\212\012Sr\246\156\142\156\1994PS\135KA\157\169k4\130\179w\182A\183\026\210T\175\151\215\223\250\011tu\172A\1656\149\027\165R\177\201\168V\027\203W\203e\171\141\133.\183\154\196R\217\003L*\181\225\207\249\211\173\005lV\001\149V\192b\023\208\234\143\0148}Zk\211@sf\206\178\142\156\221\159e2~\2458\228r/\235\007\"\226xg%\194\238\149Y\155\219k\210\178\231\182\231\204\249\179\228R\171M\206\214\149\177\208%\137\215\252\007\1656\145\247\007\132\253\131T\205\1390\2195\233\155\002\141\149\148Qq\208\b&\198\198\215%\183\185\225610\218\006\183\203J[\142\24677\155E\242\170C\163\232\r\1277\228\132)\200\238\1672:\188\179\169L~\1562\205\166\200\b\166W\2474\134\135%\225\176\226kW\137)\205\149^}9\205\182\004\212F\218\014\189\021\017H\181\141\166j\199\210\146,\184s~22\248\238\135\189T[pDy\208\149\1270\127\239\139\006\251\\]\021\157v\181\r\182e\230\212v\228,t\166\171\173\021n\145\220\199\145\211\168\2407\231\006\194\236UJ*\201\237\021+\128\217K:\236\151W C\161v8v\154\203T\152\146\207\228\185\204>G\1858[\249\011\194\254Q\138\230%\184\237\250\n\205:\190\210J\002U\\4\128I\173k\135\000\221\021\b\1558" let d_4fff47472c2ce7d1d0360d2345161ba6 = "7\217o\133\154d\153\202\187q\218QB\027\029\185\t\143ds\142)F\003\223H\170ma4f\024\0126D\140\149En\006\007\138\180sm\1751\027A\178\178\218\221\2360\173\218\178a\030\130\252\166\004z\148(\146\021\236[\134\138\229\025\220bR\030=I\242PXL\143\226\178\004\175\158\181\180\128V\193\216R)\240\1737 \224\221\025pr\022(\173\214Bo\216\155R\019\200z\004\000\236\160\182\222\239&PP\141\007F\221^\200Q\186cW\128\027wT\153\156\225#\003\130_O\236\248\206\207\186*I\172\244\145\b\213\144\2161\b\199\239\"\246\253\203\234\139\189\239\251\222\178\226q\141'\174\236X\152\133\208\142\153uj\197Aha\161X\242nfa\181\031?\181VQ[\1593T\215\023f\198\244\",\200\248\233\211\224\139l\025&\202J\020a[.\014\029mZ\248Y\139\225l\194P\128\1939 \005\022x\017wg\168\171\007\000\218\128\014 \201o\217!c\178\182l\160\024\026\003\168\244\228\1825\200m\161\174\168\178\232\234\133M\245\243<\178\003\004\137\133`\170{*\252Y\128\162\218:;J\167\238JKd\158\162\158\193<\199\240\002\221K\132W\173\227\181\183\164w\b9\210G\179U\031\251\132\230S_\2081U\232\0140|\143\233\007,?\194\253\164md\227\196\141\023_\023\137\133\237\016\134?\192\254\196\240\151\024\149\215\028\141=\2045\252\169\016\162\029\141\159*\192\017\240s\132\011M\145#\214J\188\207\220,U\017\017/\244\162\021N\015\0143\199\246?\248\192\193=\147?\141I\132\163\154}7\128\153\2204\188\1759\244\183\014\210\235\174|\166\180\243(W\141m\030Q-\143\136\149\014\165\210\177\183\182<\242\168\221\030\223\250\1969\231]p.\151B\030\141l\173\216\253\138\tCR\003|+%\198\127\177\230\194\180\180\211\030\223RiI]\162l\006\127\182\137B\142\227\191h\175H\1483\128a\003\193<\246\141$u\141\255\203\213@7\219\1853U\234\161a\158xH\014Z\135\180\195\196h\171\0306R\140\022\170\201iT0\216t\215\020\163F\1694\169Y\1433\215\230r\174\024\247\244#\222\220\014w\205\146[y~\237@\233\254\023\165\bU\132\150{\242|\005\225$\002\159GKFU6#\158\218\238\156{\166\251\210\152\136\179\026\254\130\164\141\022[\158\245\130x\138\234\016r\"I\242\233\141E\136\0257\139\t\146\246\220 c3\215SSm\1673\160\016X\016\180\022\188M\030\1404gb\235\243\026x\171\182\158\026\028\176V\219\147z(e\021g\204\003\204\140\209\183\209b6\154\002K\168\162\025F\141K\1520Vv\\\151\136\029K< \203\019.\183\174\199\177\178\177I^\171Om\198L\152\228\166\023\212\131W\217\176\181c\230r\155\163\188\132|)$w\148Y\255\150\005E\157\254\187{.F3\"\159)\235\r\\=\167\131\231\"\171_\222x\173>\146\187\004z\132\235S\161eS\0200H\134\021\184KsO\190B\029\220j\247\1333\177\026\203\148\152\188\144#\195a\018nC\129\027\2450j\199w-\143\207\200U\131\200\020 \001\011\226$E$l/\193\177\187\148\n\132\252\161L\189\1278}\024\241\208)\141\245\170\185\128\022\145nJ\193\184w\188b_,is\131Lf\139\151\245\128~\150\023\0270\223\020z\160\1620\172 \173\206\255\212\027\001h\130\250H\158Z\171\219a\145\237\128=2\137>\131\253\226\030Jg\027\r\154\241p\t\177\1739@\147\228\023}\218\151\228\1620\231\1405\213\235\208=\132E\180\237w\195\178\153Qv\249.5\217S\206]F\217@`l\210\168|!\018ECFs\172\028\027\145\248\164\205P&\186\150GI\163}\226n\016\003\218CO[\159[\192\148\130.\217rR\154\154P\162$\182\136\182zY\004\217\2168dq\b6\227)8\006\175\128\200*\2499E\225\206w\148\242\134\213\nL\222\204^\244I\178\\\245\217\1662\158.1\031\250\020\2397=\176Nl\213\007\235-d\bN\003\028iI7\029l\231\194\2061\018E0f\\\210\166Xx]\198\201\177\191\137j\178d6;H\140\167(F$w \240\0303\194\194\130'\1440\182\017\006\161\016\216x\237sI\251\2425\021H\000\211\203^#\225\204\245Sa\157\204\023\163\142\224rX\202(\254W\131\029\028@\018i\200\004\178Z\\\133\\\179\007\017P\175Ac?@U\163\170\2294_\209\031\194\"\025\164\138I\220\192\1916B@5\144$5\024\t\212Aj\233r%\005eP\221\128\2459`\159b\r\223\188\232E\191A\027 \203\240\027\127\130q\180\012\248i\174\217\143Rt/p\b7\211?\207\007P\142b[+\230.}6Nrx\030\161T\203\164\000\135\247\200~ka7\239\231;`ys\220\207\166\183j\207\234)\235\245\129\182\142\026`\0114I\195f\248\217\027\156\134\231\200O~\176M@@\168\218\18422\164\231\223\172\141\197\135\224\133;\151\210\026\181\251\144\021\014\237\153FS0\224\170\235w\159j\136\133\002\199\242#P\151\140-\0191\224CMD\183\214\155G\136\253Y\193sd\234\189m=z\189b>U\184Pp0\237\187bI?AX\201\217\2385\158K\244\196\"uK\170\031Z\\q^j\158[\\1\159Z\177\132\14512\030?\2064\187\138J\004\011\154\244\1476\229\191\232uQ\192t^\140d\163\232\132\231Z\244\204X+\241\164\183-\197A\239y\184\227\255*\177\129\225\006\202\199\130\171n&\247\189\244\154\153\189r\133O-\131y@\225\012\236\001\028\169-j\015\005\135\140\n_\170\199f2\218>g\138\018\185C\185\253\146\006\130\2553\149\167&2\181u\236\198\179\203,l\146n^\225\170\234\154X;r\237\233\203\179\186y\201Q\209\017[:t\229\201\203\147\220\188`+k\027[8p\233\241\2033\023\252\137g\173\150\145\153}\023\030\133;\1830\166\162\166\161=\2312\028\174\127\188\148\161\160a`\215\153\251\2150\161\011\230\226\206\220q\234.p\224W\179\190PO\234\196\173\231\230\225\233\188\202z,\246\252\129ZPU\131\133~$}CW]\133\005\204\253\159My;\197\188>\210\190\213Z\146\135\137.\207\022Tb\1740\014\184\204\177\209\145V\224\148\162_\239\\\165G_\238\223\011\159\020\189\011+\031\157\232\139+\014\187\012\024\168\016\128\195\144\145\016\017P:f\026\232\151\024FMA\154U\028\210\137\193\194\2170\230\203\243\025\185\015\022\240\143:\179\165\213T\153/\153\011\211\023\158\208\149gv\017@\249\167b\130p\1411\022)\141\204\234\023b\129\133\022Yl\137\165\150\2337`\249\223w\253\177T\169\159*\253\r0\208 \131A\184p\014T\146d(\176\194J\171\172\182\198Z\235\172\183\193\198\191\003\1875\1692\189\244\214G_\229*\026%\217\1341&h\205\015g\195\236\254\245\240\154clh\145\128\176\242V\003\136\131\213\b\169\213\233-\n\0213\139[\216\031\132\202p\016\143\210`/\230\\\r\213K\227\138\001\191\213+\000w#h\012\160'\180d/G\248\019R\191T\133V\133P\181\018\017\236\250\159}\202x\165]\133\171\016\0188$\157\194(\bA\166\208\149\1762\225}\186W\014%\201\150d\153I2\018F\171;\019I^*\190\207\2232\166\153n\134\153f\153m\142\185\230\153\239\164\215\222x\235\157\247>d\t\"\"\018\"#\n\162\"\0262@td\136\024\200Z.\024\178\241\166\130G\135\226\169\176\012\127rA )\162\"&\194J@\150\178.\254`\198\235\209k\130\137&\153\172\207\020S\ry\234\153\231\210N&\195\240$\019xqn:\140_\202k\155\131!\154f>\240Z\169M\243\218\007v\b\136\001\172\234,+L\200Ne{ID\158\005\217\170(!\176\194FLl\176\242\000B\";m\186\232\242\201\245;P\229\241&O\027\207\1362T\250\207\252\231\202B7\208\161\028=\136B8G\016\194\016\014\024B\233\225\183\157G\003'\160}\171t;\127\208\004\134F\020\204\195\22031G=(xg\232p\157F\025\r\193\197\2356\018.\217!\0068Ud#\002Y\196\230ZXF+-\131\216\189Vj\203\144\186&\250\233\138\218\144z>#G\133\145\170\004m\015\226N\146\016\138\200/PPnM\218\254\198-?\155 N6\146\248\001\165\005\t\255/\180\209\192\017\160\029\023]pT\029\004#\025\254\191w>\222\198\000\242NH\229\129\030\005(\2372\b\232[\185\128=\219\017\190\127\203'\148\185\128\249\002\016a\012\t\249\234\244\127\225^\147\178/\199r+w\138p\002N\197oD\199\199\152hO\225:na\026sXG\019\031\240\181\243 \137\239\235\186\173\245\203\235\147\203\255\207\023\180\194#\"\1834b\019\1797\211\149\1287\192)\151?Ykj\203v\199\190-\238?\128-\128\138\007\248\255\172'=\161\238\134\003\254o\244\159\031\255\002\240\217o\128\207\030\221\249\240\236\199\141\031K?\250\173\241\245G\163\031~\178\127/z\n\002\230\002;=\001y\204~\142d\030X\197=\167y.[\021\007\0281\228\185\191Y\206Q\188\225\206\218s]3\236\184\189\142\249A\199\236\226\176$g\029\006&S\028f(\254\223|\225\178a\203\142\003w\002B\"b\018\222|\248\146S:c\151\179\025\193\137\248\160\018*L\132(\241\018$J\146!\139V\142\\\005*T\209\169VK\175I\179\022\173:\156\138\005\167\253r\216AO\189\244\204\171Xj\162\183\166\140q\195o;\194\209Ws~\154hK\164\252I\t\187#c\147\177n\218n\155\029\014\235I\nN\208H*\157\165\192\227\011\212U\213\132\028\145\145\190\129\216\208\127\198R\235X'%\163\224\161F\016\127\001\212\002\005\011\017.N\180\024\177\210%K\145*R\190\018\133\138\148)\246\213\139\026\213\169\215\160M\165vn\202\227i\1686:s\213\021w\221s\199\193\175\014\144\157\175\023@\136\188\181\243\243\224P\176e\205\024\024\004r\233\029}\175W\242j\211G?JS\016\175]\203\003;\255`?\223\161|{\229\184\185\226\232=\012\145^;R\139\255\2130B\221\211\174\017!r\226B\1555\b\024lA\002\182\139aA\n\244\193\247?\242\244\170\030E\157\173^\1392;!3\127\252\218\137\138I\239\192g\1357\238\204=\245\166\150vGv\223=\178O_\236sD\154M1I\137\153\208\225\253(\012\145\030b\003t\030t\179M0uSJ!\141\007\127\230\012\137KW\137\1421\200\187^\144\001-\144[\236\131\130\135\142B-\165Z#\226I\138\130\028**\232gQY\184\137\236\136\145A\158\187T\138\212G\246\"#.\145\202m" @@ -166,8 +164,6 @@ module Internal = struct let d_62016f2316dffaac5eecc447ca24c81c = "Z\195\229\202C\147\172\201\012\133\016g\129\1363\134A\135z\186\216\000]!\192\004Fk\245\251\253\207\238\128\029\005\186a\196\181\221`\004\1644\\\184\031[ \136\195\144'\139\152w;+\213\0116X%\165t\000^\204\243FG2C \213\004\017\211\208\132\198\r\136\re\205\1838\031Az\225u\148s\250\194?<\151\132\225\209\218\196\203l=\015\006&K\002E_\228!:w\2361\214\027\188\134\201\231\158\002uhH\229\152\160\203\224i\015K\n\130WPh\\\127\018Jv\143\147\026\000+\1348h\207]S\200\143\221]\166\022\216\132\180\171\190@\194c\187\1296\170\164\169\131\174\232y\1423T[\000A,Jz\240\207\029\215\253\174\129R\189\149Tx\251\018\149P\b\rP\185\149;\203\245\238\183\235\218\166*\148\011\0219Y\226&`\165M\232)\148\024R\245A\0067)L\n\156\021F\167\236\157:\211\189Gb\153ot\224A\248\208\151\250\185\159\\w\222\130\017\129\1736m\131\232\240\180VD\024Q\253\004.C\nD\194\193\133\217\030\164\016\192\1536\015+$\207\253\209\140\028\000^\018\1483\165\183LO\182\168\201\016r\150\187n\174\\b\205{c\157\166\183\215\165\235\150\247\203\187\243\177\155\207\242\197\249\017\\l,\016}B\156\145\178u\202[\135h[\163b\132K\207;\189Fg\194\206\225|I\206\215u\014\240\250\226\b\131\216\181\030B\152\211\186\004\151\188~p]\021\203\167\195`V\244\173~d:b\158\169 \022\164\194\183T\t&\129\022\144\152\015x\155\025\136k\018c\142\232ox\149\0274b(\"\017\218\168\254\184\154\028\156\132\025\0118V\250\180+\233\143\205\206\246\159\171\031\007f\194\224\024\243A\"Q\018\180\0196Q(\219aY\247\165L\137\225\147\219\234\137\185S#\206\007>\247\026Sj\215o\218\006\0055-\000hM\247\215}\254\136\r\244\250\tM4r\234\189%\156\020h\172\\2\028\026\011\237\t\178c\211-\180\139@\026\191\019]\158\209\180\219\196\143\135\198\019k\242\025\005\235n\156\028\225s\167\155]\201\239\247\216\215\229\180\227\217@A\168\186\168\251-E\230l\204\237\224\237e\030\026\215\196.S0-F\027\152vkK\\{\128\030\254\020q@*\000^\1846{\1920\n\158\204\220m\200@B\220a\194\002\134\253\188\179\206\194\230\137\197U\145\254\190Wo9\193\172\006_ry\207\181\249\242G\135\206\243\129T\2425HPc/;&\210\208\197\151\"\146\195\249\188Iq\031\129\001\006\000\156p\138\145\165S\n(8_4\183\226K\001\211\230\209;\159\167t\132:t\024\249\130\244^\131%'e\146z\023ua9\173KA\229\143\197\235N\253|\239\254\"J\209\205\003\129\017\236\236\135}&r\031\148\176\129\199\136'\172\1608\014o\141\205\216{\138l1\247;J\189V\229\130Q\158\190A}\160\144$\\m`CP\189J\224\1495V\234\181iB\215k\141\132\232rR\229\178\156\172\243\173\173\127Y\n;\149\166\160\148\255\149j\211K\243\140\134!?j\015\rT\188f\226\254R\242\180\140\158\128\028\222\185\230\193\t\000q\255\241\233\205\229\012G8,\019j\184\169\193C\178)4MH_\014\184\208\165\166\026\241.\255u\217\246\138&\016\241\1918W\2176\0199\228\128\165\188\132\023\024\029V\127\132O\011\215\227\204\210\229\202\186\236:]\159\187\148\005\189\1863q[0Rn\017>w\215\242\192\217\167\241\196:\137\b\0056N\180i\136\155_\182\222\015U\031'y\202\215\221\0267X\1583\235\181\151F\141P\191\137\253T\250w\175k4\152\183$\164\157\002\153@;As+{W\218\190nl\182\020\221\002gX]\184\189^\230\188\169\184\129<(\219\004\218 \160\218\172\026\176\015\1296\019\023\007\001\241\144\251\204\144\"x\rw\184\182\003\248\227V\207Y\145\2394\226\218\204\252(\133L\004\r\159V\170\219\201\003\192@\000\005\188-\024>\020\024\031?\rz\232\245G<\004p\002j\233\220\160E\1432k}\203\007\183\211\030\230\234^\030\244\014 J\001\211\031^\2037\233(\182N\000\019\022\148\158\205\133\140\011\225\153\146\213E\218d\234l&\209\129\031\251\246f\218\243S\187\137t\1302\139\172k]c\139\237\236\015\022\233\180\150N\174q\149#N\159rhk\180d\209\248Y\134V'\001\005\145K\002\151\198Z\132N@v\252\2511zn\243\164L\028{V\0298;\206y*\138\233\253\244\174\240\005\028a\181o\\\018\198\177\015\221\214V\244+0\247\006.\218L]\000\156\018~\248\141\030\154\138\221\175\226s.<\236\128\145\183CS7\135\156\168\225\000\211\135\179\183\186\141GJ\181\193\243\1778\216\209\156\171Y|\186_\149p\182\243i\021n\028.\243\224\212\211,5\211\150^\163\137\246\151~\179q\216a\163\230\155\156\222\149\014N\183\238\232\129\230c&\016\"D&t\144\227O(A\225\144\000\021\236\018 8\015fB@jSR\026\249Gr\1976\023\159\b\170MH\t5\197J\164\137\241\215z\158\250&*\028\140M\231\\h\216Q\163\240\186\000\241w\187\134{\1441c\230\005\203\248V\243[\255\190/\211\133\134\203:\250\t\191.U\181|\\>Ts5\157\252\141W\231'\129\218\176\177P\192 \176\151\026\\\240\202\231\1552\185\183\183\025\026\245hR[\213\028\189\134\245\134\128\130\006U\181\233\210\012*\225\018\157TJ7\166]\241>Wn\232\r\189B\131n,\220\171_\171\218\216o>\144\2354\205\000\238H)\181:-\225\015\227\170\168>9wBP\219\146\222\\_O\214\159\178\136M\130\004\234Q\210pA\211\165g\211h\220\237\224\209\169\226\220Ry\210Fuq\211\161\163Nm\238@\024\212P\248\136\161W\133\223\226cc\227\164V\212\177\219\028\185\133<\1357p\201]>\174+\250>$\232\162\254\138\005\247MFi\247?\149\015\248-\251\255\207\183\222\129i\236\193'#\001\004wu\221\189E\239\146M\194\158\024\225\248\209\226 }7~\170\197\216;\018\128\127|\152\251;/\148\199C\240\130\158\229\027\156\188'\230\214\172z\027\160\229\026 \249\227\n&\161\211T\165H\"8N\202\133rC7\199m,+<\208\158\140l\142d\2030<\246\147\130\1435d\221\250JU\254c\011jmz\004g\190\022\250H\171X\153`5]\232*y9\192*V\174\155\187v]]V\163\128\164\129\206\001\028\136]E\248\171\249B\025\000\242\189\208#\251o\132\218I1\030c\157m\164MD\218D\219\223\189\004'\005\230vM\000 1Y\150\247\0147\188\183R\146v\175\180\133`\1891L\027\181\000\180Q\250\192\196&v\024\231\137\021\170_\178\233\21459\151J\164=\1977\206to\189%h\134{\221u\025e7cr-\214\188\025%++\179\142\022\002\170\166\170UU\021\193\000*\005\185\244\029X\173\028\149\172\169\012=7L\128\006\220gd\133O\229c%\186\227[l\222J\245\1514\144 \n\239\224\001\232a\171\031\205\161\221\184]\029\135\234.\139E\174I\177\168\153\242JiM\182Q\151\250\\>PX\197\195\177\226%\131g\027\n\178\186\138\128\004\195\170\172\134\161\151\128\162:\184\171r\215\".\222m\023\024\209\150\205\218\222\228\184\134\248:\199\196m\209\2249Q\031c\161\185\246\251F\237A\197\152\250\152\187\205\255\002UM\164\192\172\198\218\1485\158yd!\240B\217.\247\131\255\237\247P\149\243\220\228<~\242\198\253\197g\209\183\236]` \014\030\206\250\149\135\172\227\007\163\130$*\132\175i\127\251\243\153\1661\001x\160\195atKbq/\231\153M8\136d\159[c\156T\015d\166\207'\208D\203\174\127\252\189\003\017\168\001\162%\016\192\241\017\030\159$goJ\027\146\018Q\205\005\b\222\b\016\155\158\134\153\143\223\156R&\2363\233\t\241\174vF\190\160\018\228\159\012\021\1398\184\215E\028\149\1462'KJ^\185\020\251n7\166\004i\028\161\206\195\1919\228J\245\1814\131ZE\244\167\204\131\188+\190\004\238\025%\0306\014\160K\012L\203\171 \025\176q_\163\026\214\175+\176qF\241B\196R\016f\164-\220\"\186\139)rpw\2549\1446\144\158\252@8\023\242W'\180\235\220\b\150Mqu\165\184\152`\026/\199\024;\153s\186\206m\200\t\023\237@\231*\227\171\163l\174\167\227\201K\144\251v\031!\1915\151\027\210V\139@\027#\024ev\144\144\168\248iP\153\202}/\233\158\172\\e\172\246\204\229\240!\179\203\2005\144\162\196\229\185n\201/;\178\024\029\184\253\021\007\173\253\160n\238L^\127\150XY\237J\242\t^\167\166\202zLV\219\004\202K\135\182\174\168G\192\200\147\031m\154\011\026\200\136\246\019(\228\142;y\214\207\140\200T\011z&\199\024\139 \246\1770\215\198\018\193Mz\178\247]\206\235\203\156QM\210\014\012\001\200\149\014\127\242\r1PT\170\170f&wm+k\216q\177\168\142\202$\248\154\027\147\012l\193\137KlH\151t=9Kpq\243\2148\201b&\249\227S'\201\005\217[\230\183\212O\240vWc\233R\245\020X\149\133\226\221a\235\245\206\141C6Z\222t\132\027\135\0295\b\165\133\189\244g\237\237\2178\224\181?\180l\145\208J\153\136\165t\019\219K>b\222\134\178-\n\136#\028O\028\147}\168\255\2057\218\212<\0243\163vp?oA*\244\255\240ih/\242};\014\215\162\196\202o\191\251\146\187\159\127\014\192&\152\245\221Bc\178*2H\152\182V\r\001\179L\148\153<\024m\136\182\030\140\187\004\2155\002\177\140\"5u$8x\190\154\228D\129:\ndd\141\149\232\023\195kv\029\133L\198\014G\202\158\194H\238\172K\197%\145d(2'y}\202\193b\\\018\226\222\202\162w\215\199{\135\186\022bWw\127\014\239\223\156\235\181^\220 *QZ\189{\248\227\158\152S\148Z=Sz\017\127\160\022\147\253q;\166|[&\159O8y\014t\026\147,~\255\200\2369\005qL\227{\2221G\201{\031~\215\206\142%\249\194\195%\141\150\175\131(G\170\132o\176R7[-6\139\190\152\018YyH\227\145\204\240q\029\237\174\173\177\203\n\173\186\229i\223\244<\244\136\162\152\176\132{v\251\144\243^\023\151Z\248\011K\226x\172=\181\240\179`\006sj\227$\141\211\139\203\006j\233\227li::before {\n content: '\226\128\162';\n}\n\n.odoc-search .search-entry .entry-comment div {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment p {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment code {\n display: inline;\n white-space: nowrap;\n}\n\n/* First level titles */\n\n.odoc-toc>ul>li>a {\n font-weight: 500;\n}\n\n.odoc-toc li ul {\n margin: 0px;\n padding-top: 0.25em;\n}\n\n.odoc-toc ul {\n list-style-type: none;\n}\n\n.odoc-toc ul li {\n padding: 0.25em 0;\n}\n\n.odoc-toc>ul>li {\n margin-bottom: 0.3em;\n}\n\n.odoc-toc ul li li {\n border-left: 1px solid var(--toc-list-border);\n margin-left: 5px;\n padding-left: 12px;\n}\n\n/* Tables */\n\n.odoc-table {\n margin: 1em;\n}\n\n.odoc-table td,\n.odoc-table th {\n padding-left: 0.5em;\n padding-right: 0.5em;\n border: 1px solid black;\n}\n\n.odoc-table th {\n font-weight: bold;\n}\n\n/* Mobile adjustements. */\n\n@media only screen and (max-width: 110ex) {\n body {\n margin: 2em;\n padding: 0;\n }\n\n body.odoc {\n display: block;\n }\n\n .odoc-toc {\n position: static;\n width: auto;\n min-width: unset;\n max-width: unset;\n border: none;\n padding: 0.2em 1em;\n border-radius: 5px;\n margin-bottom: 2em;\n }\n}\n\n/* Print adjustements. */\n\n@media print {\n body {\n color: black;\n background: white;\n }\n\n body nav:first-child {\n visibility: hidden;\n }\n}\n\n/* Source code. */\n\n.source_container {\n display: flex;\n}\n\n.source_line_column {\n padding-right: 0.5em;\n text-align: right;\n background: #eee8d5;\n}\n\n.source_line {\n padding: 0 1em;\n}\n\n.source_code {\n flex-grow: 1;\n background: #fdf6e3;\n padding: 0 0.3em;\n color: #657b83;\n}\n\n/* Source directories */\n\n.odoc-directory::before {\n content: \"\240\159\147\129\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-file::before {\n content: \"\240\159\147\132\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-folder-list {\n list-style: none;\n}\n\n/* Syntax highlighting (based on github-gist) */\n\n.hljs {\n display: block;\n background: var(--code-background);\n padding: 0.5em;\n color: var(--color);\n overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n color: #df5000;\n}\n\n.h" - let d_6573d83a382edbb1785a8f45c85c3975 = "\197&\159\202(?\2397/\139(\146\186\151I\172\241\191LC\150\031%\141\133\157\220\190\014!\151\129\204\239/\138H\138_\187}f\246\186x\173\252\140\176\002\174gp\133\250\193\168\248v\024.\014\007\137;h\246/\236\180\239\216\194\173\155\191b\r\229Co \193\155\127\161?\222\006\138?&o\221\212\197\134~N\1504<\229\178\174\182\128\241`\165\151l\171%\156\165\\\248\2043\201\17930\183\148p\1807\228\240w\141\007\173W\217\220\167u\227\186+yC3\136\0187(bl{\184K\228q\187\201\170u\179\027\024\181\205uO\185\236\171\173\227\193\202\255\255\227\157\224L\017\006:\219tD6\178\141\179\173>w\166-\224*(~.\027q=\147\206\170\160\174S\021\028,\004\012`\218\132\199\151\024\229\028\166\179\220\2404\13309\127\021^\007\153\005\205L\172\004\244\171\250\181(A\162=Q\150\244\210\011]P\132#kq\253W1\229\007;-Q=(I\160\207\015n\191\n\152\0296>g\2462\238\022\184\187\250N\001\165\002\217\184\219\145\0060/\019\130\230\127]>\197\144S4'\003\222\155J\191um<\151\181\200\005Q\174\205\143\030\183E\167\207r\231\nF\211n\\\005\005!\246\018\137\021\241N\215\187\011\230\141\"V\229\1637\193\213E,\246\162\219\224\150\148k\159\239\011\205\190z\199\003s\135\232\148\246\180\128,\135\003\240\002\197\181g\159\172y\140\031\226\204\195;\196\219\004\213assxVf\194\216\155\017\173\158\247o$\251g\243W\139\255\214\255B\148\139\246\027cN\131\139\227yJ\210\212\153\\`{\016\142\133\151>\204\179W\207X\027\147h7\189\030L\146sxJ6\202\200\205\175\219;\204\166\142\174\026\253\199\023{\023;A\178]\229\140\226\244\001\179\133\031n\207\169\207\149\2327\199\249\180\190\1934n`\157\201\191m\168.\219\221\236.\238kS\\\190\214\187`\241\172G\192\197\219<\133\213Ve5S,\213\243jg\242\207\017?\202i\230\130\028MDG\"\167\184\222\129\173\219-\186]i\249t&\223\147\194\238\158\183\134\255j\234\239\\\206\179\025#\224\162O\211\2197\191\150;2\227\025\231\207\203\004t\238\159\240\"\2112\253I{\195\148\249?\184\018\163>\191:\165\1502\182\242\212\225\006\193\172S\022.=h!\224\195\180x1>\221\247\193\160\255\233\131\240\171\016\171\139\241}\184\002\207>Q\146k\149\218\224\228\192\204\128\237\241\241\127z\235\007\240#R\241\221\249x2\023'\241\003\024BS\019\205x\185g\180\220#\202\202\246hAi\177\189\130\190[\022\1670=\199%\\\127\020\1583\177\003\248\201\222\250\249\248]\177\244\200\0161\169\238\192~\130?f\1596\127\221\229\1308\176\156&\161\137\251\251\212W\231N\134\231\154\193}\135\222c\175\237\r \204\131\248\159\190\189\255\219Nh\232$\129\134R\202A\162\145\195:\222\029\143f\191`\127\2318Dr\189=\138Z\209E\012,j0b\016\252\241\251Z\226\127\155\193'\162\223\140\204\140\193Oa\2449s\005\171\161\197\148\154\167\142R\199\217\244\n\228c\030\022R\001\t,\003fz\011D\2070\149\128DW\142\224\138d\r\029M\166\240\213\0039\243s\0260\138\194B\144-j\182\251.\128\000\004\000\132\191\174\r\242\217\169\222\222\031\252\2428 \130\155\244\012p\255*\245\1791\144\203\158\195\2248.\017\224\030\254\220\213\025S\245\143\145\024\195j\209jC\140\029\248\208\159\196\193\230\241\211\229\0119\164\144Q\240\204[\249\159\232*q\160\217?9#rl\011\216\198\197N\177\216\187\153o\209J\184\134zc\018\238\247\224\002\201j%\214\202'\167+\198u\242E$\173h%9}|\176\249g\177\023u\000\150\255\220\155F=\1381J6,\151h3\216\003`P\235\167\198\141\229\0202\194d\140\205y\181cx\151\147\245\011\192\150\155\195\174\219T\219\200\\;\139\172\"\219\210L\149m\210\177q\029\223\210\rZ\011\140\241\214m\138$\169\200M^XOw\156m>\231\158B\229j\223\161\169\147\178\017\1953\2013\003(j\209\160\030\130 \216\171k\181P\151ymW\180\003g^\186\007\030)\239\236\147\241\\\238O}\195f\254\185=PDyyX(\153f\011l\127#z\147K\129:./\157\nE\193\2321\025\199\242\159I\158\165\188JN\136\"\005\182!@2o\241_\149TJ\148\143\128\236\n\217HA}o\\o}\193'\241\019\153^\165p\175\177\191+m,\213\200\027\183\149\179%\002\132\1816\208\214D\167n\165\200\239\128\252c\025wp\206{%\139\188\0199^6>U\176\023\000\176\250\155\230\186\254\197\141u5\205sE\017\236\150\025+G\135\255k\012x\212\158\168\218\249\17224\029\229uk\231\224\244\217G\242\"\234\2312\252X\014\131\213\182tI=\231.\132\224\184\197\130\019X\181\014Ng`:\134@wS$&\186\219H\2374\201/\238\191\200\195\027+\201\254!V#\150\171\199r1V\251\240\146&N\173,\172\182\1373\0124\002?\022yS\199\1347\006qp\238\\Mmm\141r\173a\160\166\134\208\180\166L\240\248O9\171k\028\\$\215<\192\238\002\154\151\227\011\029\198\217\179\178\173\199\2135k\150\219\173\226Q\215Q\131\235'\148\235s\019i\163\171:;?\186\165\\\251\030{\218\254\189\211\012\186\145;\1742Hw\198\193\137\250\005f\207\185E`/\202.h\205\0308;\161\220\197}/kg\182\020Qs\200\2202G\206W\148\188r\005t\152\134,P\170\014\168\140\190q\160\218\181%Vo\225l\029\151\250\225S\217\211\015\129\219\029L\226\140e\023[\187\215o\001O7\140\217\"\190\233*\209\b\238EJV\251\141\232M\\c\187\2114\197\127\000\nv\156\017\234!\b\218\232\213\251\194\029\224\151o\2314\024\238\223\167bb\168\181\128\161a\142\237\203/5\022\139\2244\174\127w\198\213U\213\212T\209\249\128\161\015\207\029\171\229\174\020\1428\015\209h\1873\".Bg#\233\016\147C\127i\176\207\2336\148%T\030AW\215\001\183K\252`w\131\186\213(R\241N\015\163<\129\002\016\135\t\129d\220\184\012.\189\002\151\\\198\007fr\224\000\190\163\250j\2479pz\220\157\201\024\012\b(\224}\224\r@\004\128\177;\1477U>y|\169sW\r\030\12893o\254\196~\183\169e\212\027h\025\132\151\\\006C\017\136NG\188n\251\136K\001\127\167L\163\159\023\156?]=\211\187\227\243R\224\157\251\025\199\198\1425\236\146\2362\212\214\030q\133\t8?\188\250\015\139\146\202\227\\\246q\229\248qk\162\193\135\127\028\203\184\234\024\255\145{\220\186n,\248\243EV\224\186`\239XP\182u\029\198\229\161\135\223\201\135\183\128\188)\216M\148\1851\206\2301\207\173\223I\215O\165ug\183\142\202\174\217\200Dob\204#\243\206p\184\243\206\028\001\230&l\003\147\179yT\225\221r\214\157\242Q\133g\183\018$\029J_\212\208\020Z\028\030k\181I\151\1327\133\026\022\165C\224\229\140\182p\136=\161'GcK\204\243i\152l\130\205Q\002Ey&\222\025\001\150\198p\228\016\179g\014\141\230+\238\254\173^\160br\187K3\200\238\b\240\242o\192\133A\190V\018/\163\1791\026\204\239\171\202\234\2302U\130\210\132\132\178YJzS\012\232\132\025\211%q\251_\140\179\170\178\2351\004\134`\022\r\130i03_\147\224\213\184\157=\192tN\192\029\249\250\r\155\166\137n]O\n\169F\195\007\161\019A\031\228m\128r\027 \253\206\2193\1841\169\153``\1985W\186C\225\180\179_\250|$2\0303\191\251z\132\139\158\b\157\012)\141<\163\225\029\219\251\193\233\150\235\220\213Pn\003\156\219\000>c\134Tq\232\250\196k\221\198\185\162\185\246\165O\237\1613&\230D\200\253o \024\243\158M\152\025<>-v\215\029|\1370,O\156\171\233\218\189uB\216\143\169\241\239\149\240\214\214\027\189\182Z\222tVt\129\200\173j[\185\174o\237\158\219/\214\146}\177IC=\017\187N\b\166\217c\211\014\139\235f\173\171\208\184#\nD\191\236$\218\231\250jx\253\020\184w\163\197\218\235Lvi\235\1964\154\017\203\019\229\217\232\204\221\006\187a7\139n\021\229\229aF\154|\190\205\206\194\133\220\176rx\140:\151\227\b\141\243\218\002y\134\217\163{Y\236=\134\217\129\188R_Y\130\ru\208\193\253\027i\193\204>2*\166\192\242\173\158\147\154\231\181,Aa\152\2171nj\175\199e*\203\172o(\162\177\247e\150\153<\174\222qS\153\0290\140\022\232\199\\y$m&w\250b\157\133\029\227V3\134\017\181\224\2298\198\234B\223*WU\229\135\179\204{'\015Z\248\236\161\196>k\222\231~)SO\003\157\215hWQzC[\202L\184\235\225\193\173_\145_\189\183\183\247\183TY\234\196\231;7\158\1869_0\255\0265wQ\237\169\255\134oZ\181\188\251S\181`\220\173\213+p\188\252\1636\200\2022\187\019\147\204\159h\249\197\145\132;\163\233\129Hl \b\019\014\188\149\171\1924\210&\147|XPr\213\143\199=\n\196\144M2\189\140\147;\222\185j7\192M\004\145,\1591G_cM\174\204\243YLz{|\014\131\182_\n \239\005{\162y\222\212T\147\211\182\141.\145a\194u7\151\252\201\229\134@\2394\200|\248@\141Y\250\186\207\195\156\179\195\235\213Vl\000\1855H(\158 w\188\158\018\214\018\219\172E\160y_\254\205\163\187o\192\183\138\194\198\030q\003h\207nht4\156\t\028\213pcPI\190\250\214\233L\217q\185\222\000L\214\226\200\205CJh\199%\171\rO\206\134l\129o'3Ta\246\250\254K#\029*zs\203\221h\172\160~N\173\160\249&\031\135m\226\194z\b\137\166A\"P.uO\011\174\135{\196\153)X\243G\249\139\138\231\012\003\201,\143~\255>k\202\140\142jP \016I0\138\167\015~\220k\149\179\b\195\2344\141?\167[?\186\018\181\213\146\185\218\021\001Zz\158?\176|\145\128-4\140p$\178\163S\207B\211\255}\140\233)\140\211]6\n\239\138\002\131s\018\184-\216\201\r\226\224\153\228\217\217y\023y\241\212\202\197\022T\128\201\\\165\253\230\003;\1855\203\014B\208\153\154U\019\007\1279\223M\142K\019\177\193K\239\150\167\194c/\198\222\011\176\172\229\191\242\031\006\023D\223\021\000\b\026\005\178^\241\185#\143\167To\207\227\017@\028\012\220\233\162\155\179\143\139!\229\228\229\142&\195\229\129\180\155\240\191\216\130~\176T\218\219\221.\206\157\021(\167G \140\031\130\1652x(^(\017\146<\178\024/.\194\139#tU*\155\027\133b\145\240E\"\132\219j\164\165@\192\181\240\2286\b\229\n\181B\222\226\015\004=\028\020c\0069x\016\216\131\000\231\004\153\224x\161X\192\238\141\252\170rK?\137}\168\029|\019\138\181\212D5\223_\200\011\183\141\255J\244oK\233S\1895i\188\150\200^\182@\\Dy\191@|o\249\005!\2130\159E\143@\230\025\140\012\138\192\204\215\194\142U\131\007a\005\157(@FQ\179\145z\251}\230\011\248\192\219G\225U\240-`y\203\129\154\224\239y\t\248\249\241\227\"\156\005\195\198\248\227\1772>\224\181\021!#c\207\137\186\209\021\005\2172D>de\181l\250\155\179\189\165Q\153\226\251v\031\239\143w&\252\248_\026N\1642\r#\027u\001\149\000!L,\149]\247O\201Q!\202\140W\231e\248\204\011\132\134\186r\201\002\222\164\144\215\197\157b\1784\133\247\253\1835\153j\004\"\183\212N\250af\225\031\155\138\128\163\199\148:\170\029P%Ta\234\196h\144\148E&^o\142\215y\237x\154\130M\255m,F\141\140\t\198R\\\215\200X\188YFc\1667XO\153Z\025-\224\199%\230\240,d\025\143\001\136\193J\160\219q\"\nS\188\138\r7\231\135\235\205\004\226\193\155\227>8n\2301\143\179Q\150\148W,\185\193\128\179\1444b\140c\204@u\245[\139U\209oX\006c3[7\168kh\186\029\230m\146\201gm7';]8h HY\161\144\228\254_U_\153\196\rK\025[\172.\231hxpy>\007Z7l\165LS\191\197\025\223w!\029\014\242)\000LUe\156\184\152\193XB\200S\152v\205Y\248\231\211\219:\001\1598;hp2\230\182\233\144+\217&\006\165|t\019\209c)O\161/)zIx" let d_660c0a9ac6b1a9b2cd6b6ff6cf9e5ed0 = "-\228\005\177!{\236\146\199@e`J&\214\181\139\235\174\b\214\178\183\183AxG\185\155:%D\018=x\240$6\242\186i\225\016\133:)DD\168\015\139\219\162-\139p5\148Y\177\017\129\023\208\191\219\236\178c.\211\209\174S\218\221#9I\168U\179\028N\252\017\222\143#\028#\007\239r\229;\247\236{\212$\174\165\241\188\187mZ\r\239\168\171U\183\139\201\203\242\022\187\145w$\186R\178\243\156\2123(8p\214\t\153\251\149\233\155m+\165\219;\029\023X\022\181\003.[!\b \214I^bb\232\003\249\029E\255\195\132~O\210)\209\211\160\248\185I\135\201\192\bH\254c\129\246\244\"\154X\021\000\148@\014\152\243\026\171\020\139\191\213\rL\233X\006O\007EhG\015-\138\237\227\002\141\031\174tN\024\\\249\138o7J:3\232\182\181\170\197\174\129\130c\020!28\nt\220\145u\228\178V\187\017\246\012\001\241^i\181\238z\172U\222\197\201\254R\179\214\201=\143\162\166\134\205\148d\021\181!|\231o\200\"\210\192\020l\172\027\231U\190N=\191ZQ\172\221\001C\028\233B\160\132q\168*\222\2418;\017S\170\179\212\254B\156?G&\160\184\253\021\239\175\199j\247b\139\212\2549b=^w{\160r\020\209\197\\O> \\$nE\146\198K\026P\016\180\245\139\r\134\149q\028\016uc\031\025h{\250#\172Y&\145s\020\171\141a\016b\018UF\004j\147\1623g4]\025\154\023\006\148\136\241t=N\1432\180g\136=\212\225\163n.$NV\000\185\171,\128\n\146\155\031\154\211\215>\1481\225-C>\1484\2185\016\228FU\219\154\002^\023>\178\170\029)\n\128!\238\233;\t\201\219e\130>\246\217\145G\246\020\254D8\181\170\027M\007\211S\169\012\227\218$\190\246\021F\017\165\175\217g]iA\218C\002Z\222!\015\198\151\132b\192\020\197\247\174y\002\209\133\149\160T\021\031*\1850\153\217\236\204Q\021\029#\181W\163i\2415k\248U\005\193\150\003G\203\154\153Q\132\153\159\177\248\193\221\140:zf\227f\138\173\\\155\226\252\007\176\253\135+\247\144G\190\142\213\150\021\129\145\1879p\nm\156@i\206^b\159z\129C\150h \151\170\202\162\157\026\014\153\148\148\189\239y\236\144\252.\203J\011\002\207\229\228\024\014z\210\189W\169\228\212\012\140\1565t\2447B\191-l\241,y\183\156\023\127H\205\208a\198\177\240\157>HBqa\179\158\223ei\145\185\167\014q\226\231\223Ul\140\189\169k5\218\019\188U\2272\189\0221\1806w\157\141\133\233%-\136\189\209\2042\216\247 \204^b:\018\234\155c\233\141Tt\241Q\139\150\012\188o\201\152n\151\128\154\178\195C\005\135J\179&[\230\161\142v\030uO\011j\243\141Z\133\151x\1341w\186\183r8\148\244\005\006\007\209\238\129\134\n\202\208<\187=\233\175\007\019C\239~\189\253\246\163o\184.\249W\222\134K\175\161\004C\246\006H\175\156\021\n\238\176\237\1871\254\131\023\026\247o\211o\1660\196\191\168\172/1\031\160\245z'?\146\1792`2\252\198\153=' \211\202_\0128\157|\249\183\199\163\236\192\\\255\243L\0249z\019:+\147\159\150\231\244]S*\206\127\220-:\254 \157\186\160\002\197\249\154\140Ir@\220\147\152\205\029T\014\191t\005D\137\187>\138\191\153\200\197\137\161\t0\174\172\b}\011t\162)g\137f\2520\1923\231GS\136\145\164\207\200\147b\152[\030nY\166\1885\029\178*\007\228\r\217\181\253\017C\160!.\187!OT\025U]r\187T\196\248\220,-\255=8\022\233\248\253\138G\244\183\154\007c-\158\219}b\233sB\207\196\156\168(\189)+\171#4\016\184!\134\005\210v\022}\019K\216\tg\209A>\202e y\180t=\170\252\025T\211\234IL\003*\018\025\011\162\145\139\181\030J\024>\154\031\215lA\181\209\247\003\237\207\160\222\229\028Z\143mG\134C\029\2332\216\143[\255de\222\164\173\192dN\224L\026\007p\245\166tE\238\149\151\198\150\207\174J\156\162|hX.}B\163\156x\205B\250\180\231\139_\172-0\224Mj\207Oub\132\1777\183\142G\006F\238\154\147\"\220ukp\002\137\253\014\142\253\184\128]\207dK\130j\019\003P\208\190\248\135\254'0\189H\247\196\249\207?\128\244B/9\127Y\187\140\244\234\188W\000\245oM\184\241\137@\246\234\229\238X\247\184\183s\237\238\247\223\016&\020\230\134\t\027\159S\023\163ZF\230\131\026oS\168@\217\146\225s\024Q\161\180\1603G\240\189\020\129m\200\195\021\255\003\129\222t\011\2075\003\248\175y\139z\150\rD\152w8\252\024\143\248\180;Jb\234\028\021rCS\154j64\135\225\005\172\210\129\247\192\175\002\154W\181\161\188\241\176\163\245\248c\227\153\006\213#'\203\017j\173\183\187\250\249\179\028e\012i\213\2018{$B;\023\158\1416\2154\232+*\163a\224\214\2466\174\243\170\131\\w'X:\011^\202r\159\0215'|\235>\023\155|\1745\015A\249\031\146\211\142\018\196\186\r\147\182\1455w\194\189v]\220\179t$\161\004\219\184\198\198\182\193\128\222\018u\170\212\135k\000\\\255\226Q\1692\204]\192\r\195C\130uM\026_\168=kK\156\158\238RG\228\018?&&\234\234\127\254\165\021s\243\024\235\250G\183\150t\161\172\249M,}\181S\169O\214\2195\160C\247zmKP\204\0020D/\002?$\183\254\137\253\142\t\252\237K\243\178\154PsU\141\209\216\217\024\162w&\021\193\160\174\238\248\200`b,\233\030?\235\158\170\015\244\190iO\023\140W\235\219/i\152l+[\2261'\003\168w5\031\237\rU\025\191\182\215DR\178\007\211\030\027\231\015?2l\242d\175\134\178Z:\136R\166\222[\131\170>\025\215mx\229F\025LYCaXuu\254~MR7s\227\247zVm\224\025T\136b\"\147\192\184g[\011\219\138ca[\213\237\208\154\182\214\220\021\226,\189\210\155\140\012eR\018\136\187c\011\163Ia\177\231\021\251\254\164y\170\155\154Ld\136\218?\181\"\186\028\141n\215\150E\240\025\174\000u\129D\222\"Ap\007H\213\197F\027\253\198\247\213\137\247hL\230bb\169\234\206\012\220Y\190\1819\210\018YZ\206\027\170\208\238o\253\138s\169>0\152\217\017\023'\197\011\237\192,+\249\n\014\229\1690\018kwi\183\238\237\237IO{$-\244\227\026#1\241L[\158\216\208\149d}\178\237}\028\182\189\135j\005Z\158\251\002\006\141W.\167\171G\138 O1\\'\021u\189\167I\138\1358\007\025\021\184j\028\175\153\184qgyK\157\134\184\181\245\138zO\163\127\160q6\203\171\245\170\006\171v\183Uo+'\245Hao\b\022q\243\164E\240\132\214]\137\167\178\023\145\129\243\130\141\163\004\166\201\\u\234\165\025\024\169\177b\151\208E\212\167{W\027\\\014\167M\143.\241\147\208'\241\168\011\149]:\007\193\135\161\224\150\145\216\251\203u\160\006+B{\231e\230\139\179;N\017\135Z!\194\166\168\145\178\211\169j /\217\137\138\246\0155R\253\232\213\191t\nqx\183\238\198`_\021\220\142n$k\164\128\"T\254\181\159\145*\185H\225Q\218\140\244\129\200\155\247.\246\249\030}\222\021?\200\237s\167\028\14131\159-:fgm\012|I\015\175\210&2\1789\198^\1379\161\246\007w\155p\149D\254~0\231\230\158gq.n8\184uGk6\154M\187\028-\205A\193\022\t\1784\158\255\226\139_\166\239\174\004e\022\236_\179\145\195n\253\1371l\016\162\020\127\220j\018\249^\169\133\159\2266~:\2274(\004\022\249\203!Of\019\218\018W\025h\006s[\157--\023\247\016_\154\221\187R>\152wn\016WyPk\253q\200\128B\127\200:\231\133\176\202^Y\re\152\nE\030\153\002h\217>\211\027\173\019\2450\141pf\133\185\170\160\232\187\197n\149\193H\225\241O\154\b\200\143\023Q\183e\142f\189OA\030\005\177M[Kak(Lmm8S\181\162V\165\017\193\167\152\2377v\140\213\024\196\160\214Fl\143\178\159\218\224\176\178$\020h\018B>!5F5R\234\230\022\001\163\227\184M_\152\007\157\t)%F\137\168\234\133\n\138\197S\223l\153\n:\237r\217\147\178\244\236\178\014\231W\222\147\145u[\164\176\197]v\208G\169\187\134\233\199v\148&\220\020{Ko\1891\b\027\133:\007\1687\007b\018\002\235\196\181\216\204\018\198\"\193)\130\173\220fb\tG6*Gxt\140\205\177\254\031\255ao\233\128\t\166@K]\178(\139\182Y\238;\030\232\240\146\154U\208\134b\130R\1298*\197mG\149BlEB\187D\1742k$\252\218\237\"\024\224\233\247\156\233\246\245~\023\1861\137\156\023#;\181x\131A7O}\1952qx\031\137F\145\252[\026\157\221j\157*\219\248\232\246w \242\163\221\196\254|\191\153\182\026\229\252\151\014#\139\252\175\243vFw<\220zW\196?\242\189\226\231\246\171\155\031\251\172\195\004\021\252%\252\207Z\243$\007l'\184&\205\140rV\130\132{n+\158\188\234\236y\152\131\206\197w\245\146Q\189\207\205\216\140\166\014\253dk\173\223Qa]\216\209M~g\203\213*h\158UD\239L\247\177\191\225\232\205\187\129\206G\201fd\246\188N\200z\141\012\012\135\007\160K\253\164\014}\233\242\0157@K!\157\005\238\226_\167\t\240\143\020\015zms\022\180\167\233\202\219v\t3\131\236\232\222\140m\195\127\t\027\238\224Xm\130C[']\191\006xa2\019\238\226\252\015\2471\175J \133\219>1\229/\146\151\239\250\177\254 X\240\162\147\1630\176\133\231\249\188:\179\014\134\129\177\031~\189\006\166\195\188\169\175\135(\229\166%5\191\191\248Uy\172y\221/\127N\151#\131\229\190\160T\205t\145q\015#5`*\239\159\007\143~\218\158\137I\158B\210bJ\191\127\159\028\1651\211E\139\211\219\229\006\213\226\142\215\022j\164K\145fk{\192W4\020(24\014\205\231=\247\207b|\217&\224\173\030\209\191$\030\166\178\233\200\242\158\165\178U\203\218\027\248\191\007\185\216\195\145\235\129\195\158\224\157\158\246\150Oe\141\0311\179\189\206N\157&\206x\012\212mb\146\001\007\236\198#\170\249B\146;\169\r:+\172\252\155\147J6\211\163\t\007\179~\193\178#6a\181\199\196\200f/3Q\197?\029\248\150tt\196o\221\007\252\179\249T\161\212\205d\155{\251\131<\234\169\251G>{RD:|\255\193.p#\132" @@ -222,6 +218,8 @@ module Internal = struct let d_82e50be00ae24b186041d9600dcb0660 = "1\174\228\137k0\197\198Cp\201e\229a\133@\230\150A\1955\246\232\234\173\176\226\186\002)c\166\247q;\171\244\197\151\158p\129\204\154~\171\237\r\185\233\017\253\176\157\199a\241\n\2522\143\255S\216\021\241+Q\227np\160\019\134e\190\130\028\143\238Z\164ZBi\011\214\246\129\2407!\131\133'>&T\148\145\149\202H\155&\254\219OF\1660\156]\197\135KKq\255\196\139_-\200\201\163\020\\(\216\226I3\031\238m_ef\160\015?\007K\154\230c\011k\139\023h\023\226\165c}\021\232{\004\252\249\003\251\1519\030\222O\030\166o\173/\209b\146/\000\151\188\018\231x\163\248l,\253,\234\211v0;\183\248T\t\233\149\190\168A\n\147\2440\161\200\230G7t\nd#\205\144\251\003\165L\229Y\182\196f\184`Rx\030%\219Q\2428\201\143~jm\194\ry\165\178&\021\129a\172P.\022\185\219]\1639S$eh\018p\157\237\t\237 \003\001\029:W\214\236\233eN\165t\247[gK\151:>\143\2470\015\025(\1573\203\012]}\234^iQ\227\235\134\168\023\184\026t\206q\234\240\253\163v\174\029\254v\241\143\214\156(|\145\188|\182\183yA]\226\025\141V#r\231\005\221\244\210P\170:\132\231\014\183\148\167\220\255\237\"WTr2\232\215\030L:\004\221\2254\128\164?\131\135\228%\196>j\2286\143~\149<\024\168J,N~\132#\196\018\011\188\156!\232\175d{@\248\191\227\170?U1k\002\184!\2403\198dZK\006\244]K\206\196\251\0274y\021Q\217vo\138\007N67\140)\031\210\011\132]\198\138\240\214u+C\248\142\176$\191\157\245\194\202\132~\245\219J\189x\223\027T\187\178^\017\233P\253\190$\166\027\015=\140\252IiC\218\232\205\197\001p\134\163\r\232,\231\187\169HugF\191=s\221\186\206\226-Qo'K\210\179o_s7\174ZV!\214\171/=\202\199\004|\r\132\188\145\223\017\153m_\144\139%!\222\188\253\227\011\n\"\189\160\252S)[KzF\155\179\016\206wp\198\230-\233QD\003w8\251$\238\031\147\129\016\200\229\201#\234\137x\006\154\016\136Tl3\186h\160L\225\150\020,\136\217\243Y\148ac9\176\248\175\197\164\250k&\194\197/\252\165\003\160\r\223PTV\254\181\137\155\188\220\212\223\222l\024\206\150\188\017\189\214\231\163\027{\164\239\221\158\156\142\253\217h24\203\154k\003\170I\203d\223\150f\188\"\007L\248\144\b\176y\137\193#M\029|9\187w^\238\156\250\215Y\155\255\244w\241\145\199\153\029EIE\149\129\229tQ\139\161\140#'\209\173B8\253\015\1898{\162U\157\027\190\232\169f\191\211\248\r\224\024w\135\031\211%kv\152\247 w)\028yt\135u\006\180)3?\250\248\019\127<\133A+\178\251\233\226\188\220\239\026\196n\146'\142q\021\229\017\171\162+5r@\196\172Vy\1443\030p\173\017\128\162c\012\243\022\\\222\225\239\ta\234\134\169C&\"\217\149\"a\165\192\178\246\213\235\245\169\233\174\015!\016M~\254+\247\014\018\145\205Fp=\002\134\024 \169P\153\175KN>\011@\028Hw8\242\200a\200\151\r\244V\136^\250\201ZGD\226.\186O\136\144\236J\161\160\227w\0191\029oS)\022\22267\187?(\192&\179JT\007\030\018\000(\198\2307%l\187\164\133\0198\028\253\176nXYl\189\137\249=;\148$\005v\195\205\149W\136P#\nGt)T\175\155f\244K\023J\221\025\233Pr2\016\206\223\239\174\012F\182\129\132\002E\172\025\137%\006\150\133\167#r\146z\183\021\230\249\031\027+\165\025\226\161\142\197\t\015\229W\242\027\132hDC\161x\210\226\221\014S\184\237\165\191\022+\169\2221,\179\\\0236\165(\139+l(\012Y.\255?\225\242\177\196$\155\029\242;W:\155\209\163\159\138\2083\165\1980N\220\027\160\159\015\127\015\003\2072\129-\2145\130\182Rj\159e\181\131\218%\224\196\228W\142I\165\167YV\138\020\237\160%\188\t$\148/\248\253\254\019\138\209\141pffax\179$VhKS\0287\bMLFw\230 \225\233\146\2403\170\b\212\201,\002y6K\236\160\174\029T\n\017w:WQ\138\181\179r0\"\187@\171\165\021\148s\204\239\169\019~\248y}\137N\245\\$j\000\000\168\191M\193\233\133\222\003_!G>\134\192\2124\177\022\020}\195\229\151\246\254\188h\219\004zS\202\143_\134\141\161^P\229\155\206\171\171\254\253\130\217v\b\142kz2\249{\017<\156\229\245\237\194\216\211[\187\234r\135k\193m\245\216$m\216\129(\031\131fQ{U\205\140\253S\017?\194\183\0117\190\235\026w\174\000\192\150\162\191\146\246`1\231\000Ms\003Y\2510\166h\003\243\141\193\029!n\219\156M:Pu\176\244j\1954\023:\180\234\200*^?*K(\011z\203%\132\171,\r\233zA\141\2342\137\140\012\243\180$=\016\176\216\166\031\235g\021B\181\156S\253W\194\244\031\144\2223\\\138\166s3|\251\195X\185\159\240c\028\021\18616N\207EBa\247\152\191L\224\242\023\231\2545a\193Atd\020}^\170\148k\015\231\024/\1477\131fS\237qDW)\193\151]k\222\191\185\023h\155R\144l\139\130S\224\000`77\003\154M!C..\024go\151`\001P\175+\000%A2\152\184\181\170\231p\253\165\184\027\207\130uK\185P?\168:n*\011\150\149\024\1441\179a\250|P\170\192=\214B!\233\001\253\224\174\026\028\242\178\148\206\137G\142|*\246\227\176\146\163\221%\027<\003\015\160#\155W\012\165*\022X6\188~n\187\136\136\158i\019\015\140w9_\164\186G\247\151GWF_\230n_\173z\209+\251\012\209\183P\213\131\173&\219\187WO\133S\007\027\194\018\134\166Tu\170fRV\219.\228\164\197h\183^zu&\139[\149~\134\167P\171\164\129\213\189\r\226\171\165@\169\186\167\226\171\1804\154H\217\213?3\179\208\210\148\214\247\212\245\216\006/\224\142<\160\233M\240O\2437Y\177\236/I\229M\000\249\022C\014\194\028v\230\235\168\234,l\018gG\146\173\n\228\248i\166by\230SM\025\178\1914\168\007\214UG\220\202\241\023\248U/\022\019I%;\180Bfu\029!\2077\149Y\166\188\177\214\248\199\223\019p\222x\130\201$b\014{\137\255\253\1679F\185QI\134\211O\027\132\154\221\178\231^\003\188h\239b\130\246~\020\022w\223\230\174\214\127\186\1639]\128Os]V\161g\249\237\212 K\170\227B|\197\142/.n\213\\\232\021\127\251\175\027\131\159r\1878P\218/\128\238\020m\230FP\254\221\188\026\235v\003\169ac\139d\025v\200Q\248\138e\245\137\r\235m\018\229\1978\164-:\190$\148\146x\012]\199\160o$\004\226\205_\154\026\202bSXI\213o\195\224%\003\162\148r]\031\018\217B\130\224\015\195<\026\158\024v\250S6k\016v\006\205\196\178\208\207\203\"\023\154\191g\183\1721~FJ\1547\172\134\192}_x%\252f\208\165^l?X^\158G\027(\157\203\153\238\144\231g\170\165\240kj\140\152\244\007\178\179\129\169if\189\204\227\199L@\187\235sg\221\154\163%\230\016E\255\175J\249\185\031\225Y%V+;+\226\024\255\207U\244\027H\005;-\128\152aM\172:5\220\143>0\206\244MA\171\223\023\241#\160h\"s\146\175\153\006\029\236r\016~\019\237^\221P\163\180i\029o\218/GvO\156\031$~f\208\200\202\187\169\137\245D\204\006O\195\n\001\004^\021]e\202\202a\142\163\203\003e\162e\006\216\014P\219,\169\173\127|\020N\249\225i9\142M\198\247I\029Y\2208h\162\201o:\185WGo\183\002\150$K\130\181\225e\001:i\217\134^m\166\234@\027FL\174\229\131\197\162\b\bv=\001g\247-\185\1447br\028\163\178r\220q\029t\001\168Q{@\184\129\027\223\015\025M,\004\128\163W\027T\181 \169D\1938O\208\0171\131\180\241[\249mH[dN\\y\237\222d56\153\131x\029\181\b\240*\208\200\212e\000e\231\132{\246\160\231,\155W\1352\212\0247-#\187\223]\156\159u\201m\216\135&{\215\160i{\152'-'\157\163_\160\189\020:\153\2003=$\224\253\249\244/\138\240\167\202\196n\168@|\1808n\149\202\199t^.\015\214p\1929\015\015i8.\r-s\r\189eAt\006\178\011\202\191\134L\249\000nq,\153\028\156\140[\235Z\031\025\021m\152\023\018\147\161\018\244X\155\186\021T\2021~\164\127\030\224\137\144\006\b\002\147v\003`\206\015\158\028\014X2\167\204\206\242B\169\156\204>\152\168\002\233R`&'VF&\1276\233@\031\2172\230\138\031\203\143\142Z\1651\142u(^\r\154M\r \028\148\183\131\150\246^tn\007\\,\154e\220\228\216\154\249zt\164w\165\128\023\005\165a\241\1973\200\221\246\141\001\160\242\201aDo\140\026\127\152\244\213\023\129\239\252\014B,W\216\000\030\151\210fG\165X1\168\205\189\210`\152\023\129\003;\241\228rn\200\176\233\192\134y\170\131\234\000\160*\003\207\2352\015\011\235\246\249\003\223}\135\149<\254\163\208\231\1428OB6\176/W\146[\175-/]M)\216Y\0177(\192\137\233_\254\206\000\000W\178\030\127\144\212\171\150\029\133\138x\149A*_\158\015\r\138\196\148?(\224x\239\192\173\191\191(\224\141|\190\244\030\224\015L\128\183@\255\201\153(\211\214m\185\198\173\225\225\130D\186\177\151x\224e_\207\130\219k\132\2071!\027\230\127Z\151\131\208\170\"\143\200e\248\135#\012\197\029\234\163\155\167\153\193%\144\203j\254\154A\184(\220\024\169z\217\243\211\251b\242U\207\031\127\020\231a>?\175\170,\191\148\r\228\rN\139X\131S\027DQ4\198v\136\228\211\171M[4\\\025,\151\168\200\138P;&\164\216f\244\225\023\180g\171\026\tO\215\170\161\238\166\151S\139\t\250\027l\019\234\151\007\024\156{\210\154\184\191l\151\229qD\196\207+\015-\192\141\t\174\015c\159\227\130\189\151\132\226^\235\190\147\226P\195\014\190\020\183A\186Q\253\200'\145\133\021\161\188\176\030z\231\210\228\170\154\218\148\004]b\240\194\178Q\183\142\251\214\180\187\211+\197\199\136Hc3\168lP6\200F\201\233\189\151\205\145$1\127k.\023\223sJw\151\021\1494g\165\201\1830\182\022h\nb\155\146;\152\252M\181-\201\005\172]\230\213.P\127\210\173W\031\254\2362\249'\197\220\234\2126\146\225;{?A\238P\247U\244\2186\144k\167\182\183\235\246\240\182\200\202j\169\025\000JL\236\160\212'\014u\164\236u*\250\191\137\170\168\247\252\027\2101\2390\003\213\026\031\1760\209\024@[c\002*%\228qO\253\216\247z\253\202\t\250\228}\178\250\207\011=[\137\216\251\022\227U\184E>\027\219\027^\"uhV\127\2455\214\145\246\"*K\200o\185\130\146\175*\145\164\175\146>\006\202\166\211\202\030+p\241^\198U\127*\245\217\220{\250\136\243W\021GF\16757)\237\139']\t\159\192\216\151\188\173B\211\191\183\180\003\242 r\188\158\250\133\244\138'\148\220\140\191r&\226\t\227\225\\\1298\225\211\178\144I\129\"\244$=\t\026\012f\191\175 !Y\148\176+z8[&Apl\207=O\171\156\223\2064\156k\253\181\180,1\214\205Ze\159\167\252\007\182\176\170\183Im\238\234\173\240@\176}\233\167\182l\141\13695\169D\164V(f\217\248x\139\020a\016\174\186.m\165\138\026n\156,!\162\200\135\206\017\236\157(\b\225\129`\204h\236(8\199\194O\154\218\244\149\212\n\128\t\031\162n\215\127KS\015(\221\029\131\242o\244\154t\129X?\242='\tr\178}B\129\160{B\024\178nqXR\189\135LR<\015\203\188f\127)\241\239Ro\215N:\190\231\030e\188m\164n\170\195\143\225F\1446\204&[[6% K\249\138\215\228;\231\n\243q\227\197^\178_\134\196\025\153\142\143\179\155r\002\236\198i\142\234\190\202\176\251g\030\159o\024\213\158e\238s\143\247\0166%&^\195\023!\173\b)\219\182\2037$\135U\025X\241\001\166\250\179\227\156c|gv|,\\\196gn\030\197iy\000\203^{8\004\191\230\163\196\200R\232\223\166\b\174\157\017\242\149\007q\174\149^\154\133\207I\141O~\246\130\nSw\202C\168\215\rJ\198\022\228\250\240[\1950\241\002l\152Oe\199\238D\195O\171\220\248\002\232J\188\001u\025>\188p\140\204\172\185.\189\026/N\246:n\023\152\134\002\197B\170X\185\255\012\193\023\251\193r\016L\b\139~\002S~L\233\006\221V\249u9\012\209k\r\235@\027J)\200\162\132\170\n\221h7\234\217\014\181\230S\138\191f\178y\143\249!H\170J\230l\029$'^55(\016\240\196u\218\180.:\220;\029\168\136h\152\194\201\030\141\154\233QV\173Z\210(\249^uP=]\214\015MY\1824\167 o\227\027\212h\157*\177\199\174\020\1325\255f\139\172G\178\248Qk\000\227\012\164\209\178X{\225\250\\\144\242]\233eU\133W\1360U\202w+\241\130\175\158^\b\162\135\171}\152\012\254\250\002\227\134\146d+" + let d_84811cd56c3f0eb2d5d94c7292ab6a8a = "ariable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag {\n color: #a71d5d;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n color: #458;\n font-weight: 500;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n color: #63a35c;\n}\n\n.hljs-tag {\n color: #333333;\n}\n\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n color: #795da3;\n}\n\n.hljs-addition {\n color: #55a532;\n background-color: #eaffea;\n}\n\n.hljs-deletion {\n color: #bd2c00;\n background-color: #ffecec;\n}\n\n.hljs-link {\n text-decoration: underline;\n}\n\n.VAL,\n.TYPE,\n.LET,\n.REC,\n.IN,\n.OPEN,\n.NONREC,\n.MODULE,\n.METHOD,\n.LETOP,\n.INHERIT,\n.INCLUDE,\n.FUNCTOR,\n.EXTERNAL,\n.CONSTRAINT,\n.ASSERT,\n.AND,\n.END,\n.CLASS,\n.STRUCT,\n.SIG {\n color: #859900;\n ;\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/\n" + let d_85abdb3958833b34c40b86687e370356 = "\"\213w\223\021_s\204M\247\167Z;c\170\226\023\223!`\2472\253GP\182T\233FBu\133\023v.\149\214[-\b\130\132\226\157\140\244\012\211\184z9\147!J\018\138#S\223\203\209*\214\176y7\222\221\1916o\133\129>[\0126\201\239\020\227M\197\206\201\164\2098\167`/ \015\223\017*\134\231\002\173\168?\227\188(:\230a#Q4x\181H\254A>\174\197\187$Rs\221\144\167\252\205\159\183\170\160\157\146\023n<\135a\220\014\128\012\234\154\015\175\182\145\143\148\139\019W\006>4\002w\198\228\218\143\130I\244H\211\171Vq\168\174E\031f\016/\163U\128\149\212Kl\228\139U\227Ga7\2252Mz\021\199\n]I\016\144\198'Lbw\247Z\020=/\193\191\017|\219Z\026\169\029\n\129\131\141\208`\188\185\163U\184$\2365u\231\160%\247\131\253N\134;\132\210\237\132\227\154\139\208u\157\127HVT\249tVhkp\157\240`\239\250\245\192\175OX\146a\197\232[<#L\220$\156q\027\193\028aZ\\\177\134\160k\201\251\147\0264U\012\176P\131.\142 \169s\006\204L\205\025\011\216\229\246K,\162Ab\241\244\244\019\245\184\229\214O\225\178\210\208\020\2051\141\197#\n\178]B\220\171XW{fO\194\181\254\027\130\176\019\152\230Wo\176\145\166bf\205Q4\157\179\r,\186J\184@\131\177\134#H\175\232\016\204\138\144\195\216_\176\195\024axx\220\207\236AK'\238\004m\234\212\165U\157\134\144N\156c]\020\203\157\211nN\141\015\192\252\254r\n+\238&\188[\174\177\021\149\004[\238\206H\229RW,\234\019\183\185\207)I=\197M\n\015\142\".l\220\216\127\152\176:\002[\228\242Z\227m\165\220%\022\022\152\179\234\141\181%\155~\no\173\014\028\231I0\163\029r\000d\181\000\202J{\150L\030\252\148\"\184J8\161\232\204\222\231\208mLSE\156\239&\153M5p\167\149\154\203\170\218y2\186\15549f\003\235\252\244dSO0\249\227M\172\200\219\253+\232\156\155y\168\147\148)\190\175c~'\246\163\027`)\030\130G*\132\169[0\199\007\154Y\154\138N*\155\141\134\132\243\1811\138\209\1723&\184I\231\131J'\183\153\184!o\139\170\011u\213\203T_\026\222\130\025y\166z\238\212\231B\172-\149\004\160\015\212\210\178v\239\172d\193\011\201;G\148\023(jE0\237\252\129\226\168\247\230\194\012lX;\244'\127\157\142\205\012\142s\201K\209>\022Z;\163q\208O\171\213\226\164\208b\012\1452`\165\245 sz\r\158k\004*P[\158'vz\219@.\189\241\174\142V\221\213(\134\212\246I\213Y\199\201\001\220j\201\204\157\0042,\029\246\153\196\233\145\223\193\159\185\241\242\194\0163\148\149\143\026\169\136\228\t\139vU\231\167z\217\\\021\171O6mF\021\171\252\181q\"U\014\172\022c%%O\223(\007\214\153\142g\011\243w\194\171vm|\015\167!\173\254\016\"\221\004\135\028F\240\187\186\199\219\220\193\148\\BQmzB\019\139\019\215\133\138H\b'\031\129\142\138\167\133?\030\230;\195\190\227V\\[U\174\160\200\016B\244g7_\220;I!\015LQ\012FCI\154=a\241;T\1823\146R? \247\209j\019\232\189K\136 \130d\161!\019\174a\179\002\197\t\011N\147J\005\166\222Y\209}V\r=\006B\\j\026:\019\130\223\1445\191s\226\139k0;\172ep,e\217\027\218!\141b\191\201\021\219\168\244\197\244\221\182\191\156&?E\254\029\157\163=O(&\180n1\1705Y4\021\217\231&\238\193\159)\247\162<\232\030\248\"]\249\150\2119#\218_\255\231\127\211\241\001V\142V\189\139\218'Cd;}V\191\186\232\213\031\219<\194\212;f#\024\195\170\156:<1\179\229\199\182\211\166\159\150\198S\245\173\142j\189L\133\b\244t\024\197\028\155\247^;\218F-3\151\227\188\207\007\235\155\026\179\1470\186\151\182\251i%\219\143\161\130\146\226>\247\221{\132\209\189\201\182\223\177F6\0117\140\0288S\197]\175\200L\250\163\157L\207\239\209j?\166\023\207T?\174-J\173\149\162\155 /\255@5\029'/\201\199'L\216\\\205\1367\156F\166,+[9\137{\019B3Nn(\011{O\132\217\179\209!\150\219\221\227\165\197\170\226\203*\"\199\207\229\185\027`\149\227\161\138\2356\206\214\179\135[\192\181\154\235\200\250\148\r\007\160\2137\145\021\025\252R\247\158h\252\0298\173^\006\249\159\b\243\1456\219\170\012\255\198\237\147\238S\203\134t.8\127\205\230\131\169\251\161\156\196\020\209N9O9\193\031\243!\130\243b\200\248j\233\171F\003\246\005\227Y\177\212\167\163SLT\021e\164\137\n\162\\B\219\166\243\203\217V\194\135\155\0301\161\128\166\r\206\181]\213\164H\1735\137\016Xc\131\005\031U~\179\246v\157\241\143\174\137\023\139\152\186\241IMi.\\V\n\216\241\154\007\202\235\235\129$(\205G\134\006\191\231\249\203\184\202\184\2188\165\020o\174\235wl\129\216\235)\133\011\n\180\195\137{B\183\165\187\194\031R\201\\?\226{@\163\254\167\0304\200jI>@n}\029\183\012,'\201\188|\164\\P\195\191\015\172\020\132\132\011\000l\222\n\023\228\003I\016\255L[\200o\026)m7~\176\237m\001\194\014\026R,\184\215\143\207)Q\198\206\225\t\004;\127\253\0158\002\011\015\253y\227\251\241\128\175\227\242!\245O\172\248\003^\129T'a3\235\004>\235_\b*\234\130L8\227`\147_p\n\130\143\229B\204\023\001\025\175\127\031\133\170jc\233)\r\236{\012\207\205\158y\254\220Q\001\252\003c\254\214s\018\146*&X\237\218\230&m;\139(\161H{\191xR\196\169\145\196\191RuQ,\218 \022\028M\213\188\024\184\175\254\217\250\131\215 !\234\187\020\180\173\172\249\239\169\157\151\188gnq\030\243\181x\189\180\183\197\247\024M9\004u/\020\244\180\021*>\252~\178T\205\176y^\220\216Ym\219\031%p\232\159\158\235\012|&e{{\215\131\016x\199\168\205\154\189\251\\o\229\157\143\186\227~\204g\133\204\244\239U\137\rpYo\136[\174\204\167\191K\237\248s=\213\016_VR\2176\028\198\127dViF-i\178f\b\238\252(b'\213%\159\151+\127\204\243\021\221\200\142/\253e\152eH>\205\1428~\135b\253\223\162]\005\027\142\172\213};\180gH\247\253\145\213\027 `4t#\140\135\155\198\136\199\151\181d/;\2440\230\251Zg4l\236 ~\187\239\134\r\164\230\014\131\004f\\]r +c\201\225\171\b\019\187yY\162\150\197\245J\025\144b\020r\142\211\220iuP\173]\006\r\027\192\168q\153\246fNs\233s\r\175<\166m\024\230Yx\rqDK\137\201\251l\207a9\127*\005\198]\187\137\229\218\248\135\137\221\187\140\254R\181\027\236\241O|X\019\127\236\153\219\179\027p\176\200\022\229\182\b\231S\253\0205\214\248j;G\169\226\180_m\028\163\167\176wv\027\156\235\156z/p\003\163\152\006^\202\194X\231\159\226\030\017\006\019\196\232^\t\148\255G\003\003.#b;]\1670\230\243\185\213\198bu;\1713,\004\012dR\239O\235\217\188)\173G\239G&\025@\216+\223\000\181W[G\135\179\r\137\158{\145\144\182K\014\2528T\201\243\186\244\1388\189\139\231\133*q\224\151w\138\208\n\252\173$\237\201\240o\219e\226\022K\253O?\193\023re\"B\183\144\142\180!\194oW9\152\182\026\194j\173x\020+\127/#\213oeG\188\236\184J/\155Q?\233\254M\146\182\012}\160\184x\168\171\175\182\174\1895gn\212\178tx\249\216X_,\189\tA\248\021H\026\003\2532\232\170\134\211:rs\150T\223\218UY\144\138\130\253\208\211e\024\227\154\193gT\166\165\019\180\145\178$PF\154HO\027\031\167\1414a2K\223\190\231d\213n\020\153\017J\216\254\177\242\2384\193\189\175(\141\1907\197\247\129\019\217G\138v\190]\b\240>E\181\171c\020sd\209FZ\170RKi#\221\209\030\012\192\177\242\136\1629ph\252\151\127\219|\222\014>\242k\020c5\253B'\219\179\212\165\021\157\143\232R\191X\245\027&#\002Mi\212\002\201DY\168F\251\215\199B\138\246\156l\232t0\214\2212d\250\011\176nN\183\188\176\228\189TeMY\209\215\187\151\225\165z\243]^\130{\247QE)\229\027\2530\235\135\015\211\186\189y\r\248\r67\225Q\157\136\141m\236\252\163\166]\002\182\196\251\001\147\140\026i\"\151\160\141\148\131\221\n\146\158\166%\229R\149\"y\243\149\239\152v\011m\194r\024-]\029\237\201\211\247Kgj|f\197\019BZH\206l\247\020\222\254\228\211\219+{,Q\029\248\192\157\175,L<\222\170\186\158z\221\158\181\217\158z\162\209\021\029M\027\156\152\163L\223\225\198\237JO\241\139\214\232\231\228\188E\151\148\220s`\154\163\254\231\200\167\028\141\128x\220U\138\227\236G\016\167\236\1984]\244\147k8\195%\210V#\248\195aslA\127(V\156\030\241\136\194JT_\251\170%\225Te\002\212#-\015G\197}#S\207\239\198\003\011\187Q\198D\136n\021?m=uv~&\018\148\202\157\211\221\252$z\228\212\023\003Y\156\184\179W\222\250\188\165\218Y\186\154\140\236\182\170\134e\183\248\235\2516/)x\238z\207\138\221X\220\232\130vV)\011\015\182>#\254]41\"\219\143\235g\169\029T\199^\195\245\017\150T\170s\167\210\021w\166\253\255\003\011\214\181\137v\019\209\171\230[\021\027x\2367\134]w\157\127:\252\182\184\216\131\201U\019\154\198N\203\210G\219\218\240E\192\213\1812\154N\0308\006\164e\236\230\234bOQ\225\165\215\015j\215\021\159x\170\153\247\243#\131%-\249 p\217\021X\243\180\223j6,\186\197H\218\189\233tL\153V\179\184\165\004\020\189\197\190\151=7?w*V\"\"|\133l\242 \198|\2321\131\015al\252\243\157E\137\253M\139\127h]2\144\227\147^\213\197\156B\017u7\002\227\157(\170XQ$\198\184\238\029\140\217\1626\137/S\026\165\255\216\214\251\182\243\1278\190\162d\168\016\132\190\201\143\130\249\t\153hm\186}\180p\024\151.f\252\012\139\241i\006DD\t2\178K?|\223Z\022M'\031\n\163\144&^\026-\006y\185,l\186\024\020*v1\239Z\183\190d\138\184\240\178Y\191n\030\251?{\152\241h\156zk\232\197\214\172a2\212M\150g;\186k\177\156\251;\206\205\206\r7'\191\137B)4\249\152\193\201@\255\243\135\180\153\253\173K\191k[\218\239\184\015v\187L\222J^\138\216\184\170\186\207\224\020\234\196\244B\199\162Y\172\254\240\187J\232v\1700\177l\153\246\007\001%wyA\229\228\251\180-\155\181\155\183\240\189\022V\209\185r\242\015\2034KQN\178-\140s0<\216^\028m+\182\220@\241\253\135\245'O\253\230\143\159r\161L\006Ac\151dBYfFt\248\2547L\240w\2556\212\239\234\182\237\218[+\163\233Bk\018-m\150o\000\155v\237\016\021\133\023\129\251n;r\178\222gA\004TY\\XXp\225${\212\136}\185H\250\229\206x-\2253\210\215\174\000*A\142j\177h\213ZH\147\r!\243\139\159\194Zv\182\179\195\215d\b\140HBW\155\254\253a\229\239O\149\132h\149H\233\027`\152R\148\191\190J]\0042\197n\148\222\192Z\230\171\190\n\158\223\003A\255c\151\238\132\022\158U\207\222\154h\249\027\219>\250\176x\020\1341Z\232\229s\209E\185\195k?[\218\189\232\159\193\159\160Q\024\161\218{\158\202V\171\004\030\194\176\189wO\241\183\228\166\230o\167~\147\174\155\030V\244}\254\231\163\194\203G\252\177\194+\135\027\218>\150\134.nIM\012\234\212\221H\031\003\229\186qn\011\156:\n\164\167\181\023\206\158S\175m\004\021\131\1316^`\131\241\251Lk\206o\217U\0072\175S\142\020\156\195:\149O>XT\151q\186\163\176\211\128\te\001?\221r?\180x\182\186\221\193l\197\007\220\202_\255m\028Z\209j\173zwM~\128\147\239-{\254\182\000\206\168\129\012\152\000[\197\210\240\204L\214\026r\194p\197\216\016\205\203\031\239\149`\203bL\175R/z8z\151\192\188\240\186et\129\189\154p$\022\210c\143h\011\012L\238x\005\176\015\237\2332\148\237*\217\217\184i\179tn\023\216\185[N\180d\127\022)\002\225\231\243\139@\203M<\165\179\187J\132<\187{\223K\202+\215*2\217M(\191k\237\133\149YQI\002\134\193t\253\222\151\0044\169\221E\174\235\142Q\021\029\"j\023\135\007\151\142\140'\152\170\184\197\214$o\238\218\135\031\253w\202\229\186\217\000\153\157\021u\223I\220;\134J\211I\151\158\012\204\166\167\156-N\212\179\245+\n\181\150\169\156\174_'\217y\247\204\237Hw>\021\2264c\178\145\154\200\127\197{;\028fl\240\235\b\212\187\163" let d_85fb54fe884a953ae1b62548b94b5a6e = "=\149\011\141e\002\255sR\254\029\161\224\255\194 \149\228/\190\025\026\156\234\148WTn\181\169\143S\248\160\247.\\?\243\214\137\n\248\153U\133U\240\159\237\193\016j\189\152\187\176|or\178\166A&r\201\139\207a.\191\220\173\224\0069\1403\194R{\211J\140\248\149\206\165\228[\136Px\142\183;Z\007\015\135<\018I\168\135c\183\015\179\191\178\186\16368\131y\026\151o\245Pc\136@\149\177L\228\142\210\212\238\252$\168o\019w\129\187\212//\127\160*k\233\022\185F\199\199\162\175.<'c\136\185<\134X\246\220B\169*y+\249\210\221\228\153\017V\015\139\199\178.\199\147o\219\193n\240k\209\228\130\156\231\231\157\174\224\153y\218\193\246\187\237K\029\235\218\216go\183<-\127:\252q\237\199g\133\174\228\199\231\215,\172\254x\199\210\000m\128&\2487\217KZf\128\134\239\2450\174d\014\216\239\245l\1920\213\171\223`1\1875\154*=Z\231\128\167\155\147C\1411\2425\192FU\r\1806\131\028\171\171\244\189r\137\255\134\015\203Q\224JV\021\2130o\253\136\213\000\164\199\216%\023\176b\167W\019S\214S\243E\238^\139\223\163u\014{z9\217\148\017\250(J\237\159\216Z\152R\1454\164\172\021\243\187\237GH\t\007\238\1975\242\237c\239\223\244O\230\175\193\133\161\240\197\159\023\253;\248<\178j\239\022+c\192\167\146\016\149\200\169\216\206\135\179\224\252V-\154Tr\251\t?QE`\027>~t2/\233F:a\001Ye\022\147\20568ml\005\179\224\252\023\242\160qs\196\210.\023\245\218l\162\161v\181\209\189o\157\149]\146l\223[Er\160\245SM\164\211r\199{{j\204{\240pg\031\215\232\015W\031\024\181\176\007B*\177\030\178\0225W\247\000S\149GbZ\236\149$\ra\242\174\211~s\164\\8\214\1667\171\163\165\226V\163\140\221\234\019\151\154\140\159P\148S\213!\242\246\127.\200kL\155$\238j\131IY\155]J1\152S\148u\002\247\168\138*#\1336\254\128\213\172\147\218y\248\031\169\161\241\003\131\022\254`\139\214\024\031\154\026t\025i(\215\143\206\213\225\230riDY\227\220\195YP!\165QS\236\031B3\23028\031\148\150\179\026\220by.+\022\\\220F\253|\014\246\225/\191\206={\240\198\177/\207\224\159\158\133\031\255N5\006\214\0275\254Yp=\188\000\152,n9\206\150\165\221U\233l\186\209\185:\0219\207\002m\248Q\157\027\130\\m\198\2463\143\180\024\026YL|\244\135\030\199\024\166 0\153'\228D\159\254gs\140Xz\219\200\175\029E\224\185\015q\022ENx\005Y\216Y\244\218\155\248Wqq\0229\190w\139}s\127\155\194\220\189\253\231\197P\227T\179\221I1\209i\167\173,_}(\232u\224\\\228F\139\1863\006\199t\135\248\189\246\230c\222`\209v\197\225\248\196?\134\199\003ca\"\152\173\231\152\237\193\189!s^\141\220\020\197\159\191Sb\145ZZ\186\199\247n\177m\030\248\012Gk\146\025E\198\218\232\208\212\224\017R\194FP\244\241\003\239PLN;\197L\163a0-\24922\184g\236z^\012\250\213b3\224\199Y\199\239w\012yhB\017\224\183\030\247\225\213\132\130o\139>\251\135~\224%dh\247\022\220\174\031f\157\158MC\178\223P\193\208(\127\237\146\215\222\027\183q\022k\153\028'\155C\012\182\244\215\007\178@]\205\173\137\174\150\004\201B\196\127\131C\181\222\247j\246\183\t5\021\236\197\b\153e\160\t\229\150\207e\000{\166\158_\234k\227Z\246\150W\217\172\016q1\150\186\135\194j\228\242\192\141X\178\144\128\254\141\160z\193`\243\187G\227\176u\029\169\187\015\167\236*\170\187yy\140~\"\209\011>\186\237\152{\133\241\243\228S6\207\201\164\135\229*qcW\169i\220Y\229\180p\196z\214\132 \234\207t764\205\029\159\190\227d\209#JEik\179D;\220w\230`Lyj\212\231vJI\252\202\231\169|\133\031\224N\136_\205)\181\212\147\2295\195^\011\153el<\241\225]4\162\254\184*k\026\129\216\134\165>\020c\241\159\236\221 \211\152\bQ\154wrqh\178s\220\181t\177qO\017\172i\0246\018\200p\178\196N\182\147\205\172\146)$u1\1902\195E)K\201\193\027\024\196t\158\249\014&0\1812xyqq\240JW\215\224\149\197\167\007.u\023\199+!\245>\031\164\190\018\006\211A\027\252\001h\189\014f\217\2139\220u\189\235\216\137i\135\188\230\222\248\132\194\178\210\192f\187\185\028Fm\215hs\128\b\238z\181\181\175+1\204\170 \018\160$\204\177\251~\141+~\176B\189RO\225\153\233\018\141U\n\154\207\217_*\tts-\250\030\246\162\221\"\145X\216b\014\173\182S\ni\164\209&H\216^2NZ\252\149\217\022\240\236\140g\175\235H\217}xwq\221\205\023\199h'&\250@'\183\157r\191-\251s?\155\031\233d\209\171TZISW\153U\029\229\204\t\227\242\204\236s\155;\252Y\137\153\198\248c\237\219_\219V\213\168\213\130\024\209\204w\254h\167\226\220\136\223\227\250\147g\255>\228\201\195\000\223{Y\017\001\208\234\171\150H;q\220\225\148(\222G\239\250'Y\153\030\152\202\250\030\134\235\148\189c\021U\b\005e\2226\182\217\016c\149z\248\029=\220\160\160\150/\176\213\146\165U\253~G\176\150\127\236\225!\002v\199\247\203\223v\169\176G0\212?\017x\242\249=\255\023\163l\2280\197\187c\165\127\215\224\132\243B\178iwQq\195\016l8\012u\247\219Xv\014\163F\161\0217\182\b\148\153\213\197\027S\166\193&+\210\213\219c\t\020\156uE\027\026\\1\155\173\"\214\252\159\127\212^\224\1685\024k\0113\170\015q\184\007\237\153&\226\194c\237\\7\143e8\228\018m:kU\179aO\170\2122\206\226\006\151\175U\175P\171_\205\206~*'\135\137\150\177\150L8\134\019t\214$\164\161\190\248p\213<\149\231\209\149W\243\164b!j(\17507\175`=B\179\209$)\\\201\202L\230Q\172g\196\165\149\253\237O9(\182V\219Mc\215\198\144*\252\153&\195\231\246\187u\182\019\186\205p\158J#Q\006\203\173\001\190\\R\154K\133\129\225\240\023\243\243\250M\255-8G,Pj\164\004\172RG`\185\028\r\190\230\198a\159\2404A\254j\017r7=\204\004\190U\140@\233s\011\198@Vi\135g\193x,T\139\217\197\\t\016\140/\029@\"\014\154\017<\174\017\190\r\1610\151\252$\166\187$*\141S\192\200G0\182\014\226Q7~&\189\b\201\136d\023\022\190\159\153u\224\207\131\026|\206\239\133\238\252\179.\151v`\251\150}y\185\022'\180\156\2419d\177\136\173\209\136$A\171\182\240u\253:\189,\239,\0123\145-J#6r\172Q\183\191\185\028\160\027\167:\208~\185\017\145\159[L\2434\242\193\145\165\189\031\227\143\191xHyK0\015\tp){gv\164\170\201$\233\151\012\208'=\\\1813\007\2157 \204\152\220\1509\213/\"lb\026\129\207\140\218\014\003.\r\001f&\228h\204%\128A\239\012{\244\169\209TZj4:\252\241\004\192\210f\231\153\152\236\015s6OW\016\206\145\1489\024&\022\253b2cy\016\155\187\193\189\001\186\208\214\217\191\002\254F\199c\017A2\175=\153q\173\181\232\1622\247\166\160N\r\157\028\217d\228k3\175\174\165\r<<\1302R\180\241>\199a8\130\135\222\159\153_\210\179\136#\\\t\145\232:\n\254\249\248\186D6\"o\026F-\020\143>x\243zv\129\001.\242F\012\238\250\169\181\240>\198\236\135\182|\161^Hs\021f\140\023\215\011\163k\235\178\225\197\211(\234+\145\159\239\157\206)\016\194\197\222\176\193U\191\171^:\011\205\158\202\200f\167ed\209\198\139\129KC\219a\128\226C\138\188\231\005u*\138e\213\215$\183\174\165\183V\r\217>r\203H\209\198\253\156\142\225\b\190\128\150\210N\246\254\212\139\193\191O\250\003~E\148W)\016\136\174\192\211\137VW\016\133V\242\151\200\243\152!\204\002yI\128V\006\145.\198:d\167\000\018\173\020\168\171\146\232!\244\018\225\231\002(W3\241S\172\222\\\170\173\204{\194\255 5\243\160K\220\142\248\221x{\218\2118(\146\251tZG\237\157x\007\014\253a\031f\212\233$\159\192>\005\165\138^\001\139)\149\176\024\189\162\n\240\230\213&m \220?\022w8L\184\191\157\019\144\150\15017GY%za\2196\208\1549\"2q\133a\152q\174\181\0214\208\1523\001\139\255\234\135\174\026\198\197\238\174\184\178\186;\177u\235\004\169\030\n\200\252\157\248!QL\201'\132X)\186\153\207\137\001\241\224\203\131\175\204y\253\163\b`\140x\237\227\200\181\143\130B\248\149\240\169\004\176\159\253\027\153q\247{\209\176\005\127DCDlBmh\220\127*\020\243W3\165\205L\148\159z\154\247\2017d\027\246\198\246WB\235\166\154Z\026\246{\161\251\162{\148\027\167v)\151i\253)c\141\182\139\\a\208\233E\"\161Q\223\142\214\235\214H\226\214\232S\021\202\154\006\161H\"\212\027\168\182mSs\218\242\255\134\177\158f\200c\177\243\1685\027\187\243\235\029\144\185\216\193\145t[\166\217\169\146\250\232=\152<\154\000\216\164\244\250u\186\154\136m\195\222\216\222\016H\026\167\182K\184&\194\247\176l\157\203\028\129\005\252\014\246\166\025\149\160T\173!t\239\214BHm\251{rZ\029Y\1502\1495\203*-l\156\235\173\175\179\243\185\254\251o\160\232\234\210\130\031\179\172\247UogZ\174\142\167=SgcB:_\141i\201O\161\140r\171\188\162\1789V-\015\209\164\001e\217\019\133Z\143\235\178\245\178\178\254\167\205\191\174A\007\130MN\200\241\216\204@\186-\211\232\210J\189\244^|>\163\020\216\168\240\134\140\198Hu\249\198]\177]\024\011\014\161\177\017\229\2498\194=x\174\158\023\140\192\252\0017;\253\168DX\170\208\016\186Oh!\196\214\169\254\236\206m\204!)\140\237\031\172\225\187\138\018\238\027\188\185\027\193\252\027$\251\018\1866\014&\\\242\230q\194C(\023\137\172\017\173\147\135i\146c#^,\198\248\136\225\235\214\235\230zE\242\138-h\029S\143\1455\219f\219F\173\163\234+\t\\\181=9\142\223\130\143\139\230\207\203B8\149s\207\140\243\178'\251s{sg\2550:\189.\175\163\218\225qy\156d\254QW\161\171\152\127\207Vh+\024=\158`jZZ\154V=s q`fd\230`\226\224\140\145\nL\172M\020w\254\237p\196\163\241\014w\\\172\171\189+\017\1411\199\026\237\002@\156\202ESgvL\157\166\199J\007JG\000\139\"z\243\161\237\218\171&\028\243\014\000\196\240\232\135\197\212\0040g=\161\028\127I\167\224\195_\127\189\244\b\028\235\137uV\253%\173\140_\246\197X\230\200!Z\015\186\234\213\128\240\149\203\228f\234\142\152\137\020\011\135\1635C\024\0123\137bf\194f\152\159!\246\217\209\175\162\196v\187\248\155\191:+\205\150e\n h!V\219\208\183\022w\216\196\251 \016H\244^P\248\234\203\001a\1959\240\028W\135X%4\0182W\247\247\031\253\254|\173\223\233)g\022\141j\237C\253\252\239\031\2530M\167\029i\2537\025\239\155;\187\253W\161)\031K\012\196\183\028\216}\176n\191\2038Ww\226\244\165yF\029t\018\213\184\170\215M8\253n\180\253\245\157[\018o\191\223\185}\252\249\198\186\165:7{\"d\146\240\228\165\227$\021\139\229\241$\170{\019\187\154\215\236(\216\251Mm\022\158h\244\202\159+YJ\172\004\240\012\021\165T\234\016\019\182\244\191\b-\031\193\160\155\216\186\174\250-\155\rZ\175\182_\211B\021:\005e\226\n\005\185\028\175\166\144\169\218\000YQP\005-\202\031\255\023\003\130y\167H\219\142[\197\248E\186(\235\248\225\134\163\201\161q\b\218\1551\014y\208\182\170\219\230\175\218\030\237\213\220<>\141\166rTa\172\172\213\200fx\197h\025fK\022\228\231l\147>G#-\213\154h\207\238ARX\234\000N\194\014\023u\179\\b\164LC\030\n\252,z\130u\178R\157\129\030\166" @@ -230,8 +228,6 @@ module Internal = struct let d_86df3bac1a1e0286b91bf5a166ab459f = "wOF2\000\001\000\000\000\000a\132\000\017\000\000\000\001\005\164\000\000a!\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\026t\027\129\159T\028\146J\006`\000\133,\b\1300\t\154\022\017\b\n\130\143\b\129\240l\011\133\n\000\0016\002$\003\138\016\004 \005\131P\007\142O\012\129U\027\213\242\023dn\243\188\164\212]U\180\253s\199\177\158\138\177k@\221\213\181>\219\020\162]0\221\220\137@wp\137\170\166\227\020\255\255\159\150\\\140a\0286P\181\172\150\181\254!&\136\218\142\130\149sQFQ\205\173\247\218T\209\243ZB\193&CU\177\ra?L\246\211FC\141\142\138R\248\162\200\184\216$7\201)\199\182\029x~\168\153\238\213TJ\147 \177\161\228\026J7\026\026\170r\248\190T\149i\205\204\207`.T7\245\206\166\218\012\243\251\135\190\220\157>\168\031\250\127\025\199\179\182y\182\228\220\233X\172\1908d\165\025\130\026\204\189\252\141K=\ngs,\222\237(\024#\150\224\011o\234\155\248\019\166\194\245\"?q\240\194\159O\218\248+*}\2002\192v\221\016\"eX\228\240#\207\247\239\223\255\255\247Q5\215\185\226y\000> \181\156N\025\164T\234P\206v\029\209\156\255\179\187\151K\028\b\030Br\137\163\t\226i\192k@\249\144\026}\2400M\251!\0215J\169\136\017J\251\168\184Q\017\007\162j\200\234\153\005\137\178\020\018\163)\132KY\201\172<.\027\195'\165\190\184\159_+}\127\144w\022\128f\t\143\152\146\244\160\136\202\179\143*\025S#+o\000\230V`LA]Q1\022\1450\215\193\138m\172\169\216F\142h\021\1490\0260\224\202\230\024V\252\029z\017m\221\255_\135\194\230X\003\143d\b!\249]\224\177\246\203\228\160\168\1443Y\177y\198e\190/\194\238\149e\171]\003\252>]\1753\002\195\140\244\174r\235\132\1392}\218T4\187+\248\192\242{\n\240\249G\141\182\149\2180\154\000O\007F\n\210\165MsQ\021\223\148i\n,J=\178\030Y\001R\232\198\179\006\218\200$\239\129\238\206{\178\149\228\011\224\223/u\189\183sE\153\176\154\183\217\176\199\014\208\007\135\228\131 HA\233\168\168S\212\234\170'\135\253\207\233\127\250H\178\138u]\228\218\127\245\251\165\238.\192\169\128\132\006gx`\233\136\135\165\243LP\b\217\028\229f3\175\227v+&XMR\017\221d\191\127\180\162\142\216)\020<\t<\225\\\223\155d\154\018,\255,\2091\247\192U\168\184#\167\190\179\007\001\176\180-\212S\208\015Y-\148\195\135\237\017+\128\000\2353\213\175\170\186{f\022\150\132\232\191\177\134J\192\239!C%x8\183\218\133\160\213\138\143g\\\140\132\188\243Y\160Pqp\241?\171\246\203\239\227\185\tu\189Z\177A\144@`\227b#\132\141\144\128 L\242\t\187\001\000\169\b\254\229\246\249\224;p\176\226\248\n|#\170;\1472E\147\020Mw\231\144a\218<[\156St\181\001O\254\1273\245\181\243{3\004\176K\254\128%\029 :\145\138\196\207t\170A\016\192\015\153\250\014)\1483\247\221\153\183\243\222\206\166\193\"-V\004\023\018\140\005\004\018\129\001$\bkgv\177\024, ~&\029\145\018\0292\244s\004\004EB\129\2501\198\162qHE\239\220\169\244\239|\220\185\251M\235\020*\023e\229\202\199Eg\030\254\185w\250oc\001\165\223\026\244\220:\209\006\234t\252cc\129E8E\1905(\012\211\136\226\249\127\1509\155\157K\221\165}\186\229\196\129B\184\161K\140D\198\207\166\191\164\171\161T\137\\a\018\183\194\209=B\"\241{VFz\132\003\158\239\175\031\239\172\173\029\192\005|n\251\237w\169\236\214\031?\244\253\142\231\001&\218,\022H\147J\200Qa\0195Q\b)d}\251\169\221\217\187\t\161\2411\166\214|\012mP\149H\002\128\203\139uQ5\142u\157)<\031W\211f^\031\168[0\192\192^\135\193\137\187[\141\159f\199\137\151eT\212\132\218\004\216xP\155\132e\148\139P8\190\178\248\018$\212w\163\222|\t\253\238\222\150A\130\004\t\018\172\200\244r\221\243\222\019\255\249\191\221\216\238\247\189\0293s\212TEEEDDD\213\030K\201\128;S\015\r\224h\247\175}\173C6s\007\161N\223\007M\240@La2\172\205\134\195\235@1\146C\152\132\180~\207\204\\vKA\149\237\011\000<\190\157\145\021x\170\004\184\011\192Q(R.0P0\200$V\218\017(TT\142\139\024q\014\1414j\215\209\198@Z\227e\166G\142D\022\185\134\148\209\132t\241\173\014\136\225\143%\004\028V\2288\234~\015H\181@\151\131\1935U\016}r_\\\t\190\151{6+HP\128i\215\b6\190\248\1891\026\239{#,\220w\015X8\004/}~\141\021\178\0017\210\173\131\204@e\245z\186\140\001\n\133\021W`\228\205\028\004}\207\2311\171\015l\206\201\012!B\023@p\160tr\031\138\027\001\137\179\142;h\175F[\173\183\210buf\153b\156\017\006\169Q\165D\158l\022\233:I`\018\014\185\221\183\144MS\bi\238K\200\230I\132<\0259\228\254(\151M\165\242(8\165+\182M\011]\018\186;v\185Y\022;\0126MK\191\212\144\190\135\134p]\023ru\139\234\t\193{I(\214\150\164\174\244!L\189\149\149$\003\012$\225\161\195%e\211\213\247\218\181R'Z\209\137>\146A3_\1446i\151N\233\146n\233\145^\017\164_\006dPF\164O\250'\004@\207\139I\195z5\149\133x\152\236\242I\135oZ\128\b\218\205\209\025x\147\153\190.\2447\0207\142xx\144U?Kh\142\236>\001\154\173\019\b\161\162\137.!\137\134\193\222\151\193\222g!\1844G\177\012{\141\219YxO\155\r\221\220\1875\138\173\214[i\177\186G\179\182)\219\184m\1966h\171\217\170\182\1465\204\187X\204\222,[\250\214\t\tL\194\239\0277\223M\189\2016\143M\188\tX4\011V\157\250\229\139w\249/V\235\186\187\174\175\139\235\244:\186\226\254\213\188v\174\205km\186|5\172y\211\025\153I\198\024f@^\191U\177\1386\223\149\187z\209\231G\153+u\165l\131V\220\138^\161+\016zJ\210\199n\203q\241XS\022E\218\250G\127\2347+>\235\135}\187\175\246y'\029\214\162\201\246\199\027{u/\237\250\158\179\199\163)2m\143j\014'\244\168\030\210\182\182\162L\129\127\030\247\232\140\238\210Im\238\200\014n\255\214.\012\t\151\169\168\144q\b&Z\"S\127\234[}\168W\249O\182)u\191n\214\229:[\199Kv\176#k/\211F\216j\253le\183\137\135\139\171\174f\213\148\026g\239\141\168AU\211\254UU%\149W\217e\233Q\149\190t\146\192\2448\188\140\229[\234\146\149G\137K\128\233\149@.\250\149/y\007yY\231\136\247\129\132E\228Y\184(\146X\004;\023j\167\004\148\254d`\177\006\130\134\030\133D_\251J\214r\030\132\199[\142\212\160_\220\tV\175@~\210\213O`l\179e\160q\195W~\245\012\141\243X\206\025\161\174\129R\215\219\024\153\150\150fA\221\209X\153U\\K\001-\133uWJr\229\192$>\180\155\226\211\252n\023 \166\029Z\248\240c\166\153\153!_\155\222U\206\216$\nc\003%Aa+s`c\255Io\226(X\159)r\174H\225\169\130\243\000a\154)\012A(b\219\031Da!g\170\028\015\168\223\130\144p\n,\003i\002\002\012\004T\153x\217\250\"\146k\193\203\240A\n\144\158J\017\020EYU*2\251JA\150\169\185\214\224R@\n `\021\000\132L\184HH[w\143c\148\135\236/'~\247\154\155\\\027\204\166\162\021\143\n\021\177V\197L\244\025';\175\236N\253\223\1369\016D#4\242\161\187\143\246\255\165(;\251C\150\213\193\196\178i\194\136\137\129!\001\129\167\201\0271'\215g\242\156\203\145'GV8 \014\003\169\153oBE\142`\t\199\189<\129W\004\178\2558\248|\019OC\217\197\2470\250\134|\233w\245\235\250O\253\128\215\024\193\250@\127\219E\145\231%\204&\180\024\018.D\024(\1703\027\243y\017\018\149\208x\204D\180z\174\029\142C&A\027\143j8\012\003\244\139\021\192\243\128g\012{\137L\169R\196%\209\025}\152\234\178\007-\012\0077X\029\002\131\177\174\1383\231\014\188\244U+\197\251\016\173JXj\238uiq\237\249\206\191\195\203\226\233\161&\251\199\245\001r\195\145OG\142\030\190\154N\164\016\012\028\132\245B\001\1914\r\023%\237=\223\132\241g\193\180\206\243\217,\210\223\254\015\170\216'BlD\231y\024\199\184\004|\000d\210\185\216\020\211\017\245\182a\219a\023\1853\206Sz\239\011-\202\215\004H\179\137\237\177\023\177\031\226\136\137]r\021r\011\226\190I|\245\r\242\163\141\252\213\214\157\b\219\219\180\205\178\144gP\166BLO\198\234\173\192\182\2106'\164\198\145\245#{\160z\232\168\231\221\167\189\207_m`\206\222\197\255\197\254\146\003\234\007\t\233#\145\018^\018\019N\153\016\242m6\154]\029\152\176\187\205g\236\022#\220B~\007i\225=\004B\212[]\028k\163\189\189E\201Y\023^\228\190J\158\231\007i2\1683r\139\173\205\160.P*\149[\241I\217\130\186{\166\020]\195\170y\135fVd\022&|lq6[\016\162\183\141\211\232\168\012\148a&\242\146\165\012\006\165\162\244\224|\139\024@.o\2297\207\016I\005\169\129\223?|\139V\170\179\255\b2$\1674X\127}{\255X\1858\\x\188\191\210\134-\219v\157:s\238\194\165+\215n\220z\242\237\251\207\127\1535\197L\227X\004\014\135$\016%M3\233\245\186\"\153d>\159,\020\220\197\"\165TK\213\235\180F#\221lzZmF\167\195\234\014yGf\172\217Y\209\220\\n}#\176\183W8\184\176\174\175\173\219[\237\254\222x\248\160\244\248h>=\217\159\159\029/\031\153\031\127\236\252\228\211\157A\203_%\202\215\196\190\193\246-\178\239\144|O\241\007\244\159$\184?\216\021\173\252\014\153?\224\204\160M`\205B\006\011\178_\145\003\224\228\160\169r\200aA\142@\028E\2378:\167\133\191\135H\216\198\163\2165\195\224:r70\184\137\220-\019\185\237\158 \247AZ1z\130\151\167\b\188\021\253&#as\019\188-1\169x4\014 pE\028\188\006d\017\215\b\136s\r\255\184,@\003\177\235\012\205\183\157\133\207H\0268\140?\231O\001\192F\004\156\128\129\150\236C\148f\227\196\020\031}\1799\002\140\224\200E\239\237u\003\223f\029\229\240|??\003k\001\015\018\140g\215\207\218\137\\-\\\1312>\192\177\190\175\254\169g\222\022\182D\140\0209\n4\251\169\202\234\135\138\250\153\202TF\153\212\243i\247\253\159RN\169M'\194\241\216\028$\159@\155Ja5\158H\179\183\135\174\213<\179j\011\"\215\236\144{\015\222\171y\205\210[\176\139\184\219a\0073\003U\011KJ\151\007\172\"t\171\135$\203_\135\181\177\135]\\v\"\028'D\188\241]\n\253f\145\144)\220\153\164\233\002s\251_\006\128A\171\025(5\163\1335~s\168)W\194\240\133\195\1770\004\164\196\249\025\221NI@\166d\151\210\029\000\001*\"!\001\223\130X\"n\144\239Z\140\135\210\023\225\029+\001\178\168\159I\189\239jiM\248\n\159\162\130\179m\178\128\134/L\135S4,E\026\147U\138i\016Ill\016\027\027\012\206\131\192\"Qd:\007\1747\023\243~\251\210\138\177\022C;&\149\157]\187\130\244\180}\139]Gz\199%e\191.\199M\217oK\189\143KS81\220\004\012-\156j\132\151\249\208\"\029Z\1589\b\239\021F\138jS;\151\173K\251\195Z\185\187L\138\234\163\232\021nf\bu\231\149\136%\177|\221'@u\t[\022\163\206\255M%!\001\208*\208\217\nWy\164\157\134[\233\163\200N\133J\192.\007S\003\136\012F\190x}\223\152>\019\253\243\031\0293\237\220\204:~}\154$\023C;\027L,\144\146\187)$h\019t\020\224U\204\"L\166-:\218P\188p9\150\23770\212\150\012\224\025\172,^\241\012\197!M\235\184\149\179~q'\140\146\174\t\232\136\028\023\005a6\189Z:T\024\184\211\137\185Q\020O\131\0196\247L\005\129\167pNB><\130u%\128X\006N\184\185\153\022\210\021f\170\002n\164l>\r\212\020A\026\196\b\168\143\165\004\219\173\239>\135\211e\183\249\022=\182\217\011\212\"E\137\202c\238\164\019\0270\245d\173\209I\255\202\212j\005n \248r\177\132d\1684\002\170\165\233\222\249,3\202\168V\160e\180\140V\199\234\145P\132T\148R `\020\027\239\029g\186{\248\213\203\247gI\127\149\242w\130\132\018\026mQ\031\131\216\182\202\216\173\172\227\148$\166\200\192v\177\023\\\176\151f\214Z\233\183\228$\1418\182\252\246\217\228{\142 1\139enJE\128\192(\155\229p2oA\238\011\t:p/Z/\156w1I\r\159I\241\147\232\242\1390/\220>_;\\,Y|\193\"D\234\128<\143\219uQ\178-\224\199\175\223\127t\182\237h\217\203\175\166\003\162jW*\1492\14038!\230\147\148d[3\161\227@\018\242O'>4\142\240,\146\177r\250\225FbW\181\203\220\227\222+\252\2187\180+\145\252\200\139\207\250\245'\027HA\206I\128{\1687\163\030\028\231G9\157h\134T\225\014\\\224\226(\023\023S\020\005ope\143\162\225l\146\175d\221\135\029\134\b\236\185/\175\145R\179\167[<\159\142Ts\2539\000\175\166\0253H\127%\143[\0311\176\161n\\Q'\023\242\192N\199!\228\145Z\183y\237T5:\182\238\196\132\137\1988G\002\234)\165X[aN\199\129r\022\186\025\214\176\007\213\154%\206l\247\223\024_\171\166\180R\012\129O\212r\148A\127\194\215\216\152>J\199\232\243\242\252\165'\244\207\228\249\000\160\161\201\169w\235\168\226\tQ\167\166\170\021\026C\179\006g\146\020\160\195rv\247\002\130\014\221\147T\220\137v\024\198\164}&\189FV\022\026\030P?\155\142\240\193\170\191\218\200\212\024\025\203\200\018\208\164\005\249H\203\t+Aa\137\217\179\172\189\165\170\0300\219\029\151'/\155\187M|\164\1505\000+\017v@\177\245;;\004J\210{U1)\206\168\031\148\186>\158c\251\229\2388\020\175\252\156b\011B\240m\194.\128C\146\238\159\132]&\130\tu\161,&D\005\r@\025\135\234\166\140jn \019\237&\151=\238l&\243`\196/C)\219\251%Gl/L\133H\147\007\182E\149\1665\195\na\158\171\154{u\215\229\244\159\144?\187#\155\0283\011b\2037\158\r\202\022\156\154*-+,I\135\005w" - let d_89fc6729d4ac5445a0939af01bd9324b = "ljs-keyword,\n.hljs-selector-tag {\n color: #a71d5d;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n color: #458;\n font-weight: 500;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n color: #63a35c;\n}\n\n.hljs-tag {\n color: #333333;\n}\n\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n color: #795da3;\n}\n\n.hljs-addition {\n color: #55a532;\n background-color: #eaffea;\n}\n\n.hljs-deletion {\n color: #bd2c00;\n background-color: #ffecec;\n}\n\n.hljs-link {\n text-decoration: underline;\n}\n\n.VAL,\n.TYPE,\n.LET,\n.REC,\n.IN,\n.OPEN,\n.NONREC,\n.MODULE,\n.METHOD,\n.LETOP,\n.INHERIT,\n.INCLUDE,\n.FUNCTOR,\n.EXTERNAL,\n.CONSTRAINT,\n.ASSERT,\n.AND,\n.END,\n.CLASS,\n.STRUCT,\n.SIG {\n color: #859900;\n ;\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/" - let d_8c0686848665c0616f4fed0880a6fa6b = "wOF2\000\001\000\000\000\000ah\000\017\000\000\000\000\246\248\000\000a\005\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\026t\027\129\162\002\028\144F\006`\000\133,\b\1300\t\154\022\017\b\n\129\240h\129\208<\011\133\016\000\0016\002$\003\138\028\004 \005\131`\007\142u\012\129U\027\017\227\023\2166\237\134a\189YU\t\224\187\253\132\162B\025\183\147\232NPm\251\212\147w\0017\198i\208\029\156\196\020\251\213\228\255\255\179\146\019\025c'*f\020\127\162`\028!\195\218\146-\138g\171[\006\203%\186\245F.\227\154lBK\019\249\254\194w>\236&W\016\171\135\028\179\224`\250\183\217\031b?\168\221\226\219]\173\131\167h\215BV\001v\235\006>\018B\209\157\206\196\203\251\203\248\234H\247\181\219\158\249\004\004!`H\017 E\196\187\214\207\243s\251s\239{{{[3j\212\2466F8\198\154\209#6h\149\018qD\164Q\128_l\240#\191\213\223\001\191\208_\024\213\2327\003\163\192\234M\237\237\238\153yo\023 \193\003\015\196\025o\192\255%@\006\208~cY\140V\011\030\004.Y\144q\177%%\159\005\023^\152*\200\020}\241\207\247\135\228\185\239\239\210\206z\132\002\222\027X\235\134\017-\141K\029\143`@\255\000\191\205^\239N\004T,@\005\137\nA*\031\217\006\216\205\242\188\253\149sko\209\223E\177\200\243\"W\151\181\188\168\250\223\169\t\1931\\\196\014\240\026uC\209\027\168O\157[]\025\186\177\254\243\1502\164\250\190\157Hq~\134\252R\168j\185\225\216\175\026\150\016\130JQb\004F\186>\156{\252\180\1896\151\235%iJI\030\208\128PM( 6\134\141\153\209c\205\198N\242\255\012\001\206Y\174) \0152G\198|\133\019\239\242\127\236\001w*\162[\229\212V}V\000\255>\168\203\175'Y\166A\019\143mI\182\00700\147\143J\178\135K\152\238\168k\238w\021P\187\016\226\212.\177\228\204]\247\215\006d\1792\001\242\246C\2197+J\2404o\024|\005\177\147\197\178_\192\239|\130&\223\138\154\162NW\189,\190\168+\229U^\031\017\156x^\030Z\158\142\136\003\133\251\207in\129f\164\".\159\n\129\235\002\192\252?\223\254J\020V^U`\185\209IW\233\186\136^dg\001@\138\188\132\238\171\138`\165M%\003\193\0254'\195mSy\231\139*U\248q\250D\129um)^\201R\004\241o\144\2330\149\b)\216?\t\bF\213\128\212k\228\015\183\245b\136\166\224!\191z\030~\027p\136\194\243\255\251\181\175o\131\183\185\144\134$\030g\017\018\139H)\1488b\231\029\220\219\197\223\012*)\146(M\236\191\255\147i\019\011Y4\245\031J\007\254\233\151?\237\238\187\138\253\180\227\192\200\245\146R\015\253\209\158\005\137\170\227qHP\014\161\249\030t&\2273>\198\196\218D\216\168L\164\142\021\185\127\155\149wg\234\175\030-\240\152\248\128#\191\011\146\229\200@\161\249\229\142\213U\245U\250\191\186[;\210\200\179\026-\209,\144\204K\250\r\154V\2071G\006\142\b0H(I\000#'\137\147\208\206\238\178\187\212\217e\247\255\251\211\178\189\247=k-\217\179'\254\227\128&\236EO\216E\231\2412T\169S\002\235\191\255\164\015O_\022X\027\129\237\249c-\200\214\144$\207\024wc\193\228\200\246,\000\007\000\004\003\228\000\001\151)\211\214@\021\021e\153*\021\208\195~\162\186\0283q_\012?9Y\225B\172\012\133Q\030\193\127*''+\212\\\132\156\153S\133\254\227\2084\147\157\135\233D!\251\166i\229\1677\1776\222@\154eB\017\011PD\002\030\145\019\188\241\003\240{,\205\003\221Y\142E\148\216_\225\223\149\180}\025\218\028\220\001?1\141\161\134\226\209\131~\027\245\234sr\\\194\134\143\181\198\0122Xc\172\200\178\152\243\146vO\164\190\029\027\220\177wffj\170\162\162\"\162\"\162j\199~\234\247\148\140\217i\012\194\229\152\n\024R\211\183>\223\214\180=\252\185\250\197\133\173]M(B \2333)\004t\253\188\187\247\222J\128\171\002\156\132\"\231\002\003\005\003[1\175=.\144_\150\131\208uk\186-\222\218c\t\228J2\169\136[\"\138(\147\241K\160Q'8\160\143\241\191\132\128#\021\182#\175\127\195\244\028H\1897\183\173\001\"\030\rV\214\131\250ySG\019x\"\0013\193\016\216x\190\214\024\133\219\026a\225\252\025\176\208\248\015{@[\0198\016\189\142Z\130\172\162\250\198fR\183\001\133\196:,\197\136\187\000\004u\237\215\210\239\031\172\205\191i!D\021@\208P\172NB\225\003\159\167\237Fl\244\155\159|\2273\235\189\171\223J=:\205\209\166S\131*%\028rL\145,^\020\011\020\247\238\129\220[\155!O\187\b2\186\222\132\226\220\157P|z\000r\213\027\160\b*\232\220\178\155+3\026\192\004\004\195%\164\129cK\177eN\245Yh\190\149\234\153~\241\158\249/\190w\254\182d\205\239FyL1kk\212t6\165?\146\254B\242\198\026-tcs\001D\000A\185\212\195sb\142\025?\150D\017\196\026\027\023|pp\235\224\166\\\159kre.\203\1859+\167\231\148\2363\011\016~\228I\"\167\241O\128\209$X\012\244S\169\178\195\t,f\2542$7b\\\\H\250\022\001\154\202\227C\208\212L8\132L`\212\tI4\012v\239\005\187\183Cp`\028I0d7\180\245\192\219Z;\255\176mk\b\170(iw\184\228\248M\217\146\183\248-j\179l\250M\189\169\240\2026\233&\217\248Y(\028(^/\2201\242%\255\184\174\175K\235\236:\190\014\174\221k+\252\203\176;\132s\183\155\235\135\237\201\250j\135\201\173\216O\214\218\245\246\019Y\r\203y\131\005\204\210\0222u\171\226\229\139V\222\202\218d+}%n\020\025\187\"\150yiW\224R.\239\229\182\196\139\139C\022\247\184\251\012\190\196\195\190\221W{\180O\247\209\222\223\183\153\221\217\155\251\2394\211\253G\255\002\223\241\005\031\241>\003\210\251\236\172\165\221\221\243v\152\162\137\014\136T\167\201C\212tY\023@.\025\164\250\219\219\218amlM\2517\211\158\237\242B\b\237\224\190z\229\247\212\147\186_7\t\189\220\221u\190N\214\225\243\247\214\246\026i\255\218X\191\213O\217~\211e\245\025\172\231]\250\237\202MR=\188xg\205\169\182j\168\170\237f\149\148\1635\149SS*\185\226+\170,\155lGCQ\219\139K\143zJ\213\155\203\012KK2\177|La\1539\144\129^d,wS\221\031\n\137E\128\252\004$\230&\215\210\243[\140l\011\020WF#kVh\172@\169K]+(n\176b\173-\030\156\021\213^\158\206\178\217\162\019\149\234j\031\168\174\255KZ\245\191\215K`\bP\222\148v\216\152(e]\245\n\1690\145a\005;\191\211\004Lr=\174\233\001\139\209\025>\177;i\245\177\2152\218\025\180\213\237\161\227\159\176\229q\229\196R\148\208\175\019\135\210\r\246W\191\192\163\236Z\165\2285-\184\16624YF\205\003\002\r\1611\021\169\254\157\018F\234\198\005\239\n\020 \213c9\185\133Uo\219BA}8\012\237-\004\218\015|\225\145\194~A\252\007\003\255S\154^\003h\140?\r\219`\163\191:.\255\026a\179-_\179\195N\187\237u\2121\199\157p\210)\167\157q\214\197\206\251o\244\216\139\184\193\178\0178H\\\\,|\002jn\220\168\249\240\225E%\136\154\150\150\154\158\1587\003\003\138\145E\144P\161\216\194\132\209\b\023\206G\132H\180(Q8\162ES\179\178\211K\144@&\201Tz\0252\bd\202\164\231\144O\161T)\131ru\244\0265\210k\214\204Y\139\022\n\173Z\185j3\139\201l\179\185\155c\014\169\185\230\2420\207\002\238\022Z\200S\167NB]\186\232u[\172'\154\217r\225d\005\001V\226f\021b\189\136\244a\180\026\023\253*\181EBZ\136?!\2160\\\027\192\254\146@\029dSC6\131\196\150\177\202V\219\024l\135\176\003?;\t\180O\158F1D\r5\236\164\161s\n\198it\206\1928;F\206\025ep\017\228\nz\215\240v\029\190\155Nj\166XC\0057\236\181=\192\181\250\134\016\001!I\156\228\185:iss\n\206\189\006\127\2000\027\212\250(\011\143l\n8\194\163\192G\019\176\017\018\001\0054\b\182\1958\027\189\133y\246\003\224\004\254\028A\189\202\175f\247\229\019\154\150q4\015\230\0231w\139\134\178\220\234\154\249j\194z\141\154\192/\185\220)\149>\248\235n\184Y1\t/Nn\222\252\244*\173\142C\217\177\168\168P\162hH4\240_\137\212\150H\193>!A\145\023\026\230\017\147\167\205)\024\207\031S\144\154\233\160\231*\178\235\248\000\196\140\205's\215|MU\0314\\\234\162\171y\222\153\235\148\198D\207\026\128P\031\171\157W\215F\162L\247\212\202\b\194\136\185$lW\129\"\151}\207a7\191\245\176~\190\134\236\229\163\133s?W\146\137\014\237\242h\204\172\167\245\000\173\190\212Q\145\200\234\204\197\170\210U\014\027d\230\195\176v\000\000\229\136\142\128n\006,\245\175\012?\145n\208\b5,7\174\212O[|l\233pu\249\147rV\243\253\1741\179\128\134\240\166\194\002F\128G\177\185s0\172^/\209\235\1652#@\201\021*\189\160\021\208\012\014\235\218;\226\152\206\137\186^\242\236\156s\158\239(S\186h\249\1902\131[\012\239\206\b\238\014\239\222\168\221\031\206\131\006=F\132\1344\212(\133\168\139\196\178\159\020\237\164\\\0113\245\159H\011\158\201\139\250\219I\213\157\163VeJcm*\186\b\215\229'C\b\230\254\000\201E\209.\156\017j\n\198E#\202C\178\181\003\200\170P-u\173\166\239;7\179\168\228\1281\248\221\190P/\131B\127\181zdv\019\147\210$#\142\233\187\128&\141\135\183d\177wP8\207\2212=j\182\150\214\173\138\221E\186\220e\183\031\144\129\170\167\175\022\241\006\136\178\167g\131\196Q[6Z\193\1362\001\243\210I_I\184N\217\169i\137\225\141pg\165\214\139jm\208\156)\216lUH\024\217\016\030\023\028w8\232C\136\158Y\\Z\196F\169p\185G&\030\195\015V\151g\"\025\213\171\198\167\249,B\189\175v\205Yk\155\000\230\000I\180*\253\248\023\222x\235\157:\2315\254\172\202\241^\164O\147Vj\171\172J\164\226s\020\r5\031\173(\234e\198@\174Sq\"R 2\018W\003\138\154\1813j\"\177\006J\003d\128\012\012\213\216\136fXZ\128\136\228\149J\164\223\241\203i\244\153x\177F\238\205(\188\029\210\187(\224\180.g\166\245\222F\230\227\000\159+\003\164\224\161\218\244%\230K\158_\149\015\231=\020\005O\220~6\238\127dO\132\180\205\202\2346+7B\211\153\152H\007\186\132n\144&\248\161\2114\245\200\145i\015\255\179dQ\023\177\205\164\127X\131?p\156\223\153=g\006\020\t\161\1484V\254\182\\\191\128_\254\240\167\191\252o\000H\253\151\175\208/\242\194:\b\002_\202/\025P\201\021\002Gr\240p\220\217Y\147\227\203\225\140\238\206\145jv`Z\139u\020\007\183\137\251\236\243\206[\127F{2\165_\186\006\127\248\011\248\255\200\r\203nR6\179e\255\208\128\019\242\181\251_\026\187:\015io1\159\222-q\161t\239\138X\236\194\151\170Se\160\171\180\209\201i\153\129\248\031\221\175\182\150O\170+\145\197AB\205!|:\210u\217\174\194-\130\238>s\224\002\227oxp#'\202A\030\248=C\163\161~i\179C\014\134\249\191w\220Lef6v$\158Ia!\002\219\133\tS\181~\243\031\152\171U\002tT\023\004\159\1660]R\178U\232p\251\237\029\215\030\220\237\016`\237;\175x\163\157oi\241\031B\217W\209^\185\181O\213A\174\169M\003$\187`\213\r:)\142ZC\0116Y\005\165\255\138}\206\162\026\211\238o\025\139\228=\164YZb\195\180\005R\001\148\132\141o\141\163\004\188\029\250\229&\209\011GF\200\190\180N\254f=\007\215\248*\145\1833\r\191\129\229.|d0r\200\bU\029T\151\139\243v4<\149\003\205d\132\014\1416\200'\019j\146\167\130\234~S\140\193\0207'\127\199\237dd\159\230\0263s\018\1524" let d_8f38ae17980f4039d715823515fd56d0 = "group\",\"\\\\rgroup\",\"\\u27ee\",\"\\u27ef\",\"\\\\lmoustache\",\"\\\\rmoustache\",\"\\u23b0\",\"\\u23b1\",\"/\",\"\\\\backslash\",\"|\",\"\\\\vert\",\"\\\\|\",\"\\\\Vert\",\"\\\\uparrow\",\"\\\\Uparrow\",\"\\\\downarrow\",\"\\\\Downarrow\",\"\\\\updownarrow\",\"\\\\Updownarrow\",\".\"];function Cr(e,t){var r=Xt(e);if(r&&l.contains(Br,r.text))return r;throw new n(r?\"Invalid delimiter '\"+r.text+\"' after '\"+t.funcName+\"'\":\"Invalid delimiter type '\"+e.type+\"'\",e)}function qr(e){if(!e.body)throw new Error(\"Bug: The leftright ParseNode wasn't fully parsed.\")}ot({type:\"delimsizing\",names:[\"\\\\bigl\",\"\\\\Bigl\",\"\\\\biggl\",\"\\\\Biggl\",\"\\\\bigr\",\"\\\\Bigr\",\"\\\\biggr\",\"\\\\Biggr\",\"\\\\bigm\",\"\\\\Bigm\",\"\\\\biggm\",\"\\\\Biggm\",\"\\\\big\",\"\\\\Big\",\"\\\\bigg\",\"\\\\Bigg\"],props:{numArgs:1,argTypes:[\"primitive\"]},handler:function(e,t){var r=Cr(t[0],e);return{type:\"delimsizing\",mode:e.parser.mode,size:Tr[e.funcName].size,mclass:Tr[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return\".\"===e.delim?Ke.makeSpan([e.mclass]):Ar.sizedDelim(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];\".\"!==e.delim&&t.push(Bt(e.delim,e.mode));var r=new Tt.MathNode(\"mo\",t);\"mopen\"===e.mclass||\"mclose\"===e.mclass?r.setAttribute(\"fence\",\"true\"):r.setAttribute(\"fence\",\"false\"),r.setAttribute(\"stretchy\",\"true\");var n=V(Ar.sizeToMaxHeight[e.size]);return r.setAttribute(\"minsize\",n),r.setAttribute(\"maxsize\",n),r}}),ot({type:\"leftright-right\",names:[\"\\\\right\"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get(\"\\\\current@color\");if(r&&\"string\"!=typeof r)throw new n(\"\\\\current@color set to non-string in \\\\right\");return{type:\"leftright-right\",mode:e.parser.mode,delim:Cr(t[0],e).text,color:r}}}),ot({type:\"leftright\",names:[\"\\\\left\"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Cr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect(\"\\\\right\",!1);var i=Ut(n.parseFunction(),\"leftright-right\");return{type:\"leftright\",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){qr(e);for(var r,n,a=ft(e.body,t,!0,[\"mopen\",\"mclose\"]),i=0,o=0,s=!1,l=0;lp\006\182\141\252IN\222\225iN\255\221]r\185\248I\028\b\017\002\193B\004\018\164@\226\016\002$\144\224\197\172\134U\168R*P\170T\196\215U\214u\149\253\214\127u\149\1911\173nk'mg\237~\167\133\224\185\159w\191r\245\188hb#\223\004\135e2\134\198\n\158\255\231\254\219>\231\1907cS\127\250\252\197\002\r4\0128k\165\t&\152\209X%\212\255\190\211>;i\030\2163lxo\017\208\137\031\000|.\144t\246\207\222e\233\202\177S\142\029\192\150\003m\166\029.\160%-\1947\208\160\155\253'!X(!\224\133\154QQ\174G{=\019\127\186\191\237\239\186\204\127\020[\223\188}\168h\186D&\244v;\223(\174\185*\028F \r\022\227\130p\024\135%\000\254\250\166V\191\236_\247.7\b\012\137\133\230\181c\025B\232\000\247L\219\171\219S\194U\231e\024\221\177t\199#\201\137\002l9\192\176\161\001\195\002\241-\218\213\204\219\193~\152\241o~\254Z\246\0121\t\217\147L\211\rb\242\245\245\208\148t\141X\r\209\12717\242J\250\136\169\181\137x\169\136W\142\030\201op\254\193y\019S\127\172\019\014\167w\247v{gk[\183\208\150:TT@\n\140\178\169\030.@\134\011\237=$l\1796(\249\207_\212_\212\234\170\209\153\251\"Dn\251K\134\146\023\020\007\"\162Zs\137\181\237\131\218\028\144\178;\207h\203-\233\233\185\022\192\031 \241\199\206\208\178j\005\016\017O\221\248\023xA\012A\019\004\024\232\n\220M\215L\018\132\244\239O~\189.\171[\179\248[Z\020TmN\148m\148\152\181u\136A\234gg\175\029J\255/\209\140\143#\198\202\199\210\017T~\149\223\255\153j\182\187\208\005\242\"u!\135\215\167\234\\t\206E\233r\246\207\000\139\153Y\128\192, a\023\140K\233\025\\\144\207\004\150\186\003\247\018\t@\204\210\165\152 \136J\160\228\167#\149\"\229\028B\149\155\218\165\155\210E\025S\239\186uW\133\162qk{\254~\159\206\2049\247\167\202\022\200\154\189\200\173\166\n\171\178\n]\129\196\005J`\222{\247\182,\252d(\179DQ\139c\149\226a,\198\132I\254\182lvy\191Qj\151Ht7\146\174[\185\147\215\141=\161\207\bu\247\151\213wQe\201*m\210\136\b\197\1559\\\255z\140\185B\179\241c\247\188\153)\225\t'\028#\178_\246c\025\211\250e{\251\215\238tVQ\216\t$\160\255\026\232U=y\005\184lI1\015\000\206.?A\007\224\207\014\001\176\136\223:\180g\b\204\195\225\251\128\159:\224\249\229Y\227\127\029\191\016Y)\246\134(\254\169\0213\1443\195\012,}\225\000\128\190\219\000\128\194\184R\134\160\130\133C\217h\218\204\254r\185I\031\148O\141\153\182\218a\175\131\142x\223\007\174\240\025\015y\202\027{\022\215\018\252\1837\250E\239\207\202\t&\154\137\153\154\217I\166v\131*\n\197\192&\1820Y\180\189\253\196Wv\213\211Xs\157\244\214n\237\215\135:\175\155\250\004\160\026U\172\202T\165\170\207\148%\134#\176\227\204\029\007.r\200\199O\029M\140a\026s\024`\t\235\216\197^\174p\149\159\248E\205VO\220'\028\011'\195\135\225b\248)6\196\t\233\251\244S\2503\230\239\184\236m\245\031\190}\011P\1683F\222\179\246\225Q\159\202\255\151\139\158\242\149^\235g\253jV\188\191\226\169\222\192\138\\\209\183\177\205\205f\242k\231}:\163s\242\029\185r\186{\143\001\139#O\007o\164\157\169\2443\127\2440\219\229K\242\203'\199\212cW\029\1866\142K\223\165\151\137\239\234y\251e\250\246\235?m\140\206\156|\255\232\145\157+\151\012Ni\194/\243\221\246\2044\204\207\255\254g\127\2517?\249\241\143\026\236\217\177i\2456\185\238Z]z\184\216\223\207\203]\031\137\193\226\252\230\023\207\030|\243\224\148\147>p\194q\239:\228\160\003\246\217k\1435VZn\216R\011-\208k\178nMj\140V*$_\030\189Z\024\243\223\150\2552(\144\191\188rr$y\225[\138)PI\197\235\031\025k\147\226?y\208\188\"\165\242\027\000Mh\243\255\007\030\006OB\138\144\148[\161_\223\244\255]\179\252\139\242]\254^\227\215\204\2394\151\tN\195\216\128/g\128\158|\161p\24630\154c\237&\206\145O\175\137,\157K\210-\249L\246\157\247\004\151\004\2032\234\000\020F\029\018\130\185d>$\130x\241Cr@{\200\141__\210\134&\017\163\0224\222h)W\151\137\184\189\000\019J\196&\181\196\199\139\014U*\140\202|y\215\215\166vt\226\194\210]\196)\162\157\025\204\026b\031\031\028\132\003\235\156\128z\148p\n\231\180\025\016\141H\142\183EK\135\022\252\174\225\204\226\207\174\022T\142gc\n\027\193\179\027\2056\127\005Lu\249b\153\007\199wtA\b\198\165\166\248\198PX}jY\147\222\n\170{\186\172+(}o\1299\242\143i,\017\026\011,\215\196H\2013\148\134\177h\214Z\130\200\152\224\140\224(\016l/\169\207\253Nz2\233\153\189t\198d&P\240\140\151\204\172MF\232\193k\128dsA\135\1626$\015\140Al\169]\234D\174\007\172S\165\132\134\243\190\167!\025R\1767B\201\237\"f\138\1890\\\205\233\015\155\024Qb\235\201w\252\227\226\0199\247\250{\240\210\173\151\137\227F\136\235.mZ\016\243\006.\156\005d\142\022\175.\003\r)\1302\251\029@n\150\164\150\178\170\128`9X\"\202\230\132y\140b\199\1542\1286\149rv\134%kQVs!1\166\199Q>#\130N\030\020\142\181\231\003GR:\006\146\150\0001\160K\185\142\216b\214\156\139)Zk\011\0168\004\165\232S\185`\177\0249ch\163>\250\163\030\030fiH\0069\231\018\133\001\205\236P\237\151\234\198z\240N\188\245_Ys\205\018R<\190I\0245N\r\018J1\139\179\242q\225\160\005\000SG\132$\152\251\132!\\\143\152\141\165\002\218\216\0144T1&U\165\170D\137\"\158z\211\023\192\136\\\021U%@\178\n\019\166\197\234n\240'\159{h\178\133\131\002l\015\129p\005\225\t!)\014\1900\002\241HI@Z\"2\146\144\149\188\216\128\208\255%\133\228\203v\016T\132\015\201\018\153\251\205\189M\199\159{\182\154\021\127\249\180\028\150\216\186\153\235\132\233\241:a\023\204c\1589\022\018\142\162\016J\226P\022FE<\170\018P\147\136P\018\234\146\215\218@\029\176\232\236\141\244\0184r\029j\\\154\028\133C\237\152\021\012uQ\245\187\245w\146;\165\007`\noZ\146\150\229\196\158\191\000s\198K}\178\178\nmlD\220\212\216\235\020>L\140\195\0193R\027\216'\127\145\134\bx\137\188z\nK\172\143\r\149\2002\199\146\187\222\002\2067xp\173\188\149\229\018\005\219\212;e\b\212\152\226\143\017,kd\018\211\168n\214\159I\138\219\162\128*J{\230\b\005\201\164\161R&A1Y\018\159\242\143[z\216\ta\223\141\186\153\170]\028\224\196\181\158L\029\131\192yw\1830\1827n\023+\t\185\022T\216?\200m\005\234\028\195\145\204DP\193\133(\020|\194\232\194\030\198\148\204\133\147p\136\151\175\228\220i\199+\190\233H\155$D.J\196d\018u\175<^Y\028\237\200\187R\001\204\216\ny\166V+\151pr\200\226H\151U\198H\002v\139(\147\180\236\172I8y\199\210\t\149\156a\196\156\t\163Ra\209\025\006o\201gme\018G-\152\241\t\241\161\169\213\211\140D5{\024\005\017\204\003\216\"\000\150\243\200\130r\229\150k\183C\027\150\221q\155\223a\023\000\251\000\245ak:\030\221\241\228\142gw\188\228\012\215\000\184\005\168\239\208\244|\184\231\211=_\238\249\206\025>\001\016\235\143\001z\203\r?\225S\249d;S\ns\029\174T7\130x\231\205t9\182T\146[[_\156\173K\r\139\001\016\232\191\005\000\128\1746a\248)\145\190Z\167~d\192\241\142\030\014\227\004\144?0\014\023\006\130\166{\135X%\204I\022@\196qE\149\197,\231-4\170\139|\004\212M%RR\243\188eU\236YP\142B4\004,\151I8W\155\214F\b\239\248\144\029cO\004W\238eNeY\165r\017\"\195\170\130\\\141\001\132H\204sP\164\214\196\233\144\231\222\017h\025\233P\159K\190\253\166\127\176!\184\233W\239T\194\152Q\223?!\187\026\137\r\221\2186\152\159L\205;>\166\204N\023\226\227\018^k\219\131\170i\247\028Ji\210ST\127@\175\173H.{\198B\016l-_\173\213W\158\186[C\223\173:\195<=\180\142\230&\189\227\135\197\142\164I6^`u{\016\178\1782\218b\201S\154\165\229\135\230\015'\1829OCsm\171<\219\217\191_\234/\147\153\204\155|\160'4j\232\217jp\161t\251\170vuH\r*\209\142\202\1787nd\208\178\205\176n\007-\191\1782\154\214\210D?H\140\189\132\223\025on)\202\211#\198)?\b|\127im\134R\170\151\239G\187\177q`\254\170\127\011\007\213\225\242\211h4\153\159\026FI\207\181]/^\024\196\155\250\186\017\b\177\237F\166I\165NO\2021m\1392\154\025X5\205\244\137n\2303\245p\020U\154$R\212~7\151STJ$\146&\030\t\130\211\211J\189\211\238H\031\1640g\016\157\152\166+\187\021qU\213M\016\"\187z\194\245\025\211\153V\176\004\218\017+\132\206B\186A/\243A\1741\209\133$1\004S\204\004\147V-\199\206<\213%w\162cV\134auc\018\187\139S\151\161\212\144t\133W\176\139\161%}\018\030\197\199\137\031Ez(\193\228\208\247`\220\141\004\tf\r\000\014\199\189MI!\021\198\0151\143A\219\007\175\186\136\220\223\140\018\2100\1678\022\250\178\020\140\184\023\245\160\177\172gP\161|\138P\130\195\130\131\1363\134\020K\021\223\142,\160\031\154LD\000j\237b\028\226<,\163\\_\215Q\001\007Yq#ffk/\155\229Bo\003\220\161\149&]M\024\031\221\026\132hP\192\220\004\216L\026u\208-\133-\149\247l\196j-\227 X\1950\166]\134E\1809\1895\1421\131\139'\144\0271\154a\250\"`\162\236w\147N\19942\234\002\230\016\001p'2\226\229\\\163i!\021{\128\225D\233\255\145.\179`q\233\226\0311u\200\242B\0293Z]m\216\2295b^9\002\180\203\143\025\189\209\161\022o3\001\226\157\142\209\229Ka\\\000\230\140\136\179%\027\169\234J\131k\166}Q\189V\197!\028\212\166\196\133.x^E\204N\154\142\"\140\030ek\196o\149\170&\171-<\232\150\145b:\128Z\166\238\004\204\019\136\252\132)\0038\007\240\205\180!\155\248\012\006o85\207y\206\171\170;|:\179y\b\135X!n\131\146\138u\t\004\007\205$\253\163F\019\182O\172/\231\003\214_\150$\235\233\210\157\132\252\147\014\028\199m=\"\162\162\004\007@\1321j\179\002\219L\188\1559\149k\155\005c1B\029\222B\195\nq\144\029\153|\158\02007r\183|\165@\137\155\020'u\153\017g\153\1627\232\137\172K\241l>\234\197N*g3IN\231 \142\149J\194m\165\022Bp?\221\205\017\198\226\173\200\145\014F\250\012E\254\024\194\255\019\146\248\172Z5Gd\183u\021S\247\225\243~A=\021\173Z\018YH1_S^#^\217X\167&\001\014\012\206\0293\204\160\166\230\017&r\164\171\2274\181qFE\1764\203\172Rb&q/\202\208n\216Z\145\134\208\148\1713\191\148\247\005\243\179\128j\"\149\219\195\160\164\146\181\018\224`\142\"\148\024\196\177\0179\255D\178Zx\029\rA\1550\202\174\007\227\132\205;\152NM\152|\165\182\004\141]\226\131;\160\152\012\141\239\176\165?\151WDV\220\001\134$\152\205\196\164\006\029\238\224wDL\170\169} \152`\160\185\166\215P\172\202\152`12\140\142\215E\207\174\228]\216\166\0038T\197\165\0195mLI\146\028\134\237\002I\2288'N}!\020\0113l)\215\136\223\001:\164\204\017\137\207\202C\239\1687z\163R4\217\023\137\183\244\236A\020\197\240L\205\028\142\131a\130X\170\186\020\197\na\176\216Z\027" - let d_95e6d8b2e4f4e5a25b3f27c86326a4cd = ";\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/\n" - let d_96c4d8e2622ac6552ccf67643b20f09c = "\",\"\\u03a1\"),ie(oe,le,xe,\"T\",\"\\u03a4\"),ie(oe,le,xe,\"X\",\"\\u03a7\"),ie(oe,le,xe,\"\\xac\",\"\\\\neg\",!0),ie(oe,le,xe,\"\\xac\",\"\\\\lnot\"),ie(oe,le,xe,\"\\u22a4\",\"\\\\top\"),ie(oe,le,xe,\"\\u22a5\",\"\\\\bot\"),ie(oe,le,xe,\"\\u2205\",\"\\\\emptyset\"),ie(oe,he,xe,\"\\u2205\",\"\\\\varnothing\"),ie(oe,le,de,\"\\u03b1\",\"\\\\alpha\",!0),ie(oe,le,de,\"\\u03b2\",\"\\\\beta\",!0),ie(oe,le,de,\"\\u03b3\",\"\\\\gamma\",!0),ie(oe,le,de,\"\\u03b4\",\"\\\\delta\",!0),ie(oe,le,de,\"\\u03f5\",\"\\\\epsilon\",!0),ie(oe,le,de,\"\\u03b6\",\"\\\\zeta\",!0),ie(oe,le,de,\"\\u03b7\",\"\\\\eta\",!0),ie(oe,le,de,\"\\u03b8\",\"\\\\theta\",!0),ie(oe,le,de,\"\\u03b9\",\"\\\\iota\",!0),ie(oe,le,de,\"\\u03ba\",\"\\\\kappa\",!0),ie(oe,le,de,\"\\u03bb\",\"\\\\lambda\",!0),ie(oe,le,de,\"\\u03bc\",\"\\\\mu\",!0),ie(oe,le,de,\"\\u03bd\",\"\\\\nu\",!0),ie(oe,le,de,\"\\u03be\",\"\\\\xi\",!0),ie(oe,le,de,\"\\u03bf\",\"\\\\omicron\",!0),ie(oe,le,de,\"\\u03c0\",\"\\\\pi\",!0),ie(oe,le,de,\"\\u03c1\",\"\\\\rho\",!0),ie(oe,le,de,\"\\u03c3\",\"\\\\sigma\",!0),ie(oe,le,de,\"\\u03c4\",\"\\\\tau\",!0),ie(oe,le,de,\"\\u03c5\",\"\\\\upsilon\",!0),ie(oe,le,de,\"\\u03d5\",\"\\\\phi\",!0),ie(oe,le,de,\"\\u03c7\",\"\\\\chi\",!0),ie(oe,le,de,\"\\u03c8\",\"\\\\psi\",!0),ie(oe,le,de,\"\\u03c9\",\"\\\\omega\",!0),ie(oe,le,de,\"\\u03b5\",\"\\\\varepsilon\",!0),ie(oe,le,de,\"\\u03d1\",\"\\\\vartheta\",!0),ie(oe,le,de,\"\\u03d6\",\"\\\\varpi\",!0),ie(oe,le,de,\"\\u03f1\",\"\\\\varrho\",!0),ie(oe,le,de,\"\\u03c2\",\"\\\\varsigma\",!0),ie(oe,le,de,\"\\u03c6\",\"\\\\varphi\",!0),ie(oe,le,ce,\"\\u2217\",\"*\",!0),ie(oe,le,ce,\"+\",\"+\"),ie(oe,le,ce,\"\\u2212\",\"-\",!0),ie(oe,le,ce,\"\\u22c5\",\"\\\\cdot\",!0),ie(oe,le,ce,\"\\u2218\",\"\\\\circ\"),ie(oe,le,ce,\"\\xf7\",\"\\\\div\",!0),ie(oe,le,ce,\"\\xb1\",\"\\\\pm\",!0),ie(oe,le,ce,\"\\xd7\",\"\\\\times\",!0),ie(oe,le,ce,\"\\u2229\",\"\\\\cap\",!0),ie(oe,le,ce,\"\\u222a\",\"\\\\cup\",!0),ie(oe,le,ce,\"\\u2216\",\"\\\\setminus\"),ie(oe,le,ce,\"\\u2227\",\"\\\\land\"),ie(oe,le,ce,\"\\u2228\",\"\\\\lor\"),ie(oe,le,ce,\"\\u2227\",\"\\\\wedge\",!0),ie(oe,le,ce,\"\\u2228\",\"\\\\vee\",!0),ie(oe,le,xe,\"\\u221a\",\"\\\\surd\"),ie(oe,le,ge,\"\\u27e8\",\"\\\\langle\",!0),ie(oe,le,ge,\"\\u2223\",\"\\\\lvert\"),ie(oe,le,ge,\"\\u2225\",\"\\\\lVert\"),ie(oe,le,ue,\"?\",\"?\"),ie(oe,le,ue,\"!\",\"!\"),ie(oe,le,ue,\"\\u27e9\",\"\\\\rangle\",!0),ie(oe,le,ue,\"\\u2223\",\"\\\\rvert\"),ie(oe,le,ue,\"\\u2225\",\"\\\\rVert\"),ie(oe,le,be,\"=\",\"=\"),ie(oe,le,be,\":\",\":\"),ie(oe,le,be,\"\\u2248\",\"\\\\approx\",!0),ie(oe,le,be,\"\\u2245\",\"\\\\cong\",!0),ie(oe,le,be,\"\\u2265\",\"\\\\ge\"),ie(oe,le,be,\"\\u2265\",\"\\\\geq\",!0),ie(oe,le,be,\"\\u2190\",\"\\\\gets\"),ie(oe,le,be,\">\",\"\\\\gt\",!0),ie(oe,le,be,\"\\u2208\",\"\\\\in\",!0),ie(oe,le,be,\"\\ue020\",\"\\\\@not\"),ie(oe,le,be,\"\\u2282\",\"\\\\subset\",!0),ie(oe,le,be,\"\\u2283\",\"\\\\supset\",!0),ie(oe,le,be,\"\\u2286\",\"\\\\subseteq\",!0),ie(oe,le,be,\"\\u2287\",\"\\\\supseteq\",!0),ie(oe,he,be,\"\\u2288\",\"\\\\nsubseteq\",!0),ie(oe,he,be,\"\\u2289\",\"\\\\nsupseteq\",!0),ie(oe,le,be,\"\\u22a8\",\"\\\\models\"),ie(oe,le,be,\"\\u2190\",\"\\\\leftarrow\",!0),ie(oe,le,be,\"\\u2264\",\"\\\\le\"),ie(oe,le,be,\"\\u2264\",\"\\\\leq\",!0),ie(oe,le,be,\"<\",\"\\\\lt\",!0),ie(oe,le,be,\"\\u2192\",\"\\\\rightarrow\",!0),ie(oe,le,be,\"\\u2192\",\"\\\\to\"),ie(oe,he,be,\"\\u2271\",\"\\\\ngeq\",!0),ie(oe,he,be,\"\\u2270\",\"\\\\nleq\",!0),ie(oe,le,ye,\"\\xa0\",\"\\\\ \"),ie(oe,le,ye,\"\\xa0\",\"\\\\space\"),ie(oe,le,ye,\"\\xa0\",\"\\\\nobreakspace\"),ie(se,le,ye,\"\\xa0\",\"\\\\ \"),ie(se,le,ye,\"\\xa0\",\" \"),ie(se,le,ye,\"\\xa0\",\"\\\\space\"),ie(se,le,ye,\"\\xa0\",\"\\\\nobreakspace\"),ie(oe,le,ye,null,\"\\\\nobreak\"),ie(oe,le,ye,null,\"\\\\allowbreak\"),ie(oe,le,ve,\",\",\",\"),ie(oe,le,ve,\";\",\";\"),ie(oe,he,ce,\"\\u22bc\",\"\\\\barwedge\",!0),ie(oe,he,ce,\"\\u22bb\",\"\\\\veebar\",!0),ie(oe,le,ce,\"\\u2299\",\"\\\\odot\",!0),ie(oe,le,ce,\"\\u2295\",\"\\\\oplus\",!0),ie(oe,le,ce,\"\\u2297\",\"\\\\otimes\",!0),ie(oe,le,xe,\"\\u2202\",\"\\\\partial\",!0),ie(oe,le,ce,\"\\u2298\",\"\\\\oslash\",!0),ie(oe,he,ce,\"\\u229a\",\"\\\\circledcirc\",!0),ie(oe,he,ce,\"\\u22a1\",\"\\\\boxdot\",!0),ie(oe,le,ce,\"\\u25b3\",\"\\\\bigtriangleup\"),ie(oe,le,ce,\"\\u25bd\",\"\\\\bigtriangledown\"),ie(oe,le,ce,\"\\u2020\",\"\\\\dagger\"),ie(oe,le,ce,\"\\u22c4\",\"\\\\diamond\"),ie(oe,le,ce,\"\\u22c6\",\"\\\\star\"),ie(oe,le,ce,\"\\u25c3\",\"\\\\triangleleft\"),ie(oe,le,ce,\"\\u25b9\",\"\\\\triangleright\"),ie(oe,le,ge,\"{\",\"\\\\{\"),ie(se,le,xe,\"{\",\"\\\\{\"),ie(se,le,xe,\"{\",\"\\\\textbraceleft\"),ie(oe,le,ue,\"}\",\"\\\\}\"),ie(se,le,xe,\"}\",\"\\\\}\"),ie(se,le,xe,\"}\",\"\\\\textbraceright\"),ie(oe,le,ge,\"{\",\"\\\\lbrace\"),ie(oe,le,ue,\"}\",\"\\\\rbrace\"),ie(oe,le,ge,\"[\",\"\\\\lbrack\",!0),ie(se,le,xe,\"[\",\"\\\\lbrack\",!0),ie(oe,le,ue,\"]\",\"\\\\rbrack\",!0),ie(se,le,xe,\"]\",\"\\\\rbr" let d_97a004cb2bb68cf384863688a3675de3 = "j\239\230\025\005E\016\187\137N\191X\186#RXYJuZw\214\157\209Sc\005\191\131Ia$\157E\236\170\016\243\027\177\165!w\225-\155\226\219\253\220\179\197\138\212n\021\187<\186\150\019\172\214+\029\015\162reK\252,L\028\024\226\228\228\153\163\024\228\130\163\221\212\235\241|z\139\016\203\192\252u\180\212q\t\163!$pj\2141\152T\193\194%\164\167I\158\162\192\005f\018* 2|\017k\232\242\"g#G\209\171\2145\246\127\001\t\204\011\157\213\160\168Ok\179\158F\014U\134N\195\132s\142\172^\165\168a\000\202# X$\208\193\0176e\226i\183dY\180D\145\130\2136\005\225\221\170\146{\142*\n\2002Q:J\145\196:\139\150\176\250\238g\0036R\168\131z\016\143v,\014\181\154\225\209\143\214C]\r\154\137\239\182\1646\137X^\"\159V'\142E\190(`\193Y\225\024?\1747\2050\177\006\139\149#j\\\020\179\230\201A\205\223\197=\007\157\159q\165\234\030\159\017\183\151\018&%K'\203Y\217\029=F\208$H\231\238\160I!\246%N\129\144(\193\004\207\215\147\180\237\016zj6)\172\186\149\180\012\155\027#\2086\190\198\015\201O\128q|o\031(\228\129\018{7x\2080\btr.NRt'\2149\018\018\217J\016\237\191\014I\148\020n\194- \130\224\029\188\141\212\134$U\r\017V\015\138.\243U\146R\130\160\227\202\142\153\136\r:\209h\182A\131T\205\128]\022*\004\000%L\194\182\167vO]\136\025\023?\028\158S\0278T\189\166 N\202\247!\137\186c\181\174\229e6m3\227\243\146\228\180\208)\027p\b\142.\175\190m\175\163b\208\169vF\163\224\185\191\224\212*a\016v3\027\018\253\138\231\133\247\1887^\1842m4\234\220;\237\165?p,\175R\179\130v\166\127i\1740'W\206a\234\242|blq\212\180\029w\250L/\159\22237g\129\141\153}\1842\214\166\242\255\206\145:7+\017U\199\160j\150C\153g.\149\180\030H\003\169#\243\139<\172\129\nM|t`d\018\200\189o\129ohp\193\181\162\216Q\161g\\\025aP\175\173]m\031\249\198\187##vb`6rr\164\136\202\228\179\210|\147\189\247\014:\191J\t\241\212\2013\029\ro\138\142D\243\023_$\168\251w\217\139RX\019\179\1645\254\238\194A\208_\247(n\255\204Z\023\156Z\146B\230$\005\029P\002\164)E\029\131\168\011\177\012\201\018\184\228`\147Em\154Eb\177 \r<\223\205\204\012\223\135000\234\129P\217^\027\253\239?\021\136\160p*\024t\"\229\1600\011\001,\026[^I\230\028\228\192!\218\157\130\021\137\160O\027?$\201\027\236\170L\208%\0155]\232\218\203\223\0174S?4w\023\016\146\146\134\225y\2266Ud\031\142\171\234l40b\223p\182\028\156i\150\201\185@\240Y\171X\024\201r(\171w\026\255g\131\243\146\210\007\012\173\028\151\239P\147\167\178\241?\204\nCH\026G\241\232\242\224\204h\183l\031\177\249C\021\239\204;\237;5\200\236\249u\205\185i7\171\027z\165\028\172\029\023\018?\\\030\183~\226\184\232\181\137\183\198\151!`\223H\224\2523\146 \176\218_\b\019`\248(\003\242d\185B\212\016\214\192\201\253\232\1594I?g\218Y\005\030\242\007\169$\207\178\234u.\251]\132\249\175\134\175\245z\176\238\r\026\220a\018\\\159\205\1855\011\158j\014\024;\201\\\025\132o\197O!#\137 I\018O\129\223\174-\213g\228H\187Y\218\128\020\204 \189\229\248\194\246\184\190\004W\183\153\137\152i\193F\1709\164\187\241eO\012\204f\206\178\237\208\224^\006\242\215}\199\161U\017\162\142\167nF\002\005\156\236\216\230\2503\251g\191pk\178\003CaR[r\246\238\130\r]\247\236,\012|\208\011\194\2436&\162\021\202\140d\160\185x\204B\130\167\145/T\242\137\160\154\153\140\244\244\139Da\214\156\025\216\019\129\149k\250\147\133\017*\226\018C\151nW\168\211\170NTs\195\246\232\194\b>B\2430\251\179C\146;\242K/\175\209\006\130L\223\224lE\215\248R5+\212\005\234_4\210:\138\020\002O:6\233\236\216\236\2387 \237V\215D\219-\187Gj\145Lg\224O\171\019\176\140\226\254<|\164\011\188z\159:\003\203\219J\164\129\171\005\253KS\242\226O\0271\217_*/G\212\157\1470u\131G\174\206\161\219=z8~\244\007\r\217\239%3L\026_\026\217\210\022\249>\232\225\165sc\172(\017;\220\2044\144\248\224\237\235\166\238\237\176\225\127\2371\169\156\204\134\004_?#Q\160\183g\236\154`\015\025U\222\018j:{\251\198Q\243pC\170\0078\1572\127\157\199\b\207u\240\235t\028\015\030@\157\215\133\178\137Q\237\188#}\191\210j\n\163mE\160S\158\017\163o\239\146n\152\213\221\141\246[\157sL1$\207m\138\168\184\182m:r7\233\138\222\251L\168\199\169\210\b=\138s\130\241\192\186\0253\151\200\216b\144\211\238\019\253\199:l\021p,\173\186\186\000\238p\026\\\016R~\003\170|Ap^ @\149?\161\137\169l\239]\215\198\180\175\181\236\017\030\018\196\238\147Dk\140\\xp=\006\253\219\231!-S\223\207\144\023\186I\183^H\029l\217W\232\223.\\^\222\184\218\216\157UL\218\143\012F\143'\1717\218\254\223v~\200E\005\157\178\168\158lG\185\194\225\149!&G3.M\014\127D\142\158_\149(+'&4\222\025W\151\238\157\170\192\007C;c\239\021\017\189Z+\214u\239\219\138\131\198\183\tH\233Pp\190$m\179\238-\238k\143\130\000c[\167\028\146\204\149\255\173\027\166\238D\232\1865\198\177\180\1341\014\231N,\004\206\152\187\rO\152\139MBy9UPp\002\0074\227\029\159\170\229\182\170\024wb\192\144\252\243\011 \011/\144\201\136\215\002\1401\023'B\249[\177\026\n\210\162\130@g6\031\003C7\131\140\187\168uP\168\146\191\223\190\155\201\131*\021\016\132\228\\\196\247\003\215\154=\139\205C-\170\019\186\176\156\bA<&\004]\192S\024).\135@\242\185 H\rWU\189\019\169\1402\t\218\199\221+3\129*c\161\202h\227\023\014\160\199\2461\012\217\229\134\153p7\138OE\021\"\233\176\239\023\014\232-'\206x\157\140\139+*\198\233\020}\0029\142\012M\140j\223/\197XB\238\202\137\146\027\195\206\246\143\253g3\235\t\172\245\031\248\227l1\198N\135J\185\161\226\169\0208\202\218\249rL*\243\2099:sw\188\1581\193\195\136\160\212\243\222m\205\149\018s\247#\212@\153\1479'\215\031L\245\019X\253\031p\183P'G\199\192\178\206l\175\214|(\158JA ie\193\234\214\177\027i\157\012\191\152\208\236l\018\161$\030*\140\135\018J\247\167\016\150O\222\028\ni\178i3\183>\152x\170\141\232U\180\138!\139?\016\221\031\127\190\235-Aw\230o\174\254\007\175\150\031\202\220*o\227\172/R*\202P\191\139\142\029\212\207\211 f7\215z\231Y\156\149\246\012\200\2195W\207\199\202\193\132\168\nF\157U\220\180\185?\006f\148\n\023\207D\021\026s\228\027l\250-\163\236\255\165?\220x\185r.v\214#\152\158\030\237\249\144\157\133\192\024\024\249\245\194\145h\b(\164\206\178\194\028\129\006A\133%\184\166U\022\228\215\255?\154\140\216\2282e\030EY\169\175\187\247\224\195\161\240\rNZ\184\004\139wy\204n\233]\213\196f\226G\206\244\229\t\1460 \214\221\130c\248*\017\017\137e\196V\200m\226\206\0192 \176|\242\139+O\166\195\1831\024C\176(P\022\176.\180\014\235.\192\249V\011\194+F\202\003;\153\149\bK\131\026\195=\190\171{\242\194\155\179\228\151\182wP9z\207\178\184\190iq\030O8\185\171\240F\026\017\165\030\157V\241\211\230|\211\254L\143h*\178\216\196;l\192Vm\019\237\244\181\161n\254\195\179\221NI\208\171i}\004h\198\127\208\140\245\132\012\227\002\154\150\134\177u\1765\023z;\231@\025\180\168\216\221\167\176\241L\225\159\158\156Ae\231\207\211\247\164\195H\161Y8\199\221,\213\183\r\174\131/\183\001\217d\191\162\162\226\250\144\003\187\142\237\242*\198\213\194\180\146\225\162I\191\002\024eF]\004U\006K\167P\188\179\229\017\134\162\157\158vc`\159\030\130\224\137\202I\216\138\018\004\213z\216\215\239\142dS\020\233\162\154\174\005\t\b\014\147L\153&^L3\133\198\175\191\236\243\197\191\156>\235\029l#\154J\134#\173G+\232\163\204`m\209L\145Un0{!\223L\192:lq\161\153~'H\163\163\024C\"\225\1788\206\168\212\171\000\003UvL\197\133\024\218,\b\127\166\192\028P\028\190\232S\238}\247\030kKCn\022\218\208\167\198\204\247\027\200\238[9\"\197\203\179\204\154\155N\r\238\012\181\219\195\031\22316L\203\255]\241\236\237\195U\240\212\146\183\197\154\243\164\183\149\015\251\215W\253F\183\190\169{\220>P\0014bV(\143\018\244\191\002\147\133\146\236\179cQ\242\231Rz\n\174\152uc\147\000\176\201\1281E\204D\184\170\214uTTu\245\230\167\172\137I+\174\200\207Ve\228\217\200\193\193NS\169\006\134r\210\b)\252\248\249\157\155\nT\155\197\180l\226\234\003Es\223\030\197\232K\022\242tU\234\024\188\211\235\017\220lO\004(\220z\254iqYU\150[2F\2286\151\169\175\019L\187\198L8}}\223P|\226\197\161\197\027\203\185\005\238c\162\169\020\004B\226\211\209\176\246\217\167\225kq\135\229;\149S\132\tw\132\140\1968$\255U\022I\236\202z\166+\0292\220\0117\150n\184\1838\182\231x_\147\170mTe\183\214k\203\241\138#_\239,\156\158\031\222xqq\252F\144M\248ZE\142\1862#\163\189>5\184\168\220\229q\178Z\149m\201%\007\213\198\199F%\135Gf\150$-\193c/\185\176\240\026y\186^\211KY\016f\193\142\193\166\154\129\142z\223b0\023\021''f\159\223#@w\207T\162<\150>\157\155\250\015\245'*\197S\153=\173m\019\168\223\\\224\171\227\136\153\208\226>\237jiu\021\029]\184\218g~\246\227\2533\011+\224\239\135\178\203\215v\148\176\242\204a\242\179=\183r3\202\214\149\132\130\207\236/j\232Uy\149cW\tn\174y^\158\155\221\211\162Y3o\027m\024Q\240\217O\155~U\155\250\182\235\248F\166d\235\205\139\027\205\207?\252x\233\250\029mcaMH{h\139\144\248w\194\019NZ~\213\003'\254\158\b\132\147\150\239t\161#j\182\216R\130\220\215\248c,\207\194\2098\134\174\144\166p=9!R>Ke\005\251\146d8MY/\016\007\164\195\175\187\159y\014D\157\215R7\004\234\178h\192\154\160C'\244\185\134\215\139+\t\155kz\137>\230\190\201\156\197\235\143PG{\230\149El\163p\005;\221g\136wJK\136w\221\167\015\204\237\136\173y\229a#\162\248\030K\176\204\160\031\149w\216\230bs\204\030=\233\168\027*\246\205-\143\220J\230\250\179\233\214()}h\184\207\028\152'#\183\229\150=r\169\145\155:f\246\136Q\139f\023\210\199\128l\164 \021\136\202\235\028Pu\215\n\2188\165\183\190\249i\190\250-\223rBcG\197\170\225}\167'\197_\213\204l10\201,\183 ?\197%\139\154\232 \163\154S.0\011" @@ -406,6 +400,8 @@ module Internal = struct let d_e4a12f7ec4801d06858e634cb2f32ebc = "\018\028\204\199H>\155\200d\242\159\131\000\016P\247\201\139\005\011me\199\005\027{\016\000\214*7\1888\224\167.Y\024\164\031\218\025\016\192\000a\160\194h\021\154\245\017\203\192\139\007\139\128`6\231\226\012r<\220\025\145\156Ql\012\254A5\147\185\011(bj\2012\200@\199\166a\020\016\185J\031\185x\196\2477\002\128S\1514\189\137=\136af\003Y&\161[\191\192\246\147\012#H\242x+-\145\185\142\202a\004\240\172_fW\209F?\134{\161\219\210\003\167p\018\134\2174\236\141U\221\156\196<_I/_<8t\002\250F\253X$\171?\168A\2473\239\139\172\230?\000`\192b\176 \206\000\224V\192RKp\227\214Z\006V\245\180\176\017\196\153\023\183\135^Fs\250qX3\159\164\139#\183o\156\025d\031\209u\240\168\174\006" + let d_e94c8f28d2a123393c1fd370776b6c2d = "erit;\n outline: 0;\n padding: 0.4rem 0.4rem 0.7rem 0.7rem;\n}\n.odoc-search .search-entry p {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry:focus-visible {\n box-shadow: none;\n background-color: var(--target-background);\n}\n\n.odoc-search .search-entry:hover {\n box-shadow: none;\n background-color: var(--toc-background-emph);\n}\n\n.odoc-search .search-entry .entry-kind {\n grid-row: 1/2;\n grid-column: 1/2;\n line-height: 1.4rem;\n font-size: calc(var(--kind-font-size-factor) * 1em);\n font-weight: bold;\n text-align: right;\n position: relative;\n bottom: 0;\n}\n\n.odoc-search .search-entry pre {\n border: none;\n margin: 0;\n}\n\n.odoc-search .search-entry pre code {\n font-size: 1em;\n background-color: var(--li-code-background);\n color: var(--li-code-color);\n border-radius: 3px;\n padding: 0 0.3ex;\n}\n\n.odoc-search .search-entry .entry-title {\n width: 100%;\n display: block;\n grid-column: 2/2;\n grid-row: 1/2;\n align-self: end;\n line-height: 1.4rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.odoc-search .entry-name {\n font-weight: bold;\n}\n\n.odoc-search .prefix-name {\n font-weight: bold;\n}\n\n.odoc-search .search-entry .prefix-name {\n opacity: 0.7;\n}\n\n.odoc-search .entry-rhs {\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-content {\n flex-grow: 1;\n flex-shrink: 1;\n min-width: 0;\n}\n\n.odoc-search .search-entry .entry-comment {\n max-height: 1.5em;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.95em;\n grid-row: 2/2;\n grid-column: 2/2;\n}\n\n.odoc-search .search-entry .entry-comment ul {\n white-space: nowrap;\n display: inline;\n}\n\n.odoc-search .search-entry .entry-comment li {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment ul>li::before {\n content: '\226\128\162';\n}\n\n.odoc-search .search-entry .entry-comment div {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment p {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment code {\n display: inline;\n white-space: nowrap;\n}\n\n/* First level titles */\n\n.odoc-toc>ul>li>a {\n font-weight: 500;\n}\n\n.odoc-toc li ul {\n margin: 0px;\n padding-top: 0.25em;\n}\n\n.odoc-toc ul {\n list-style-type: none;\n}\n\n.odoc-toc ul li {\n padding: 0.25em 0;\n}\n\n.odoc-toc>ul>li {\n margin-bottom: 0.3em;\n}\n\n.odoc-toc ul li li {\n border-left: 1px solid var(--toc-list-border);\n margin-left: 5px;\n padding-left: 12px;\n}\n\n/* Tables */\n\n.odoc-table {\n margin: 1em;\n}\n\n.odoc-table td,\n.odoc-table th {\n padding-left: 0.5em;\n padding-right: 0.5em;\n border: 1px solid black;\n}\n\n.odoc-table th {\n font-weight: bold;\n}\n\n/* Mobile adjustements. */\n\n@media only screen and (max-width: 110ex) {\n body {\n margin: 2em;\n padding: 0;\n }\n\n body.odoc {\n display: block;\n }\n\n .odoc-toc {\n position: static;\n width: auto;\n min-width: unset;\n max-width: unset;\n border: none;\n padding: 0.2em 1em;\n border-radius: 5px;\n margin-bottom: 2em;\n }\n}\n\n/* Print adjustements. */\n\n@media print {\n body {\n color: black;\n background: white;\n }\n\n body nav:first-child {\n visibility: hidden;\n }\n}\n\n/* Source code. */\n\n.source_container {\n display: flex;\n}\n\n.source_line_column {\n padding-right: 0.5em;\n text-align: right;\n background: #eee8d5;\n}\n\n.source_line {\n padding: 0 1em;\n}\n\n.source_code {\n flex-grow: 1;\n background: #fdf6e3;\n padding: 0 0.3em;\n color: #657b83;\n}\n\n.jump-to-doc-container:hover .jump-to-doc {\n display: inline;\n}\n\n.jump-to-doc {\n display: none;\n}\n\n/* Source directories */\n\n.odoc-directory::before {\n content: \"\240\159\147\129\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-file::before {\n content: \"\240\159\147\132\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-folder-list {\n list-style: none;\n}\n\n/* Syntax highlighting (based on github-gist) */\n\n.hljs {\n display: block;\n background: var(--code-background);\n padding: 0.5em;\n color: var(--color);\n overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n color: #969896;\n}\n\n.hljs-string,\n.hljs-v" + let d_ecbaa97b8be9573105676709e2dbc384 = "3\252C\149\147\203\185\\r\202\173\144:G\211n\211\195\161\151\006X\177\234L\234\146(\017\194\186D\0211(\230S\228\157\171{\167\211\235T\184\155\187\199>\128(\168\012\185\203KKS\189\248\242\004\248\197\236\142\201\014\180\"\015Y1\224.\189\142N\201\r@U\211D\208\205\005\129%\217\231\192\128\149\127\158\216\015p\016\014I\247\194\176\1403\221\210\167\238\180\212\012v\141\251(\178]1\1759\018\157\161D\141\191\250``\172\026\201_z\255\226\210!\160\229Re\167#\128\178\025By8=\230\230\1288\030\167\023\014\250n\156\232\249\b\172\156\024(\215\145Cd\131\146F\194\213Z\250\188\152[\175E\248u\220\207\by\216\152\150\238\169\242\\\240\210j\197m\213\158a\181}\031\236\168gZ\201\019Et\213x\198e\158\215\002]\160\196\154\249\184\244D\016\168\152\147\022\030 \180\245\127\145\151:7C%\215\222\019\245\254\221N\019\233\135NxJ\156A\019\248;\217f5T\141bi9wIH\197C\171Kt\001\238\197\002\235\232*\172\022Dt\185\204e\200\210\168\216\029\242\224Qe\0054\225y\197+119\188\199Z\255k\231\019\132\212\225\186;S\007Y\218m+\191\204\028JI\206_\012\161\130\250\168\230\151\195\135\253\000I\216\179!\1764'}\250I8\208\135]\242Fj\002\140\135\014\239\165\002\210\141\177'\147w1J\169\181\169`K:p\007s\245*b\168\185\141\176I\186\0152\011\251\r\171\144\236j\237$\139Z\222\129\241\206R\133\n;\180[\255\238\200)\195%\193\026\213\158<=\233\007\182n\153\214q\146\193\181-\001\167\206\"\146\214?J4G\214\2181\160E\171\155\213A\165\133\253\185F\175\254\177\b\180e\231\140\219f\172T\218\154\218>Y}~\239\212\155\171\174\172\223\015\017\004\0123\173\020\228\148\2409\227K5\203^]\163e\133\011&\222\245p\206q\171\211H@\168U\149\130\245\251a^\158\149\n\031}\171\1734\160n\255WH.\005\151\2119\\\007\201\235\018\209\238\232_H\131\144\19167\247\182\146\181\000\174\194\166_\158~y\209/\237\029\140\184/~\143\219\253Rv\156$\251\220\146\167uPU\228\136\179\209\239\2547o\1275s\173\195\189\246\r\217\218e;\2021\018\177\012\251\141v\214C\172\177\150\139o\244\245\031Y?\250(y\011\219D\167\140\184\197/_\017`x\185:\252\229c\199\219t\130q\161#d\187\241}Q\\\130\160\161\214\029u\151\201\158\023'\200\157\021\191\150\001\002G\214-\176\222\172F2J\223!\211\012\182\226@\160\173PqP\247\249B\157P\1346yZ\029\150\146\205\129\187MD\218\227?\231)\245\019bn\155\244x\220SRV\210_Y\180[\167<\222\215Kj\234\150\185\194\r\253u\246\2430C\\\153\201\247\1796\150*.\231\004\023\tI\163=\159\217\170r\234\2522\182\149\236@\169\004)H>Q\029\156SY\028\157 ?\187h\255\254\216\195\212\020L'u\215Y\194\136\006\211`\022\006\206h\162\144\139 6\b\190\0034t\227Q\132\"\t\226\168t\239}\189\167\001\166\"\181'\241\025*\128O\023\135C\190G\183\015\177\193\135\216G\234d\193\238\207\239\004b\175\020\228P\209;\185\1907\229\030\157|UZ\242\158_m\185\206=\b\149\183]H,+\196\143&\019_\255\199E\238Eh\023\191\019\166\012\237(/\138.\019\1484\244\145\148\028\019\236q\027{T\175m\253\202\233/\235\171\158\231\176_\236\151d.8\192\231\1988\149\222+w\n\188,'F\020Z\025\2268_\254a\131\141\235DP\193\172F\188\012\163P\224\bY\182d\163#\249\155[38\159}\225\163\232b{\227\175\222p\153\026^c\016\202\014/7\006N\232{\203\2026\203\018\127\022`MTLL\023\174_\154\200\023r\252K\230\149\139N\176\153\187;X\232\180'0\235&\147r\018\146\178\172K\239~\194f\175\237\180-}\238\130\003\012\209\133\018Q\195\219\140\230\024G\240\239\133\210\184`'\227\207\130\176\145+\015\209\012\186\t\026\255\179$]Z+\204H\199J[\217\151\227\233\230\242\158\130o_0\186\246\t\216L\190\178\136_qQi\155\167$\192n\148B\021`\249\223kE1\174\193\165\024F\024Dv\156\251T{\200\221\172\253\187%!\185=g\203\019\230=\028\016<\132~H,\221\004C$\213\204\157fQ\176\194x=DK\\\243\249y_\234\202\205r\179\1827\173\164\241_\137\178\196\028\204\253oz\"\156\006\147Cb\205\216\230\0126\246\254\151U\238\241\186266U\146_z\169?Bi\"\147\237\143\217\146\206?\248\221\1925\153)\169K\202\r\153\187K\172\190~\149\189\011o\139w\240\186\171y\172\b\130\127\183k\169\178\234G\144\208h\170l\157\170}o4\156\153\129b\200\146\137\246\236\024\159\1779<[\179\231\243\187\204\212T\230\129\242\150\255C\198\148\018K\204\128B\197~\163\"\1506H\221x\253\137\150\248W\164\150\218\140\028\141c\197\225\236\180\184\185\"\226\004B?\203\131\2095\020\250k\230\212Y8cq\229\135]\011\238v\215\219\024\179to![\216\189\161zl*l\205\184+\030&\196\228\002\154\"G\243\135d\222bX\011SZ\168@\223Pw\235\185\153\021uB\219\022b\218\226(\012\167\188\221\199\229\015\188\154o\127\023\024\191\002\018\163\160\140\180\173n\161\134?\180\253\209{\023\179|\017\158\011\236\220\224\186ES\159TP\145\176\164\225!\164I\175\1479\220\198*\171\141EE\231\239\167\018\251\246\1484\028\208p{\135\243#\252\212\020\233\197\190'G\015Oj\162{\203\135\030+\167R\0300\146\181\247\242\145\242\240\141\011\b\197\156A\213Z\014\189\t\237\253\144?\221\190\234\196t\1285$\242\153\137\236co\207\025\189C \131A\128m\181\212\137u\149\026u>\223\209\192\141\200H@\146d\237\212\023\231W\209\151\146\003hG|\247\170\007/\235\221\"\144\240a\254|na\216\2212\181hy\244\224c\178V\127\006\147m\157y\221\164\191d\230o\152 C\185#\001\217\004\007Y\227\135\011B\222&v|W\188\209\158\219I\146\002\028\233\n\r\\\016q\129\190\223\193u\002\178'=\146\205>[L\178\tN\1643\225t%\149\"\192){\242|wE,jr4!\238\207#G\022\166)\232\168;q\209a\189\133\156\156<\210\180EX\028TS?\251\176&\185\154\149\250D\245\1625\158\129\148I\217\228\147\b\030\200\230\029\029\172,m\t\165\215\133\223\028r\011\213\150MY\130\004\163T\178\022\193\210%ed\242;C\003\129\253/\206w\206m\182\167Tg\006\180\222\148%\b-\195'W\255\223\025\214H\012P\004\251_\207c\018\191\148\199\133#\2153gL\187\255A\130\241\2433O\\\206kj\020\016\234\145\163\226\245y\222\1466SYU\132\234\180]\219\n(\197\025(\146\180\1897\184t<\213\145\182}\144\151\150\206\003\021\177\135+\223Y\1350x\006. \247\226\168\167\145\203\143A\0191+\251\227\133n\131\227\006\005\030\242\165\011\156,.\005\141\220\142Uu\137\229R\222\194\245\171\230\132L\151\014\243\002N\190`H\233|\242\221\225TU\151\160\245\147E'p\137\198\127-+e6!\248\229h\143\182!a\161TB\130\128\168]\178Ni\137\157\175\228\165\127\146$\245\148N\152\195\225\176\254\019\143*\031i\130\031q\154\250\027\253m\016\140F\227f\149\240\007\231\180\b\189=\131bG\224\226j\127\127\1917f)\207s\165\139x\229\161\251_\128\1680\165W\201\023\156&_s4\150\245z\170:\167Q\217\214RY\226\241\135\151\152\140\007\217tf\028\245J\211\174\231a@\234\016\172\247\255\150\188J15\1817^\148\176\016g%\229W\180tTq\171\222\143\236& \132\210LE\242\220\251o#\016\129\016\026\142\226\031dle4\191c\195_\003n\012\222\132\136~\211D\012\155\224\025D\022U\191\224\188\210\241\215\188\142\211\219\179b\156\253\255\238\1397\2291*\\\214\234\253\164\016G\231\227\023\002\129?\1830\244\139\r\250\173\215?\200\131\207\246\168\000\131\017\223\204\156\164\022r_\203\164)r\022\1494\1730\237pqx`]`\016{\219\173\190\006\188\252\234\212k>\225\181NR\136c\029\1276y\160\030i\210\224h$y\205\182\175\029t\173\"\249P\021\"\165\165\213\253\211f0F\154\142\134\001\188\249\187\027\0297\251\167\174\187\222J\152Zt \141\166'\002g7\132\147]\185\007j\2440lA$\193\012\206{2WJj\231\183\127L\166\201\164_\132:=u\145\239>\183\023W\b9m4\221\181\023\152\242ek\229\254\178\005\223\162\154\023Th\016\207i9\207\175\181*V\1510\233\001\213\205tA\236\178\195\197\181\004]\213\029N\199\145y}![\254_\184\023\228\238\227\014,\151p?\0146\229\150\030\222\192\197D\209\2373\214\210h}\192\019\2187\255\248.\132:O\129\020z\138\252w\178\236\218X\209X\201\156\194j\021]N\147Y\011\175=%5\000+N%\"06\169\179\154\171j\248\246\176/\215\174/7\181\006n\\\191\249\189\187\242>\243^3\205\170\140\154\"\199>5W\230\002\168\151Y\237\252hn\249\028[\249\196;\r\207\127vX`n\232b\167\240$d3\201\159\018\224\127A\t\206\146\196\204\178d\151{\215\131\174^\167\179T\250\164\164B\129\198\163\176\030~0=\0162F\023\239\127\175\247\222v))%\243&\021\190\n\161\002s+\163\167N\207\030\248 {\249\193~\249.\001\163\165\028\028P\011S\246f\2417{\200\218\250)\127\175\242\164\141$\136\bzH\019\196\027^`\015\188w\\\142'V\0228\183=\137\139\r\241\142\230\233\129\206\218(k\146_\nWU\248\t\156\222Q\185x\252\212\137*K\234\237.\255\174\228\208\002\134O[\214\025\157_\177\191H=\174\229\156\237>\179\167\168\170rBX\186\134\006o\186\249\199\243\171I\0209\254.r7\190\195M\133QD\248\161\153\181\140^U\186\205\2244\2461Js\t\144\140\192\017\152\222\199o/\174\015\207\239\241(~_\202Q]\223\145\133\192\218\232\206y\b\245\2523\b\029&)R\001Y#3\240)(\251\248yl\222\225\130\249\205\199\219w\214\212\200{\178\221\161SY\222\030+3!)\1331\235Z\244\225N\163K\212\130s\t\2428LK E\241K\191S97\247\189\243#5G\153\157\208\150\2183V=\221s\136%0~\216O\191\210\242\196\183\b\197\156\133\135_#\129~A\145U\227fM\216\030\012\137x\2079\0035\021wb\245\157e\014\252/{R\192L\182r\226\214\198K\228\188\132\252\180\130\141^\183\173\229\127\194\241.sI\143\171D\206x0\170\128\155\150ul\130\232\135\130~\230r\\D\245.3y\234,\161\209\147\197\156\196\155\237|\164\2503\205+o?\157\1468\166\024\219\166\253>'\180riR\150\2154\188\218\029\204\nR\006\201\210\014\189\2295E\234\163\201\237\255{o\173\223f\211\001\240\187\143u\171\163\\\127\174\147\132\017\166\149\249q\208\158\251\178\139\203\242\214\200\004z\158\147g1\134\228\146\028\135\004\215ev\029_\240\254\246\201\210\193\029\141\139\185\0175?\207\159k\145\236\024O\n\015\026\189[\226/\232Xr6\255\238\127\196\169\174\195\153\143\003\248\203\173?\ra\183\168K\230\197\205\139\167\1395$\021[\155\149\168\014(&\142M\254\1671\214\229\200\253\1347\215\016u\184\004+\148\161\198\255e\249\2351\150\201&\152\179\228\210\186\140\218\157$\141\132T0\141D\019k\156\177\183\197v\171\139f\161\231\020e\243\133\236\138\138\138Hd\129\186A^9\230\148\191r\029\015\196\003\236\139+s\249JA\246Iz\169S~\204\228\230\201\251\226h\255,Q\219\171\186\146E\156\t\007`)\"e\141E\229\252\\\127I\180\133J\129\bXt\142\243\185q\206\226e\149Y+/|\198c\006IR\192\247_\156\144\144\173g\143\203\030\202\254\030\242\213\169\253w\197T)\0026\135\018\245e\144\127\217s$)qN\189R\233H\140\163#\018H\178\160\204\191$\166\005\016 X\182\130\164\211\025\156\145.A\255\144\251\239Vo'\224\204\197\236\202\208.\148\165L{a\\Q\155\\\001\243\028xw\141\158\000\024b\153\148_\215|S\192T?\252\160\147\185\241s\251\174;s\201Y<[MV\157\180\212\015\213y\187\228w\1768\163o\153\227\211\007\211\003[x\131\201s\014\028\140cYr\235\2196\221.\164w\240\239;\247j\029\n\167\209s\007\220\237S[\130\209\172\njV\025|\022a\165\250xY\2502a\133\1615\234'0^\244\254\185\133\236 \153\194\165\184Rw^1\165\172\196~\251\156\231W|\130\160\168\175\250\142\237xf4h\171zj~\128\241\1770?\180B9\216\200]\243SS\202\137\ni\219\170$w\175\173\249*\235\214Wp\168\153(v\164\b7\165d\222\245\176\1504r~\228\198\247\188\156\148\236\176\019Y\206S\233p\018\005\1515\202\127\206`\006C\148'\006\r\161\021\007\005\004\135\127%3\253>\127\131)\188C+\134\136K8\149J\025\225\015\218\242\173\005A\246l\156E*$H!Q\241\204L\159\252\136\210\234+)d&\211\237\026\183\225\018\189Z\229\206`S\225[y5\133\"\178p\244\145\181g\172\225\0255\181\t\229R\000\000p\246\190\151&\030)\170\252\243\019\022\192v\222H\189Sm\229\144\185\248\188\251\177\242b\015\003\211\168\137\199\142~\225\204\210\216\171\244?\202\155'+:\2136\238\1838\156\206\210\188\191B\197\205#\165b\012\165\240\168h\238\246F\251\174\165\252\n%\145\187\142\133\017[3.\188\213\230\171/\237\249[O\b(\200\188@\238G\130\198\219\180\202\141\224\137\027^\187\217g\bU,\\K\004W\162X\184\016\199F\238\1569\224hU9\143\237rx\172MU\031|\176\250\1328\002\163\239\215X\247\b\007X\182\175\249\194\184o\211\155\179\132{/\227\159?`\166f\011\142\205\1484\184=\023\t=\130\206\021f\004$\014\205<\205p}w\176acM\204U\218J\018\156 \142\190\168\241j\134\149\237Y\193\028G\229\130N\030\244\230\023\158\246\2401Q^C\166\251)\189\211\153~\147\nG`\212\n\164\211\218,gUv\233\011\193\239v\1917V?\016!\190#\00486\1598\127,\248\164\151\167\011\253F\129\023n\190\242ic\203e\000-\252kt\152\029m" let d_edc3c186d80de2039375bef179a67067 = "546\1985\005\225\149q\159\172\199\209\192\151Y\226\022\024\028f!D\174C\015\138E\139\165\234KT\127-Y\148\246q\030x_p{\000\172w\242\164iW\178\024}n\223\199\003\031\1468A/HRD\230\139\146\213cX}\158\157\175Y\224\221%\242\143\251\156\228\2390\226r\147\250\146\140\230\237\166\157\004\224\002\011UQq=\213\176\232\214\203S\002\228\184\163\210\232g\153%\234\163\025\200\024\192\208EV\234\129`\237\023-\145\168%\015\222\\\022\196\r\bM\214\220\142\182\242J\145P\218\230&m\027\"?\028\251*\195\206\011Qp\140\023\178a\156\193M9Y1\149\\\163\211Tn\215\169a\248\148J\190\017\139\138y\137\185\204\147gc8\135\150\244\245\139\164\192\225\012\140\205\153\020\246\203\179\000w\150d\007\251\218\244M\"\0266\251\185\196\018\175\143\\u\r}\017i\222\213\027\137\202H\211\208W\146\217\138\138nUs\127\206Pg'\161\225DR\168\199\2284bhF\175\216\160\178E\1631C\188\212\180Q\134\141Y\024\n\2132}\1475\215\180\"\165\020\223r\214j\136\242#\213\129O'\173\180DD\215\011\021\202\216,\012\144\137\230$\226X\214+iX\\\229\214\tC\196~\182\024\206\140\137\188\217\177\138\129$\194q{\221\153H\016\200\146\153]P\194\173uK\021\205\181\246\210\144\212\180DA(\2261\149\n\252\207zn\232\161\204'\220ODw\229`C-\030\166\217B\236z.\179\158\215\181\016}]V\019+\223N\157\168\246\140\232\243\182\243\177A\137\228\144]\253x\155 \169\148\162\220R\015\139\015\196W\180\t\181r0\246c\242c\027\219\242\165\161\"\181\190\222\173\180\184\221\243!\015\150\174+J\214\185,\138\139 W.\212|\r\1497\000\022\199\146.\217\000\223\004\002l\026;=\1650bE\245\011%\137\129m\136\216F,\136w\159P\247Bc\t\199Ki\214\201\168qs\221\131zv\245\138v\174w[\136\143&\005\017+m7\173\139E\206]\209}2G9S\179\147 T\183Ri_\026\141#\028p\023\250\197\219\252\b(\002Y\243\"\017l\019 \162\151\232\003\019F\255\014\192\224u2Gn\rI\243\224\n\239\162\185Aqt}\001W\153KI\185B\131\007\227\197\136!\210\158:\235\190\153\208\232\149\233{&\021H\199\197M<\226Z\023\220\224-\128\196\023\170\166\018\242n\016\172\181\026\217\166\146{K\020\238\025\128\023u\147\029F\158D&\205\023\024r\208zn\176\128I>#\187\2429\014\175\173\024\229\250\156\230\173\004\155\132{\157\233:\012E\1847\178\240\153\156,\020\146\237\234\177X\202\153P\243\136\028\241ZA\240\240\245\230\132\129\135\214\209N\215SFU\146\147yQ.\157|\142\251\191X\211#\222(b\bW\192+jR~\168\203a\173(\184\169\143\255\148&,\232\021::\234d\"0\031\0195\012\247i\218l\217\138hN\244V\149\129\198\237\134E\244jI\235\242PZ\162\0167\b\164%j^\162lZ<\230\199\204\019\031!\182\029\187\234F\243\006\128\213y\199\017\151\001\168W\233\147g\215\228\190\183/[\250,\159yk\190<\189\231A\023\193\225\146\212\220\214?\185I*+\n9\144|\249\227H&\2234u\252\254Z\179\241\217;\202\164w\241\026\215*\022\141\177Eo\252\163\n\154\178\219\185\0295\251K\229X\214\244\164\172\205\\^\177\234\210\031\250\197\172\027\2078\168\182r_\169\006S\004\214\166\245\2007K\155\158^\212R\127`;\170(\135\164\r\142\185\173M\163\234\133g\020\150\007\1860\139w\190\143i\011\007K\203:\r\233\001eK,W\236\249b\218\178\234~In\145P\156fD\019\243\018\191\217\214\214h\240\237\171\183,;Q\198\163`T\012\225\244\245{|\191\204z\180\186>7\222\249h\224\24798\199\017\238\228\254\180i\136\007\160\138v?X\156\132@|\204\252MF\236\250\248\166Z\141\190\233O\173\203\201=G\143\004\207\199g\170\194\187S\227\023\007\164S\214W\230n\249\130\208\189p:2\184 \188\158\187\135\027\030:9\169\218`\190\218=\181\132\199\142\157\b[\159=\235\142\011\006\137;\190c\196\025\148\191\233\195\206.\n\211\202\226}\215\020V\173l/\239c\240~\228\225\228\191\158Z\227p\187+\029\027\203\190\145\177\216,n\254PS-\213,\163\1771\022\239\191>\159\236\241t\217j\142\192\192%\2374\207\208#\200\157D\149O\018\139>\245\213\139g@@\188.\127\135V\202&?M\161V\137\145\250\243\236\207\r\229\249\233:&\229\020T\169\146`p\007\145\130\129\241\206\140D\204\207~\244<\139E8\001\162\161\137\204\234\213\136\225h\184\153]D\249\215q\140z/E\164\216\249\176\194N\163\245]\127\021\127\134d\155\189Q\231zP\147\144\186\180.m\222j\209pE\209\t\208Tq\212\164\241\168\174\208\189Z\015\165\206x0\132 \202&\244\2488\129\182aBA4\235\\\022\029\225K\027Pu53p\250\020\016?(^b\249\137x\244kk\179IV\176\204\253?d\255\135\145\142Ef\206\0154\135\168N\156\151\205\161\185\n\132i\215\1757\174o\159@R\162\030\168\247@V\157\016m5\151\172q\150\140\166;+\142\246%\153\t\tq\191D:\170\2086\234\030\027\000\224\251\247\214\133\163=\148Nf\205F\201\011K\139\016\025\145\227\129\234\137\031\229\187\146E\173\0121\171q\251T\207\172\218\216\000\020\251\161\194\214\149\210\153m\209\216>\0183\250\208\216\007F\196\242#\146\147\196>\238\245m\148\016\145\175J\189\211\217v\175\221\142\154\247\"\212\134X\001h(fG\217\245\029\227\027\217Q\132\227\214l\150\170\203\031\227\241bO\255\183\020RVqc\139\224\233S\024\212ZE\221\255sg\201^]\174\217u\202\230\142e\130.q\214H\212A\251\145\147\156<\165\195\225\192\135\201m\234\252\134\012\127,\1836v\166\143k\251\244\006\155,,\220*\136\019\191\n\162\193Ym\157y\025q\219\248\206\128j\145]\220\243Q\022\1543\007\030\158a(\190\219\173\211t=\128%\220m\164\031\224.\238\2034}\142\157=lw<\026\175\152\220\185\167\182#\1981Q\131=\237e\210\186g\222\224\214\022\187\199\153\145\245\1483\189\011^z\017\014\251\187\194\220\187W\175M\028\168]*^h\176\152!\245e\231\167'\031\248u\228\0248\006I\002\015\241\171\160\174\189-\168/x\238s]\181,\001\156!u\192xoq]s^\165\186&Q{\201\192*\248O\233mQ\174\132h\145\1838R\229\235\251\209\169\189C\021M\219\156\021\023I\220\194?\180\021\161p\245\015\154\255\180\2166\216\239O\251\244\207\235|[~\162\205;\194\220\243\132\139\219\164\2167\208\151JvD\191#U\246\255cV\250\245\237\186l/\018 \232r\135\171[4M\137\220\136\161\232\020\183\205\233\170\011\238;5\028R\255v~0'T^\240\2095\248\018\201k\138\180S\206n\220o6Co\232io\209\017\175\174\031\1337\030\236)\155g\203k\170\205\151\243.\155\171kP\156\207x0\188\182\196\197o\228\190A\185Y\157\223\172\173\011\024\230Bo#\162\238\222y\163\180hj1spF\216~\222\235Q\251\158h/,\132\140W\216\222\196\188\245?\211\177\206\191\227\239t4=\029oT\012['\167r\029\184O\210\180\170}Qp\150!\176\182'\204[\168O&z\218R9iaj\221\162\208\140\194\206\011\154\174\185\251\195\162&\177\252\219\135\152q\017o\180\151]\223\236\139q\187;d\029\003\243r\235tie\206\142\160\169\183L\023\241)\220NJ\158\253\201\212c\141\003\214fZ(\239\158\193Vl\152#\020\222N\206\1741\210\178\030Z\028\022\148l\253o\239\024\152\131!*\174\252\150\242\203\204\167Z#v\129\238\\\160\254\247\028\007u\234.p;\220\179Q}\142\157\b\166\214o\001W\134\133\249\225U\162\130\213\006\207\144T\245\207h\024\132\132\179\252\207\022\023#W\170\204\193\186\235}\025\163c\170,\143c\249\021\160d\n\140N&m\216\nA\225\215\249_=\028\005\245\180\190\205)\203\140\198P\222\167@\217\193\129n\203\003\201\252\213q\193\202\187y]\029\170\173\221F\153\177<$\156q\027\228\170\131\027\203\189\236r\213\197\030\230\252\029\163\131\1897\234*\175\019\007\219\130\169\219n\003\163\029\236\225\205\195\203C\195\197\129\187\006\154\201\163s\206\r\244Vl\234\137%\162\229\\\134C\178\169k\014lj\004\023\023\240\131#\006/\179\151\147\235Z\\\020\1654A\206\214\211\000}\2421\226\140[\149\023\206\001\132\004\131\194\254C\007a}\001E\227\007\192!h\250\012\162k\226$`\198Xa\001z\141hKn\212\167\158\210z\2268\192D\163\194!\004w\238\210\031\018\023\229\223!\187\011\217lDV\195QN\003\172\168\132\196\178\137W0\146\237\015P\158\0209\216U=\171\135\004M\183\0237y\247\207\030\219\024\240\226HF4\250\242\191\195\212\153\147R\143\216&\216\222\203\222q\1339K\196\234\1521'\158G\224\016\184\170\016\168\152yXq@~\208f3~\193\253\024\168\146C?\134K\183J\183\244cp\251\025\132\006\136\003m\020\210KW\164h\211\238\135\0021\255x9\163\007#M\200\177\127Sq\007\237e\129\247\142(>>N\231B\021\128?\186f\243[0VP\186\137x\2330j}\2068\2110X\218\0259\027=\007v,\133l\221;ld\177\244}\029\153-\016\005S(\029\029\237|\238\\y)d\239_[_E\196/\193\229\025\232\005\141w3\030\238\231>\156\000\t\209\132\159\225\1726\160\186\150\238n\150\"x\156r`\186\237\208\142\217m\001\237m@\217\t\224s\189M\206t\212\172\221\243\230\249\170\132J\0312\1679\242,\239\192\184_\180X77U\179\006\168f\192u\254\224\184}3\231Y\156\238\184+Q\245\227\027\135M!\226\200\012\006\007\154Lhr\252\159ZC\173\001 \155\r\161eI\136/\001\196\245\167,\223\244c\168\231\022\204\231d\162\"{\182.Y\220\249\249\147|\243W\166O\211\216\140\007\219\005\142\234Wv4{\251\147#\157\1800\130$\145DO\188\219V\145*\181\195\134!\139.+Co\146faqid\235\139m\141F\003L\239\030}\224\249\148\221\014\135\022I.\016\170\235\129\n\136\200\191\235G\142F\202\230dHd\2505\206\191\141\021\134\242\252\150\135WW\204m\134gRgZ\251p\200z\149\020!\031\202\183\148\137p\200\031T\212U\175YNX\2513\0242\239aa}\146\236\0241cd\2171+@U\213EqS\231\211\129\150]\135\003" @@ -509,7 +505,7 @@ module Internal = struct | "highlight.pack.js" | "/highlight.pack.js" -> Some [ d_6b9eea5bd2cdd91f629293ab3b8808d1; d_30baf6fb746860926fdd280eefc46735; d_7df05ceea77c14d78f1f1df8f98def4f; d_106b469c9254e3a72af1bc5085256cca; d_5fcd7eba230acf47d54c1897a9a9c394; d_df9507781455088adf4ca1bd7fc0a321; d_b223e3337242ba6cf0905995918760a5; d_d6a1be8caf2478248edb48ee82070d9e; d_98850966979dd224456f716b44220d69; d_9873a9ace25bcd721b8eeb6b8dad71cf; d_b23657c0bc089d459bc6099791f97c23; d_f9c0b1a6ea9c119cb0f7ead5c3dac542; d_80a0027403c5ad56c7da4589713b2348; d_fe8f6a1f53d067d447bae579dc60d6f0; ] | "katex.min.css" | "/katex.min.css" -> Some [ d_2d798108ddda42cb699f6ad4421e720e; d_b128d6f091a42be5d7a929703f09ac36; d_1476b6e94be68e530a90bd0723d69c88; d_e357f75b8a7d9a6031bbdc38adcf1422; d_ad152fcf832897f8629ca758460f3d22; d_7c9075f31df2a532c3135ae327c84a92; ] | "katex.min.js" | "/katex.min.js" -> Some [ d_0c2c3443b618aef3ac4519dd2b159bbe; d_a2070486fb8e9102cd1537ebd1216a96; d_48a6338945c47ceb84d335248c3d6873; d_ad48849637d7c8349cb3e6952d5c8699; d_32baa17e8a53bbd439c58b0d89bc0503; d_c7561e7d22eb89e10083cfba7680012c; d_d04b09d89ef0b9af8a297a3592a2e4b1; d_c0cf7351fa27f73a72840e453c4b15f3; d_fadfd470a088dde5c3755136ac4b6188; d_326148c9e075f26f4dd5ee3862f61cf6; d_a55141bd5690b03d71c9675038f73b3f; d_225bdd9918928e02697ef5570454bf56; d_bf8e1c09c2162b9bb4b6578a59cc8069; d_bb5a8ed07dc95fa6f9f51938da398a35; d_b93e718b1ddefad06d18d9736584ad78; d_e12a510e69c6b3e0210294eedc2c3be3; d_bf043adf1d8ba761903c6f3447bae9d3; d_80ae3e22d162129b593049c0dc7f2407; d_d7b447b6bfc36721f581470728505547; d_92e0c0a734f49413d685531ad3f0a03e; d_cabefc6c9607b95a33af32a8c8832767; d_a03f60fbbac88837b2763d52df2c0820; d_5795c26325c462426548bd12ff6ef7a1; d_c0939c104021af2b0d9b24c7102061f2; d_3a7455b94742964a6cc5e84e314a6cfb; d_dc2a908015f68e5bff245fff4e602604; d_96c4d8e2622ac6552ccf67643b20f09c; d_37935d98135b118d937e895f4bb55add; d_efe21915ced6043dcaa8ff576e7948c7; d_fe0aa5b4043d6894e289163dd38508b7; d_dc29762de1ae6c28b3b3cc202f52ac6f; d_2c5af911fa1596ad2eef3a7e342be949; d_01738333fc004372ab1ae8bc7d370677; d_0d6ec6387686b4173900d29c91f338ee; d_5f9942b4d85184e45b9addfc25ca6fd4; d_105a9e030400f28a404c6badd930fe01; d_79c029f6f746a52f4a8bc8b6280c5c88; d_3a50124eae7017a15bb92024b9f6c8ad; d_d1d8d575696cbb5a4994efc9e2862948; d_a6e92521674c97f4d1bd649490d8a987; d_8f38ae17980f4039d715823515fd56d0; d_a841840589a3efb0465e49e0d8f985b5; d_e33d592534625de6438003412e1d8813; d_5b12b53efc1e6da3a434634e81c2251b; d_c7270ab94b84005c36e6e864e6ea5b10; d_5e57240b8ff6745d663ebd2060201199; d_02c9bc01125e92ce389d2ac93e62d14b; d_0d4c13a0e6487657499a2f37795ab83b; d_8ff622534e1e1348711c11358657050b; d_a8b5fa32242a1d360076af4bdc9dafbe; d_725c52bce5d22dff34816d0cea74cf51; d_a6db9cb29ea27586d2138cf4f8710b12; d_31ee9944b6c75c4351486bc790988371; d_1005d4f63119125aeb03e8a2fa265969; d_9ff5a6ec97f55e01b81f13d9d3f0ff67; d_f361846717ba3e91093152df70d5aab3; d_e462cdcfecbc18ac1f1e447bf1ed3697; d_0d5bde992f9fa1c53103cd024ff5833b; d_1b66f4e8c1fbc1c74875f8da050cc1d0; d_bad0217136fdcd657898ee631bd512d1; d_428c2b0f069b4ffaef294dc85aef1e4b; d_cb988ca0480d611a7c52551adcc9ed48; d_cdc6e947cdb2e0bb7fae7f338ffa12a0; d_f56cd226d59f4d3190a095998f97ac56; d_f5d214c6b91ee7f61f5a433fcdd70682; d_f4caf2cb8610b6735641c064e6453b79; d_da739bd79e1901a19d34fbf2d1a16298; ] - | "odoc.css" | "/odoc.css" -> Some [ d_fa1c053d8b56d1e18253a2cf90453dfb; d_e17d79834bf5120a96c58d54a0ebfd29; d_3c0fd09a46dafedd922d3c7247ae8164; d_dd310317f27add09a8e020a67a028cb7; d_1748a7036eb134e2f5e68d79313a1372; d_65627a2f7cd45ea24715b66452954999; d_89fc6729d4ac5445a0939af01bd9324b; ] + | "odoc.css" | "/odoc.css" -> Some [ d_fa1c053d8b56d1e18253a2cf90453dfb; d_e17d79834bf5120a96c58d54a0ebfd29; d_3c0fd09a46dafedd922d3c7247ae8164; d_dd310317f27add09a8e020a67a028cb7; d_1748a7036eb134e2f5e68d79313a1372; d_e94c8f28d2a123393c1fd370776b6c2d; d_84811cd56c3f0eb2d5d94c7292ab6a8a; ] | "odoc_search.js" | "/odoc_search.js" -> Some [ d_baa9e7597ed780d04fe80009b6d2457e; ] | _ -> None @@ -558,7 +554,7 @@ let hash = function | "highlight.pack.js" | "/highlight.pack.js" -> Some "f7f17015c0de1023c93929e3725a9248" | "katex.min.css" | "/katex.min.css" -> Some "1a262c83aa48d3ba34dd01c2ec6087d8" | "katex.min.js" | "/katex.min.js" -> Some "0376fd70eef224e946e13788118db3d1" - | "odoc.css" | "/odoc.css" -> Some "e0969de2e227384142d98b2aea09d7ed" + | "odoc.css" | "/odoc.css" -> Some "2cd6e100067b73e2a944409efe944c83" | "odoc_search.js" | "/odoc_search.js" -> Some "baa9e7597ed780d04fe80009b6d2457e" | _ -> None @@ -597,6 +593,6 @@ let size = function | "highlight.pack.js" | "/highlight.pack.js" -> Some 54535 | "katex.min.css" | "/katex.min.css" -> Some 20978 | "katex.min.js" | "/katex.min.js" -> Some 270376 - | "odoc.css" | "/odoc.css" -> Some 26708 + | "odoc.css" | "/odoc.css" -> Some 26810 | "odoc_search.js" | "/odoc_search.js" -> Some 2158 | _ -> None From ec233fe8d39119bbd20e03cd9fc57fd6aa6306e6 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 6 Dec 2023 15:40:09 +0100 Subject: [PATCH 33/35] occurrences: only count persistent one Signed-off-by: Paul-Elliot --- src/document/generator.ml | 2 +- src/loader/implementation.ml | 2 +- src/model/lang.ml | 4 +- src/odoc/bin/main.ml | 12 +--- src/odoc/occurrences.ml | 27 ++++---- src/xref2/compile.ml | 4 +- src/xref2/link.ml | 4 +- test/occurrences/double_wrapped.t/b.ml | 4 +- test/occurrences/double_wrapped.t/run.t | 83 +++---------------------- 9 files changed, 30 insertions(+), 112 deletions(-) diff --git a/src/document/generator.ml b/src/document/generator.ml index 1c5b72e5e7..cdba1ffae0 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -256,7 +256,7 @@ module Make (Syntax : SYNTAX) = struct let documentation = let open Paths.Path.Resolved in match documentation with - | Some (`Resolved p, _) when not (is_hidden (p :> t)) -> ( + | Some (`Resolved p) when not (is_hidden (p :> t)) -> ( let id = identifier (p :> t) in match Url.from_identifier ~stop_before:false id with | Ok link -> Some link diff --git a/src/loader/implementation.ml b/src/loader/implementation.ml index 7fc5941679..55c011adea 100644 --- a/src/loader/implementation.ml +++ b/src/loader/implementation.ml @@ -315,7 +315,7 @@ let process_occurrences env poses loc_to_id local_ident_to_loc = | p -> ( match find_in_env env p with | path -> - let documentation = Some (path, is_persistent p) + let documentation = if is_persistent p then Some path else None and implementation = Some (Unresolved path) in Some { documentation; implementation } | exception _ -> None) diff --git a/src/model/lang.ml b/src/model/lang.ml index c6ba7edab1..dd4abf6a68 100644 --- a/src/model/lang.ml +++ b/src/model/lang.ml @@ -23,9 +23,7 @@ module Source_info = struct | Resolved of Identifier.SourceLocation.t type ('doc, 'impl) jump_to = { - documentation : ('doc * bool) option; - (* The boolean indicate if the path is "persistent": from the same - compilation unit. *) + documentation : 'doc option; implementation : 'impl jump_to_impl option; } diff --git a/src/odoc/bin/main.ml b/src/odoc/bin/main.ml index 539457f406..70d9cc6b8c 100644 --- a/src/odoc/bin/main.ml +++ b/src/odoc/bin/main.ml @@ -1113,11 +1113,9 @@ end module Occurrences = struct module Count = struct - let count directories dst warnings_options include_hidden include_own - = + let count directories dst warnings_options include_hidden = let dst = Fpath.v dst in Occurrences.count ~dst ~warnings_options directories include_hidden - include_own let cmd = let dst = @@ -1131,16 +1129,10 @@ module Occurrences = struct let doc = "Include hidden identifiers in the table" in Arg.(value & flag & info ~docs ~doc [ "include-hidden" ]) in - let include_own = - let doc = - "Include identifiers from the compilation in the table." - in - Arg.(value & flag & info ~docs ~doc [ "include-own" ]) - in Term.( const handle_error $ (const count $ odoc_file_directories $ dst $ warnings_options - $ include_hidden $ include_own)) + $ include_hidden)) let info ~docs = let doc = diff --git a/src/odoc/occurrences.ml b/src/odoc/occurrences.ml index 48b38ebb80..9922257112 100644 --- a/src/odoc/occurrences.ml +++ b/src/odoc/occurrences.ml @@ -119,33 +119,28 @@ end = struct tbl end -let count ~dst ~warnings_options:_ directories include_hidden include_own - = +let count ~dst ~warnings_options:_ directories include_hidden = let htbl = H.create 100 in let f () (unit : Odoc_model.Lang.Compilation_unit.t) = - let incr tbl p persistent = + let incr tbl p = let p = (p :> Odoc_model.Paths.Path.Resolved.t) in let id = Odoc_model.Paths.Path.Resolved.identifier p in if (not (Odoc_model.Paths.Path.Resolved.is_hidden p)) || include_hidden - then if persistent || include_own then Occtbl.add tbl id + then Occtbl.add tbl id in let () = List.iter (function | ( Odoc_model.Lang.Source_info.Module - { documentation = Some (`Resolved p, persistent); _ }, + { documentation = Some (`Resolved p); _ }, _ ) -> - incr htbl p persistent - | Value { documentation = Some (`Resolved p, persistent); _ }, _ -> - incr htbl p persistent - | ClassType { documentation = Some (`Resolved p, persistent); _ }, _ - -> - incr htbl p persistent - | ModuleType { documentation = Some (`Resolved p, persistent); _ }, _ - -> - incr htbl p persistent - | Type { documentation = Some (`Resolved p, persistent); _ }, _ -> - incr htbl p persistent + incr htbl p + | Value { documentation = Some (`Resolved p); _ }, _ -> incr htbl p + | ClassType { documentation = Some (`Resolved p); _ }, _ -> + incr htbl p + | ModuleType { documentation = Some (`Resolved p); _ }, _ -> + incr htbl p + | Type { documentation = Some (`Resolved p); _ }, _ -> incr htbl p | _ -> ()) (match unit.source_info with None -> [] | Some i -> i.infos) in diff --git a/src/xref2/compile.ml b/src/xref2/compile.ml index 4b257bfd5d..4aeebe29b3 100644 --- a/src/xref2/compile.ml +++ b/src/xref2/compile.ml @@ -94,9 +94,7 @@ and source_info_infos env infos = let open Source_info in let map_doc f v = let documentation = - match v.documentation with - | Some (p, persistent) -> Some (f p, persistent) - | None -> None + match v.documentation with Some p -> Some (f p) | None -> None in { v with documentation } in diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 0fd8c37ca9..0c1488b20c 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -533,9 +533,7 @@ let rec unit env t = | Some inf -> let jump_to v f_impl f_doc = let documentation = - match v.documentation with - | Some (p, persistent) -> Some (f_doc p, persistent) - | None -> None + match v.documentation with Some p -> Some (f_doc p) | None -> None in let implementation = match v.implementation with diff --git a/test/occurrences/double_wrapped.t/b.ml b/test/occurrences/double_wrapped.t/b.ml index 9c65111cd5..6a01b082fe 100644 --- a/test/occurrences/double_wrapped.t/b.ml +++ b/test/occurrences/double_wrapped.t/b.ml @@ -10,4 +10,6 @@ module M : A.M = struct end module type Y = A.M -let _ = let open A in 1 ||> 2 +let _ = + let open A in + 1 ||> 2 diff --git a/test/occurrences/double_wrapped.t/run.t b/test/occurrences/double_wrapped.t/run.t index a0660c6c29..5361b9d035 100644 --- a/test/occurrences/double_wrapped.t/run.t +++ b/test/occurrences/double_wrapped.t/run.t @@ -63,8 +63,10 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc $ occurrences_print main__.occ | sort +A only uses "persistent" values: one it defines itself. $ occurrences_print main__A.occ | sort +"Aliased" values are not counted since they become persistent $ occurrences_print main__B.occ | sort Main was used directly 0 times and indirectly 7 times Main.A was used directly 2 times and indirectly 5 times @@ -73,12 +75,13 @@ Uses of values Y.x and Z.y (in b.ml) are not counted since they come from a "loc Main.A.t was used directly 1 times and indirectly 0 times Main.A.x was used directly 1 times and indirectly 0 times +"Aliased" values are not counted since they become persistent $ occurrences_print main__C.occ | sort Main was used directly 0 times and indirectly 2 times Main.A was used directly 1 times and indirectly 1 times Main.A.x was used directly 1 times and indirectly 0 times -Now we can merge both files +Now we can merge all tables $ cat > files.map << EOF > main__A.occ @@ -87,7 +90,8 @@ Now we can merge both files > EOF $ odoc aggregate-occurrences main.occ main__.occ --file-list files.map -o aggregated.txt - $ occurrences_print aggregated.txt | sort + $ occurrences_print aggregated.txt | sort > all_merged + $ cat all_merged Main was used directly 0 times and indirectly 11 times Main.A was used directly 4 times and indirectly 6 times Main.A.(||>) was used directly 1 times and indirectly 0 times @@ -99,41 +103,14 @@ Now we can merge both files Compare with the one created directly with all occurrences: $ odoc count-occurrences -I . -o occurrences.txt - $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 11 times - Main.A was used directly 4 times and indirectly 6 times - Main.A.(||>) was used directly 1 times and indirectly 0 times - Main.A.M was used directly 2 times and indirectly 0 times - Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 2 times and indirectly 0 times - Main.B was used directly 1 times and indirectly 0 times + $ occurrences_print occurrences.txt | sort > directly_all + $ diff all_merged directly_all -We can also include persistent ids, and hidden ids: - - $ odoc count-occurrences -I main__A -o occurrences.txt --include-own - $ occurrences_print occurrences.txt | sort - string was used directly 1 times and indirectly 0 times +We can also include hidden ids: $ odoc count-occurrences -I main__A -o occurrences.txt --include-hidden $ occurrences_print occurrences.txt | sort - $ odoc count-occurrences -I main__A -o occurrences.txt --include-own --include-hidden - $ occurrences_print occurrences.txt | sort - Main__A was used directly 0 times and indirectly 2 times - Main__A.x was used directly 2 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times - - $ odoc count-occurrences -I . -o occurrences.txt --include-own - $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 13 times - Main.A was used directly 4 times and indirectly 8 times - Main.A.(||>) was used directly 1 times and indirectly 0 times - Main.A.M was used directly 2 times and indirectly 0 times - Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 4 times and indirectly 0 times - Main.B was used directly 1 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times - $ odoc count-occurrences -I . -o occurrences.txt --include-hidden $ occurrences_print occurrences.txt | sort Main was used directly 0 times and indirectly 11 times @@ -149,45 +126,3 @@ We can also include persistent ids, and hidden ids: Main__A was used directly 1 times and indirectly 0 times Main__B was used directly 1 times and indirectly 0 times Main__C was used directly 1 times and indirectly 0 times - - $ odoc count-occurrences -I . -o occurrences.txt --include-own --include-hidden - $ occurrences_print occurrences.txt | sort - Main was used directly 0 times and indirectly 13 times - Main.A was used directly 4 times and indirectly 8 times - Main.A.(||>) was used directly 1 times and indirectly 0 times - Main.A.M was used directly 2 times and indirectly 0 times - Main.A.t was used directly 1 times and indirectly 0 times - Main.A.x was used directly 4 times and indirectly 0 times - Main.B was used directly 1 times and indirectly 0 times - Main__ was used directly 0 times and indirectly 2 times - Main__.C was used directly 1 times and indirectly 1 times - Main__.C.y was used directly 1 times and indirectly 0 times - Main__A was used directly 1 times and indirectly 2 times - Main__A.x was used directly 2 times and indirectly 0 times - Main__B was used directly 1 times and indirectly 1 times - Main__B.Z was used directly 0 times and indirectly 1 times - Main__B.Z.y was used directly 1 times and indirectly 0 times - Main__C was used directly 1 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times - - -REMARKS! - - $ odoc count-occurrences -I main__B -o b_only_persistent.occ - $ odoc count-occurrences -I main__B -o b_with_own.occ --include-own - $ occurrences_print b_only_persistent.occ | sort > only_persistent - $ occurrences_print b_with_own.occ | sort > with_own - $ diff only_persistent with_own | grep Main.A.x - < Main.A.x was used directly 1 times and indirectly 0 times - > Main.A.x was used directly 2 times and indirectly 0 times - -This is because the persistent Y.x is resolved into Main.A.x. So maybe relying -on Ident.persistent is not the good way of knowing if it is persistent or not? - - $ odoc count-occurrences -I main__A -o a_with_own_and_hidden.occ --include-own --include-hidden - $ occurrences_print a_with_own_and_hidden.occ | sort - Main__A was used directly 0 times and indirectly 2 times - Main__A.x was used directly 2 times and indirectly 0 times - string was used directly 1 times and indirectly 0 times - -That's a problem: it should be Main.A and Main.A.x From 0bc0fb00bc1426a1714c5493c04070de5d25d843 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Tue, 5 Dec 2023 17:46:51 +0100 Subject: [PATCH 34/35] Remove rendering of links to documentation Signed-off-by: Paul-Elliot --- src/html/html_source.ml | 30 ++++--------------- src/html_support_files/odoc.css | 8 ----- .../odoc_html_support_files.ml | 14 ++++----- 3 files changed, 12 insertions(+), 40 deletions(-) diff --git a/src/html/html_source.ml b/src/html/html_source.ml index edd3cd32d4..4a859369d4 100644 --- a/src/html/html_source.ml +++ b/src/html/html_source.ml @@ -24,31 +24,11 @@ let html_of_doc ~config ~resolve docs = let children = List.concat @@ List.map (doc_to_html ~is_in_a) docs in match info with | Syntax tok -> [ span ~a:[ a_class [ tok ] ] children ] - | Link { documentation; implementation } -> ( - let href_implementation = - Option.map (Link.href ~config ~resolve) implementation - in - let href_documentation = - Option.map (Link.href ~config ~resolve) documentation - in - let body = - match href_implementation with - | Some href -> [ a ~a:[ a_href href ] children ] - | None -> children - in - match href_documentation with - | None -> body - | Some href -> - [ - span - ~a:[ a_class [ "jump-to-doc-container" ] ] - [ - span ~a:[] body; - a - ~a:[ a_href href; a_class [ "jump-to-doc" ] ] - [ txt " 📖" ]; - ]; - ]) + (* Currently, we do not render links to documentation *) + | Link { documentation = _; implementation = None } -> children + | Link { documentation = _; implementation = Some anchor } -> + let href = Link.href ~config ~resolve anchor in + [ a ~a:[ a_href href ] children ] | Anchor lbl -> [ span ~a:[ a_id lbl ] children ]) in span ~a:[] @@ List.concat @@ List.map (doc_to_html ~is_in_a:false) docs diff --git a/src/html_support_files/odoc.css b/src/html_support_files/odoc.css index bb5e9d8ff7..32efd6a713 100644 --- a/src/html_support_files/odoc.css +++ b/src/html_support_files/odoc.css @@ -1203,14 +1203,6 @@ td.def-doc *:first-child { color: #657b83; } -.jump-to-doc-container:hover .jump-to-doc { - display: inline; -} - -.jump-to-doc { - display: none; -} - /* Source directories */ .odoc-directory::before { diff --git a/src/html_support_files/odoc_html_support_files.ml b/src/html_support_files/odoc_html_support_files.ml index 7c48414c81..9315575264 100644 --- a/src/html_support_files/odoc_html_support_files.ml +++ b/src/html_support_files/odoc_html_support_files.ml @@ -164,6 +164,8 @@ module Internal = struct let d_62016f2316dffaac5eecc447ca24c81c = "Z\195\229\202C\147\172\201\012\133\016g\129\1363\134A\135z\186\216\000]!\192\004Fk\245\251\253\207\238\128\029\005\186a\196\181\221`\004\1644\\\184\031[ \136\195\144'\139\152w;+\213\0116X%\165t\000^\204\243FG2C \213\004\017\211\208\132\198\r\136\re\205\1838\031Az\225u\148s\250\194?<\151\132\225\209\218\196\203l=\015\006&K\002E_\228!:w\2361\214\027\188\134\201\231\158\002uhH\229\152\160\203\224i\015K\n\130WPh\\\127\018Jv\143\147\026\000+\1348h\207]S\200\143\221]\166\022\216\132\180\171\190@\194c\187\1296\170\164\169\131\174\232y\1423T[\000A,Jz\240\207\029\215\253\174\129R\189\149Tx\251\018\149P\b\rP\185\149;\203\245\238\183\235\218\166*\148\011\0219Y\226&`\165M\232)\148\024R\245A\0067)L\n\156\021F\167\236\157:\211\189Gb\153ot\224A\248\208\151\250\185\159\\w\222\130\017\129\1736m\131\232\240\180VD\024Q\253\004.C\nD\194\193\133\217\030\164\016\192\1536\015+$\207\253\209\140\028\000^\018\1483\165\183LO\182\168\201\016r\150\187n\174\\b\205{c\157\166\183\215\165\235\150\247\203\187\243\177\155\207\242\197\249\017\\l,\016}B\156\145\178u\202[\135h[\163b\132K\207;\189Fg\194\206\225|I\206\215u\014\240\250\226\b\131\216\181\030B\152\211\186\004\151\188~p]\021\203\167\195`V\244\173~d:b\158\169 \022\164\194\183T\t&\129\022\144\152\015x\155\025\136k\018c\142\232ox\149\0274b(\"\017\218\168\254\184\154\028\156\132\025\0118V\250\180+\233\143\205\206\246\159\171\031\007f\194\224\024\243A\"Q\018\180\0196Q(\219aY\247\165L\137\225\147\219\234\137\185S#\206\007>\247\026Sj\215o\218\006\0055-\000hM\247\215}\254\136\r\244\250\tM4r\234\189%\156\020h\172\\2\028\026\011\237\t\178c\211-\180\139@\026\191\019]\158\209\180\219\196\143\135\198\019k\242\025\005\235n\156\028\225s\167\155]\201\239\247\216\215\229\180\227\217@A\168\186\168\251-E\230l\204\237\224\237e\030\026\215\196.S0-F\027\152vkK\\{\128\030\254\020q@*\000^\1846{\1920\n\158\204\220m\200@B\220a\194\002\134\253\188\179\206\194\230\137\197U\145\254\190Wo9\193\172\006_ry\207\181\249\242G\135\206\243\129T\2425HPc/;&\210\208\197\151\"\146\195\249\188Iq\031\129\001\006\000\156p\138\145\165S\n(8_4\183\226K\001\211\230\209;\159\167t\132:t\024\249\130\244^\131%'e\146z\023ua9\173KA\229\143\197\235N\253|\239\254\"J\209\205\003\129\017\236\236\135}&r\031\148\176\129\199\136'\172\1608\014o\141\205\216{\138l1\247;J\189V\229\130Q\158\190A}\160\144$\\m`CP\189J\224\1495V\234\181iB\215k\141\132\232rR\229\178\156\172\243\173\173\127Y\n;\149\166\160\148\255\149j\211K\243\140\134!?j\015\rT\188f\226\254R\242\180\140\158\128\028\222\185\230\193\t\000q\255\241\233\205\229\012G8,\019j\184\169\193C\178)4MH_\014\184\208\165\166\026\241.\255u\217\246\138&\016\241\1918W\2176\0199\228\128\165\188\132\023\024\029V\127\132O\011\215\227\204\210\229\202\186\236:]\159\187\148\005\189\1863q[0Rn\017>w\215\242\192\217\167\241\196:\137\b\0056N\180i\136\155_\182\222\015U\031'y\202\215\221\0267X\1583\235\181\151F\141P\191\137\253T\250w\175k4\152\183$\164\157\002\153@;As+{W\218\190nl\182\020\221\002gX]\184\189^\230\188\169\184\129<(\219\004\218 \160\218\172\026\176\015\1296\019\023\007\001\241\144\251\204\144\"x\rw\184\182\003\248\227V\207Y\145\2394\226\218\204\252(\133L\004\r\159V\170\219\201\003\192@\000\005\188-\024>\020\024\031?\rz\232\245G<\004p\002j\233\220\160E\1432k}\203\007\183\211\030\230\234^\030\244\014 J\001\211\031^\2037\233(\182N\000\019\022\148\158\205\133\140\011\225\153\146\213E\218d\234l&\209\129\031\251\246f\218\243S\187\137t\1302\139\172k]c\139\237\236\015\022\233\180\150N\174q\149#N\159rhk\180d\209\248Y\134V'\001\005\145K\002\151\198Z\132N@v\252\2511zn\243\164L\028{V\0298;\206y*\138\233\253\244\174\240\005\028a\181o\\\018\198\177\015\221\214V\244+0\247\006.\218L]\000\156\018~\248\141\030\154\138\221\175\226s.<\236\128\145\183CS7\135\156\168\225\000\211\135\179\183\186\141GJ\181\193\243\1778\216\209\156\171Y|\186_\149p\182\243i\021n\028.\243\224\212\211,5\211\150^\163\137\246\151~\179q\216a\163\230\155\156\222\149\014N\183\238\232\129\230c&\016\"D&t\144\227O(A\225\144\000\021\236\018 8\015fB@jSR\026\249Gr\1976\023\159\b\170MH\t5\197J\164\137\241\215z\158\250&*\028\140M\231\\h\216Q\163\240\186\000\241w\187\134{\1441c\230\005\203\248V\243[\255\190/\211\133\134\203:\250\t\191.U\181|\\>Ts5\157\252\141W\231'\129\218\176\177P\192 \176\151\026\\\240\202\231\1552\185\183\183\025\026\245hR[\213\028\189\134\245\134\128\130\006U\181\233\210\012*\225\018\157TJ7\166]\241>Wn\232\r\189B\131n,\220\171_\171\218\216o>\144\2354\205\000\238H)\181:-\225\015\227\170\168>9wBP\219\146\222\\_O\214\159\178\136M\130\004\234Q\210pA\211\165g\211h\220\237\224\209\169\226\220Ry\210Fuq\211\161\163Nm\238@\024\212P\248\136\161W\133\223\226cc\227\164V\212\177\219\028\185\133<\1357p\201]>\174+\250>$\232\162\254\138\005\247MFi\247?\149\015\248-\251\255\207\183\222\129i\236\193'#\001\004wu\221\189E\239\146M\194\158\024\225\248\209\226 }7~\170\197\216;\018\128\127|\152\251;/\148\199C\240\130\158\229\027\156\188'\230\214\172z\027\160\229\026 \249\227\n&\161\211T\165H\"8N\202\133rC7\199m,+<\208\158\140l\142d\2030<\246\147\130\1435d\221\250JU\254c\011jmz\004g\190\022\250H\171X\153`5]\232*y9\192*V\174\155\187v]]V\163\128\164\129\206\001\028\136]E\248\171\249B\025\000\242\189\208#\251o\132\218I1\030c\157m\164MD\218D\219\223\189\004'\005\230vM\000 1Y\150\247\0147\188\183R\146v\175\180\133`\1891L\027\181\000\180Q\250\192\196&v\024\231\137\021\170_\178\233\21459\151J\164=\1977\206to\189%h\134{\221u\025e7cr-\214\188\025%++\179\142\022\002\170\166\170UU\021\193\000*\005\185\244\029X\173\028\149\172\169\012=7L\128\006\220gd\133O\229c%\186\227[l\222J\245\1514\144 \n\239\224\001\232a\171\031\205\161\221\184]\029\135\234.\139E\174I\177\168\153\242JiM\182Q\151\250\\>PX\197\195\177\226%\131g\027\n\178\186\138\128\004\195\170\172\134\161\151\128\162:\184\171r\215\".\222m\023\024\209\150\205\218\222\228\184\134\248:\199\196m\209\2249Q\031c\161\185\246\251F\237A\197\152\250\152\187\205\255\002UM\164\192\172\198\218\1485\158yd!\240B\217.\247\131\255\237\247P\149\243\220\228<~\242\198\253\197g\209\183\236]` \014\030\206\250\149\135\172\227\007\163\130$*\132\175i\127\251\243\153\1661\001x\160\195atKbq/\231\153M8\136d\159[c\156T\015d\166\207'\208D\203\174\127\252\189\003\017\168\001\162%\016\192\241\017\030\159$goJ\027\146\018Q\205\005\b\222\b\016\155\158\134\153\143\223\156R&\2363\233\t\241\174vF\190\160\018\228\159\012\021\1398\184\215E\028\149\1462'KJ^\185\020\251n7\166\004i\028\161\206\195\1919\228J\245\1814\131ZE\244\167\204\131\188+\190\004\238\025%\0306\014\160K\012L\203\171 \025\176q_\163\026\214\175+\176qF\241B\196R\016f\164-\220\"\186\139)rpw\2549\1446\144\158\252@8\023\242W'\180\235\220\b\150Mqu\165\184\152`\026/\199\024;\153s\186\206m\200\t\023\237@\231*\227\171\163l\174\167\227\201K\144\251v\031!\1915\151\027\210V\139@\027#\024ev\144\144\168\248iP\153\202}/\233\158\172\\e\172\246\204\229\240!\179\203\2005\144\162\196\229\185n\201/;\178\024\029\184\253\021\007\173\253\160n\238L^\127\150XY\237J\242\t^\167\166\202zLV\219\004\202K\135\182\174\168G\192\200\147\031m\154\011\026\200\136\246\019(\228\142;y\214\207\140\200T\011z&\199\024\139 \246\1770\215\198\018\193Mz\178\247]\206\235\203\156QM\210\014\012\001\200\149\014\127\242\r1PT\170\170f&wm+k\216q\177\168\142\202$\248\154\027\147\012l\193\137KlH\151t=9Kpq\243\2148\201b&\249\227S'\201\005\217[\230\183\212O\240vWc\233R\245\020X\149\133\226\221a\235\245\206\141C6Z\222t\132\027\135\0295\b\165\133\189\244g\237\237\2178\224\181?\180l\145\208J\153\136\165t\019\219K>b\222\134\178-\n\136#\028O\028\147}\168\255\2057\218\212<\0243\163vp?oA*\244\255\240ih/\242};\014\215\162\196\202o\191\251\146\187\159\127\014\192&\152\245\221Bc\178*2H\152\182V\r\001\179L\148\153<\024m\136\182\030\140\187\004\2155\002\177\140\"5u$8x\190\154\228D\129:\ndd\141\149\232\023\195kv\029\133L\198\014G\202\158\194H\238\172K\197%\145d(2'y}\202\193b\\\018\226\222\202\162w\215\199{\135\186\022bWw\127\014\239\223\156\235\181^\220 *QZ\189{\248\227\158\152S\148Z=Sz\017\127\160\022\147\253q;\166|[&\159O8y\014t\026\147,~\255\200\2369\005qL\227{\2221G\201{\031~\215\206\142%\249\194\195%\141\150\175\131(G\170\132o\176R7[-6\139\190\152\018YyH\227\145\204\240q\029\237\174\173\177\203\n\173\186\229i\223\244<\244\136\162\152\176\132{v\251\144\243^\023\151Z\248\011K\226x\172=\181\240\179`\006sj\227$\141\211\139\203\006j\233\227li::before {\n content: '\226\128\162';\n}\n\n.odoc-search .search-entry .entry-comment div {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment p {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment code {\n display: inline;\n white-space: nowrap;\n}\n\n/* First level titles */\n\n.odoc-toc>ul>li>a {\n font-weight: 500;\n}\n\n.odoc-toc li ul {\n margin: 0px;\n padding-top: 0.25em;\n}\n\n.odoc-toc ul {\n list-style-type: none;\n}\n\n.odoc-toc ul li {\n padding: 0.25em 0;\n}\n\n.odoc-toc>ul>li {\n margin-bottom: 0.3em;\n}\n\n.odoc-toc ul li li {\n border-left: 1px solid var(--toc-list-border);\n margin-left: 5px;\n padding-left: 12px;\n}\n\n/* Tables */\n\n.odoc-table {\n margin: 1em;\n}\n\n.odoc-table td,\n.odoc-table th {\n padding-left: 0.5em;\n padding-right: 0.5em;\n border: 1px solid black;\n}\n\n.odoc-table th {\n font-weight: bold;\n}\n\n/* Mobile adjustements. */\n\n@media only screen and (max-width: 110ex) {\n body {\n margin: 2em;\n padding: 0;\n }\n\n body.odoc {\n display: block;\n }\n\n .odoc-toc {\n position: static;\n width: auto;\n min-width: unset;\n max-width: unset;\n border: none;\n padding: 0.2em 1em;\n border-radius: 5px;\n margin-bottom: 2em;\n }\n}\n\n/* Print adjustements. */\n\n@media print {\n body {\n color: black;\n background: white;\n }\n\n body nav:first-child {\n visibility: hidden;\n }\n}\n\n/* Source code. */\n\n.source_container {\n display: flex;\n}\n\n.source_line_column {\n padding-right: 0.5em;\n text-align: right;\n background: #eee8d5;\n}\n\n.source_line {\n padding: 0 1em;\n}\n\n.source_code {\n flex-grow: 1;\n background: #fdf6e3;\n padding: 0 0.3em;\n color: #657b83;\n}\n\n/* Source directories */\n\n.odoc-directory::before {\n content: \"\240\159\147\129\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-file::before {\n content: \"\240\159\147\132\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-folder-list {\n list-style: none;\n}\n\n/* Syntax highlighting (based on github-gist) */\n\n.hljs {\n display: block;\n background: var(--code-background);\n padding: 0.5em;\n color: var(--color);\n overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n color: #969896;\n}\n\n.hljs-string,\n.hljs-variable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n color: #df5000;\n}\n\n.h" + let d_6573d83a382edbb1785a8f45c85c3975 = "\197&\159\202(?\2397/\139(\146\186\151I\172\241\191LC\150\031%\141\133\157\220\190\014!\151\129\204\239/\138H\138_\187}f\246\186x\173\252\140\176\002\174gp\133\250\193\168\248v\024.\014\007\137;h\246/\236\180\239\216\194\173\155\191b\r\229Co \193\155\127\161?\222\006\138?&o\221\212\197\134~N\1504<\229\178\174\182\128\241`\165\151l\171%\156\165\\\248\2043\201\17930\183\148p\1807\228\240w\141\007\173W\217\220\167u\227\186+yC3\136\0187(bl{\184K\228q\187\201\170u\179\027\024\181\205uO\185\236\171\173\227\193\202\255\255\227\157\224L\017\006:\219tD6\178\141\179\173>w\166-\224*(~.\027q=\147\206\170\160\174S\021\028,\004\012`\218\132\199\151\024\229\028\166\179\220\2404\13309\127\021^\007\153\005\205L\172\004\244\171\250\181(A\162=Q\150\244\210\011]P\132#kq\253W1\229\007;-Q=(I\160\207\015n\191\n\152\0296>g\2462\238\022\184\187\250N\001\165\002\217\184\219\145\0060/\019\130\230\127]>\197\144S4'\003\222\155J\191um<\151\181\200\005Q\174\205\143\030\183E\167\207r\231\nF\211n\\\005\005!\246\018\137\021\241N\215\187\011\230\141\"V\229\1637\193\213E,\246\162\219\224\150\148k\159\239\011\205\190z\199\003s\135\232\148\246\180\128,\135\003\240\002\197\181g\159\172y\140\031\226\204\195;\196\219\004\213assxVf\194\216\155\017\173\158\247o$\251g\243W\139\255\214\255B\148\139\246\027cN\131\139\227yJ\210\212\153\\`{\016\142\133\151>\204\179W\207X\027\147h7\189\030L\146sxJ6\202\200\205\175\219;\204\166\142\174\026\253\199\023{\023;A\178]\229\140\226\244\001\179\133\031n\207\169\207\149\2327\199\249\180\190\1934n`\157\201\191m\168.\219\221\236.\238kS\\\190\214\187`\241\172G\192\197\219<\133\213Ve5S,\213\243jg\242\207\017?\202i\230\130\028MDG\"\167\184\222\129\173\219-\186]i\249t&\223\147\194\238\158\183\134\255j\234\239\\\206\179\025#\224\162O\211\2197\191\150;2\227\025\231\207\203\004t\238\159\240\"\2112\253I{\195\148\249?\184\018\163>\191:\165\1502\182\242\212\225\006\193\172S\022.=h!\224\195\180x1>\221\247\193\160\255\233\131\240\171\016\171\139\241}\184\002\207>Q\146k\149\218\224\228\192\204\128\237\241\241\127z\235\007\240#R\241\221\249x2\023'\241\003\024BS\019\205x\185g\180\220#\202\202\246hAi\177\189\130\190[\022\1670=\199%\\\127\020\1583\177\003\248\201\222\250\249\248]\177\244\200\0161\169\238\192~\130?f\1596\127\221\229\1308\176\156&\161\137\251\251\212W\231N\134\231\154\193}\135\222c\175\237\r \204\131\248\159\190\189\255\219Nh\232$\129\134R\202A\162\145\195:\222\029\143f\191`\127\2318Dr\189=\138Z\209E\012,j0b\016\252\241\251Z\226\127\155\193'\162\223\140\204\140\193Oa\2449s\005\171\161\197\148\154\167\142R\199\217\244\n\228c\030\022R\001\t,\003fz\011D\2070\149\128DW\142\224\138d\r\029M\166\240\213\0039\243s\0260\138\194B\144-j\182\251.\128\000\004\000\132\191\174\r\242\217\169\222\222\031\252\2428 \130\155\244\012p\255*\245\1791\144\203\158\195\2248.\017\224\030\254\220\213\025S\245\143\145\024\195j\209jC\140\029\248\208\159\196\193\230\241\211\229\0119\164\144Q\240\204[\249\159\232*q\160\217?9#rl\011\216\198\197N\177\216\187\153o\209J\184\134zc\018\238\247\224\002\201j%\214\202'\167+\198u\242E$\173h%9}|\176\249g\177\023u\000\150\255\220\155F=\1381J6,\151h3\216\003`P\235\167\198\141\229\0202\194d\140\205y\181cx\151\147\245\011\192\150\155\195\174\219T\219\200\\;\139\172\"\219\210L\149m\210\177q\029\223\210\rZ\011\140\241\214m\138$\169\200M^XOw\156m>\231\158B\229j\223\161\169\147\178\017\1953\2013\003(j\209\160\030\130 \216\171k\181P\151ymW\180\003g^\186\007\030)\239\236\147\241\\\238O}\195f\254\185=PDyyX(\153f\011l\127#z\147K\129:./\157\nE\193\2321\025\199\242\159I\158\165\188JN\136\"\005\182!@2o\241_\149TJ\148\143\128\236\n\217HA}o\\o}\193'\241\019\153^\165p\175\177\191+m,\213\200\027\183\149\179%\002\132\1816\208\214D\167n\165\200\239\128\252c\025wp\206{%\139\188\0199^6>U\176\023\000\176\250\155\230\186\254\197\141u5\205sE\017\236\150\025+G\135\255k\012x\212\158\168\218\249\17224\029\229uk\231\224\244\217G\242\"\234\2312\252X\014\131\213\182tI=\231.\132\224\184\197\130\019X\181\014Ng`:\134@wS$&\186\219H\2374\201/\238\191\200\195\027+\201\254!V#\150\171\199r1V\251\240\146&N\173,\172\182\1373\0124\002?\022yS\199\1347\006qp\238\\Mmm\141r\173a\160\166\134\208\180\166L\240\248O9\171k\028\\$\215<\192\238\002\154\151\227\011\029\198\217\179\178\173\199\2135k\150\219\173\226Q\215Q\131\235'\148\235s\019i\163\171:;?\186\165\\\251\030{\218\254\189\211\012\186\145;\1742Hw\198\193\137\250\005f\207\185E`/\202.h\205\0308;\161\220\197}/kg\182\020Qs\200\2202G\206W\148\188r\005t\152\134,P\170\014\168\140\190q\160\218\181%Vo\225l\029\151\250\225S\217\211\015\129\219\029L\226\140e\023[\187\215o\001O7\140\217\"\190\233*\209\b\238EJV\251\141\232M\\c\187\2114\197\127\000\nv\156\017\234!\b\218\232\213\251\194\029\224\151o\2314\024\238\223\167bb\168\181\128\161a\142\237\203/5\022\139\2244\174\127w\198\213U\213\212T\209\249\128\161\015\207\029\171\229\174\020\1428\015\209h\1873\".Bg#\233\016\147C\127i\176\207\2336\148%T\030AW\215\001\183K\252`w\131\186\213(R\241N\015\163<\129\002\016\135\t\129d\220\184\012.\189\002\151\\\198\007fr\224\000\190\163\250j\2479pz\220\157\201\024\012\b(\224}\224\r@\004\128\177;\1477U>y|\169sW\r\030\12893o\254\196~\183\169e\212\027h\025\132\151\\\006C\017\136NG\188n\251\136K\001\127\167L\163\159\023\156?]=\211\187\227\243R\224\157\251\025\199\198\1425\236\146\2362\212\214\030q\133\t8?\188\250\015\139\146\202\227\\\246q\229\248qk\162\193\135\127\028\203\184\234\024\255\145{\220\186n,\248\243EV\224\186`\239XP\182u\029\198\229\161\135\223\201\135\183\128\188)\216M\148\1851\206\2301\207\173\223I\215O\165ug\183\142\202\174\217\200Dob\204#\243\206p\184\243\206\028\001\230&l\003\147\179yT\225\221r\214\157\242Q\133g\183\018$\029J_\212\208\020Z\028\030k\181I\151\1327\133\026\022\165C\224\229\140\182p\136=\161'GcK\204\243i\152l\130\205Q\002Ey&\222\025\001\150\198p\228\016\179g\014\141\230+\238\254\173^\160br\187K3\200\238\b\240\242o\192\133A\190V\018/\163\1791\026\204\239\171\202\234\2302U\130\210\132\132\178YJzS\012\232\132\025\211%q\251_\140\179\170\178\2351\004\134`\022\r\130i03_\147\224\213\184\157=\192tN\192\029\249\250\r\155\166\137n]O\n\169F\195\007\161\019A\031\228m\128r\027 \253\206\2193\1841\169\153``\1985W\186C\225\180\179_\250|$2\0303\191\251z\132\139\158\b\157\012)\141<\163\225\029\219\251\193\233\150\235\220\213Pn\003\156\219\000>c\134Tq\232\250\196k\221\198\185\162\185\246\165O\237\1613&\230D\200\253o \024\243\158M\152\025<>-v\215\029|\1370,O\156\171\233\218\189uB\216\143\169\241\239\149\240\214\214\027\189\182Z\222tVt\129\200\173j[\185\174o\237\158\219/\214\146}\177IC=\017\187N\b\166\217c\211\014\139\235f\173\171\208\184#\nD\191\236$\218\231\250jx\253\020\184w\163\197\218\235Lvi\235\1964\154\017\203\019\229\217\232\204\221\006\187a7\139n\021\229\229aF\154|\190\205\206\194\133\220\176rx\140:\151\227\b\141\243\218\002y\134\217\163{Y\236=\134\217\129\188R_Y\130\ru\208\193\253\027i\193\204>2*\166\192\242\173\158\147\154\231\181,Aa\152\2171nj\175\199e*\203\172o(\162\177\247e\150\153<\174\222qS\153\0290\140\022\232\199\\y$m&w\250b\157\133\029\227V3\134\017\181\224\2298\198\234B\223*WU\229\135\179\204{'\015Z\248\236\161\196>k\222\231~)SO\003\157\215hWQzC[\202L\184\235\225\193\173_\145_\189\183\183\247\183TY\234\196\231;7\158\1869_0\255\0265wQ\237\169\255\134oZ\181\188\251S\181`\220\173\213+p\188\252\1636\200\2022\187\019\147\204\159h\249\197\145\132;\163\233\129Hl \b\019\014\188\149\171\1924\210&\147|XPr\213\143\199=\n\196\144M2\189\140\147;\222\185j7\192M\004\145,\1591G_cM\174\204\243YLz{|\014\131\182_\n \239\005{\162y\222\212T\147\211\182\141.\145a\194u7\151\252\201\229\134@\2394\200|\248@\141Y\250\186\207\195\156\179\195\235\213Vl\000\1855H(\158 w\188\158\018\214\018\219\172E\160y_\254\205\163\187o\192\183\138\194\198\030q\003h\207nht4\156\t\028\213pcPI\190\250\214\233L\217q\185\222\000L\214\226\200\205CJh\199%\171\rO\206\134l\129o'3Ta\246\250\254K#\029*zs\203\221h\172\160~N\173\160\249&\031\135m\226\194z\b\137\166A\"P.uO\011\174\135{\196\153)X\243G\249\139\138\231\012\003\201,\143~\255>k\202\140\142jP \016I0\138\167\015~\220k\149\179\b\195\2344\141?\167[?\186\018\181\213\146\185\218\021\001Zz\158?\176|\145\128-4\140p$\178\163S\207B\211\255}\140\233)\140\211]6\n\239\138\002\131s\018\184-\216\201\r\226\224\153\228\217\217y\023y\241\212\202\197\022T\128\201\\\165\253\230\003;\1855\203\014B\208\153\154U\019\007\1279\223M\142K\019\177\193K\239\150\167\194c/\198\222\011\176\172\229\191\242\031\006\023D\223\021\000\b\026\005\178^\241\185#\143\167To\207\227\017@\028\012\220\233\162\155\179\143\139!\229\228\229\142&\195\229\129\180\155\240\191\216\130~\176T\218\219\221.\206\157\021(\167G \140\031\130\1652x(^(\017\146<\178\024/.\194\139#tU*\155\027\133b\145\240E\"\132\219j\164\165@\192\181\240\2286\b\229\n\181B\222\226\015\004=\028\020c\0069x\016\216\131\000\231\004\153\224x\161X\192\238\141\252\170rK?\137}\168\029|\019\138\181\212D5\223_\200\011\183\141\255J\244oK\233S\1895i\188\150\200^\182@\\Dy\191@|o\249\005!\2130\159E\143@\230\025\140\012\138\192\204\215\194\142U\131\007a\005\157(@FQ\179\145z\251}\230\011\248\192\219G\225U\240-`y\203\129\154\224\239y\t\248\249\241\227\"\156\005\195\198\248\227\1772>\224\181\021!#c\207\137\186\209\021\005\2172D>de\181l\250\155\179\189\165Q\153\226\251v\031\239\143w&\252\248_\026N\1642\r#\027u\001\149\000!L,\149]\247O\201Q!\202\140W\231e\248\204\011\132\134\186r\201\002\222\164\144\215\197\157b\1784\133\247\253\1835\153j\004\"\183\212N\250af\225\031\155\138\128\163\199\148:\170\029P%Ta\234\196h\144\148E&^o\142\215y\237x\154\130M\255m,F\141\140\t\198R\\\215\200X\188YFc\1667XO\153Z\025-\224\199%\230\240,d\025\143\001\136\193J\160\219q\"\nS\188\138\r7\231\135\235\205\004\226\193\155\227>8n\2301\143\179Q\150\148W,\185\193\128\179\1444b\140c\204@u\245[\139U\209oX\006c3[7\168kh\186\029\230m\146\201gm7';]8h HY\161\144\228\254_U_\153\196\rK\025[\172.\231hxpy>\007Z7l\165LS\191\197\025\223w!\029\014\242)\000LUe\156\184\152\193XB\200S\152v\205Y\248\231\211\219:\001\1598;hp2\230\182\233\144+\217&\006\165|t\019\209c)O\161/)zIx" let d_660c0a9ac6b1a9b2cd6b6ff6cf9e5ed0 = "-\228\005\177!{\236\146\199@e`J&\214\181\139\235\174\b\214\178\183\183AxG\185\155:%D\018=x\240$6\242\186i\225\016\133:)DD\168\015\139\219\162-\139p5\148Y\177\017\129\023\208\191\219\236\178c.\211\209\174S\218\221#9I\168U\179\028N\252\017\222\143#\028#\007\239r\229;\247\236{\212$\174\165\241\188\187mZ\r\239\168\171U\183\139\201\203\242\022\187\145w$\186R\178\243\156\2123(8p\214\t\153\251\149\233\155m+\165\219;\029\023X\022\181\003.[!\b \214I^bb\232\003\249\029E\255\195\132~O\210)\209\211\160\248\185I\135\201\192\bH\254c\129\246\244\"\154X\021\000\148@\014\152\243\026\171\020\139\191\213\rL\233X\006O\007EhG\015-\138\237\227\002\141\031\174tN\024\\\249\138o7J:3\232\182\181\170\197\174\129\130c\020!28\nt\220\145u\228\178V\187\017\246\012\001\241^i\181\238z\172U\222\197\201\254R\179\214\201=\143\162\166\134\205\148d\021\181!|\231o\200\"\210\192\020l\172\027\231U\190N=\191ZQ\172\221\001C\028\233B\160\132q\168*\222\2418;\017S\170\179\212\254B\156?G&\160\184\253\021\239\175\199j\247b\139\212\2549b=^w{\160r\020\209\197\\O> \\$nE\146\198K\026P\016\180\245\139\r\134\149q\028\016uc\031\025h{\250#\172Y&\145s\020\171\141a\016b\018UF\004j\147\1623g4]\025\154\023\006\148\136\241t=N\1432\180g\136=\212\225\163n.$NV\000\185\171,\128\n\146\155\031\154\211\215>\1481\225-C>\1484\2185\016\228FU\219\154\002^\023>\178\170\029)\n\128!\238\233;\t\201\219e\130>\246\217\145G\246\020\254D8\181\170\027M\007\211S\169\012\227\218$\190\246\021F\017\165\175\217g]iA\218C\002Z\222!\015\198\151\132b\192\020\197\247\174y\002\209\133\149\160T\021\031*\1850\153\217\236\204Q\021\029#\181W\163i\2415k\248U\005\193\150\003G\203\154\153Q\132\153\159\177\248\193\221\140:zf\227f\138\173\\\155\226\252\007\176\253\135+\247\144G\190\142\213\150\021\129\145\1879p\nm\156@i\206^b\159z\129C\150h \151\170\202\162\157\026\014\153\148\148\189\239y\236\144\252.\203J\011\002\207\229\228\024\014z\210\189W\169\228\212\012\140\1565t\2447B\191-l\241,y\183\156\023\127H\205\208a\198\177\240\157>HBqa\179\158\223ei\145\185\167\014q\226\231\223Ul\140\189\169k5\218\019\188U\2272\189\0221\1806w\157\141\133\233%-\136\189\209\2042\216\247 \204^b:\018\234\155c\233\141Tt\241Q\139\150\012\188o\201\152n\151\128\154\178\195C\005\135J\179&[\230\161\142v\030uO\011j\243\141Z\133\151x\1341w\186\183r8\148\244\005\006\007\209\238\129\134\n\202\208<\187=\233\175\007\019C\239~\189\253\246\163o\184.\249W\222\134K\175\161\004C\246\006H\175\156\021\n\238\176\237\1871\254\131\023\026\247o\211o\1660\196\191\168\172/1\031\160\245z'?\146\1792`2\252\198\153=' \211\202_\0128\157|\249\183\199\163\236\192\\\255\243L\0249z\019:+\147\159\150\231\244]S*\206\127\220-:\254 \157\186\160\002\197\249\154\140Ir@\220\147\152\205\029T\014\191t\005D\137\187>\138\191\153\200\197\137\161\t0\174\172\b}\011t\162)g\137f\2520\1923\231GS\136\145\164\207\200\147b\152[\030nY\166\1885\029\178*\007\228\r\217\181\253\017C\160!.\187!OT\025U]r\187T\196\248\220,-\255=8\022\233\248\253\138G\244\183\154\007c-\158\219}b\233sB\207\196\156\168(\189)+\171#4\016\184!\134\005\210v\022}\019K\216\tg\209A>\202e y\180t=\170\252\025T\211\234IL\003*\018\025\011\162\145\139\181\030J\024>\154\031\215lA\181\209\247\003\237\207\160\222\229\028Z\143mG\134C\029\2332\216\143[\255de\222\164\173\192dN\224L\026\007p\245\166tE\238\149\151\198\150\207\174J\156\162|hX.}B\163\156x\205B\250\180\231\139_\172-0\224Mj\207Oub\132\1777\183\142G\006F\238\154\147\"\220ukp\002\137\253\014\142\253\184\128]\207dK\130j\019\003P\208\190\248\135\254'0\189H\247\196\249\207?\128\244B/9\127Y\187\140\244\234\188W\000\245oM\184\241\137@\246\234\229\238X\247\184\183s\237\238\247\223\016&\020\230\134\t\027\159S\023\163ZF\230\131\026oS\168@\217\146\225s\024Q\161\180\1603G\240\189\020\129m\200\195\021\255\003\129\222t\011\2075\003\248\175y\139z\150\rD\152w8\252\024\143\248\180;Jb\234\028\021rCS\154j64\135\225\005\172\210\129\247\192\175\002\154W\181\161\188\241\176\163\245\248c\227\153\006\213#'\203\017j\173\183\187\250\249\179\028e\012i\213\2018{$B;\023\158\1416\2154\232+*\163a\224\214\2466\174\243\170\131\\w'X:\011^\202r\159\0215'|\235>\023\155|\1745\015A\249\031\146\211\142\018\196\186\r\147\182\1455w\194\189v]\220\179t$\161\004\219\184\198\198\182\193\128\222\018u\170\212\135k\000\\\255\226Q\1692\204]\192\r\195C\130uM\026_\168=kK\156\158\238RG\228\018?&&\234\234\127\254\165\021s\243\024\235\250G\183\150t\161\172\249M,}\181S\169O\214\2195\160C\247zmKP\204\0020D/\002?$\183\254\137\253\142\t\252\237K\243\178\154PsU\141\209\216\217\024\162w&\021\193\160\174\238\248\200`b,\233\030?\235\158\170\015\244\190iO\023\140W\235\219/i\152l+[\2261'\003\168w5\031\237\rU\025\191\182\215DR\178\007\211\030\027\231\015?2l\242d\175\134\178Z:\136R\166\222[\131\170>\025\215mx\229F\025LYCaXuu\254~MR7s\227\247zVm\224\025T\136b\"\147\192\184g[\011\219\138ca[\213\237\208\154\182\214\220\021\226,\189\210\155\140\012eR\018\136\187c\011\163Ia\177\231\021\251\254\164y\170\155\154Ld\136\218?\181\"\186\028\141n\215\150E\240\025\174\000u\129D\222\"Ap\007H\213\197F\027\253\198\247\213\137\247hL\230bb\169\234\206\012\220Y\190\1819\210\018YZ\206\027\170\208\238o\253\138s\169>0\152\217\017\023'\197\011\237\192,+\249\n\014\229\1690\018kwi\183\238\237\237IO{$-\244\227\026#1\241L[\158\216\208\149d}\178\237}\028\182\189\135j\005Z\158\251\002\006\141W.\167\171G\138 O1\\'\021u\189\167I\138\1358\007\025\021\184j\028\175\153\184qgyK\157\134\184\181\245\138zO\163\127\160q6\203\171\245\170\006\171v\183Uo+'\245Hao\b\022q\243\164E\240\132\214]\137\167\178\023\145\129\243\130\141\163\004\166\201\\u\234\165\025\024\169\177b\151\208E\212\167{W\027\\\014\167M\143.\241\147\208'\241\168\011\149]:\007\193\135\161\224\150\145\216\251\203u\160\006+B{\231e\230\139\179;N\017\135Z!\194\166\168\145\178\211\169j /\217\137\138\246\0155R\253\232\213\191t\nqx\183\238\198`_\021\220\142n$k\164\128\"T\254\181\159\145*\185H\225Q\218\140\244\129\200\155\247.\246\249\030}\222\021?\200\237s\167\028\14131\159-:fgm\012|I\015\175\210&2\1789\198^\1379\161\246\007w\155p\149D\254~0\231\230\158gq.n8\184uGk6\154M\187\028-\205A\193\022\t\1784\158\255\226\139_\166\239\174\004e\022\236_\179\145\195n\253\1371l\016\162\020\127\220j\018\249^\169\133\159\2266~:\2274(\004\022\249\203!Of\019\218\018W\025h\006s[\157--\023\247\016_\154\221\187R>\152wn\016WyPk\253q\200\128B\127\200:\231\133\176\202^Y\re\152\nE\030\153\002h\217>\211\027\173\019\2450\141pf\133\185\170\160\232\187\197n\149\193H\225\241O\154\b\200\143\023Q\183e\142f\189OA\030\005\177M[Kak(Lmm8S\181\162V\165\017\193\167\152\2377v\140\213\024\196\160\214Fl\143\178\159\218\224\176\178$\020h\018B>!5F5R\234\230\022\001\163\227\184M_\152\007\157\t)%F\137\168\234\133\n\138\197S\223l\153\n:\237r\217\147\178\244\236\178\014\231W\222\147\145u[\164\176\197]v\208G\169\187\134\233\199v\148&\220\020{Ko\1891\b\027\133:\007\1687\007b\018\002\235\196\181\216\204\018\198\"\193)\130\173\220fb\tG6*Gxt\140\205\177\254\031\255ao\233\128\t\166@K]\178(\139\182Y\238;\030\232\240\146\154U\208\134b\130R\1298*\197mG\149BlEB\187D\1742k$\252\218\237\"\024\224\233\247\156\233\246\245~\023\1861\137\156\023#;\181x\131A7O}\1952qx\031\137F\145\252[\026\157\221j\157*\219\248\232\246w \242\163\221\196\254|\191\153\182\026\229\252\151\014#\139\252\175\243vFw<\220zW\196?\242\189\226\231\246\171\155\031\251\172\195\004\021\252%\252\207Z\243$\007l'\184&\205\140rV\130\132{n+\158\188\234\236y\152\131\206\197w\245\146Q\189\207\205\216\140\166\014\253dk\173\223Qa]\216\209M~g\203\213*h\158UD\239L\247\177\191\225\232\205\187\129\206G\201fd\246\188N\200z\141\012\012\135\007\160K\253\164\014}\233\242\0157@K!\157\005\238\226_\167\t\240\143\020\015zms\022\180\167\233\202\219v\t3\131\236\232\222\140m\195\127\t\027\238\224Xm\130C[']\191\006xa2\019\238\226\252\015\2471\175J \133\219>1\229/\146\151\239\250\177\254 X\240\162\147\1630\176\133\231\249\188:\179\014\134\129\177\031~\189\006\166\195\188\169\175\135(\229\166%5\191\191\248Uy\172y\221/\127N\151#\131\229\190\160T\205t\145q\015#5`*\239\159\007\143~\218\158\137I\158B\210bJ\191\127\159\028\1651\211E\139\211\219\229\006\213\226\142\215\022j\164K\145fk{\192W4\020(24\014\205\231=\247\207b|\217&\224\173\030\209\191$\030\166\178\233\200\242\158\165\178U\203\218\027\248\191\007\185\216\195\145\235\129\195\158\224\157\158\246\150Oe\141\0311\179\189\206N\157&\206x\012\212mb\146\001\007\236\198#\170\249B\146;\169\r:+\172\252\155\147J6\211\163\t\007\179~\193\178#6a\181\199\196\200f/3Q\197?\029\248\150tt\196o\221\007\252\179\249T\161\212\205d\155{\251\131<\234\169\251G>{RD:|\255\193.p#\132" @@ -218,8 +220,6 @@ module Internal = struct let d_82e50be00ae24b186041d9600dcb0660 = "1\174\228\137k0\197\198Cp\201e\229a\133@\230\150A\1955\246\232\234\173\176\226\186\002)c\166\247q;\171\244\197\151\158p\129\204\154~\171\237\r\185\233\017\253\176\157\199a\241\n\2522\143\255S\216\021\241+Q\227np\160\019\134e\190\130\028\143\238Z\164ZBi\011\214\246\129\2407!\131\133'>&T\148\145\149\202H\155&\254\219OF\1660\156]\197\135KKq\255\196\139_-\200\201\163\020\\(\216\226I3\031\238m_ef\160\015?\007K\154\230c\011k\139\023h\023\226\165c}\021\232{\004\252\249\003\251\1519\030\222O\030\166o\173/\209b\146/\000\151\188\018\231x\163\248l,\253,\234\211v0;\183\248T\t\233\149\190\168A\n\147\2440\161\200\230G7t\nd#\205\144\251\003\165L\229Y\182\196f\184`Rx\030%\219Q\2428\201\143~jm\194\ry\165\178&\021\129a\172P.\022\185\219]\1639S$eh\018p\157\237\t\237 \003\001\029:W\214\236\233eN\165t\247[gK\151:>\143\2470\015\025(\1573\203\012]}\234^iQ\227\235\134\168\023\184\026t\206q\234\240\253\163v\174\029\254v\241\143\214\156(|\145\188|\182\183yA]\226\025\141V#r\231\005\221\244\210P\170:\132\231\014\183\148\167\220\255\237\"WTr2\232\215\030L:\004\221\2254\128\164?\131\135\228%\196>j\2286\143~\149<\024\168J,N~\132#\196\018\011\188\156!\232\175d{@\248\191\227\170?U1k\002\184!\2403\198dZK\006\244]K\206\196\251\0274y\021Q\217vo\138\007N67\140)\031\210\011\132]\198\138\240\214u+C\248\142\176$\191\157\245\194\202\132~\245\219J\189x\223\027T\187\178^\017\233P\253\190$\166\027\015=\140\252IiC\218\232\205\197\001p\134\163\r\232,\231\187\169HugF\191=s\221\186\206\226-Qo'K\210\179o_s7\174ZV!\214\171/=\202\199\004|\r\132\188\145\223\017\153m_\144\139%!\222\188\253\227\011\n\"\189\160\252S)[KzF\155\179\016\206wp\198\230-\233QD\003w8\251$\238\031\147\129\016\200\229\201#\234\137x\006\154\016\136Tl3\186h\160L\225\150\020,\136\217\243Y\148ac9\176\248\175\197\164\250k&\194\197/\252\165\003\160\r\223PTV\254\181\137\155\188\220\212\223\222l\024\206\150\188\017\189\214\231\163\027{\164\239\221\158\156\142\253\217h24\203\154k\003\170I\203d\223\150f\188\"\007L\248\144\b\176y\137\193#M\029|9\187w^\238\156\250\215Y\155\255\244w\241\145\199\153\029EIE\149\129\229tQ\139\161\140#'\209\173B8\253\015\1898{\162U\157\027\190\232\169f\191\211\248\r\224\024w\135\031\211%kv\152\247 w)\028yt\135u\006\180)3?\250\248\019\127<\133A+\178\251\233\226\188\220\239\026\196n\146'\142q\021\229\017\171\162+5r@\196\172Vy\1443\030p\173\017\128\162c\012\243\022\\\222\225\239\ta\234\134\169C&\"\217\149\"a\165\192\178\246\213\235\245\169\233\174\015!\016M~\254+\247\014\018\145\205Fp=\002\134\024 \169P\153\175KN>\011@\028Hw8\242\200a\200\151\r\244V\136^\250\201ZGD\226.\186O\136\144\236J\161\160\227w\0191\029oS)\022\22267\187?(\192&\179JT\007\030\018\000(\198\2307%l\187\164\133\0198\028\253\176nXYl\189\137\249=;\148$\005v\195\205\149W\136P#\nGt)T\175\155f\244K\023J\221\025\233Pr2\016\206\223\239\174\012F\182\129\132\002E\172\025\137%\006\150\133\167#r\146z\183\021\230\249\031\027+\165\025\226\161\142\197\t\015\229W\242\027\132hDC\161x\210\226\221\014S\184\237\165\191\022+\169\2221,\179\\\0236\165(\139+l(\012Y.\255?\225\242\177\196$\155\029\242;W:\155\209\163\159\138\2083\165\1980N\220\027\160\159\015\127\015\003\2072\129-\2145\130\182Rj\159e\181\131\218%\224\196\228W\142I\165\167YV\138\020\237\160%\188\t$\148/\248\253\254\019\138\209\141pffax\179$VhKS\0287\bMLFw\230 \225\233\146\2403\170\b\212\201,\002y6K\236\160\174\029T\n\017w:WQ\138\181\179r0\"\187@\171\165\021\148s\204\239\169\019~\248y}\137N\245\\$j\000\000\168\191M\193\233\133\222\003_!G>\134\192\2124\177\022\020}\195\229\151\246\254\188h\219\004zS\202\143_\134\141\161^P\229\155\206\171\171\254\253\130\217v\b\142kz2\249{\017<\156\229\245\237\194\216\211[\187\234r\135k\193m\245\216$m\216\129(\031\131fQ{U\205\140\253S\017?\194\183\0117\190\235\026w\174\000\192\150\162\191\146\246`1\231\000Ms\003Y\2510\166h\003\243\141\193\029!n\219\156M:Pu\176\244j\1954\023:\180\234\200*^?*K(\011z\203%\132\171,\r\233zA\141\2342\137\140\012\243\180$=\016\176\216\166\031\235g\021B\181\156S\253W\194\244\031\144\2223\\\138\166s3|\251\195X\185\159\240c\028\021\18616N\207EBa\247\152\191L\224\242\023\231\2545a\193Atd\020}^\170\148k\015\231\024/\1477\131fS\237qDW)\193\151]k\222\191\185\023h\155R\144l\139\130S\224\000`77\003\154M!C..\024go\151`\001P\175+\000%A2\152\184\181\170\231p\253\165\184\027\207\130uK\185P?\168:n*\011\150\149\024\1441\179a\250|P\170\192=\214B!\233\001\253\224\174\026\028\242\178\148\206\137G\142|*\246\227\176\146\163\221%\027<\003\015\160#\155W\012\165*\022X6\188~n\187\136\136\158i\019\015\140w9_\164\186G\247\151GWF_\230n_\173z\209+\251\012\209\183P\213\131\173&\219\187WO\133S\007\027\194\018\134\166Tu\170fRV\219.\228\164\197h\183^zu&\139[\149~\134\167P\171\164\129\213\189\r\226\171\165@\169\186\167\226\171\1804\154H\217\213?3\179\208\210\148\214\247\212\245\216\006/\224\142<\160\233M\240O\2437Y\177\236/I\229M\000\249\022C\014\194\028v\230\235\168\234,l\018gG\146\173\n\228\248i\166by\230SM\025\178\1914\168\007\214UG\220\202\241\023\248U/\022\019I%;\180Bfu\029!\2077\149Y\166\188\177\214\248\199\223\019p\222x\130\201$b\014{\137\255\253\1679F\185QI\134\211O\027\132\154\221\178\231^\003\188h\239b\130\246~\020\022w\223\230\174\214\127\186\1639]\128Os]V\161g\249\237\212 K\170\227B|\197\142/.n\213\\\232\021\127\251\175\027\131\159r\1878P\218/\128\238\020m\230FP\254\221\188\026\235v\003\169ac\139d\025v\200Q\248\138e\245\137\r\235m\018\229\1978\164-:\190$\148\146x\012]\199\160o$\004\226\205_\154\026\202bSXI\213o\195\224%\003\162\148r]\031\018\217B\130\224\015\195<\026\158\024v\250S6k\016v\006\205\196\178\208\207\203\"\023\154\191g\183\1721~FJ\1547\172\134\192}_x%\252f\208\165^l?X^\158G\027(\157\203\153\238\144\231g\170\165\240kj\140\152\244\007\178\179\129\169if\189\204\227\199L@\187\235sg\221\154\163%\230\016E\255\175J\249\185\031\225Y%V+;+\226\024\255\207U\244\027H\005;-\128\152aM\172:5\220\143>0\206\244MA\171\223\023\241#\160h\"s\146\175\153\006\029\236r\016~\019\237^\221P\163\180i\029o\218/GvO\156\031$~f\208\200\202\187\169\137\245D\204\006O\195\n\001\004^\021]e\202\202a\142\163\203\003e\162e\006\216\014P\219,\169\173\127|\020N\249\225i9\142M\198\247I\029Y\2208h\162\201o:\185WGo\183\002\150$K\130\181\225e\001:i\217\134^m\166\234@\027FL\174\229\131\197\162\b\bv=\001g\247-\185\1447br\028\163\178r\220q\029t\001\168Q{@\184\129\027\223\015\025M,\004\128\163W\027T\181 \169D\1938O\208\0171\131\180\241[\249mH[dN\\y\237\222d56\153\131x\029\181\b\240*\208\200\212e\000e\231\132{\246\160\231,\155W\1352\212\0247-#\187\223]\156\159u\201m\216\135&{\215\160i{\152'-'\157\163_\160\189\020:\153\2003=$\224\253\249\244/\138\240\167\202\196n\168@|\1808n\149\202\199t^.\015\214p\1929\015\015i8.\r-s\r\189eAt\006\178\011\202\191\134L\249\000nq,\153\028\156\140[\235Z\031\025\021m\152\023\018\147\161\018\244X\155\186\021T\2021~\164\127\030\224\137\144\006\b\002\147v\003`\206\015\158\028\014X2\167\204\206\242B\169\156\204>\152\168\002\233R`&'VF&\1276\233@\031\2172\230\138\031\203\143\142Z\1651\142u(^\r\154M\r \028\148\183\131\150\246^tn\007\\,\154e\220\228\216\154\249zt\164w\165\128\023\005\165a\241\1973\200\221\246\141\001\160\242\201aDo\140\026\127\152\244\213\023\129\239\252\014B,W\216\000\030\151\210fG\165X1\168\205\189\210`\152\023\129\003;\241\228rn\200\176\233\192\134y\170\131\234\000\160*\003\207\2352\015\011\235\246\249\003\223}\135\149<\254\163\208\231\1428OB6\176/W\146[\175-/]M)\216Y\0177(\192\137\233_\254\206\000\000W\178\030\127\144\212\171\150\029\133\138x\149A*_\158\015\r\138\196\148?(\224x\239\192\173\191\191(\224\141|\190\244\030\224\015L\128\183@\255\201\153(\211\214m\185\198\173\225\225\130D\186\177\151x\224e_\207\130\219k\132\2071!\027\230\127Z\151\131\208\170\"\143\200e\248\135#\012\197\029\234\163\155\167\153\193%\144\203j\254\154A\184(\220\024\169z\217\243\211\251b\242U\207\031\127\020\231a>?\175\170,\191\148\r\228\rN\139X\131S\027DQ4\198v\136\228\211\171M[4\\\025,\151\168\200\138P;&\164\216f\244\225\023\180g\171\026\tO\215\170\161\238\166\151S\139\t\250\027l\019\234\151\007\024\156{\210\154\184\191l\151\229qD\196\207+\015-\192\141\t\174\015c\159\227\130\189\151\132\226^\235\190\147\226P\195\014\190\020\183A\186Q\253\200'\145\133\021\161\188\176\030z\231\210\228\170\154\218\148\004]b\240\194\178Q\183\142\251\214\180\187\211+\197\199\136Hc3\168lP6\200F\201\233\189\151\205\145$1\127k.\023\223sJw\151\021\1494g\165\201\1830\182\022h\nb\155\146;\152\252M\181-\201\005\172]\230\213.P\127\210\173W\031\254\2362\249'\197\220\234\2126\146\225;{?A\238P\247U\244\2186\144k\167\182\183\235\246\240\182\200\202j\169\025\000JL\236\160\212'\014u\164\236u*\250\191\137\170\168\247\252\027\2101\2390\003\213\026\031\1760\209\024@[c\002*%\228qO\253\216\247z\253\202\t\250\228}\178\250\207\011=[\137\216\251\022\227U\184E>\027\219\027^\"uhV\127\2455\214\145\246\"*K\200o\185\130\146\175*\145\164\175\146>\006\202\166\211\202\030+p\241^\198U\127*\245\217\220{\250\136\243W\021GF\16757)\237\139']\t\159\192\216\151\188\173B\211\191\183\180\003\242 r\188\158\250\133\244\138'\148\220\140\191r&\226\t\227\225\\\1298\225\211\178\144I\129\"\244$=\t\026\012f\191\175 !Y\148\176+z8[&Apl\207=O\171\156\223\2064\156k\253\181\180,1\214\205Ze\159\167\252\007\182\176\170\183Im\238\234\173\240@\176}\233\167\182l\141\13695\169D\164V(f\217\248x\139\020a\016\174\186.m\165\138\026n\156,!\162\200\135\206\017\236\157(\b\225\129`\204h\236(8\199\194O\154\218\244\149\212\n\128\t\031\162n\215\127KS\015(\221\029\131\242o\244\154t\129X?\242='\tr\178}B\129\160{B\024\178nqXR\189\135LR<\015\203\188f\127)\241\239Ro\215N:\190\231\030e\188m\164n\170\195\143\225F\1446\204&[[6% K\249\138\215\228;\231\n\243q\227\197^\178_\134\196\025\153\142\143\179\155r\002\236\198i\142\234\190\202\176\251g\030\159o\024\213\158e\238s\143\247\0166%&^\195\023!\173\b)\219\182\2037$\135U\025X\241\001\166\250\179\227\156c|gv|,\\\196gn\030\197iy\000\203^{8\004\191\230\163\196\200R\232\223\166\b\174\157\017\242\149\007q\174\149^\154\133\207I\141O~\246\130\nSw\202C\168\215\rJ\198\022\228\250\240[\1950\241\002l\152Oe\199\238D\195O\171\220\248\002\232J\188\001u\025>\188p\140\204\172\185.\189\026/N\246:n\023\152\134\002\197B\170X\185\255\012\193\023\251\193r\016L\b\139~\002S~L\233\006\221V\249u9\012\209k\r\235@\027J)\200\162\132\170\n\221h7\234\217\014\181\230S\138\191f\178y\143\249!H\170J\230l\029$'^55(\016\240\196u\218\180.:\220;\029\168\136h\152\194\201\030\141\154\233QV\173Z\210(\249^uP=]\214\015MY\1824\167 o\227\027\212h\157*\177\199\174\020\1325\255f\139\172G\178\248Qk\000\227\012\164\209\178X{\225\250\\\144\242]\233eU\133W\1360U\202w+\241\130\175\158^\b\162\135\171}\152\012\254\250\002\227\134\146d+" - let d_84811cd56c3f0eb2d5d94c7292ab6a8a = "ariable,\n.hljs-template-variable,\n.hljs-strong,\n.hljs-emphasis,\n.hljs-quote {\n color: #df5000;\n}\n\n.hljs-keyword,\n.hljs-selector-tag {\n color: #a71d5d;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n color: #458;\n font-weight: 500;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n color: #63a35c;\n}\n\n.hljs-tag {\n color: #333333;\n}\n\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n color: #795da3;\n}\n\n.hljs-addition {\n color: #55a532;\n background-color: #eaffea;\n}\n\n.hljs-deletion {\n color: #bd2c00;\n background-color: #ffecec;\n}\n\n.hljs-link {\n text-decoration: underline;\n}\n\n.VAL,\n.TYPE,\n.LET,\n.REC,\n.IN,\n.OPEN,\n.NONREC,\n.MODULE,\n.METHOD,\n.LETOP,\n.INHERIT,\n.INCLUDE,\n.FUNCTOR,\n.EXTERNAL,\n.CONSTRAINT,\n.ASSERT,\n.AND,\n.END,\n.CLASS,\n.STRUCT,\n.SIG {\n color: #859900;\n ;\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/\n" - let d_85abdb3958833b34c40b86687e370356 = "\"\213w\223\021_s\204M\247\167Z;c\170\226\023\223!`\2472\253GP\182T\233FBu\133\023v.\149\214[-\b\130\132\226\157\140\244\012\211\184z9\147!J\018\138#S\223\203\209*\214\176y7\222\221\1916o\133\129>[\0126\201\239\020\227M\197\206\201\164\2098\167`/ \015\223\017*\134\231\002\173\168?\227\188(:\230a#Q4x\181H\254A>\174\197\187$Rs\221\144\167\252\205\159\183\170\160\157\146\023n<\135a\220\014\128\012\234\154\015\175\182\145\143\148\139\019W\006>4\002w\198\228\218\143\130I\244H\211\171Vq\168\174E\031f\016/\163U\128\149\212Kl\228\139U\227Ga7\2252Mz\021\199\n]I\016\144\198'Lbw\247Z\020=/\193\191\017|\219Z\026\169\029\n\129\131\141\208`\188\185\163U\184$\2365u\231\160%\247\131\253N\134;\132\210\237\132\227\154\139\208u\157\127HVT\249tVhkp\157\240`\239\250\245\192\175OX\146a\197\232[<#L\220$\156q\027\193\028aZ\\\177\134\160k\201\251\147\0264U\012\176P\131.\142 \169s\006\204L\205\025\011\216\229\246K,\162Ab\241\244\244\019\245\184\229\214O\225\178\210\208\020\2051\141\197#\n\178]B\220\171XW{fO\194\181\254\027\130\176\019\152\230Wo\176\145\166bf\205Q4\157\179\r,\186J\184@\131\177\134#H\175\232\016\204\138\144\195\216_\176\195\024axx\220\207\236AK'\238\004m\234\212\165U\157\134\144N\156c]\020\203\157\211nN\141\015\192\252\254r\n+\238&\188[\174\177\021\149\004[\238\206H\229RW,\234\019\183\185\207)I=\197M\n\015\142\".l\220\216\127\152\176:\002[\228\242Z\227m\165\220%\022\022\152\179\234\141\181%\155~\no\173\014\028\231I0\163\029r\000d\181\000\202J{\150L\030\252\148\"\184J8\161\232\204\222\231\208mLSE\156\239&\153M5p\167\149\154\203\170\218y2\186\15549f\003\235\252\244dSO0\249\227M\172\200\219\253+\232\156\155y\168\147\148)\190\175c~'\246\163\027`)\030\130G*\132\169[0\199\007\154Y\154\138N*\155\141\134\132\243\1811\138\209\1723&\184I\231\131J'\183\153\184!o\139\170\011u\213\203T_\026\222\130\025y\166z\238\212\231B\172-\149\004\160\015\212\210\178v\239\172d\193\011\201;G\148\023(jE0\237\252\129\226\168\247\230\194\012lX;\244'\127\157\142\205\012\142s\201K\209>\022Z;\163q\208O\171\213\226\164\208b\012\1452`\165\245 sz\r\158k\004*P[\158'vz\219@.\189\241\174\142V\221\213(\134\212\246I\213Y\199\201\001\220j\201\204\157\0042,\029\246\153\196\233\145\223\193\159\185\241\242\194\0163\148\149\143\026\169\136\228\t\139vU\231\167z\217\\\021\171O6mF\021\171\252\181q\"U\014\172\022c%%O\223(\007\214\153\142g\011\243w\194\171vm|\015\167!\173\254\016\"\221\004\135\028F\240\187\186\199\219\220\193\148\\BQmzB\019\139\019\215\133\138H\b'\031\129\142\138\167\133?\030\230;\195\190\227V\\[U\174\160\200\016B\244g7_\220;I!\015LQ\012FCI\154=a\241;T\1823\146R? \247\209j\019\232\189K\136 \130d\161!\019\174a\179\002\197\t\011N\147J\005\166\222Y\209}V\r=\006B\\j\026:\019\130\223\1445\191s\226\139k0;\172ep,e\217\027\218!\141b\191\201\021\219\168\244\197\244\221\182\191\156&?E\254\029\157\163=O(&\180n1\1705Y4\021\217\231&\238\193\159)\247\162<\232\030\248\"]\249\150\2119#\218_\255\231\127\211\241\001V\142V\189\139\218'Cd;}V\191\186\232\213\031\219<\194\212;f#\024\195\170\156:<1\179\229\199\182\211\166\159\150\198S\245\173\142j\189L\133\b\244t\024\197\028\155\247^;\218F-3\151\227\188\207\007\235\155\026\179\1470\186\151\182\251i%\219\143\161\130\146\226>\247\221{\132\209\189\201\182\223\177F6\0117\140\0288S\197]\175\200L\250\163\157L\207\239\209j?\166\023\207T?\174-J\173\149\162\155 /\255@5\029'/\201\199'L\216\\\205\1367\156F\166,+[9\137{\019B3Nn(\011{O\132\217\179\209!\150\219\221\227\165\197\170\226\203*\"\199\207\229\185\027`\149\227\161\138\2356\206\214\179\135[\192\181\154\235\200\250\148\r\007\160\2137\145\021\025\252R\247\158h\252\0298\173^\006\249\159\b\243\1456\219\170\012\255\198\237\147\238S\203\134t.8\127\205\230\131\169\251\161\156\196\020\209N9O9\193\031\243!\130\243b\200\248j\233\171F\003\246\005\227Y\177\212\167\163SLT\021e\164\137\n\162\\B\219\166\243\203\217V\194\135\155\0301\161\128\166\r\206\181]\213\164H\1735\137\016Xc\131\005\031U~\179\246v\157\241\143\174\137\023\139\152\186\241IMi.\\V\n\216\241\154\007\202\235\235\129$(\205G\134\006\191\231\249\203\184\202\184\2188\165\020o\174\235wl\129\216\235)\133\011\n\180\195\137{B\183\165\187\194\031R\201\\?\226{@\163\254\167\0304\200jI>@n}\029\183\012,'\201\188|\164\\P\195\191\015\172\020\132\132\011\000l\222\n\023\228\003I\016\255L[\200o\026)m7~\176\237m\001\194\014\026R,\184\215\143\207)Q\198\206\225\t\004;\127\253\0158\002\011\015\253y\227\251\241\128\175\227\242!\245O\172\248\003^\129T'a3\235\004>\235_\b*\234\130L8\227`\147_p\n\130\143\229B\204\023\001\025\175\127\031\133\170jc\233)\r\236{\012\207\205\158y\254\220Q\001\252\003c\254\214s\018\146*&X\237\218\230&m;\139(\161H{\191xR\196\169\145\196\191RuQ,\218 \022\028M\213\188\024\184\175\254\217\250\131\215 !\234\187\020\180\173\172\249\239\169\157\151\188gnq\030\243\181x\189\180\183\197\247\024M9\004u/\020\244\180\021*>\252~\178T\205\176y^\220\216Ym\219\031%p\232\159\158\235\012|&e{{\215\131\016x\199\168\205\154\189\251\\o\229\157\143\186\227~\204g\133\204\244\239U\137\rpYo\136[\174\204\167\191K\237\248s=\213\016_VR\2176\028\198\127dViF-i\178f\b\238\252(b'\213%\159\151+\127\204\243\021\221\200\142/\253e\152eH>\205\1428~\135b\253\223\162]\005\027\142\172\213};\180gH\247\253\145\213\027 `4t#\140\135\155\198\136\199\151\181d/;\2440\230\251Zg4l\236 ~\187\239\134\r\164\230\014\131\004f\\]r +c\201\225\171\b\019\187yY\162\150\197\245J\025\144b\020r\142\211\220iuP\173]\006\r\027\192\168q\153\246fNs\233s\r\175<\166m\024\230Yx\rqDK\137\201\251l\207a9\127*\005\198]\187\137\229\218\248\135\137\221\187\140\254R\181\027\236\241O|X\019\127\236\153\219\179\027p\176\200\022\229\182\b\231S\253\0205\214\248j;G\169\226\180_m\028\163\167\176wv\027\156\235\156z/p\003\163\152\006^\202\194X\231\159\226\030\017\006\019\196\232^\t\148\255G\003\003.#b;]\1670\230\243\185\213\198bu;\1713,\004\012dR\239O\235\217\188)\173G\239G&\025@\216+\223\000\181W[G\135\179\r\137\158{\145\144\182K\014\2528T\201\243\186\244\1388\189\139\231\133*q\224\151w\138\208\n\252\173$\237\201\240o\219e\226\022K\253O?\193\023re\"B\183\144\142\180!\194oW9\152\182\026\194j\173x\020+\127/#\213oeG\188\236\184J/\155Q?\233\254M\146\182\012}\160\184x\168\171\175\182\174\1895gn\212\178tx\249\216X_,\189\tA\248\021H\026\003\2532\232\170\134\211:rs\150T\223\218UY\144\138\130\253\208\211e\024\227\154\193gT\166\165\019\180\145\178$PF\154HO\027\031\167\1414a2K\223\190\231d\213n\020\153\017J\216\254\177\242\2384\193\189\175(\141\1907\197\247\129\019\217G\138v\190]\b\240>E\181\171c\020sd\209FZ\170RKi#\221\209\030\012\192\177\242\136\1629ph\252\151\127\219|\222\014>\242k\020c5\253B'\219\179\212\165\021\157\143\232R\191X\245\027&#\002Mi\212\002\201DY\168F\251\215\199B\138\246\156l\232t0\214\2212d\250\011\176nN\183\188\176\228\189TeMY\209\215\187\151\225\165z\243]^\130{\247QE)\229\027\2530\235\135\015\211\186\189y\r\248\r67\225Q\157\136\141m\236\252\163\166]\002\182\196\251\001\147\140\026i\"\151\160\141\148\131\221\n\146\158\166%\229R\149\"y\243\149\239\152v\011m\194r\024-]\029\237\201\211\247Kgj|f\197\019BZH\206l\247\020\222\254\228\211\219+{,Q\029\248\192\157\175,L<\222\170\186\158z\221\158\181\217\158z\162\209\021\029M\027\156\152\163L\223\225\198\237JO\241\139\214\232\231\228\188E\151\148\220s`\154\163\254\231\200\167\028\141\128x\220U\138\227\236G\016\167\236\1984]\244\147k8\195%\210V#\248\195aslA\127(V\156\030\241\136\194JT_\251\170%\225Te\002\212#-\015G\197}#S\207\239\198\003\011\187Q\198D\136n\021?m=uv~&\018\148\202\157\211\221\252$z\228\212\023\003Y\156\184\179W\222\250\188\165\218Y\186\154\140\236\182\170\134e\183\248\235\2516/)x\238z\207\138\221X\220\232\130vV)\011\015\182>#\254]41\"\219\143\235g\169\029T\199^\195\245\017\150T\170s\167\210\021w\166\253\255\003\011\214\181\137v\019\209\171\230[\021\027x\2367\134]w\157\127:\252\182\184\216\131\201U\019\154\198N\203\210G\219\218\240E\192\213\1812\154N\0308\006\164e\236\230\234bOQ\225\165\215\015j\215\021\159x\170\153\247\243#\131%-\249 p\217\021X\243\180\223j6,\186\197H\218\189\233tL\153V\179\184\165\004\020\189\197\190\151=7?w*V\"\"|\133l\242 \198|\2321\131\015al\252\243\157E\137\253M\139\127h]2\144\227\147^\213\197\156B\017u7\002\227\157(\170XQ$\198\184\238\029\140\217\1626\137/S\026\165\255\216\214\251\182\243\1278\190\162d\168\016\132\190\201\143\130\249\t\153hm\186}\180p\024\151.f\252\012\139\241i\006DD\t2\178K?|\223Z\022M'\031\n\163\144&^\026-\006y\185,l\186\024\020*v1\239Z\183\190d\138\184\240\178Y\191n\030\251?{\152\241h\156zk\232\197\214\172a2\212M\150g;\186k\177\156\251;\206\205\206\r7'\191\137B)4\249\152\193\201@\255\243\135\180\153\253\173K\191k[\218\239\184\015v\187L\222J^\138\216\184\170\186\207\224\020\234\196\244B\199\162Y\172\254\240\187J\232v\1700\177l\153\246\007\001%wyA\229\228\251\180-\155\181\155\183\240\189\022V\209\185r\242\015\2034KQN\178-\140s0<\216^\028m+\182\220@\241\253\135\245'O\253\230\143\159r\161L\006Ac\151dBYfFt\248\2547L\240w\2556\212\239\234\182\237\218[+\163\233Bk\018-m\150o\000\155v\237\016\021\133\023\129\251n;r\178\222gA\004TY\\XXp\225${\212\136}\185H\250\229\206x-\2253\210\215\174\000*A\142j\177h\213ZH\147\r!\243\139\159\194Zv\182\179\195\215d\b\140HBW\155\254\253a\229\239O\149\132h\149H\233\027`\152R\148\191\190J]\0042\197n\148\222\192Z\230\171\190\n\158\223\003A\255c\151\238\132\022\158U\207\222\154h\249\027\219>\250\176x\020\1341Z\232\229s\209E\185\195k?[\218\189\232\159\193\159\160Q\024\161\218{\158\202V\171\004\030\194\176\189wO\241\183\228\166\230o\167~\147\174\155\030V\244}\254\231\163\194\203G\252\177\194+\135\027\218>\150\134.nIM\012\234\212\221H\031\003\229\186qn\011\156:\n\164\167\181\023\206\158S\175m\004\021\131\1316^`\131\241\251Lk\206o\217U\0072\175S\142\020\156\195:\149O>XT\151q\186\163\176\211\128\te\001?\221r?\180x\182\186\221\193l\197\007\220\202_\255m\028Z\209j\173zwM~\128\147\239-{\254\182\000\206\168\129\012\152\000[\197\210\240\204L\214\026r\194p\197\216\016\205\203\031\239\149`\203bL\175R/z8z\151\192\188\240\186et\129\189\154p$\022\210c\143h\011\012L\238x\005\176\015\237\2332\148\237*\217\217\184i\179tn\023\216\185[N\180d\127\022)\002\225\231\243\139@\203M<\165\179\187J\132<\187{\223K\202+\215*2\217M(\191k\237\133\149YQI\002\134\193t\253\222\151\0044\169\221E\174\235\142Q\021\029\"j\023\135\007\151\142\140'\152\170\184\197\214$o\238\218\135\031\253w\202\229\186\217\000\153\157\021u\223I\220;\134J\211I\151\158\012\204\166\167\156-N\212\179\245+\n\181\150\169\156\174_'\217y\247\204\237Hw>\021\2264c\178\145\154\200\127\197{;\028fl\240\235\b\212\187\163" let d_85fb54fe884a953ae1b62548b94b5a6e = "=\149\011\141e\002\255sR\254\029\161\224\255\194 \149\228/\190\025\026\156\234\148WTn\181\169\143S\248\160\247.\\?\243\214\137\n\248\153U\133U\240\159\237\193\016j\189\152\187\176|or\178\166A&r\201\139\207a.\191\220\173\224\0069\1403\194R{\211J\140\248\149\206\165\228[\136Px\142\183;Z\007\015\135<\018I\168\135c\183\015\179\191\178\186\16368\131y\026\151o\245Pc\136@\149\177L\228\142\210\212\238\252$\168o\019w\129\187\212//\127\160*k\233\022\185F\199\199\162\175.<'c\136\185<\134X\246\220B\169*y+\249\210\221\228\153\017V\015\139\199\178.\199\147o\219\193n\240k\209\228\130\156\231\231\157\174\224\153y\218\193\246\187\237K\029\235\218\216go\183<-\127:\252q\237\199g\133\174\228\199\231\215,\172\254x\199\210\000m\128&\2487\217KZf\128\134\239\2450\174d\014\216\239\245l\1920\213\171\223`1\1875\154*=Z\231\128\167\155\147C\1411\2425\192FU\r\1806\131\028\171\171\244\189r\137\255\134\015\203Q\224JV\021\2130o\253\136\213\000\164\199\216%\023\176b\167W\019S\214S\243E\238^\139\223\163u\014{z9\217\148\017\250(J\237\159\216Z\152R\1454\164\172\021\243\187\237GH\t\007\238\1975\242\237c\239\223\244O\230\175\193\133\161\240\197\159\023\253;\248<\178j\239\022+c\192\167\146\016\149\200\169\216\206\135\179\224\252V-\154Tr\251\t?QE`\027>~t2/\233F:a\001Ye\022\147\20568ml\005\179\224\252\023\242\160qs\196\210.\023\245\218l\162\161v\181\209\189o\157\149]\146l\223[Er\160\245SM\164\211r\199{{j\204{\240pg\031\215\232\015W\031\024\181\176\007B*\177\030\178\0225W\247\000S\149GbZ\236\149$\ra\242\174\211~s\164\\8\214\1667\171\163\165\226V\163\140\221\234\019\151\154\140\159P\148S\213!\242\246\127.\200kL\155$\238j\131IY\155]J1\152S\148u\002\247\168\138*#\1336\254\128\213\172\147\218y\248\031\169\161\241\003\131\022\254`\139\214\024\031\154\026t\025i(\215\143\206\213\225\230riDY\227\220\195YP!\165QS\236\031B3\23028\031\148\150\179\026\220by.+\022\\\220F\253|\014\246\225/\191\206={\240\198\177/\207\224\159\158\133\031\255N5\006\214\0275\254Yp=\188\000\152,n9\206\150\165\221U\233l\186\209\185:\0219\207\002m\248Q\157\027\130\\m\198\2463\143\180\024\026YL|\244\135\030\199\024\166 0\153'\228D\159\254gs\140Xz\219\200\175\029E\224\185\015q\022ENx\005Y\216Y\244\218\155\248Wqq\0229\190w\139}s\127\155\194\220\189\253\231\197P\227T\179\221I1\209i\167\173,_}(\232u\224\\\228F\139\1863\006\199t\135\248\189\246\230c\222`\209v\197\225\248\196?\134\199\003ca\"\152\173\231\152\237\193\189!s^\141\220\020\197\159\191Sb\145ZZ\186\199\247n\177m\030\248\012Gk\146\025E\198\218\232\208\212\224\017R\194FP\244\241\003\239PLN;\197L\163a0-\24922\184g\236z^\012\250\213b3\224\199Y\199\239w\012yhB\017\224\183\030\247\225\213\132\130o\139>\251\135~\224%dh\247\022\220\174\031f\157\158MC\178\223P\193\208(\127\237\146\215\222\027\183q\022k\153\028'\155C\012\182\244\215\007\178@]\205\173\137\174\150\004\201B\196\127\131C\181\222\247j\246\183\t5\021\236\197\b\153e\160\t\229\150\207e\000{\166\158_\234k\227Z\246\150W\217\172\016q1\150\186\135\194j\228\242\192\141X\178\144\128\254\141\160z\193`\243\187G\227\176u\029\169\187\015\167\236*\170\187yy\140~\"\209\011>\186\237\152{\133\241\243\228S6\207\201\164\135\229*qcW\169i\220Y\229\180p\196z\214\132 \234\207t764\205\029\159\190\227d\209#JEik\179D;\220w\230`Lyj\212\231vJI\252\202\231\169|\133\031\224N\136_\205)\181\212\147\2295\195^\011\153el<\241\225]4\162\254\184*k\026\129\216\134\165>\020c\241\159\236\221 \211\152\bQ\154wrqh\178s\220\181t\177qO\017\172i\0246\018\200p\178\196N\182\147\205\172\146)$u1\1902\195E)K\201\193\027\024\196t\158\249\014&0\1812xyqq\240JW\215\224\149\197\167\007.u\023\199+!\245>\031\164\190\018\006\211A\027\252\001h\189\014f\217\2139\220u\189\235\216\137i\135\188\230\222\248\132\194\178\210\192f\187\185\028Fm\215hs\128\b\238z\181\181\175+1\204\170 \018\160$\204\177\251~\141+~\176B\189RO\225\153\233\018\141U\n\154\207\217_*\tts-\250\030\246\162\221\"\145X\216b\014\173\182S\ni\164\209&H\216^2NZ\252\149\217\022\240\236\140g\175\235H\217}xwq\221\205\023\199h'&\250@'\183\157r\191-\251s?\155\031\233d\209\171TZISW\153U\029\229\204\t\227\242\204\236s\155;\252Y\137\153\198\248c\237\219_\219V\213\168\213\130\024\209\204w\254h\167\226\220\136\223\227\250\147g\255>\228\201\195\000\223{Y\017\001\208\234\171\150H;q\220\225\148(\222G\239\250'Y\153\030\152\202\250\030\134\235\148\189c\021U\b\005e\2226\182\217\016c\149z\248\029=\220\160\160\150/\176\213\146\165U\253~G\176\150\127\236\225!\002v\199\247\203\223v\169\176G0\212?\017x\242\249=\255\023\163l\2280\197\187c\165\127\215\224\132\243B\178iwQq\195\016l8\012u\247\219Xv\014\163F\161\0217\182\b\148\153\213\197\027S\166\193&+\210\213\219c\t\020\156uE\027\026\\1\155\173\"\214\252\159\127\212^\224\1685\024k\0113\170\015q\184\007\237\153&\226\194c\237\\7\143e8\228\018m:kU\179aO\170\2122\206\226\006\151\175U\175P\171_\205\206~*'\135\137\150\177\150L8\134\019t\214$\164\161\190\248p\213<\149\231\209\149W\243\164b!j(\17507\175`=B\179\209$)\\\201\202L\230Q\172g\196\165\149\253\237O9(\182V\219Mc\215\198\144*\252\153&\195\231\246\187u\182\019\186\205p\158J#Q\006\203\173\001\190\\R\154K\133\129\225\240\023\243\243\250M\255-8G,Pj\164\004\172RG`\185\028\r\190\230\198a\159\2404A\254j\017r7=\204\004\190U\140@\233s\011\198@Vi\135g\193x,T\139\217\197\\t\016\140/\029@\"\014\154\017<\174\017\190\r\1610\151\252$\166\187$*\141S\192\200G0\182\014\226Q7~&\189\b\201\136d\023\022\190\159\153u\224\207\131\026|\206\239\133\238\252\179.\151v`\251\150}y\185\022'\180\156\2419d\177\136\173\209\136$A\171\182\240u\253:\189,\239,\0123\145-J#6r\172Q\183\191\185\028\160\027\167:\208~\185\017\145\159[L\2434\242\193\145\165\189\031\227\143\191xHyK0\015\tp){gv\164\170\201$\233\151\012\208'=\\\1813\007\2157 \204\152\220\1509\213/\"lb\026\129\207\140\218\014\003.\r\001f&\228h\204%\128A\239\012{\244\169\209TZj4:\252\241\004\192\210f\231\153\152\236\015s6OW\016\206\145\1489\024&\022\253b2cy\016\155\187\193\189\001\186\208\214\217\191\002\254F\199c\017A2\175=\153q\173\181\232\1622\247\166\160N\r\157\028\217d\228k3\175\174\165\r<<\1302R\180\241>\199a8\130\135\222\159\153_\210\179\136#\\\t\145\232:\n\254\249\248\186D6\"o\026F-\020\143>x\243zv\129\001.\242F\012\238\250\169\181\240>\198\236\135\182|\161^Hs\021f\140\023\215\011\163k\235\178\225\197\211(\234+\145\159\239\157\206)\016\194\197\222\176\193U\191\171^:\011\205\158\202\200f\167ed\209\198\139\129KC\219a\128\226C\138\188\231\005u*\138e\213\215$\183\174\165\183V\r\217>r\203H\209\198\253\156\142\225\b\190\128\150\210N\246\254\212\139\193\191O\250\003~E\148W)\016\136\174\192\211\137VW\016\133V\242\151\200\243\152!\204\002yI\128V\006\145.\198:d\167\000\018\173\020\168\171\146\232!\244\018\225\231\002(W3\241S\172\222\\\170\173\204{\194\255 5\243\160K\220\142\248\221x{\218\2118(\146\251tZG\237\157x\007\014\253a\031f\212\233$\159\192>\005\165\138^\001\139)\149\176\024\189\162\n\240\230\213&m \220?\022w8L\184\191\157\019\144\150\15017GY%za\2196\208\1549\"2q\133a\152q\174\181\0214\208\1523\001\139\255\234\135\174\026\198\197\238\174\184\178\186;\177u\235\004\169\030\n\200\252\157\248!QL\201'\132X)\186\153\207\137\001\241\224\203\131\175\204y\253\163\b`\140x\237\227\200\181\143\130B\248\149\240\169\004\176\159\253\027\153q\247{\209\176\005\127DCDlBmh\220\127*\020\243W3\165\205L\148\159z\154\247\2017d\027\246\198\246WB\235\166\154Z\026\246{\161\251\162{\148\027\167v)\151i\253)c\141\182\139\\a\208\233E\"\161Q\223\142\214\235\214H\226\214\232S\021\202\154\006\161H\"\212\027\168\182mSs\218\242\255\134\177\158f\200c\177\243\1685\027\187\243\235\029\144\185\216\193\145t[\166\217\169\146\250\232=\152<\154\000\216\164\244\250u\186\154\136m\195\222\216\222\016H\026\167\182K\184&\194\247\176l\157\203\028\129\005\252\014\246\166\025\149\160T\173!t\239\214BHm\251{rZ\029Y\1502\1495\203*-l\156\235\173\175\179\243\185\254\251o\160\232\234\210\130\031\179\172\247UogZ\174\142\167=SgcB:_\141i\201O\161\140r\171\188\162\1789V-\015\209\164\001e\217\019\133Z\143\235\178\245\178\178\254\167\205\191\174A\007\130MN\200\241\216\204@\186-\211\232\210J\189\244^|>\163\020\216\168\240\134\140\198Hu\249\198]\177]\024\011\014\161\177\017\229\2498\194=x\174\158\023\140\192\252\0017;\253\168DX\170\208\016\186Oh!\196\214\169\254\236\206m\204!)\140\237\031\172\225\187\138\018\238\027\188\185\027\193\252\027$\251\018\1866\014&\\\242\230q\194C(\023\137\172\017\173\147\135i\146c#^,\198\248\136\225\235\214\235\230zE\242\138-h\029S\143\1455\219f\219F\173\163\234+\t\\\181=9\142\223\130\143\139\230\207\203B8\149s\207\140\243\178'\251s{sg\2550:\189.\175\163\218\225qy\156d\254QW\161\171\152\127\207Vh+\024=\158`jZZ\154V=s q`fd\230`\226\224\140\145\nL\172M\020w\254\237p\196\163\241\014w\\\172\171\189+\017\1411\199\026\237\002@\156\202ESgvL\157\166\199J\007JG\000\139\"z\243\161\237\218\171&\028\243\014\000\196\240\232\135\197\212\0040g=\161\028\127I\167\224\195_\127\189\244\b\028\235\137uV\253%\173\140_\246\197X\230\200!Z\015\186\234\213\128\240\149\203\228f\234\142\152\137\020\011\135\1635C\024\0123\137bf\194f\152\159!\246\217\209\175\162\196v\187\248\155\191:+\205\150e\n h!V\219\208\183\022w\216\196\251 \016H\244^P\248\234\203\001a\1959\240\028W\135X%4\0182W\247\247\031\253\254|\173\223\233)g\022\141j\237C\253\252\239\031\2530M\167\029i\2537\025\239\155;\187\253W\161)\031K\012\196\183\028\216}\176n\191\2038Ww\226\244\165yF\029t\018\213\184\170\215M8\253n\180\253\245\157[\018o\191\223\185}\252\249\198\186\165:7{\"d\146\240\228\165\227$\021\139\229\241$\170{\019\187\154\215\236(\216\251Mm\022\158h\244\202\159+YJ\172\004\240\012\021\165T\234\016\019\182\244\191\b-\031\193\160\155\216\186\174\250-\155\rZ\175\182_\211B\021:\005e\226\n\005\185\028\175\166\144\169\218\000YQP\005-\202\031\255\023\003\130y\167H\219\142[\197\248E\186(\235\248\225\134\163\201\161q\b\218\1551\014y\208\182\170\219\230\175\218\030\237\213\220<>\141\166rTa\172\172\213\200fx\197h\025fK\022\228\231l\147>G#-\213\154h\207\238ARX\234\000N\194\014\023u\179\\b\164LC\030\n\252,z\130u\178R\157\129\030\166" @@ -288,6 +288,8 @@ module Internal = struct let d_a8b5fa32242a1d360076af4bdc9dafbe = "n o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Tt.MathNode(\"mglyph\",[]);r.setAttribute(\"alt\",e.alt);var n=F(e.height,t),a=0;if(e.totalheight.number>0&&(a=F(e.totalheight,t)-n,r.setAttribute(\"valign\",V(-a))),r.setAttribute(\"height\",V(n+a)),e.width.number>0){var i=F(e.width,t);r.setAttribute(\"width\",V(i))}return r.setAttribute(\"src\",e.src),r}}),ot({type:\"kern\",names:[\"\\\\kern\",\"\\\\mkern\",\"\\\\hskip\",\"\\\\mskip\"],props:{numArgs:1,argTypes:[\"size\"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ut(t[0],\"size\");if(r.settings.strict){var i=\"m\"===n[1],o=\"mu\"===a.value.unit;i?(o||r.settings.reportNonstrict(\"mathVsTextUnits\",\"LaTeX's \"+n+\" supports only mu units, not \"+a.value.unit+\" units\"),\"math\"!==r.mode&&r.settings.reportNonstrict(\"mathVsTextUnits\",\"LaTeX's \"+n+\" works only in math mode\")):o&&r.settings.reportNonstrict(\"mathVsTextUnits\",\"LaTeX's \"+n+\" doesn't support mu units\")}return{type:\"kern\",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return Ke.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=F(e.dimension,t);return new Tt.SpaceNode(r)}}),ot({type:\"lap\",names:[\"\\\\mathllap\",\"\\\\mathrlap\",\"\\\\mathclap\"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:\"lap\",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;\"clap\"===e.alignment?(r=Ke.makeSpan([],[wt(e.body,t)]),r=Ke.makeSpan([\"inner\"],[r],t)):r=Ke.makeSpan([\"inner\"],[wt(e.body,t)]);var n=Ke.makeSpan([\"fix\"],[]),a=Ke.makeSpan([e.alignment],[r,n],t),i=Ke.makeSpan([\"strut\"]);return i.style.height=V(a.height+a.depth),a.depth&&(i.style.verticalAlign=V(-a.depth)),a.children.unshift(i),a=Ke.makeSpan([\"thinbox\"],[a],t),Ke.makeSpan([\"mord\",\"vbox\"],[a],t)},mathmlBuilder:function(e,t){var r=new Tt.MathNode(\"mpadded\",[Rt(e.body,t)]);if(\"rlap\"!==e.alignment){var n=\"llap\"===e.alignment?\"-1\":\"-0.5\";r.setAttribute(\"lspace\",n+\"width\")}return r.setAttribute(\"width\",\"0px\"),r}}),ot({type:\"styling\",names:[\"\\\\(\",\"$\"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode(\"math\");var i=\"\\\\(\"===r?\"\\\\)\":\"$\",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:\"styling\",mode:n.mode,style:\"text\",body:o}}}),ot({type:\"text\",names:[\"\\\\)\",\"\\\\]\"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n(\"Mismatched \"+e.funcName)}});var mn=function(e,t){switch(t.style.size){case x.DISPLAY.size:return e.display;case x.TEXT.size:return e.text;case x.SCRIPT.size:return e.script;case x.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};ot({type:\"mathchoice\",names:[\"\\\\mathchoice\"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:\"mathchoice\",mode:e.parser.mode,display:ht(t[0]),text:ht(t[1]),script:ht(t[2]),scriptscript:ht(t[3])}},htmlBuilder:function(e,t){var r=mn(e,t),n=ft(r,t,!1);return Ke.makeFragment(n)},mathmlBuilder:function(e,t){var r=mn(e,t);return It(r,t)}});var cn=function(e,t,r,n,a,i,o){e=Ke.makeSpan([],[e]);var s,h,m,c=r&&l.isCharacterBox(r);if(t){var u=wt(t,n.havingStyle(a.sup()),n);h={elem:u,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-u.depth)}}if(r){var p=wt(r,n.havingStyle(a.sub()),n);s={elem:p,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-p.height)}}if(h&&s){var d=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;m=Ke.makeVList({positionType:\"bottom\",positionData:d,children:[{type:\"kern\",size:n.fontMetrics().bigOpSpacing5},{type:\"elem\",elem:s.elem,marginLeft:V(-i)},{type:\"kern\",size:s.kern},{type:\"elem\",elem:e},{type:\"kern\",size:h.kern},{type:\"elem\",elem:h.elem,marginLeft:V(i)},{type:\"kern\",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var f=e.height-o;m=Ke.makeVList({positionType:\"top\",positionData:f,children:[{type:\"kern\",size:n.fontMetrics().bigOpSpacing5},{type:\"elem\",elem:s.elem,marginLeft:V(-i)},{type:\"kern\",size:s.kern},{type:\"elem\",elem:e}]},n)}else{if(!h)return e;var g=e.depth+o;m=Ke.makeVList({positionType:\"bottom\"," + let d_acb2c4605ac55515799c591d47af558a = "ljs-keyword,\n.hljs-selector-tag {\n color: #a71d5d;\n}\n\n.hljs-type,\n.hljs-class .hljs-title {\n color: #458;\n font-weight: 500;\n}\n\n.hljs-literal,\n.hljs-symbol,\n.hljs-bullet,\n.hljs-attribute {\n color: #0086b3;\n}\n\n.hljs-section,\n.hljs-name {\n color: #63a35c;\n}\n\n.hljs-tag {\n color: #333333;\n}\n\n.hljs-attr,\n.hljs-selector-id,\n.hljs-selector-class,\n.hljs-selector-attr,\n.hljs-selector-pseudo {\n color: #795da3;\n}\n\n.hljs-addition {\n color: #55a532;\n background-color: #eaffea;\n}\n\n.hljs-deletion {\n color: #bd2c00;\n background-color: #ffecec;\n}\n\n.hljs-link {\n text-decoration: underline;\n}\n\n.VAL,\n.TYPE,\n.LET,\n.REC,\n.IN,\n.OPEN,\n.NONREC,\n.MODULE,\n.METHOD,\n.LETOP,\n.INHERIT,\n.INCLUDE,\n.FUNCTOR,\n.EXTERNAL,\n.CONSTRAINT,\n.ASSERT,\n.AND,\n.END,\n.CLASS,\n.STRUCT,\n.SIG {\n color: #859900;\n ;\n}\n\n.WITH,\n.WHILE,\n.WHEN,\n.VIRTUAL,\n.TRY,\n.TO,\n.THEN,\n.PRIVATE,\n.OF,\n.NEW,\n.MUTABLE,\n.MATCH,\n.LAZY,\n.IF,\n.FUNCTION,\n.FUN,\n.FOR,\n.EXCEPTION,\n.ELSE,\n.TO,\n.DOWNTO,\n.DO,\n.DONE,\n.BEGIN,\n.AS {\n color: #cb4b16;\n}\n\n.TRUE,\n.FALSE {\n color: #b58900;\n}\n\n.failwith,\n.INT,\n.SEMISEMI,\n.LIDENT {\n color: #2aa198;\n}\n\n.STRING,\n.CHAR,\n.UIDENT {\n color: #b58900;\n}\n\n.DOCSTRING {\n color: #268bd2;\n}\n\n.COMMENT {\n color: #93a1a1;\n}\n\n/*---------------------------------------------------------------------------\n Copyright (c) 2016 The odoc contributors\n\n Permission to use, copy, modify, and/or distribute this software for any\n purpose with or without fee is hereby granted, provided that the above\n copyright notice and this permission notice appear in all copies.\n\n THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n ---------------------------------------------------------------------------*/\n" + let d_ad152fcf832897f8629ca758460f3d22 = "ize10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:\"\"}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-box;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:\"(\" counter(katexEqnNo) \")\";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:\"(\" counter(mmlEqnNo) \")\";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:" let d_ad48849637d7c8349cb3e6952d5c8699 = "0.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z\",oiintSize1:\"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z\",oiintSize2:\"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\\nc0 110 84 276 504 276s502.4-166 502.4-276z\",oiiintSize1:\"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z\",oiiintSize2:\"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z\",rightarrow:\"M0 241v40h399891c-47.3 35.3-84 78-110 128\\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\\n 151.7 139 205zm0 0v40h399900v-40z\",rightbrace:\"M400000 542l\\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z\",rightbraceunder:\"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z\",rightgroup:\"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\\n 3-1 3-3v-38c-76-158-257-219-435-219H0z\",rightgroupunder:\"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z\",rightharpoon:\"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\\n 69.2 92 94.5zm0 0v40h399900v-40z\",rightharpoonplus:\"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z\",rightharpoondown:\"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z\",rightharpoondownplus:\"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\\nm0-194v40h400000v-40zm0 0v40h400000v-40z\",righthook:\"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z\",rightlinesegment:\"M399960 241 V94 h" @@ -400,8 +402,6 @@ module Internal = struct let d_e4a12f7ec4801d06858e634cb2f32ebc = "\018\028\204\199H>\155\200d\242\159\131\000\016P\247\201\139\005\011me\199\005\027{\016\000\214*7\1888\224\167.Y\024\164\031\218\025\016\192\000a\160\194h\021\154\245\017\203\192\139\007\139\128`6\231\226\012r<\220\025\145\156Ql\012\254A5\147\185\011(bj\2012\200@\199\166a\020\016\185J\031\185x\196\2477\002\128S\1514\189\137=\136af\003Y&\161[\191\192\246\147\012#H\242x+-\145\185\142\202a\004\240\172_fW\209F?\134{\161\219\210\003\167p\018\134\2174\236\141U\221\156\196<_I/_<8t\002\250F\253X$\171?\168A\2473\239\139\172\230?\000`\192b\176 \206\000\224V\192RKp\227\214Z\006V\245\180\176\017\196\153\023\183\135^Fs\250qX3\159\164\139#\183o\156\025d\031\209u\240\168\174\006" - let d_e94c8f28d2a123393c1fd370776b6c2d = "erit;\n outline: 0;\n padding: 0.4rem 0.4rem 0.7rem 0.7rem;\n}\n.odoc-search .search-entry p {\n margin: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry:focus-visible {\n box-shadow: none;\n background-color: var(--target-background);\n}\n\n.odoc-search .search-entry:hover {\n box-shadow: none;\n background-color: var(--toc-background-emph);\n}\n\n.odoc-search .search-entry .entry-kind {\n grid-row: 1/2;\n grid-column: 1/2;\n line-height: 1.4rem;\n font-size: calc(var(--kind-font-size-factor) * 1em);\n font-weight: bold;\n text-align: right;\n position: relative;\n bottom: 0;\n}\n\n.odoc-search .search-entry pre {\n border: none;\n margin: 0;\n}\n\n.odoc-search .search-entry pre code {\n font-size: 1em;\n background-color: var(--li-code-background);\n color: var(--li-code-color);\n border-radius: 3px;\n padding: 0 0.3ex;\n}\n\n.odoc-search .search-entry .entry-title {\n width: 100%;\n display: block;\n grid-column: 2/2;\n grid-row: 1/2;\n align-self: end;\n line-height: 1.4rem;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.odoc-search .entry-name {\n font-weight: bold;\n}\n\n.odoc-search .prefix-name {\n font-weight: bold;\n}\n\n.odoc-search .search-entry .prefix-name {\n opacity: 0.7;\n}\n\n.odoc-search .entry-rhs {\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-content {\n flex-grow: 1;\n flex-shrink: 1;\n min-width: 0;\n}\n\n.odoc-search .search-entry .entry-comment {\n max-height: 1.5em;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 0.95em;\n grid-row: 2/2;\n grid-column: 2/2;\n}\n\n.odoc-search .search-entry .entry-comment ul {\n white-space: nowrap;\n display: inline;\n}\n\n.odoc-search .search-entry .entry-comment li {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment ul>li::before {\n content: '\226\128\162';\n}\n\n.odoc-search .search-entry .entry-comment div {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment p {\n display: inline;\n white-space: nowrap;\n}\n\n.odoc-search .search-entry .entry-comment code {\n display: inline;\n white-space: nowrap;\n}\n\n/* First level titles */\n\n.odoc-toc>ul>li>a {\n font-weight: 500;\n}\n\n.odoc-toc li ul {\n margin: 0px;\n padding-top: 0.25em;\n}\n\n.odoc-toc ul {\n list-style-type: none;\n}\n\n.odoc-toc ul li {\n padding: 0.25em 0;\n}\n\n.odoc-toc>ul>li {\n margin-bottom: 0.3em;\n}\n\n.odoc-toc ul li li {\n border-left: 1px solid var(--toc-list-border);\n margin-left: 5px;\n padding-left: 12px;\n}\n\n/* Tables */\n\n.odoc-table {\n margin: 1em;\n}\n\n.odoc-table td,\n.odoc-table th {\n padding-left: 0.5em;\n padding-right: 0.5em;\n border: 1px solid black;\n}\n\n.odoc-table th {\n font-weight: bold;\n}\n\n/* Mobile adjustements. */\n\n@media only screen and (max-width: 110ex) {\n body {\n margin: 2em;\n padding: 0;\n }\n\n body.odoc {\n display: block;\n }\n\n .odoc-toc {\n position: static;\n width: auto;\n min-width: unset;\n max-width: unset;\n border: none;\n padding: 0.2em 1em;\n border-radius: 5px;\n margin-bottom: 2em;\n }\n}\n\n/* Print adjustements. */\n\n@media print {\n body {\n color: black;\n background: white;\n }\n\n body nav:first-child {\n visibility: hidden;\n }\n}\n\n/* Source code. */\n\n.source_container {\n display: flex;\n}\n\n.source_line_column {\n padding-right: 0.5em;\n text-align: right;\n background: #eee8d5;\n}\n\n.source_line {\n padding: 0 1em;\n}\n\n.source_code {\n flex-grow: 1;\n background: #fdf6e3;\n padding: 0 0.3em;\n color: #657b83;\n}\n\n.jump-to-doc-container:hover .jump-to-doc {\n display: inline;\n}\n\n.jump-to-doc {\n display: none;\n}\n\n/* Source directories */\n\n.odoc-directory::before {\n content: \"\240\159\147\129\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-file::before {\n content: \"\240\159\147\132\";\n margin: 0.3em;\n font-size: 1.3em;\n}\n\n.odoc-folder-list {\n list-style: none;\n}\n\n/* Syntax highlighting (based on github-gist) */\n\n.hljs {\n display: block;\n background: var(--code-background);\n padding: 0.5em;\n color: var(--color);\n overflow-x: auto;\n}\n\n.hljs-comment,\n.hljs-meta {\n color: #969896;\n}\n\n.hljs-string,\n.hljs-v" - let d_ecbaa97b8be9573105676709e2dbc384 = "3\252C\149\147\203\185\\r\202\173\144:G\211n\211\195\161\151\006X\177\234L\234\146(\017\194\186D\0211(\230S\228\157\171{\167\211\235T\184\155\187\199>\128(\168\012\185\203KKS\189\248\242\004\248\197\236\142\201\014\180\"\015Y1\224.\189\142N\201\r@U\211D\208\205\005\129%\217\231\192\128\149\127\158\216\015p\016\014I\247\194\176\1403\221\210\167\238\180\212\012v\141\251(\178]1\1759\018\157\161D\141\191\250``\172\026\201_z\255\226\210!\160\229Re\167#\128\178\025By8=\230\230\1288\030\167\023\014\250n\156\232\249\b\172\156\024(\215\145Cd\131\146F\194\213Z\250\188\152[\175E\248u\220\207\by\216\152\150\238\169\242\\\240\210j\197m\213\158a\181}\031\236\168gZ\201\019Et\213x\198e\158\215\002]\160\196\154\249\184\244D\016\168\152\147\022\030 \180\245\127\145\151:7C%\215\222\019\245\254\221N\019\233\135NxJ\156A\019\248;\217f5T\141bi9wIH\197C\171Kt\001\238\197\002\235\232*\172\022Dt\185\204e\200\210\168\216\029\242\224Qe\0054\225y\197+119\188\199Z\255k\231\019\132\212\225\186;S\007Y\218m+\191\204\028JI\206_\012\161\130\250\168\230\151\195\135\253\000I\216\179!\1764'}\250I8\208\135]\242Fj\002\140\135\014\239\165\002\210\141\177'\147w1J\169\181\169`K:p\007s\245*b\168\185\141\176I\186\0152\011\251\r\171\144\236j\237$\139Z\222\129\241\206R\133\n;\180[\255\238\200)\195%\193\026\213\158<=\233\007\182n\153\214q\146\193\181-\001\167\206\"\146\214?J4G\214\2181\160E\171\155\213A\165\133\253\185F\175\254\177\b\180e\231\140\219f\172T\218\154\218>Y}~\239\212\155\171\174\172\223\015\017\004\0123\173\020\228\148\2409\227K5\203^]\163e\133\011&\222\245p\206q\171\211H@\168U\149\130\245\251a^\158\149\n\031}\171\1734\160n\255WH.\005\151\2119\\\007\201\235\018\209\238\232_H\131\144\19167\247\182\146\181\000\174\194\166_\158~y\209/\237\029\140\184/~\143\219\253Rv\156$\251\220\146\167uPU\228\136\179\209\239\2547o\1275s\173\195\189\246\r\217\218e;\2021\018\177\012\251\141v\214C\172\177\150\139o\244\245\031Y?\250(y\011\219D\167\140\184\197/_\017`x\185:\252\229c\199\219t\130q\161#d\187\241}Q\\\130\160\161\214\029u\151\201\158\023'\200\157\021\191\150\001\002G\214-\176\222\172F2J\223!\211\012\182\226@\160\173PqP\247\249B\157P\1346yZ\029\150\146\205\129\187MD\218\227?\231)\245\019bn\155\244x\220SRV\210_Y\180[\167<\222\215Kj\234\150\185\194\r\253u\246\2430C\\\153\201\247\1796\150*.\231\004\023\tI\163=\159\217\170r\234\2522\182\149\236@\169\004)H>Q\029\156SY\028\157 ?\187h\255\254\216\195\212\020L'u\215Y\194\136\006\211`\022\006\206h\162\144\139 6\b\190\0034t\227Q\132\"\t\226\168t\239}\189\167\001\166\"\181'\241\025*\128O\023\135C\190G\183\015\177\193\135\216G\234d\193\238\207\239\004b\175\020\228P\209;\185\1907\229\030\157|UZ\242\158_m\185\206=\b\149\183]H,+\196\143&\019_\255\199E\238Eh\023\191\019\166\012\237(/\138.\019\1484\244\145\148\028\019\236q\027{T\175m\253\202\233/\235\171\158\231\176_\236\151d.8\192\231\1988\149\222+w\n\188,'F\020Z\025\2268_\254a\131\141\235DP\193\172F\188\012\163P\224\bY\182d\163#\249\155[38\159}\225\163\232b{\227\175\222p\153\026^c\016\202\014/7\006N\232{\203\2026\203\018\127\022`MTLL\023\174_\154\200\023r\252K\230\149\139N\176\153\187;X\232\180'0\235&\147r\018\146\178\172K\239~\194f\175\237\180-}\238\130\003\012\209\133\018Q\195\219\140\230\024G\240\239\133\210\184`'\227\207\130\176\145+\015\209\012\186\t\026\255\179$]Z+\204H\199J[\217\151\227\233\230\242\158\130o_0\186\246\t\216L\190\178\136_qQi\155\167$\192n\148B\021`\249\223kE1\174\193\165\024F\024Dv\156\251T{\200\221\172\253\187%!\185=g\203\019\230=\028\016<\132~H,\221\004C$\213\204\157fQ\176\194x=DK\\\243\249y_\234\202\205r\179\1827\173\164\241_\137\178\196\028\204\253oz\"\156\006\147Cb\205\216\230\0126\246\254\151U\238\241\186266U\146_z\169?Bi\"\147\237\143\217\146\206?\248\221\1925\153)\169K\202\r\153\187K\172\190~\149\189\011o\139w\240\186\171y\172\b\130\127\183k\169\178\234G\144\208h\170l\157\170}o4\156\153\129b\200\146\137\246\236\024\159\1779<[\179\231\243\187\204\212T\230\129\242\150\255C\198\148\018K\204\128B\197~\163\"\1506H\221x\253\137\150\248W\164\150\218\140\028\141c\197\225\236\180\184\185\"\226\004B?\203\131\2095\020\250k\230\212Y8cq\229\135]\011\238v\215\219\024\179to![\216\189\161zl*l\205\184+\030&\196\228\002\154\"G\243\135d\222bX\011SZ\168@\223Pw\235\185\153\021uB\219\022b\218\226(\012\167\188\221\199\229\015\188\154o\127\023\024\191\002\018\163\160\140\180\173n\161\134?\180\253\209{\023\179|\017\158\011\236\220\224\186ES\159TP\145\176\164\225!\164I\175\1479\220\198*\171\141EE\231\239\167\018\251\246\1484\028\208p{\135\243#\252\212\020\233\197\190'G\015Oj\162{\203\135\030+\167R\0300\146\181\247\242\145\242\240\141\011\b\197\156A\213Z\014\189\t\237\253\144?\221\190\234\196t\1285$\242\153\137\236co\207\025\189C \131A\128m\181\212\137u\149\026u>\223\209\192\141\200H@\146d\237\212\023\231W\209\151\146\003hG|\247\170\007/\235\221\"\144\240a\254|na\216\2212\181hy\244\224c\178V\127\006\147m\157y\221\164\191d\230o\152 C\185#\001\217\004\007Y\227\135\011B\222&v|W\188\209\158\219I\146\002\028\233\n\r\\\016q\129\190\223\193u\002\178'=\146\205>[L\178\tN\1643\225t%\149\"\192){\242|wE,jr4!\238\207#G\022\166)\232\168;q\209a\189\133\156\156<\210\180EX\028TS?\251\176&\185\154\149\250D\245\1625\158\129\148I\217\228\147\b\030\200\230\029\029\172,m\t\165\215\133\223\028r\011\213\150MY\130\004\163T\178\022\193\210%ed\242;C\003\129\253/\206w\206m\182\167Tg\006\180\222\148%\b-\195'W\255\223\025\214H\012P\004\251_\207c\018\191\148\199\133#\2153gL\187\255A\130\241\2433O\\\206kj\020\016\234\145\163\226\245y\222\1466SYU\132\234\180]\219\n(\197\025(\146\180\1897\184t<\213\145\182}\144\151\150\206\003\021\177\135+\223Y\1350x\006. \247\226\168\167\145\203\143A\0191+\251\227\133n\131\227\006\005\030\242\165\011\156,.\005\141\220\142Uu\137\229R\222\194\245\171\230\132L\151\014\243\002N\190`H\233|\242\221\225TU\151\160\245\147E'p\137\198\127-+e6!\248\229h\143\182!a\161TB\130\128\168]\178Ni\137\157\175\228\165\127\146$\245\148N\152\195\225\176\254\019\143*\031i\130\031q\154\250\027\253m\016\140F\227f\149\240\007\231\180\b\189=\131bG\224\226j\127\127\1917f)\207s\165\139x\229\161\251_\128\1680\165W\201\023\156&_s4\150\245z\170:\167Q\217\214RY\226\241\135\151\152\140\007\217tf\028\245J\211\174\231a@\234\016\172\247\255\150\188J15\1817^\148\176\016g%\229W\180tTq\171\222\143\236& \132\210LE\242\220\251o#\016\129\016\026\142\226\031dle4\191c\195_\003n\012\222\132\136~\211D\012\155\224\025D\022U\191\224\188\210\241\215\188\142\211\219\179b\156\253\255\238\1397\2291*\\\214\234\253\164\016G\231\227\023\002\129?\1830\244\139\r\250\173\215?\200\131\207\246\168\000\131\017\223\204\156\164\022r_\203\164)r\022\1494\1730\237pqx`]`\016{\219\173\190\006\188\252\234\212k>\225\181NR\136c\029\1276y\160\030i\210\224h$y\205\182\175\029t\173\"\249P\021\"\165\165\213\253\211f0F\154\142\134\001\188\249\187\027\0297\251\167\174\187\222J\152Zt \141\166'\002g7\132\147]\185\007j\2440lA$\193\012\206{2WJj\231\183\127L\166\201\164_\132:=u\145\239>\183\023W\b9m4\221\181\023\152\242ek\229\254\178\005\223\162\154\023Th\016\207i9\207\175\181*V\1510\233\001\213\205tA\236\178\195\197\181\004]\213\029N\199\145y}![\254_\184\023\228\238\227\014,\151p?\0146\229\150\030\222\192\197D\209\2373\214\210h}\192\019\2187\255\248.\132:O\129\020z\138\252w\178\236\218X\209X\201\156\194j\021]N\147Y\011\175=%5\000+N%\"06\169\179\154\171j\248\246\176/\215\174/7\181\006n\\\191\249\189\187\242>\243^3\205\170\140\154\"\199>5W\230\002\168\151Y\237\252hn\249\028[\249\196;\r\207\127vX`n\232b\167\240$d3\201\159\018\224\127A\t\206\146\196\204\178d\151{\215\131\174^\167\179T\250\164\164B\129\198\163\176\030~0=\0162F\023\239\127\175\247\222v))%\243&\021\190\n\161\002s+\163\167N\207\030\248 {\249\193~\249.\001\163\165\028\028P\011S\246f\2417{\200\218\250)\127\175\242\164\141$\136\bzH\019\196\027^`\015\188w\\\142'V\0228\183=\137\139\r\241\142\230\233\129\206\218(k\146_\nWU\248\t\156\222Q\185x\252\212\137*K\234\237.\255\174\228\208\002\134O[\214\025\157_\177\191H=\174\229\156\237>\179\167\168\170rBX\186\134\006o\186\249\199\243\171I\0209\254.r7\190\195M\133QD\248\161\153\181\140^U\186\205\2244\2461Js\t\144\140\192\017\152\222\199o/\174\015\207\239\241(~_\202Q]\223\145\133\192\218\232\206y\b\245\2523\b\029&)R\001Y#3\240)(\251\248yl\222\225\130\249\205\199\219w\214\212\200{\178\221\161SY\222\030+3!)\1331\235Z\244\225N\163K\212\130s\t\2428LK E\241K\191S97\247\189\243#5G\153\157\208\150\2183V=\221s\136%0~\216O\191\210\242\196\183\b\197\156\133\135_#\129~A\145U\227fM\216\030\012\137x\2079\0035\021wb\245\157e\014\252/{R\192L\182r\226\214\198K\228\188\132\252\180\130\141^\183\173\229\127\194\241.sI\143\171D\206x0\170\128\155\150ul\130\232\135\130~\230r\\D\245.3y\234,\161\209\147\197\156\196\155\237|\164\2503\205+o?\157\1468\166\024\219\166\253>'\180riR\150\2154\188\218\029\204\nR\006\201\210\014\189\2295E\234\163\201\237\255{o\173\223f\211\001\240\187\143u\171\163\\\127\174\147\132\017\166\149\249q\208\158\251\178\139\203\242\214\200\004z\158\147g1\134\228\146\028\135\004\215ev\029_\240\254\246\201\210\193\029\141\139\185\0175?\207\159k\145\236\024O\n\015\026\189[\226/\232Xr6\255\238\127\196\169\174\195\153\143\003\248\203\173?\ra\183\168K\230\197\205\139\167\1395$\021[\155\149\168\014(&\142M\254\1671\214\229\200\253\1347\215\016u\184\004+\148\161\198\255e\249\2351\150\201&\152\179\228\210\186\140\218\157$\141\132T0\141D\019k\156\177\183\197v\171\139f\161\231\020e\243\133\236\138\138\138Hd\129\186A^9\230\148\191r\029\015\196\003\236\139+s\249JA\246Iz\169S~\204\228\230\201\251\226h\255,Q\219\171\186\146E\156\t\007`)\"e\141E\229\252\\\127I\180\133J\129\bXt\142\243\185q\206\226e\149Y+/|\198c\006IR\192\247_\156\144\144\173g\143\203\030\202\254\030\242\213\169\253w\197T)\0026\135\018\245e\144\127\217s$)qN\189R\233H\140\163#\018H\178\160\204\191$\166\005\016 X\182\130\164\211\025\156\145.A\255\144\251\239Vo'\224\204\197\236\202\208.\148\165L{a\\Q\155\\\001\243\028xw\141\158\000\024b\153\148_\215|S\192T?\252\160\147\185\241s\251\174;s\201Y<[MV\157\180\212\015\213y\187\228w\1768\163o\153\227\211\007\211\003[x\131\201s\014\028\140cYr\235\2196\221.\164w\240\239;\247j\029\n\167\209s\007\220\237S[\130\209\172\njV\025|\022a\165\250xY\2502a\133\1615\234'0^\244\254\185\133\236 \153\194\165\184Rw^1\165\172\196~\251\156\231W|\130\160\168\175\250\142\237xf4h\171zj~\128\241\1770?\180B9\216\200]\243SS\202\137\ni\219\170$w\175\173\249*\235\214Wp\168\153(v\164\b7\165d\222\245\176\1504r~\228\198\247\188\156\148\236\176\019Y\206S\233p\018\005\1515\202\127\206`\006C\148'\006\r\161\021\007\005\004\135\127%3\253>\127\131)\188C+\134\136K8\149J\025\225\015\218\242\173\005A\246l\156E*$H!Q\241\204L\159\252\136\210\234+)d&\211\237\026\183\225\018\189Z\229\206`S\225[y5\133\"\178p\244\145\181g\172\225\0255\181\t\229R\000\000p\246\190\151&\030)\170\252\243\019\022\192v\222H\189Sm\229\144\185\248\188\251\177\242b\015\003\211\168\137\199\142~\225\204\210\216\171\244?\202\155'+:\2136\238\1838\156\206\210\188\191B\197\205#\165b\012\165\240\168h\238\246F\251\174\165\252\n%\145\187\142\133\017[3.\188\213\230\171/\237\249[O\b(\200\188@\238G\130\198\219\180\202\141\224\137\027^\187\217g\bU,\\K\004W\162X\184\016\199F\238\1569\224hU9\143\237rx\172MU\031|\176\250\1328\002\163\239\215X\247\b\007X\182\175\249\194\184o\211\155\179\132{/\227\159?`\166f\011\142\205\1484\184=\023\t=\130\206\021f\004$\014\205<\205p}w\176acM\204U\218J\018\156 \142\190\168\241j\134\149\237Y\193\028G\229\130N\030\244\230\023\158\246\2401Q^C\166\251)\189\211\153~\147\nG`\212\n\164\211\218,gUv\233\011\193\239v\1917V?\016!\190#\00486\1598\127,\248\164\151\167\011\253F\129\023n\190\242ic\203e\000-\252kt\152\029m" let d_edc3c186d80de2039375bef179a67067 = "546\1985\005\225\149q\159\172\199\209\192\151Y\226\022\024\028f!D\174C\015\138E\139\165\234KT\127-Y\148\246q\030x_p{\000\172w\242\164iW\178\024}n\223\199\003\031\1468A/HRD\230\139\146\213cX}\158\157\175Y\224\221%\242\143\251\156\228\2390\226r\147\250\146\140\230\237\166\157\004\224\002\011UQq=\213\176\232\214\203S\002\228\184\163\210\232g\153%\234\163\025\200\024\192\208EV\234\129`\237\023-\145\168%\015\222\\\022\196\r\bM\214\220\142\182\242J\145P\218\230&m\027\"?\028\251*\195\206\011Qp\140\023\178a\156\193M9Y1\149\\\163\211Tn\215\169a\248\148J\190\017\139\138y\137\185\204\147gc8\135\150\244\245\139\164\192\225\012\140\205\153\020\246\203\179\000w\150d\007\251\218\244M\"\0266\251\185\196\018\175\143\\u\r}\017i\222\213\027\137\202H\211\208W\146\217\138\138nUs\127\206Pg'\161\225DR\168\199\2284bhF\175\216\160\178E\1631C\188\212\180Q\134\141Y\024\n\2132}\1475\215\180\"\165\020\223r\214j\136\242#\213\129O'\173\180DD\215\011\021\202\216,\012\144\137\230$\226X\214+iX\\\229\214\tC\196~\182\024\206\140\137\188\217\177\138\129$\194q{\221\153H\016\200\146\153]P\194\173uK\021\205\181\246\210\144\212\180DA(\2261\149\n\252\207zn\232\161\204'\220ODw\229`C-\030\166\217B\236z.\179\158\215\181\016}]V\019+\223N\157\168\246\140\232\243\182\243\177A\137\228\144]\253x\155 \169\148\162\220R\015\139\015\196W\180\t\181r0\246c\242c\027\219\242\165\161\"\181\190\222\173\180\184\221\243!\015\150\174+J\214\185,\138\139 W.\212|\r\1497\000\022\199\146.\217\000\223\004\002l\026;=\1650bE\245\011%\137\129m\136\216F,\136w\159P\247Bc\t\199Ki\214\201\168qs\221\131zv\245\138v\174w[\136\143&\005\017+m7\173\139E\206]\209}2G9S\179\147 T\183Ri_\026\141#\028p\023\250\197\219\252\b(\002Y\243\"\017l\019 \162\151\232\003\019F\255\014\192\224u2Gn\rI\243\224\n\239\162\185Aqt}\001W\153KI\185B\131\007\227\197\136!\210\158:\235\190\153\208\232\149\233{&\021H\199\197M<\226Z\023\220\224-\128\196\023\170\166\018\242n\016\172\181\026\217\166\146{K\020\238\025\128\023u\147\029F\158D&\205\023\024r\208zn\176\128I>#\187\2429\014\175\173\024\229\250\156\230\173\004\155\132{\157\233:\012E\1847\178\240\153\156,\020\146\237\234\177X\202\153P\243\136\028\241ZA\240\240\245\230\132\129\135\214\209N\215SFU\146\147yQ.\157|\142\251\191X\211#\222(b\bW\192+jR~\168\203a\173(\184\169\143\255\148&,\232\021::\234d\"0\031\0195\012\247i\218l\217\138hN\244V\149\129\198\237\134E\244jI\235\242PZ\162\0167\b\164%j^\162lZ<\230\199\204\019\031!\182\029\187\234F\243\006\128\213y\199\017\151\001\168W\233\147g\215\228\190\183/[\250,\159yk\190<\189\231A\023\193\225\146\212\220\214?\185I*+\n9\144|\249\227H&\2234u\252\254Z\179\241\217;\202\164w\241\026\215*\022\141\177Eo\252\163\n\154\178\219\185\0295\251K\229X\214\244\164\172\205\\^\177\234\210\031\250\197\172\027\2078\168\182r_\169\006S\004\214\166\245\2007K\155\158^\212R\127`;\170(\135\164\r\142\185\173M\163\234\133g\020\150\007\1860\139w\190\143i\011\007K\203:\r\233\001eK,W\236\249b\218\178\234~In\145P\156fD\019\243\018\191\217\214\214h\240\237\171\183,;Q\198\163`T\012\225\244\245{|\191\204z\180\186>7\222\249h\224\24798\199\017\238\228\254\180i\136\007\160\138v?X\156\132@|\204\252MF\236\250\248\166Z\141\190\233O\173\203\201=G\143\004\207\199g\170\194\187S\227\023\007\164S\214W\230n\249\130\208\189p:2\184 \188\158\187\135\027\030:9\169\218`\190\218=\181\132\199\142\157\b[\159=\235\142\011\006\137;\190c\196\025\148\191\233\195\206.\n\211\202\226}\215\020V\173l/\239c\240~\228\225\228\191\158Z\227p\187+\029\027\203\190\145\177\216,n\254PS-\213,\163\1771\022\239\191>\159\236\241t\217j\142\192\192%\2374\207\208#\200\157D\149O\018\139>\245\213\139g@@\188.\127\135V\202&?M\161V\137\145\250\243\236\207\r\229\249\233:&\229\020T\169\146`p\007\145\130\129\241\206\140D\204\207~\244<\139E8\001\162\161\137\204\234\213\136\225h\184\153]D\249\215q\140z/E\164\216\249\176\194N\163\245]\127\021\127\134d\155\189Q\231zP\147\144\186\180.m\222j\209pE\209\t\208Tq\212\164\241\168\174\208\189Z\015\165\206x0\132 \202&\244\2488\129\182aBA4\235\\\022\029\225K\027Pu53p\250\020\016?(^b\249\137x\244kk\179IV\176\204\253?d\255\135\145\142Ef\206\0154\135\168N\156\151\205\161\185\n\132i\215\1757\174o\159@R\162\030\168\247@V\157\016m5\151\172q\150\140\166;+\142\246%\153\t\tq\191D:\170\2086\234\030\027\000\224\251\247\214\133\163=\148Nf\205F\201\011K\139\016\025\145\227\129\234\137\031\229\187\146E\173\0121\171q\251T\207\172\218\216\000\020\251\161\194\214\149\210\153m\209\216>\0183\250\208\216\007F\196\242#\146\147\196>\238\245m\148\016\145\175J\189\211\217v\175\221\142\154\247\"\212\134X\001h(fG\217\245\029\227\027\217Q\132\227\214l\150\170\203\031\227\241bO\255\183\020RVqc\139\224\233S\024\212ZE\221\255sg\201^]\174\217u\202\230\142e\130.q\214H\212A\251\145\147\156<\165\195\225\192\135\201m\234\252\134\012\127,\1836v\166\143k\251\244\006\155,,\220*\136\019\191\n\162\193Ym\157y\025q\219\248\206\128j\145]\220\243Q\022\1543\007\030\158a(\190\219\173\211t=\128%\220m\164\031\224.\238\2034}\142\157=lw<\026\175\152\220\185\167\182#\1981Q\131=\237e\210\186g\222\224\214\022\187\199\153\145\245\1483\189\011^z\017\014\251\187\194\220\187W\175M\028\168]*^h\176\152!\245e\231\167'\031\248u\228\0248\006I\002\015\241\171\160\174\189-\168/x\238s]\181,\001\156!u\192xoq]s^\165\186&Q{\201\192*\248O\233mQ\174\132h\145\1838R\229\235\251\209\169\189C\021M\219\156\021\023I\220\194?\180\021\161p\245\015\154\255\180\2166\216\239O\251\244\207\235|[~\162\205;\194\220\243\132\139\219\164\2167\208\151JvD\191#U\246\255cV\250\245\237\186l/\018 \232r\135\171[4M\137\220\136\161\232\020\183\205\233\170\011\238;5\028R\255v~0'T^\240\2095\248\018\201k\138\180S\206n\220o6Co\232io\209\017\175\174\031\1337\030\236)\155g\203k\170\205\151\243.\155\171kP\156\207x0\188\182\196\197o\228\190A\185Y\157\223\172\173\011\024\230Bo#\162\238\222y\163\180hj1spF\216~\222\235Q\251\158h/,\132\140W\216\222\196\188\245?\211\177\206\191\227\239t4=\029oT\012['\167r\029\184O\210\180\170}Qp\150!\176\182'\204[\168O&z\218R9iaj\221\162\208\140\194\206\011\154\174\185\251\195\162&\177\252\219\135\152q\017o\180\151]\223\236\139q\187;d\029\003\243r\235tie\206\142\160\169\183L\023\241)\220NJ\158\253\201\212c\141\003\214fZ(\239\158\193Vl\152#\020\222N\206\1741\210\178\030Z\028\022\148l\253o\239\024\152\131!*\174\252\150\242\203\204\167Z#v\129\238\\\160\254\247\028\007u\234.p;\220\179Q}\142\157\b\166\214o\001W\134\133\249\225U\162\130\213\006\207\144T\245\207h\024\132\132\179\252\207\022\023#W\170\204\193\186\235}\025\163c\170,\143c\249\021\160d\n\140N&m\216\nA\225\215\249_=\028\005\245\180\190\205)\203\140\198P\222\167@\217\193\129n\203\003\201\252\213q\193\202\187y]\029\170\173\221F\153\177<$\156q\027\228\170\131\027\203\189\236r\213\197\030\230\252\029\163\131\1897\234*\175\019\007\219\130\169\219n\003\163\029\236\225\205\195\203C\195\197\129\187\006\154\201\163s\206\r\244Vl\234\137%\162\229\\\134C\178\169k\014lj\004\023\023\240\131#\006/\179\151\147\235Z\\\020\1654A\206\214\211\000}\2421\226\140[\149\023\206\001\132\004\131\194\254C\007a}\001E\227\007\192!h\250\012\162k\226$`\198Xa\001z\141hKn\212\167\158\210z\2268\192D\163\194!\004w\238\210\031\018\023\229\223!\187\011\217lDV\195QN\003\172\168\132\196\178\137W0\146\237\015P\158\0209\216U=\171\135\004M\183\0237y\247\207\030\219\024\240\226HF4\250\242\191\195\212\153\147R\143\216&\216\222\203\222q\1339K\196\234\1521'\158G\224\016\184\170\016\168\152yXq@~\208f3~\193\253\024\168\146C?\134K\183J\183\244cp\251\025\132\006\136\003m\020\210KW\164h\211\238\135\0021\255x9\163\007#M\200\177\127Sq\007\237e\129\247\142(>>N\231B\021\128?\186f\243[0VP\186\137x\2330j}\2068\2110X\218\0259\027=\007v,\133l\221;ld\177\244}\029\153-\016\005S(\029\029\237|\238\\y)d\239_[_E\196/\193\229\025\232\005\141w3\030\238\231>\156\000\t\209\132\159\225\1726\160\186\150\238n\150\"x\156r`\186\237\208\142\217m\001\237m@\217\t\224s\189M\206t\212\172\221\243\230\249\170\132J\0312\1679\242,\239\192\184_\180X77U\179\006\168f\192u\254\224\184}3\231Y\156\238\184+Q\245\227\027\135M!\226\200\012\006\007\154Lhr\252\159ZC\173\001 \155\r\161eI\136/\001\196\245\167,\223\244c\168\231\022\204\231d\162\"{\182.Y\220\249\249\147|\243W\166O\211\216\140\007\219\005\142\234Wv4{\251\147#\157\1800\130$\145DO\188\219V\145*\181\195\134!\139.+Co\146faqid\235\139m\141F\003L\239\030}\224\249\148\221\014\135\022I.\016\170\235\129\n\136\200\191\235G\142F\202\230dHd\2505\206\191\141\021\134\242\252\150\135WW\204m\134gRgZ\251p\200z\149\020!\031\202\183\148\137p\200\031T\212U\175YNX\2513\0242\239aa}\146\236\0241cd\2171+@U\213EqS\231\211\129\150]\135\003" @@ -505,7 +505,7 @@ module Internal = struct | "highlight.pack.js" | "/highlight.pack.js" -> Some [ d_6b9eea5bd2cdd91f629293ab3b8808d1; d_30baf6fb746860926fdd280eefc46735; d_7df05ceea77c14d78f1f1df8f98def4f; d_106b469c9254e3a72af1bc5085256cca; d_5fcd7eba230acf47d54c1897a9a9c394; d_df9507781455088adf4ca1bd7fc0a321; d_b223e3337242ba6cf0905995918760a5; d_d6a1be8caf2478248edb48ee82070d9e; d_98850966979dd224456f716b44220d69; d_9873a9ace25bcd721b8eeb6b8dad71cf; d_b23657c0bc089d459bc6099791f97c23; d_f9c0b1a6ea9c119cb0f7ead5c3dac542; d_80a0027403c5ad56c7da4589713b2348; d_fe8f6a1f53d067d447bae579dc60d6f0; ] | "katex.min.css" | "/katex.min.css" -> Some [ d_2d798108ddda42cb699f6ad4421e720e; d_b128d6f091a42be5d7a929703f09ac36; d_1476b6e94be68e530a90bd0723d69c88; d_e357f75b8a7d9a6031bbdc38adcf1422; d_ad152fcf832897f8629ca758460f3d22; d_7c9075f31df2a532c3135ae327c84a92; ] | "katex.min.js" | "/katex.min.js" -> Some [ d_0c2c3443b618aef3ac4519dd2b159bbe; d_a2070486fb8e9102cd1537ebd1216a96; d_48a6338945c47ceb84d335248c3d6873; d_ad48849637d7c8349cb3e6952d5c8699; d_32baa17e8a53bbd439c58b0d89bc0503; d_c7561e7d22eb89e10083cfba7680012c; d_d04b09d89ef0b9af8a297a3592a2e4b1; d_c0cf7351fa27f73a72840e453c4b15f3; d_fadfd470a088dde5c3755136ac4b6188; d_326148c9e075f26f4dd5ee3862f61cf6; d_a55141bd5690b03d71c9675038f73b3f; d_225bdd9918928e02697ef5570454bf56; d_bf8e1c09c2162b9bb4b6578a59cc8069; d_bb5a8ed07dc95fa6f9f51938da398a35; d_b93e718b1ddefad06d18d9736584ad78; d_e12a510e69c6b3e0210294eedc2c3be3; d_bf043adf1d8ba761903c6f3447bae9d3; d_80ae3e22d162129b593049c0dc7f2407; d_d7b447b6bfc36721f581470728505547; d_92e0c0a734f49413d685531ad3f0a03e; d_cabefc6c9607b95a33af32a8c8832767; d_a03f60fbbac88837b2763d52df2c0820; d_5795c26325c462426548bd12ff6ef7a1; d_c0939c104021af2b0d9b24c7102061f2; d_3a7455b94742964a6cc5e84e314a6cfb; d_dc2a908015f68e5bff245fff4e602604; d_96c4d8e2622ac6552ccf67643b20f09c; d_37935d98135b118d937e895f4bb55add; d_efe21915ced6043dcaa8ff576e7948c7; d_fe0aa5b4043d6894e289163dd38508b7; d_dc29762de1ae6c28b3b3cc202f52ac6f; d_2c5af911fa1596ad2eef3a7e342be949; d_01738333fc004372ab1ae8bc7d370677; d_0d6ec6387686b4173900d29c91f338ee; d_5f9942b4d85184e45b9addfc25ca6fd4; d_105a9e030400f28a404c6badd930fe01; d_79c029f6f746a52f4a8bc8b6280c5c88; d_3a50124eae7017a15bb92024b9f6c8ad; d_d1d8d575696cbb5a4994efc9e2862948; d_a6e92521674c97f4d1bd649490d8a987; d_8f38ae17980f4039d715823515fd56d0; d_a841840589a3efb0465e49e0d8f985b5; d_e33d592534625de6438003412e1d8813; d_5b12b53efc1e6da3a434634e81c2251b; d_c7270ab94b84005c36e6e864e6ea5b10; d_5e57240b8ff6745d663ebd2060201199; d_02c9bc01125e92ce389d2ac93e62d14b; d_0d4c13a0e6487657499a2f37795ab83b; d_8ff622534e1e1348711c11358657050b; d_a8b5fa32242a1d360076af4bdc9dafbe; d_725c52bce5d22dff34816d0cea74cf51; d_a6db9cb29ea27586d2138cf4f8710b12; d_31ee9944b6c75c4351486bc790988371; d_1005d4f63119125aeb03e8a2fa265969; d_9ff5a6ec97f55e01b81f13d9d3f0ff67; d_f361846717ba3e91093152df70d5aab3; d_e462cdcfecbc18ac1f1e447bf1ed3697; d_0d5bde992f9fa1c53103cd024ff5833b; d_1b66f4e8c1fbc1c74875f8da050cc1d0; d_bad0217136fdcd657898ee631bd512d1; d_428c2b0f069b4ffaef294dc85aef1e4b; d_cb988ca0480d611a7c52551adcc9ed48; d_cdc6e947cdb2e0bb7fae7f338ffa12a0; d_f56cd226d59f4d3190a095998f97ac56; d_f5d214c6b91ee7f61f5a433fcdd70682; d_f4caf2cb8610b6735641c064e6453b79; d_da739bd79e1901a19d34fbf2d1a16298; ] - | "odoc.css" | "/odoc.css" -> Some [ d_fa1c053d8b56d1e18253a2cf90453dfb; d_e17d79834bf5120a96c58d54a0ebfd29; d_3c0fd09a46dafedd922d3c7247ae8164; d_dd310317f27add09a8e020a67a028cb7; d_1748a7036eb134e2f5e68d79313a1372; d_e94c8f28d2a123393c1fd370776b6c2d; d_84811cd56c3f0eb2d5d94c7292ab6a8a; ] + | "odoc.css" | "/odoc.css" -> Some [ d_fa1c053d8b56d1e18253a2cf90453dfb; d_e17d79834bf5120a96c58d54a0ebfd29; d_3c0fd09a46dafedd922d3c7247ae8164; d_dd310317f27add09a8e020a67a028cb7; d_1748a7036eb134e2f5e68d79313a1372; d_65627a2f7cd45ea24715b66452954999; d_acb2c4605ac55515799c591d47af558a; ] | "odoc_search.js" | "/odoc_search.js" -> Some [ d_baa9e7597ed780d04fe80009b6d2457e; ] | _ -> None @@ -554,7 +554,7 @@ let hash = function | "highlight.pack.js" | "/highlight.pack.js" -> Some "f7f17015c0de1023c93929e3725a9248" | "katex.min.css" | "/katex.min.css" -> Some "1a262c83aa48d3ba34dd01c2ec6087d8" | "katex.min.js" | "/katex.min.js" -> Some "0376fd70eef224e946e13788118db3d1" - | "odoc.css" | "/odoc.css" -> Some "2cd6e100067b73e2a944409efe944c83" + | "odoc.css" | "/odoc.css" -> Some "0dd873f4f54223ac467142340429aa6c" | "odoc_search.js" | "/odoc_search.js" -> Some "baa9e7597ed780d04fe80009b6d2457e" | _ -> None @@ -593,6 +593,6 @@ let size = function | "highlight.pack.js" | "/highlight.pack.js" -> Some 54535 | "katex.min.css" | "/katex.min.css" -> Some 20978 | "katex.min.js" | "/katex.min.js" -> Some 270376 - | "odoc.css" | "/odoc.css" -> Some 26810 + | "odoc.css" | "/odoc.css" -> Some 26709 | "odoc_search.js" | "/odoc_search.js" -> Some 2158 | _ -> None From 78d27accab9c2967958fbaaea8c86aafefb2c462 Mon Sep 17 00:00:00 2001 From: Paul-Elliot Date: Wed, 6 Dec 2023 17:58:00 +0100 Subject: [PATCH 35/35] Only compute occurrences of odoc modules For a fairer comparison with master in ocurrent-bench Signed-off-by: Paul-Elliot --- doc/driver.mld | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/driver.mld b/doc/driver.mld index 3ea57bbe38..563a44a138 100644 --- a/doc/driver.mld +++ b/doc/driver.mld @@ -213,8 +213,9 @@ let add_prefixed_output cmd list prefix lines = !list @ Bos.Cmd.to_string cmd :: List.map (fun l -> prefix ^ ": " ^ l) lines -let compile file ?(count_occurrences = true) ?parent ?(output_dir = Fpath.v "./") +let compile file ?(count_occurrences = false) ?parent ?(output_dir = Fpath.v "./") ?(ignore_output = false) ?source_args children = + let count_occurrences = count_occurrences || (Option.is_some source_args) in let output_basename = let ext = Fpath.get_ext file in let basename = Fpath.basename (Fpath.rem_ext file) in