Class: Rigor::Type::AcceptsResult

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/type/accepts_result.rb

Overview

Immutable value object returned by ‘Rigor::Type#accepts(other, mode:)`. Carries the three-valued answer alongside the boundary mode the answer was computed under and an ordered list of textual reasons describing which rules fired.

AcceptsResult is the dual of ‘SubtypeResult` (Slice 5+). Acceptance answers “is `other` passable to `self` at a method-parameter or assignment boundary?”, consulting the gradual-typing rules in docs/type-specification/value-lattice.md when `mode` is `:gradual`, and the strict subset relation when `mode` is `:strict`. Phase 2c ships full `:gradual` semantics; `:strict` is reserved for later slices and currently raises ArgumentError.

Reasons are stored as plain strings for now. Slice 5+ MAY upgrade them to structured records (rule id, supporting facts, dynamic provenance); callers MUST treat the reasons array as opaque except for human-readable logging.

See docs/internal-spec/internal-type-api.md (“Result Value Objects”).

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trinary, mode: :gradual, reasons: nil) ⇒ AcceptsResult

Returns a new instance of AcceptsResult.

Parameters:

  • trinary (Rigor::Trinary)
  • mode (Symbol) (defaults to: :gradual)

    currently ‘:gradual` (default) or `:strict`.

  • reasons (Array<String>, String, nil) (defaults to: nil)

    textual reasons; a single string is wrapped, ‘nil` becomes an empty array.

Raises:

  • (ArgumentError)


36
37
38
39
40
41
42
43
44
# File 'lib/rigor/type/accepts_result.rb', line 36

def initialize(trinary, mode: :gradual, reasons: nil)
  raise ArgumentError, "trinary must be Rigor::Trinary, got #{trinary.class}" unless trinary.is_a?(Trinary)
  raise ArgumentError, "mode must be one of #{MODES.inspect}, got #{mode.inspect}" unless MODES.include?(mode)

  @trinary = trinary
  @mode = mode
  @reasons = normalize_reasons(reasons).freeze
  freeze
end

Instance Attribute Details

#modeObject (readonly)

Returns the value of attribute mode.



30
31
32
# File 'lib/rigor/type/accepts_result.rb', line 30

def mode
  @mode
end

#reasonsObject (readonly)

Returns the value of attribute reasons.



30
31
32
# File 'lib/rigor/type/accepts_result.rb', line 30

def reasons
  @reasons
end

#trinaryObject (readonly)

Returns the value of attribute trinary.



30
31
32
# File 'lib/rigor/type/accepts_result.rb', line 30

def trinary
  @trinary
end

Class Method Details

.maybe(mode: :gradual, reasons: nil) ⇒ Object



55
56
57
# File 'lib/rigor/type/accepts_result.rb', line 55

def maybe(mode: :gradual, reasons: nil)
  new(Trinary.maybe, mode: mode, reasons: reasons)
end

.no(mode: :gradual, reasons: nil) ⇒ Object



51
52
53
# File 'lib/rigor/type/accepts_result.rb', line 51

def no(mode: :gradual, reasons: nil)
  new(Trinary.no, mode: mode, reasons: reasons)
end

.yes(mode: :gradual, reasons: nil) ⇒ Object



47
48
49
# File 'lib/rigor/type/accepts_result.rb', line 47

def yes(mode: :gradual, reasons: nil)
  new(Trinary.yes, mode: mode, reasons: reasons)
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



82
83
84
85
86
87
# File 'lib/rigor/type/accepts_result.rb', line 82

def ==(other)
  other.is_a?(AcceptsResult) &&
    trinary == other.trinary &&
    mode == other.mode &&
    reasons == other.reasons
end

#hashObject



90
91
92
# File 'lib/rigor/type/accepts_result.rb', line 90

def hash
  [AcceptsResult, trinary, mode, reasons].hash
end

#inspectObject



94
95
96
# File 'lib/rigor/type/accepts_result.rb', line 94

def inspect
  "#<Rigor::Type::AcceptsResult #{trinary.inspect} mode=#{mode}>"
end

#maybe?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/rigor/type/accepts_result.rb', line 68

def maybe?
  trinary.maybe?
end

#no?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'lib/rigor/type/accepts_result.rb', line 64

def no?
  trinary.no?
end

#with_reason(reason) ⇒ Object

Returns a new AcceptsResult whose reasons list is ‘self.reasons` with `reason` appended. Used by combinator-style routing in Inference::Acceptance to thread context through nested acceptance checks without mutating any object.



76
77
78
79
80
# File 'lib/rigor/type/accepts_result.rb', line 76

def with_reason(reason)
  return self if reason.nil? || reason.empty?

  self.class.new(trinary, mode: mode, reasons: reasons + [reason])
end

#yes?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/rigor/type/accepts_result.rb', line 60

def yes?
  trinary.yes?
end