Module Sarek_parse_helpers

val loc_of_ppxlib : Ppxlib.Location.t -> Sarek_ast.loc

Convert ppxlib location to Sarek location

exception Parse_error_exn of string * Ppxlib.Location.t

Parse exception

val loc_to_sloc : Ppxlib.Location.t -> Sarek_ast.loc
val functor_type_path_msg : string

A functor application inside a type path (F(X).t). flatten used to return [] for it, so the type came out named "" — and an unresolvable name is turned into an empty placeholder record by Sarek_types.type_of_type_expr, not into an error.

val labelled_arrow_type_msg : string

A labelled or optional argument in an ARROW TYPE. Ptyp_arrow's label used to be read as _, so x:int -> int and int -> int parsed to the same TEArrow — the label was dropped from the type while the corresponding parameter is refused outright by collect_fun_params.

val parse_type : Ppxlib.core_type -> Sarek_ast.type_expr

Parse a core_type to type_expr.

The final arm refuses rather than returning a placeholder: it used to answer TEConstr ("unknown", []) for every core_type shape not listed, and Sarek_types.type_of_type_expr maps an unrecognised constructor to TRecord (name, []) — an empty record type. So an annotation the parser could not read became a phantom type named "unknown" that unified with nothing and was reported, if at all, as a type error somewhere else (backlog-192).

val parse_record_fields : Ppxlib.label_declaration list -> (string * bool * Sarek_ast.type_expr) list
val gadt_constructor_msg : string

A GADT-style constructor declaration (C : int -> t). pcd_res and pcd_vars were never read, so the return type and the existential binders were dropped and the constructor was recorded as if it had been written C of int — for a parameterised type that is a different declaration.

val parse_variant_constructors : Ppxlib.constructor_declaration list -> (string * Sarek_ast.type_expr option) list
val extract_type_from_pattern : Ppxlib.pattern -> Sarek_ast.type_expr option

Extract type annotation from a Ppxlib pattern if present

val alias_binder_msg : string

An as alias in a BINDER position (let (p as x) = e, fun (p as x) ->). extract_name_from_pattern used to answer the alias name and throw the inner pattern away, so every name p bound was silently absent from the kernel environment and surfaced later as an unbound variable — pointing at the USE, not at the alias.

val binding_coercion_msg : string

let x :> t = e — a coercion on a binding.

val binding_univars_msg : string

let f : type a. ... — a locally abstract type on a binding.

val binding_type : Ppxlib.value_binding -> Sarek_ast.type_expr option

The declared type of a let binding, from EITHER spelling.

let (x : t) = e puts the annotation in the PATTERN (Ppat_constraint). let x : t = e — the spelling almost everything in this tree uses — puts it in pvb_constraint instead, and that field was never read: the annotation was silently dropped, so a kernel-local let sum : float = ... was typed by inference with the declared width ignored, and an annotated module constant was dropped entirely by Sarek_parse.parse_payload for want of a type (backlog-192).

Both are read here, pattern first.

val extract_name_from_pattern : Ppxlib.pattern -> string option

Extract variable name from a Ppxlib pattern

val extract_param_from_pattern : Ppxlib.pattern -> Sarek_ast.param

Extract parameter from pparam_desc

val existential_pattern_msg : string

Existential type binders on a constructor pattern (C (type a) p). The binder list in Ppat_construct's payload was read as _, so the pattern parsed as the plain C p and the locally abstract type simply was not there.

val parse_pattern : Ppxlib.pattern -> Sarek_ast.pattern

Parse a Ppxlib pattern to Sarek pattern

val parse_binop : string -> Sarek_ast.binop option

Parse a binary operator

val parse_unop : string -> Sarek_ast.unop option

Parse a unary operator

module Ast_502 = Astlib.Ast_502
module To_502 : sig ... end
module From_502 : sig ... end
val expression_to_502 : Ppxlib_ast__Import.Js.Ast.Parsetree.expression -> Ppxlib_ast__Versions.OCaml_502.Ast.Parsetree.expression
val expression_of_502 : Ppxlib_ast__Versions.OCaml_502.Ast.Parsetree.expression -> Ppxlib_ast__Import.Js.Ast.Parsetree.expression
val pattern_of_502 : Ppxlib_ast__Versions.OCaml_502.Ast.Parsetree.pattern -> Ppxlib_ast__Import.Js.Ast.Parsetree.pattern
val case_of_502 : Ppxlib_ast__Versions.OCaml_502.Ast.Parsetree.case -> Ppxlib_ast__Import.Js.Ast.Parsetree.case
type fun_body =
  1. | Fun_body of Ppxlib.expression
  2. | Fun_cases of Ppxlib.case list
val is_function_expression_502 : Ppxlib_ast__Import.Js.Ast.Parsetree.expression -> bool
val same_position : Stdlib.Lexing.position -> Stdlib.Lexing.position -> bool
val same_location : Ppxlib.Location.t -> Ppxlib.Location.t -> bool
val expression_at_loc : Ppxlib.expression -> Ppxlib.Location.t -> Ppxlib__.Import.Ast.expression option
val pattern_of_param : Ppxlib.pattern -> Ppxlib.pattern
val return_coercion_msg : string

A coercion in a function's return position (fun x :> t -> e).

val annotation_arity_msg : string

An annotation with fewer arrows than the function has parameters. Shared between the two places that put a declared type into a RESULT slot.

val peel_arrows : int -> Sarek_ast.type_expr -> Sarek_ast.type_expr option

Strip n leading arrows off a type, or None if it has fewer than n.

val fun_return_type : Ppxlib.expression -> Sarek_ast.type_expr option

The declared RESULT type of a function expression, if it has one.

Pexp_function's type_constraint option slot is where OCaml >= 5.1 puts the : t of let f (x : int32) : int32 = ... — NOT in the pattern. It was read as _ by collect_fun_params, so every kernel helper's declared return type was silently discarded and the helper's result type came from inference alone (backlog-192).

EVERY Pexp_function on the way down is inspected, not just the outermost. An earlier revision of this function read only the outermost and justified it by saying a nested one "belongs to that inner function and not to the binding" — which is false, because collect_fun_params below DESCENDS through Pfunction_body and merges the inner function's parameters into the binding's list. After that flattening there is no inner function left for the annotation to belong to, and let f (x : int32) = fun (y : int32) : float32 -> ... had its float32 dropped while the flattened spelling of the same function had it honoured. Measured: the two spellings compiled to different verdicts, exit 0 versus a unification error.

The LAST constraint on the way down wins, and it is peeled by the number of parameters collected AFTER it — because a constraint sitting above further parameters describes a FUNCTION type, not the flattened result. let f (x : int32) : (int32 -> int32) = fun (y : int32) -> y therefore yields int32, not the arrow. Too few arrows is refused rather than half-applied.

val collect_fun_params : Ppxlib.expression -> Ppxlib.pattern list * fun_body option
val is_function_expression : Ppxlib_ast__Import.Js.Ast.Parsetree.expression -> bool