Module: Rigor::Effects::Label
- Defined in:
- lib/rigor/effects/label.rb
Overview
The effect-label grammar and the subsumption relation over it (ADR-103 WD1; normative in
docs/type-specification/effect-labels.md).
A label is a dot-path of lowercase segments — io, io.net.http, nondet.time. The relation
that matters is segment-aware prefix subsumption: io admits io.net.http and rejects
iota. Every method here is pure and total; a malformed input is answered, never raised on,
so a caller can ask valid? and the rest in either order.
Constant Summary collapse
- PATTERN =
label = segment { "." segment },segment = [a-z][a-z0-9]*. Deliberately narrow: no underscores, no hyphens, no uppercase, no empty segment, no trailing dot. The same grammar is the RFC'slabelproduction, so a label spells identically in Steins and Rigor. /\A[a-z][a-z0-9]*(?:\.[a-z][a-z0-9]*)*\z/
Class Method Summary collapse
-
.ancestors(label) ⇒ Object
The label's proper ancestors, outermost first and excluding the label itself:
"io.net.http"->["io", "io.net"]. -
.parent(label) ⇒ Object
The label one segment shallower, or
nilfor a root (and for a malformed label). -
.root(label) ⇒ Object
The label's outermost segment — the root whose ownership the registry checks.
-
.segments(label) ⇒ Object
The label's segments, outermost first:
"io.net.http"->["io", "net", "http"]. -
.subsumes?(bound, label) ⇒ Boolean
Whether
boundadmitslabelunder segment-aware prefix subsumption. -
.valid?(str) ⇒ Boolean
Whether
stris a well-formed label.
Class Method Details
.ancestors(label) ⇒ Object
The label's proper ancestors, outermost first and excluding the label itself:
"io.net.http" -> ["io", "io.net"]. A root has no ancestors.
58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/rigor/effects/label.rb', line 58 def ancestors(label) parts = segments(label) return [].freeze if parts.length <= 1 result = [] prefix = nil parts[0...-1].each do |segment| prefix = prefix ? "#{prefix}#{SEPARATOR}#{segment}" : segment result << prefix end result.freeze end |
.parent(label) ⇒ Object
The label one segment shallower, or nil for a root (and for a malformed label).
47 48 49 50 51 52 53 54 |
# File 'lib/rigor/effects/label.rb', line 47 def parent(label) return nil unless valid?(label) index = label.rindex(SEPARATOR) return nil unless index label[0, index] end |
.root(label) ⇒ Object
The label's outermost segment — the root whose ownership the registry checks.
72 73 74 |
# File 'lib/rigor/effects/label.rb', line 72 def root(label) segments(label).first end |
.segments(label) ⇒ Object
The label's segments, outermost first: "io.net.http" -> ["io", "net", "http"].
A malformed label yields an empty array rather than a partial parse.
30 31 32 33 34 |
# File 'lib/rigor/effects/label.rb', line 30 def segments(label) return [].freeze unless valid?(label) label.split(SEPARATOR).freeze end |
.subsumes?(bound, label) ⇒ Boolean
Whether bound admits label under segment-aware prefix subsumption. A label subsumes
itself; io subsumes io.net.http; io does NOT subsume iota, because the match is on
segment boundaries and not on characters.
39 40 41 42 43 44 |
# File 'lib/rigor/effects/label.rb', line 39 def subsumes?(bound, label) return false unless valid?(bound) && valid?(label) return true if bound == label label.start_with?("#{bound}#{SEPARATOR}") end |
.valid?(str) ⇒ Boolean
Whether str is a well-formed label. Anything that is not a String is not.
24 25 26 |
# File 'lib/rigor/effects/label.rb', line 24 def valid?(str) str.is_a?(String) && PATTERN.match?(str) end |