Module Incremental_kernel__Node

A module internal to Incremental. Users should see Incremental_intf.

A Node.t is one node in the incremental DAG. The key invariants of a node t are:

Outside of stabilization, when the recompute heap is empty, the invariant implies that if is_necessary t, then t.recomputed_at >= c.changed_at for all children c of t. I.e. it implies that all necessary nodes aren't stale.

module Packed : sig ... end

For performance reasons, we do not use an OCaml existential type for Node.Packed.t:

include module type of sig ... end
type 'a t = 'a Incremental_kernel__Types.Node.t = {
id : Incremental_kernel__.Node_id.t;
mutable recomputed_at : Incremental_kernel__.Stabilization_num.t;
mutable value_opt : 'a Incremental_kernel__.Uopt.t;
mutable kind : 'a Incremental_kernel__Types.Kind.t;
mutable cutoff : 'a Incremental_kernel__.Cutoff.t;
mutable changed_at : Incremental_kernel__.Stabilization_num.t;
mutable num_on_update_handlers : int;
mutable num_parents : int;
mutable parent1_and_beyond : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t array;
mutable parent0 : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t;
mutable created_in : Incremental_kernel__Types.Scope.t;
mutable next_node_in_same_scope : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t;
mutable height : int;
mutable height_in_recompute_heap : int;
mutable prev_in_recompute_heap : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t;
mutable next_in_recompute_heap : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t;
mutable height_in_adjust_heights_heap : int;
mutable next_in_adjust_heights_heap : Incremental_kernel__Types.Packed_node.t Incremental_kernel__.Uopt.t;
mutable old_value_opt : 'a Incremental_kernel__.Uopt.t;
mutable observers : 'a Incremental_kernel__Types.Internal_observer.t Incremental_kernel__.Uopt.t;
mutable is_in_handle_after_stabilization : bool;
mutable on_update_handlers : 'a Incremental_kernel__.On_update_handler.t list;
mutable my_parent_index_in_child_at_index : int array;
mutable my_child_index_in_parent_at_index : int array;
mutable force_necessary : bool;
mutable user_info : Core_kernel.Info.t option;
creation_backtrace : Core_kernel.Backtrace.t option;
}
val sexp_of_t : ('a ‑> Sexplib.Sexp.t) ‑> 'a t ‑> Sexplib.Sexp.t
val is_valid : 'a t ‑> bool
val is_necessary : 'a t ‑> bool
include Core_kernel.Invariant.S1 with type t := a t
type 'a t
val create : Incremental_kernel__.Scope.t ‑> 'a Incremental_kernel__.Kind.t ‑> 'a t
val set_kind : 'a t ‑> 'a Incremental_kernel__.Kind.t ‑> unit

One should only set the kind of a node using set_kind -- using t.kind <- will violate invariants.

val pack : _ t ‑> Packed.t
val same : _ t ‑> _ t ‑> bool
val iteri_children : _ t ‑> f:(int ‑> Packed.t ‑> unit) ‑> unit

iteri_children t ~f applies f to all children of t.

val get_parent : _ t ‑> index:int ‑> Packed.t

get_parent t ~index raises unless 0 <= index < t.num_parents.

val add_parent : child:'a t ‑> parent:'b t ‑> child_index:int ‑> unit
val remove_parent : child:'a t ‑> parent:'b t ‑> child_index:int ‑> unit
val swap_children_except_in_kind : _ t ‑> child1:_ t ‑> child_index1:int ‑> child2:_ t ‑> child_index2:int ‑> unit
val is_const : _ t ‑> bool
val is_in_recompute_heap : _ t ‑> bool
val is_necessary : _ t ‑> bool

is_necessary t iff t is a descendant of an observer or t is a Freeze node.

val is_valid : _ t ‑> bool

is_valid t returns true iff the left-hand-side of t's defining bind hasn't changed since t was created.

val should_be_invalidated : _ t ‑> bool

should_be_invalidated t returns true iff t has an invalid child that implies that t should be invalid. It doesn't take into account t.created_in.

val edge_is_stale : child:_ t ‑> parent:_ t ‑> bool

edge_is_stale returns true iff child has changed since parent was computed, and implies is_stale parent. edge_is_stale is constant-time.

val is_stale : _ t ‑> bool

is_stale t is true if t has never been computed or if some child changed since t was last computed. is_stale doesn't take into account t.created_in.

val needs_to_be_computed : _ t ‑> bool

needs_to_be_computed is is_necessary t && is_stale t

val value_exn : 'a t ‑> 'a

Getting the value of a node.

value_exn t raises iff Uopt.is_none t.value_opt. unsafe_value t is safe iff Uopt.is_some t.value_opt.

val unsafe_value : 'a t ‑> 'a
val get_cutoff : 'a t ‑> 'a Incremental_kernel__.Cutoff.t
val set_cutoff : 'a t ‑> 'a Incremental_kernel__.Cutoff.t ‑> unit
val on_update : 'a t ‑> 'a Incremental_kernel__.On_update_handler.t ‑> unit

on_update t on_update_handler adds an on-update handler to t.

val run_on_update_handlers : 'a t ‑> 'a Incremental_kernel__.On_update_handler.Node_update.t ‑> now:Incremental_kernel__.Stabilization_num.t ‑> unit

run_on_update_handlers t node_update ~now runs t's on-update handlers, except those created at the stabilization now.

val keep_node_creation_backtrace : bool Core_kernel.ref
val user_info : _ t ‑> Core_kernel.Info.t option
val set_user_info : _ t ‑> Core_kernel.Info.t option ‑> unit
val has_child : _ t ‑> child:_ t ‑> bool

These functions are meant for debug, as they are not very efficient.

val has_parent : _ t ‑> parent:_ t ‑> bool