package b0
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Software construction and deployment kit
Install
dune-project
Dependency
Authors
Maintainers
Sources
b0-0.0.5.tbz
sha512=00a6868b4dfa34565d0141b335622a81a0e8d5b9e3c6dfad025dabfa3df2db2a1302b492953bbbce30c3a4406c324fcec25250a00b38f6d18a69e15605e3b07e
doc/src/b0/b0_def.ml.html
Source file b0_def.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318(*--------------------------------------------------------------------------- Copyright (c) 2020 The b0 programmers. All rights reserved. Distributed under the ISC license, see terms at the end of the file. ---------------------------------------------------------------------------*) open B0_std let exit_b0_file_error = 121 (* See B0_driver.Exit.b0_file_error *) let pp_error_str ppf () = Fmt.tty_string [`Fg `Red; `Bold] ppf "Error" (* Scopes *) exception Err of string module Scope = struct type t = Nil | Lib of string | File of (string * Fpath.t * Fpath.t) list let current = ref Nil let sealed = ref false (* Library scopes (.libname) *) let lib lib = current := Lib (String.concat "." [""; lib; ""]) (* File scopes *) let file = function | Nil | Lib _ | File [] -> None | File ((_, f, _) :: _) -> Some f let dir = function | Nil | Lib _ | File [] -> None | File ((_, _, d) :: _) -> Some d let location_in_backtrace file bt = match Printexc.backtrace_slots bt with | None -> None | Some slots -> (* find earliest slot that has [file] *) let rec loop file found slots i max = match i > max with | true -> found | false -> match Printexc.Slot.location slots.(i) with | None -> loop file found slots (i + 1) max | Some loc -> match String.equal loc.Printexc.filename file with | false -> loop file found slots (i + 1) max | true -> loop file (Some loc) slots (i + 1) max in loop (Fpath.to_string file) None slots 0 (Array.length slots - 1) let current_to_loc_str use_bt = match !current with | Lib lib -> Fmt.str "Library %a:" Fmt.(code string) lib | File ((name, file, _) :: _) -> let loc = match use_bt with | None -> "line 1" | Some bt -> match location_in_backtrace file bt with | None -> "line 1" | Some loc -> Fmt.str "line %d, characters %d-%d" loc.Printexc.line_number loc.Printexc.start_char loc.Printexc.end_char in Fmt.str "File %S, %s:" (Fpath.to_string file) loc | Nil | File [] -> invalid_arg "no current scope" let err_error err bt = Fmt.str "@[<v>%s@,%a: %s@]" (current_to_loc_str (Some bt)) pp_error_str () err let err_uncaught exn bt = Fmt.str "@[<v>%s@,%a: B0 file raised an uncaught exception.@, @[<v>%a@]@]" (current_to_loc_str None) pp_error_str () Fmt.exn_backtrace (exn, bt) let root file = let catch_exn exn bt = let err = match exn with | Err err -> err_error err bt | exn -> err_uncaught exn bt in Fmt.epr "@[%s@]@." err; exit exit_b0_file_error in let setup_fmt () = (* XXX we want style ! But we didn't setup the driver config yet :-( We should look Sys.argv for --color and the B0_COLOR env var. Forcing for now, this will be set again later by B0_driver.Cli.conf. *) Fmt.set_tty_cap ~cap:`Ansi () in current := File (["", file, Fpath.parent file]); setup_fmt (); Printexc.record_backtrace true; Printexc.set_uncaught_exception_handler catch_exn let is_root () = match !current with | File (["", _, _]) -> true | _ -> false let open' name file = match !current with | File ((pre, _, _) :: _ as ss) -> let pre = String.concat "" [pre; name; "."] in current := File ((pre, file, Fpath.parent file) :: ss) | _ -> invalid_arg "illegal scope context, no root" let close () = match !current with | File (s :: ss) -> current := File ss | Lib _ -> current := Nil | _ -> invalid_arg "no scope to close" let qualify_name n = let prefix = match !current with | Lib n -> n | File ((pre, _, _) :: _) -> pre | File [] | Nil -> invalid_arg "no scope" in String.concat "" [prefix; n] let current () = !current let seal () = (* XXX it would be nice to remove the set_uncaught_exception_handler added by init. See https://github.com/ocaml/ocaml/issues/9248 *) sealed := true exception After_seal of string end (* Names *) type t = { scope : Scope.t; name : string; basename : string; doc : string; meta : B0_meta.t } type def = t let scope d = d.scope let file d = Scope.file d.scope let scope_dir d = Scope.dir d.scope let name d = d.name let basename d = d.basename let doc d = d.doc let meta d = d.meta (* Defining values *) module type VALUE = sig type t val def_kind : string val def : t -> def val pp_name_str : string Fmt.t end module type S = sig type t val define : ?doc:string -> ?meta:B0_meta.t -> string -> def val def_kind : string val def : t -> def val name : t -> string val basename : t -> string val doc : t -> string val equal : t -> t -> bool val compare : t -> t -> int val meta : t -> B0_meta.t val has_meta : 'a B0_meta.key -> t -> bool val find_meta : 'a B0_meta.key -> t -> 'a option val get_meta : 'a B0_meta.key -> t -> ('a, string) result val add : t -> unit val list : unit -> t list val find : string -> t option val get : string -> t val get_or_suggest : string -> (t, t list) result val get_or_hint : string -> (t, string) result val get_list_or_hint : ?empty_means_all:bool -> string list -> (t list, string) result val pp_name_str : string Fmt.t val pp_name : t Fmt.t val pp_doc : t Fmt.t val pp_synopsis : t Fmt.t val pp : t Fmt.t module Set : Set.S with type elt = t module Map : Map.S with type key = t end module Make (V : VALUE) = struct type t = V.t let def_kind = V.def_kind let def = V.def let name v = name (V.def v) let basename v = basename (V.def v) let doc v = doc (V.def v) let scope v = scope (V.def v) let equal v0 v1 = String.equal (name v0) (name v1) let compare v0 v1 = String.compare (name v0) (name v1) let meta v = meta (V.def v) let has_meta k v = B0_meta.mem k (meta v) let find_meta k v = B0_meta.find k (meta v) let get_meta k v = match find_meta k v with | Some v -> Ok v | None -> Fmt.error "%s %a does not define metadata %a" (String.Ascii.capitalize V.def_kind) V.pp_name_str (name v) B0_meta.Key.pp_name k let defs = ref String.Map.empty let add v = defs := String.Map.add (name v) v !defs let is_name n = String.for_all (fun c -> c <> '.') n let illegal_name_error n = Fmt.str "%a is not a legal %s name, dots are not allowed." Fmt.(code string) n V.def_kind let seal_error n = Fmt.str "%s %a illegaly created after B0 file initialization." (String.Ascii.capitalize V.def_kind) V.pp_name_str n let duplicate_error n = Fmt.str "%s %a already defined in scope." (String.Ascii.capitalize V.def_kind) V.pp_name_str n let err_undefined n = Fmt.str "%s %a undefined in scope." (String.Ascii.capitalize V.def_kind) V.pp_name_str n let qualify_name n = if not (is_name n) then raise (Err (illegal_name_error n)) else Scope.qualify_name n let define ?(doc = "undocumented") ?(meta = B0_meta.empty) n = match !Scope.sealed with | true -> raise (Scope.After_seal (seal_error n)) | false -> (* XXX with Printexc.get_callstack and a bit of munging we could maybe get the exact definition point. *) let scope = Scope.current () in let name = qualify_name n in match String.Map.mem name !defs with | true -> raise (Err (duplicate_error n)) | false -> { scope; name; basename = n; doc; meta } let scoped_find n = match String.Map.find (Scope.qualify_name n) !defs with | exception Not_found -> None | v -> Some v let find = scoped_find let get n = match scoped_find n with | Some v -> v | None -> raise (Err (err_undefined n)) let get_or_suggest n = match scoped_find n with | Some v -> Ok v | None -> let add_sugg k v acc = if String.edit_distance k n <= 2 then v :: acc else acc in Error (List.rev (String.Map.fold add_sugg !defs [])) let get_or_hint n = match get_or_suggest n with | Ok _ as v -> v | Error suggs -> let kind ppf () = Fmt.pf ppf "%s" def_kind in let hint = Fmt.did_you_mean in let pp = Fmt.unknown' ~kind V.pp_name_str ~hint in Fmt.error "@[%a@]" pp (n, List.map name suggs) let list () = match Scope.is_root () with | true -> let add _ v vs = v :: vs in String.Map.fold add !defs [] | false -> let prefix = Scope.qualify_name "" in let add k v vs = if String.starts_with ~prefix k then v :: vs else vs in String.Map.fold add !defs [] let get_list_or_hint ?(empty_means_all = false) ns = if empty_means_all && ns = [] then Ok (List.sort compare (list ())) else let rec loop vs es = function | [] -> if es <> [] then Error (String.concat "\n" (List.rev es)) else Ok (List.rev vs) | n :: ns -> match get_or_hint n with | Ok v -> loop (v :: vs) es ns | Error e -> loop vs (e :: es) ns in loop [] [] ns let pp_name_str = V.pp_name_str let pp_name = Fmt.using name pp_name_str let pp_doc = Fmt.using doc (Fmt.tty_string [(* Hear DKM *) `Faint]) let pp_synopsis ppf v = Fmt.pf ppf "%a %a" pp_name v pp_doc v let pp ppf v = let pp_non_empty ppf m = match B0_meta.is_empty m with | true -> () | false -> Fmt.pf ppf "@, %a" B0_meta.pp m in Fmt.pf ppf "@[<v>@[%a@]%a@]" pp_synopsis v pp_non_empty (meta v) module T = struct type nonrec t = t let compare = compare end module Set = Set.Make(T) module Map = Map.Make(T) end (*--------------------------------------------------------------------------- Copyright (c) 2020 The b0 programmers Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 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. ---------------------------------------------------------------------------*)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>