Sarek_envmodule StringMap : sig ... endtype var_info = {vi_type : Sarek_types.typ;vi_mutable : bool;vi_is_param : bool;Kernel parameter?
*)vi_index : int;For parameter ordering
*)vi_is_vec : bool;Is this a vector parameter?
*)}Information about a variable
Reference to an intrinsic function or constant.
"Sarek_stdlib"; "Float32", "sin") -> Sarek_stdlib.Float32.sin"Sarek_stdlib"; "Int32", "add_int32") -> Sarek_stdlib.Int32.add_int32This enables extensibility: user libraries can define their own intrinsics via %sarek_intrinsic and the PPX will reference them correctly.
val intrinsic_ref_name : intrinsic_ref -> stringGet the qualified name of an intrinsic ref for debugging/printing
val intrinsic_ref_display_name : intrinsic_ref -> stringGet user-friendly display name for error messages (no core prefix)
type intrinsic_fun_info = {intr_type : Sarek_types.typ;intr_ref : intrinsic_ref;Reference to stdlib module function
*)intr_convergence : Sarek_core_primitives.convergence option;Convergence requirement. None means NoEffect. User libraries can specify ConvergencePoint or WarpConvergence.
*)}Information about an intrinsic function. Device code is resolved at JIT time via Sarek_registry.
type intrinsic_const_info = {const_type : Sarek_types.typ;const_ref : intrinsic_ref;Reference to intrinsic constant
*)}Information about an intrinsic constant. Device code is resolved at JIT time via Sarek_registry.
type type_info = | TIRecord of {ti_name : string;ti_fields : (string * Sarek_types.typ * bool) list;name, type, mutable
*)}| TIVariant of {ti_name : string;ti_constrs : (string * Sarek_types.typ option) list;constructor name, optional arg type
*)}Information about a custom type
type t = {vars : var_info StringMap.t;types : type_info StringMap.t;intrinsic_funs : intrinsic_fun_info StringMap.t;intrinsic_consts : intrinsic_const_info StringMap.t;constructors : (string * Sarek_types.typ option) StringMap.t;constr -> (type_name, arg_type)
*)fields : (string * int * Sarek_types.typ * bool) StringMap.t;field -> (type_name, index, type, mutable)
*)current_level : int;For let-polymorphism
*)local_funs : (string * Sarek_scheme.scheme) StringMap.t;Local function definitions with polymorphic schemes
*)}The typing environment - immutable
val empty : tEmpty environment
Environment operations - all return new environments
val add_var : StringMap.key -> var_info -> t -> tval add_type : StringMap.key -> type_info -> t -> tval add_intrinsic_fun : StringMap.key -> intrinsic_fun_info -> t -> tval add_intrinsic_const : StringMap.key -> intrinsic_const_info -> t -> tval add_local_fun : StringMap.key -> Sarek_scheme.scheme -> t -> tA kernel-local or [@sarek.module] function. If name is also a refused intrinsic (Sarek_unlowered.table), the user's function shadows it: name resolution consults intrinsics before local functions, so without this a helper called warp_size would resolve to the refused intrinsic and be refused, or worse, silently call it. Only refused names are shadowed here; other names keep their existing resolution order.
val find_var : StringMap.key -> t -> var_info optionval find_type : StringMap.key -> t -> type_info optionval find_intrinsic_fun : StringMap.key -> t -> intrinsic_fun_info optionval find_intrinsic_const : StringMap.key -> t -> intrinsic_const_info optionval find_constructor :
StringMap.key ->
t ->
(string * Sarek_types.typ option) optionval find_field :
StringMap.key ->
t ->
(string * int * Sarek_types.typ * bool) optionval find_local_fun :
StringMap.key ->
t ->
(string * Sarek_scheme.scheme) optionGet the short module name from a module path. E.g., "Sarek_stdlib"; "Float32" -> "Float32"
Open a module: bring its bindings into scope under short names. E.g., open_module "Float32" brings Float32.sin -> sin
Also handles legacy aliases:
Create standard library environment from core primitives and the PPX registry.
Step 1: Add all core primitives from Sarek_core_primitives. These have compile-time semantic properties (variance, convergence, purity) that the PPX uses for analysis. Core primitives use CorePrimitiveRef.
Step 2: Add library intrinsics from Sarek_ppx_registry. These may shadow core primitives if they have the same name (which provides device implementations). Library intrinsics use IntrinsicRef.
Intrinsics are registered under module-qualified names (e.g., "Float32.sin") to avoid ambiguity between Float32.sqrt and Float64.sqrt. Use `open_module` to bring a module's bindings into scope under short names.
IMPORTANT: The caller must ensure stdlib modules are initialized before calling this function (e.g., via Sarek_stdlib.force_init()). This is done in Sarek_ppx.ml to avoid circular dependencies.
type lookup_result = | LVar of var_info| LIntrinsicConst of intrinsic_const_info| LIntrinsicFun of intrinsic_fun_info| LConstructor of string * Sarek_types.typ optiontype_name, arg_type
*)| LLocalFun of string * Sarek_scheme.schemename and type scheme (for polymorphism)
*)| LNotFoundLookup that checks all namespaces for an identifier
val lookup : StringMap.key -> t -> lookup_resultval known_names_in_module_of : string -> t -> Stdlib.String.t listFor a qualified name M.f, the qualified names the environment binds under the same prefix M., sorted (used to suggest a fix for a typo or a module whose intrinsics are only partly linked). [] for an unqualified name.
val pp_env : Stdlib.Format.formatter -> t -> unitDebug: print environment contents