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/refineKoru 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
~[comptime|explainer] pub tor explain-refine {
program: std/compiler:*const Program,
allocator: std/compiler:Allocator
} -> ExplainReport~[comptime|transform|pre] pub tor default {
expr: Expression,
source: Source,
item: std/compiler:*const Item,
program: std/compiler:*const Program,
reporter: std/compiler:*ErrorReporter
} -> SiteResult~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.