Source locations and structured errors for text codecs (extracted from jsont)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

OCaml 94.4%
Dune 2.1%
Other 3.6%
15 1 0

Clone this repository

https://tangled.org/gazagnaire.org/ocaml-loc https://tangled.org/did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-loc
git@git.recoil.org:gazagnaire.org/ocaml-loc git@git.recoil.org:did:plc:jhift2vwcxhou52p3sewcrpx/ocaml-loc

For self-hosted knots, clone URLs may differ based on your setup.

Download tar.gz
README.md

loc#

Source locations and structured errors shared across text codecs (JSON, TOML, YAML, XML, CSV, S-expression, ...).

Every OCaml codec library needs the same plumbing: byte ranges, line positions, context-aware error paths, and a printer that matches the OCaml compiler / GNU error convention. loc provides that plumbing as one small library so codecs depend on it instead of each reinventing it — or, worse, exposing a private error type that upstream tools cannot compose.

Provides:

  • Loc — byte and line ranges for UTF-8 source text
  • Loc.Meta — node metadata: source location and surrounding whitespace
  • Loc.Path — structural paths (Mem of string node | Nth of int node)
  • Loc.Context — navigation contexts accumulated during descent
  • Loc.Error — structured errors with an extensible kind, source location, and contextual path; formatted per the OCaml compiler / GNU error conventions
  • exception Loc.Error of Loc.Error.t — single shared exception for cross-package error propagation

Installation#

Install with opam:

$ opam install nox-loc

If opam cannot find the package, it may not yet be released in the public opam-repository. Add the overlay repository, then install it:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install nox-loc

Requires OCaml >= 4.14 and fmt.

Usage#

Raise a structured error at a specific source location:

let demo_raise () =
  let loc =
    Loc.make ~file:"config.toml"
      ~first_byte:42 ~last_byte:47
      ~first_line_num:3 ~first_line_byte:0
      ~last_line_num:3 ~last_line_byte:0
  in
  let meta = Loc.Meta.make loc in
  try Loc.Error.failf meta "expected %s, got %s" "integer" "\"nope\""
  with Loc.Error e -> print_endline (Loc.Error.to_string e)

Wrap a raised error with structural context as it bubbles up through nested object members:

let demo_push () =
  let table = ("table [server]", Loc.Meta.none) in
  try
    try Loc.Error.fail Loc.Meta.none "not a number"
    with Loc.Error e ->
      Loc.Error.push_object table ("port", Loc.Meta.none) e
  with Loc.Error e -> print_endline (Loc.Error.to_string e)

Extend the error kind for a domain-specific codec and register a printer:

type Loc.Error.kind += Unknown_key of string

let register () =
  Loc.Error.register_kind_printer (function
    | Unknown_key k -> Some (fun ppf -> Format.fprintf ppf "unknown key %S" k)
    | _ -> None)

API#

See lib/loc.mli for the full signature.

Upstream#

  • jsont — Daniel Bünzli's JSON codec library, of which this package is an extracted subset.
  • jsont_base.ml — source for Loc, Meta, Path, and the Fmt helper.
  • jsont.ml — source for the Error module (minus JSON-specific predefined errors).

License#

ISC, matching upstream. See LICENSE.md.