code wiki / (root) / nx_loop.nx

nx_loop.nx

buildroot/runtime/nx_loop.nx

13053 B350 linesdepth 3pulls 3 transitivereach 441 importersview sourcekind tooltopic loop
docsdependenciesstructsconstsfunctions

about

nx_loop.nx -- bounded-loop discipline primitive. Per docs/LOOP_DESIGN_RESEARCH.md. Provides the sealed verdict enum + settle helper for the substrate's canonical bounded-loop pattern. Replaces ad-hoc `keep == 1` sentinel-flag style with a structured verdict that distinguishes: NX_LOOP_RUNNING -- loop is still active NX_LOOP_DONE_SUCCESS -- ran to budget, body never asked to stop -- the loop did its full job NX_LOOP_DONE_EXIT -- body asked to exit early (success) NX_LOOP_BUDGET_EXHAUSTED -- budget hit before body finished NX_LOOP_ABORTED -- body asked to abort (hard error) Inspired by NASA JPL Power of 10 Rule 2 (Holzmann 2006: all loops must have a fixed upper bound) + Why3 loop-variants + Idris totality checking. Without a parser-level `bounded` keyword (queued for self-host), this module lets substrate code follow the same DISCIPLINE today with no compiler change. ===== Canonical loop pattern ===== import "nx_loop.nx" let MAX_ITERS: nx_int = 1024 var iter: nx_int = 0 var verdict: nx_int = NX_LOOP_RUNNING while verdict == NX_LOOP_RUNNING && iter < MAX_ITERS { // body here, may set verdict via constants below if early_success_cond { verdict = NX_LOOP_DONE_EXIT } if hard_error_cond { verdict = NX_LOOP_ABORTED } iter = iter + 1 } verdict = nx_loop_settle(verdict, iter, MAX_ITERS) // verdict is now one of {DONE_SUCCESS, DONE_EXIT, // BUDGET_EXHAUSTED, ABORTED} Properties (the four-pillar discipline this primitive enforces): DETECT -- verdict tells you exactly why the loop ended PREVENT -- MAX_ITERS in the loop header makes infinite loops

dependencies 3 imports · 51 importers

nx_tier.nx nx_syscalls.nx nx_clock.nx nx_loop.nx _nx_bits_clz64_oracle.nx _nx_loop_v2_oracle.nx nx_activation_steer.nx nx_attn_window.nx nx_attribution.nx nx_bpe.nx nx_chem_peak_list.nx nx_closed_loop.nx nx_conv2d.nx nx_diffusion_loop.nx

diagram shows first 10 each side; +0 more imports, +41 more importers in the complete lists below.

imports: nx_tier.nxnx_syscalls.nxnx_clock.nx

imported by: _nx_bits_clz64_oracle.nx_nx_loop_v2_oracle.nxnx_activation_steer.nxnx_attn_window.nxnx_attribution.nxnx_bpe.nxnx_chem_peak_list.nxnx_closed_loop.nxnx_conv2d.nxnx_diffusion_loop.nxnx_embedding.nxnx_gelu.nxnx_gguf.nxnx_gguf_load.nxnx_gguf_load_block.nxnx_gguf_meta.nxnx_groupnorm.nxnx_knn.nxnx_layernorm.nxnx_llm_run.nxnx_llm_run_v2.nxnx_loop_gate.nxnx_mesh.nxnx_model_spec.nxnx_monte_carlo.nxnx_ms_ssim.nxnx_multivariate.nxnx_nlex.nxnx_nparse.nxnx_patch_attribution.nxnx_placement.nxnx_quant_policy.nxnx_raster_legacy.nxnx_render_pass.nxnx_rmsnorm.nxnx_root.nxnx_rope.nxnx_silu.nxnx_ssim.nxnx_tex_sample.nxnx_theorem_ingest.nxnx_token_sample.nxnx_transformer_block.nxnx_transformer_stack.nxnx_trig.nxnx_uleb.nxnx_unet_block.nxnx_upsample.nxnx_vae_decode_stage.nxnx_vae_tile.nxnx_zbuf.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main nx_loop_settle_counted nx_loop_is_success nx_loop_settle nx_loop_is_failure nx_loop_verdict_is_valid

structs

185struct NxLoopFrame
196struct NxLoopVerdict

consts

65const NX_LOOP_RUNNING: nx_int = 0
66const NX_LOOP_DONE_SUCCESS: nx_int = 1
67const NX_LOOP_DONE_EXIT: nx_int = 2
68const NX_LOOP_BUDGET_EXHAUSTED: nx_int = 3
69const NX_LOOP_ABORTED: nx_int = 4
70const NX_LOOP_N_VERDICTS: nx_int = 5
180const NX_LV_NORMAL: i64 = 1 // body broke OR predicate matched
181const NX_LV_BOUND_EXHAUSTED: i64 = 2 // hit declared max_iters
182const NX_LV_TIMED_OUT: i64 = 3 // wall-time watchdog fired
183const NX_LV_STALLED: i64 = 4 // no progress for max_no_progress iters

functions

72func nx_loop_verdict_is_valid(v: nx_int) -> nx_int
called by 2: mainmain
83func nx_loop_is_success(v: nx_int) -> nx_int
called by 2: mainmain
89func nx_loop_is_failure(v: nx_int) -> nx_int
called by 2: mainmain
114func nx_loop_settle(verdict_in: nx_int, iter: nx_int, max_iters: nx_int) -> nx_int
called by 2: mainmain
139func nx_loop_settle_counted(verdict_in: nx_int, iter: nx_int, n_required: nx_int) -> nx_int
called by 2: mainmain
202func nx_loop_begin(max_iters: i64) -> *NxLoopFrame
216func nx_loop_begin_watchdog(max_iters: i64, max_wall_ns: i64, max_no_progress: i64) -> *NxLoopFrame
227func nx_loop_step(lp: *NxLoopFrame) -> i64
254func nx_loop_break(lp: *NxLoopFrame) -> i64
259func nx_loop_break_with(lp: *NxLoopFrame, reason: i64) -> i64
called by 1: main
265func nx_loop_mark_progress(lp: *NxLoopFrame) -> i64
called by 1: main
274func nx_loop_finish(lp: *NxLoopFrame) -> *NxLoopFrame
called by 1: main
278func nx_loop_was_normal(lp: *NxLoopFrame) -> i64
called by 1: main
291func main() -> i64