Sarek_ppxval registered_types : Sarek_ast.type_decl list Stdlib.refval registered_mods : Sarek_ast.module_item list Stdlib.refval tdecl_key : Sarek_ast.type_decl -> stringval dedup_tdecls : Sarek_ast.type_decl list -> Sarek_ast.type_decl listval dedup_mods : Sarek_ast.module_item list -> Sarek_ast.module_item listval value_to_ocaml :
loc:Ppxlib__.Location.t ->
what:string ->
Ppxlib.core_type ->
Ppxlib.expression ->
Ppxlib.expressionInterpreter value-model converters, shared by the record and variant helper generators (generate_interp_helpers).
value_to_ocaml: extract the OCaml scalar / nested-custom value of type ct from a runtime value expression (used by record from_values field converters and variant from_value payload reconstruction).
value_from_ocaml: wrap an OCaml scalar / nested-custom value of type ct into the corresponding runtime value (used by record to_values/ get_field and variant to_value).
A nested custom type (record OR variant) is delegated to its registered helper via lookup_typed <ct>_custom.type_id; the value_to_ocaml nested arm accepts BOTH VRecord and VVariant — a variant-typed field is no longer rejected with "expected record" (the L14-S2 PR #251 break). what names the field/argument for error messages.
val core_type_to_sarek_type_expr :
loc:Ppxlib.Location.t ->
Ppxlib.core_type ->
Sarek_ast.type_exprval register_sarek_module_item : loc:'a -> Sarek_ast.module_item -> unitScan a single .ml file for @@sarek.type and @sarek.module declarations and register them as a side effect (see register_sarek_type_decl, register_sarek_module_item).
This is a best-effort scan of a file that may be *different* from the one currently being compiled (e.g. a co-located file scanned implicitly by expand_kernel, or an explicit %sarek_include target) - a failure here (unreadable file, parse error, or a downstream registration error triggered by malformed @sarek.* content in the scanned file) must not silently vanish, but it also must not abort compilation of the file that triggered the scan. The whole scan (read + parse + per-declaration registration) is wrapped in one handler on purpose: every exception it can raise originates from processing the *scanned* file's content, so a malformed registration deep inside a well-parsed file is exactly as much "this file's problem" as a read or parse failure - narrowing the try to only the read/parse steps would just move the same silent swallow one level down instead of fixing it.
On failure, prints a diagnostic naming the scanned file and the exception to stderr via Printf.eprintf and returns Some diagnostic (the returned value lets callers/tests inspect the exact message; the printed side effect is what makes the failure visible during a real build). Returns None on success.
Mechanism choice: an @ocaml.ppwarning attribute (surfaced as OCaml warning 22) was tried first and rejected - this project's dune default ("dev") profile promotes warning 22 to a hard error (dune's default warning flags treat warnings 5 through 28 as fatal), so attaching it here would turn "a sibling file failed to scan" into a build failure for the *current* file, which is exactly the "compilation must still succeed" property this fix is required to preserve. A ppxlib driver-level diagnostic reduces to the same ppwarning-attribute mechanism under the hood (see Ppxlib.Driver's own lint-error-to-attribute conversion) and has the same fatality problem. Plain stderr output has no interaction with the warning/error machinery, so it is the only one of the three ranked options that is testable while satisfying "the build succeeds".
Scan a directory for .ml files with Sarek declarations, or scan a single file. Not currently invoked (dead code, pre-existing - flagged, not removed: out of scope for this change); return values are discarded here since there is no caller to surface a diagnostic to.
val generate_field_accessors :
loc:Ppxlib.location ->
Ppxlib.type_declaration ->
Ppxlib.structure_item listGenerate field accessor functions for a record type. Example: for type point with fields x and y, generates: let sarek_get_point_x (p : point) : float32 = p.x let sarek_get_point_y (p : point) : float32 = p.y
Extract type name from a core_type for registry registration
Calculate the size in bytes of a sarek type based on its fields. Uses 4 bytes for int32/float32, 8 bytes for int64/float64.
Get the accessor function for a field type (legacy SPOC path removed)
Get the setter function for a field type (legacy SPOC path removed)
Get the field count (number of primitive fields, counting nested as 1 for now)
val gen_field_read :
loc:Ppxlib.location ->
Ppxlib.core_type ->
Ppxlib.expression ->
Ppxlib.expressionHelper to generate a V2 field read expression based on field type. Dispatches to the correct Custom_helpers function. For nested custom types, generates a call using the nested type's _custom accessor.
val gen_field_write :
loc:Ppxlib.location ->
Ppxlib.core_type ->
Ppxlib.expression ->
Ppxlib.expression ->
Ppxlib.expressionHelper to generate a V2 field write expression based on field type.
val generate_custom_value :
loc:Ppxlib__.Location.t ->
Ppxlib.type_declaration ->
Ppxlib.structure_item listGenerate a <name>_custom value for Spoc_core.Vector.custom_type. For a record type (e.g., point with float32 fields), generates get/set functions using Ctypes pointer arithmetic. Supports nested custom types via their _custom accessor.
val generate_interp_helpers :
loc:Ppxlib.location ->
Ppxlib.type_declaration ->
Ppxlib.structure_item listGenerate interpreter helper module for type-safe value conversion. Provides typed constructors for custom type handling.
val generate_type_registration :
loc:Ppxlib.location ->
Ppxlib.type_declaration ->
Ppxlib.structure_item listGenerate runtime registration code for a type. The PPX emits calls to Sarek_registry at module initialization time so type info is available to codegen (record fields, variants, sizes).
val expand_kernel :
ctxt:Ppxlib.Expansion_context.Extension.t ->
Ppxlib.expression ->
Ppxlib.expressionThe main kernel expansion function
module Real64_lowering : sig ... endval expand_kernel_real64 :
ctxt:Ppxlib.Expansion_context.Extension.t ->
Ppxlib.expression ->
Ppxlib.expression%kernel.real64 ... - single-source dual lowering (palier B). See the Real64_lowering module comment above. Returns the (native, fallback) kernel pair; consume it with Sarek_real64.kernel_ir.
The %kernel.real64 ... extension for expressions (palier B).
Register sarek.module bindings on any structure we process, so libraries can publish module items for use in kernels.
This generates registration code that runs at module initialization time, registering the items in Sarek_ppx_registry. This allows cross-module references: a library can define @sarek.module items and link with the PPX so they become available to kernels in other compilation units.
val expand_sarek_include :
ctxt:Ppxlib.Expansion_context.Extension.t ->
Ppxlib.payload ->
Ppxlib_ast.Ast.structure_item%%sarek_include "path/to/file.ml" - Include types and module items from another file.
This scans the specified file for @@sarek.type and @sarek.module declarations and registers them for use in kernels in the current file. The path is relative to the current file's directory.
Declared in Extension.Context.structure_item, so the bracketed spelling takes TWO percent signs; the single-% %sarek_include "f.ml" is a structure-level expression and is refused as an uninterpreted extension. The let%sarek_include form below is the same structure-item extension.
Usage: %%sarek_include "registered_defs.ml", or let%sarek_include _ = "registered_defs.ml" as every call site in this tree writes it.
let kernel = %kernel fun ... -> let open Registered_defs in ... use types and functions from registered_defs.ml ...