Streaming opam file codec for OCaml
0
fork

Configure Feed

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

opam: split Sort into sort.ml and add Value.sort

Follow the pattern already applied to json, xml, toml, cbor, csv, and
protobuf: extract the opam value sorts (Bool, Int, String, Relop,
Prefix_relop, Logop, Pfxop, Ident, List, Group, Option, Env_binding)
into a standalone sort.ml, expose Value.sort as the Value -> Sort.t
conversion, and replace codec.ml's inline kind_name function with
Sort.to_string (Value.sort v).

Sort is re-exported at Opam.Sort so the full API is Opam.Sort.{t,
to_string, pp}.

Opam_error already had a Loc.Error facade with typed kinds
(Unexpected_char, Unterminated_string, Sort_mismatch, ...). No changes
there in this commit.

+84 -15
+2 -15
lib/codec.ml
··· 11 11 let kind c = c.kind 12 12 let pp ppf c = Fmt.string ppf c.kind 13 13 14 - let kind_name = function 15 - | Value.Bool _ -> "bool" 16 - | Value.Int _ -> "int" 17 - | Value.String _ -> "string" 18 - | Value.Ident _ -> "identifier" 19 - | Value.List _ -> "list" 20 - | Value.Group _ -> "group" 21 - | Value.Option _ -> "option" 22 - | Value.Relop _ -> "relational" 23 - | Value.Prefix_relop _ -> "prefix-relational" 24 - | Value.Logop _ -> "logical" 25 - | Value.Pfxop _ -> "prefix" 26 - | Value.Env_binding _ -> "env-binding" 27 - 28 14 let err_expected exp v = 29 - Opam_error.sort_mismatch Loc.Meta.none ~expected:exp ~found:(kind_name v) 15 + Opam_error.sort_mismatch Loc.Meta.none ~expected:exp 16 + ~found:(Sort.to_string (Value.sort v)) 30 17 31 18 let bool = 32 19 {
+1
lib/opam.ml
··· 7 7 module Meta = Loc.Meta 8 8 module Path = Loc.Path 9 9 module Error = Opam_error 10 + module Sort = Sort 10 11 module Value = Value 11 12 module Codec = Codec 12 13 module Lexer = Lexer
+1
lib/opam.mli
··· 36 36 module Meta = Loc.Meta 37 37 module Path = Loc.Path 38 38 module Error = Opam_error 39 + module Sort = Sort 39 40 module Value = Value 40 41 module Codec = Codec 41 42 module Lexer = Lexer
+34
lib/sort.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2026 Thomas Gazagnaire <thomas@gazagnaire.org> 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + type t = 7 + | Bool 8 + | Int 9 + | String 10 + | Ident 11 + | List 12 + | Group 13 + | Option 14 + | Relop 15 + | Prefix_relop 16 + | Logop 17 + | Pfxop 18 + | Env_binding 19 + 20 + let to_string = function 21 + | Bool -> "bool" 22 + | Int -> "int" 23 + | String -> "string" 24 + | Ident -> "identifier" 25 + | List -> "list" 26 + | Group -> "group" 27 + | Option -> "option" 28 + | Relop -> "relational" 29 + | Prefix_relop -> "prefix-relational" 30 + | Logop -> "logical" 31 + | Pfxop -> "prefix" 32 + | Env_binding -> "env-binding" 33 + 34 + let pp ppf s = Fmt.string ppf (to_string s)
+29
lib/sort.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2026 Thomas Gazagnaire <thomas@gazagnaire.org> 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 6 + (** Opam value sorts, used as labels in error contexts and {!Loc.Path} frames. 7 + 8 + A {e sort} is the closed enumeration of node categories the opam value 9 + grammar defines. *) 10 + 11 + type t = 12 + | Bool 13 + | Int 14 + | String 15 + | Ident 16 + | List 17 + | Group 18 + | Option 19 + | Relop 20 + | Prefix_relop 21 + | Logop 22 + | Pfxop 23 + | Env_binding 24 + 25 + val to_string : t -> string 26 + (** [to_string sort] is the opam-spec name of [sort]. *) 27 + 28 + val pp : Format.formatter -> t -> unit 29 + (** [pp] formats sorts using {!to_string}. *)
+14
lib/value.ml
··· 66 66 67 67 type file = { file_name : string; contents : item list } 68 68 69 + let sort = function 70 + | Bool _ -> Sort.Bool 71 + | Int _ -> Sort.Int 72 + | String _ -> Sort.String 73 + | Relop _ -> Sort.Relop 74 + | Prefix_relop _ -> Sort.Prefix_relop 75 + | Logop _ -> Sort.Logop 76 + | Pfxop _ -> Sort.Pfxop 77 + | Ident _ -> Sort.Ident 78 + | List _ -> Sort.List 79 + | Group _ -> Sort.Group 80 + | Option _ -> Sort.Option 81 + | Env_binding _ -> Sort.Env_binding 82 + 69 83 let bool b = Bool b 70 84 let int i = Int i 71 85 let string s = String s
+3
lib/value.mli
··· 68 68 (** An opam value. [Option (v, fs)] is the [v {f1 f2 ...}] form for 69 69 optional / filtered values. *) 70 70 71 + val sort : t -> Sort.t 72 + (** [sort v] is the opam sort of [v]. *) 73 + 71 74 (** {1:item Item} 72 75 73 76 A top-level entry in an opam file is either a [field: value] or a section