This library is in flux. APIs may change without notice. Generated from source with koruc 0.1.7 on 11/4/2026.

Refine

import std/refine

Koru Standard Library: Refine — value-level constraints on declared fields

refine.k · 2 tors

Koru Standard Library: Refine — value-level constraints on declared fields · 51 more lines
Koru Standard Library: Refine — value-level constraints on declared fields `std/refine(Name) { name: type & constraint… }` — a definition surface for constraints on ABSTRACTS: it never touches a value, only meets bounds onto a declaration another module made. The `&`-atoms meet per field name, order-independently; a meet that lands empty is a loud KORU205 refusal, never a last-wins override. SURFACE: std/refine(Server) { port: i64 & >1024 & <=65535 } meets the `std/proto(Server)` declaration — refined fields must exist there on one agreed base. The meet is name-keyed, total, confluent: `std/refine` blocks in any module fold onto one facet that lands as a typed `Item.facet_decl` — consumers match the node, never comment text. LAYERING — the point of a separate module: a bound can arrive apart from the declaration. A library declares `std/proto(Server)` plainly; a downstream module writes `std/refine(lib/home:Server) { port: i64 & >1024 }` — `home:Name` rides the named-arg channel (proto's own `app/alpha:Health` convention), addressing the type by home while the facet meets the declaration program-wide. Definition is import-scoped; the constraint rides the type, so enforcement is type-global. TARGET SCOPES: `std/refine(Server)|fpga { … }` selects a declared impl variant (`proc default|fpga` below) — `|variant` keeps its one meaning, implementation selection — and the selected impl stamps `target` onto the facet it lands. The universal facet (bare `std/refine`) meets unscoped blocks only; a `|fpga` facet meets universal + fpga blocks. A tag with no declared impl is a loud KORU122 — the target vocabulary is closed by declaration, never a facet minted under a name nobody reads. Consumers read the universal facet by default; a target-aware consumer asks for its scope (`facets.findFor`, `metFields(…, scope)`). ENFORCEMENT IS THE CONSUMER'S: refine emits data, never a check. `std/store` insert, `std/json` decode, `std/list:push` — each reads the facet at its own boundary and decides. An unconsumed facet is enumerable documentation, not a hole. v0 ATOMS: `>N` `>=N` `<N` `<=N` `==N` over integer literals, plus the `clamp(lo, hi)` normalizer — on integer scalar bases, raw (`i64`) or named through a terminal (`Port`). Disjunction (`*a | b`) is next. NOTE: `.k` files carry no host lines, so host types are spelled through `std/compiler:` aliases (Program, Item, Source, Allocator); the transform's own proc takes `std` inside its body and uses `koru_allocator()` — the canonical accessor emitted into every module (emitter_helpers.zig), riding the Debug leak counter. The explainer (`koruc <file> explain`) reports the met facet; the impl is refine.explain.kz. @retain: the generated gather invokes it.

explain-refine

comptimeexplainer koru_std/refine.k:53

default

comptimetransformpre koru_std/refine.k:57

~part terminal koru_std/refine.terminal.kz

Koru Standard Library: the terminal part of refine — joined via `~part terminal` in refine.kz; members land in koru_refine. A field base that isn't a scalar spelling may name a terminal — `port: Port` where `std/proto:i64(Port)` minted the identity. Resolve the name to its host scalar: a bare `Port` answers to the anchor's home; a qualified `home/path:Name` carries its own. Live terminal doors and erased `// proto-terminal Name: scalar` markers both resolve, so dissolution order doesn't matter.

~part body koru_std/refine.body.kz

Koru Standard Library: the refine transform body — joined via `~part body` in refine.kz; members land in koru_refine. The two `default` impl procs in refine.k dispatch here; `scope` is the facet target the selected impl stamps (null = universal). The transform body both `default` impls share — `scope` is the facet's target: null for the universal facet (bare `std/refine(S)`), "fpga" for `std/refine(S)|fpga`. The variant dispatch picked which impl ran; the scope it stamps is what that selection means.

~part fold koru_std/refine.fold.kz

Koru Standard Library: the fold part of refine — joined via `~part fold` in refine.kz; members land in koru_refine. One fold, three readers: the transform (refine.body.kz) walks it to mint the facet_decl, the explainer re-derives the report from it, and consumers (std/list, std/store, decoders) call metFields at their own boundary. Drift between them is impossible — there is one fold. Live `std/refine` invocations and `facet_decl` nodes targeting the same (home, name) — all contributors fold onto one meet, so the facet is visitation-order-independent. `scope` is the facet's target (null = universal): a contributor folds iff its own scope is null (universal — governs every target) or equals `scope`.

~part explain koru_std/refine.explain.kz

Koru Standard Library: the `explain` part of refine — joined via `~part explain` in refine.kz; members land in koru_refine. The `[explainer]` is the transform's mirror: it folds every `std/refine` block through the SAME machinery the transform uses — invWant for the addressed (home, name), parseInto for each contributor block, walkRefine for the fold, walkProto for the anchor, terminalScalar for base resolution. The report is what the meet decided, re-derived live, never a parallel re-implementation: drift between what explain says and what the facet_decl carries is impossible because both read one fold. `explain` runs INSTEAD of the pipeline, on the pre-transform tree — so this explainer also answers for programs that would REFUSE: an orphaned anchor, a missing field, a base mismatch, a non-integer bound, an empty meet all surface as `status = "refused: …"` instead of a KORU205 the user then has to decode. The canonical facet spelling — same shape the driver's marker and facet_decl carry: `name: base & >N & <=N & clamp(lo,hi)`; `spellTerms` drops the `name: ` prefix for the catalog (`port.meet = "Port & >1024"`).

~part alts koru_std/refine.alts.kz

Koru Standard Library: the disjunction part of refine — joined via `~part alts` in refine.kz; members land in koru_refine. A set is a lattice element like any other: it meets by INTERSECTION, an empty intersection is a RECORDED conflict (loud, order-independent), and the field's other terms filter it before the canonical form is fixed. One canonicalization rule keeps the lattice small: a set that lands on ONE value IS that equality. So every reader past this file sees either an `eq` or a set of two-or-more — never both, never a singleton set.