Class: Rigor::Environment::ClassRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/environment/class_registry.rb,
sig/rigor/environment.rbs

Overview

Resolves Ruby Class/Module objects to Rigor::Type::Nominal instances. The hardcoded list spans the core classes the literal typer (Slice 1) and the constant-resolution path (Slice 2 strengthening) need. This is the static fast path for built-ins; Environment falls through to RbsLoader for all other names — the two tiers are complementary.

See docs/internal-spec/inference-engine.md for the binding contract (every entry below MUST always be recognised).

Constant Summary collapse

SLICE_1_BUILT_INS =
[
  Integer,
  Float,
  String,
  Symbol,
  NilClass,
  TrueClass,
  FalseClass,
  Object,
  BasicObject
].freeze
SLICE_2_BUILT_INS =

Common Ruby core classes that user code routinely names by constant reference. Adding them to the registry lets nominal_for_name resolve Array, Hash, etc. without each call site re-listing them. The static registry is the cheap fast path; RbsLoader extends coverage to all other RBS-declared names (Slice 4, landed).

[
  Array,
  Hash,
  Range,
  Regexp,
  Proc,
  Method,
  Module,
  Class,
  Numeric,
  Comparable,
  Enumerable,
  Exception,
  StandardError,
  RuntimeError,
  ArgumentError,
  TypeError,
  NameError,
  NoMethodError,
  KeyError,
  IndexError,
  RangeError,
  ZeroDivisionError,
  IO,
  File,
  Dir,
  Encoding
].freeze
CORE_BUILT_INS =
(SLICE_1_BUILT_INS + SLICE_2_BUILT_INS).freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeClassRegistry

Returns a new instance of ClassRegistry.



81
82
83
84
# File 'lib/rigor/environment/class_registry.rb', line 81

def initialize
  @nominals = {}
  @class_objects = {}
end

Class Method Details

.defaultClassRegistry

Returns:



63
64
65
# File 'lib/rigor/environment/class_registry.rb', line 63

def default
  @default ||= build_default
end

Instance Method Details

#class_ordering(lhs, rhs) ⇒ ordering

Parameters:

  • lhs (String, Symbol)
  • rhs (String, Symbol)

Returns:

  • (ordering)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/rigor/environment/class_registry.rb', line 119

def class_ordering(lhs, rhs)
  lhs = normalize_name(lhs)
  rhs = normalize_name(rhs)
  return :equal if lhs == rhs

  lhs_class = @class_objects[lhs]
  rhs_class = @class_objects[rhs]
  return :unknown if lhs_class.nil? || rhs_class.nil?

  if lhs_class <= rhs_class
    :subclass
  elsif rhs_class <= lhs_class
    :superclass
  else
    :disjoint
  end
end

#nominal_for(class_object) ⇒ Type::Nominal

Parameters:

  • class_object (Module)

Returns:



101
102
103
104
105
106
107
# File 'lib/rigor/environment/class_registry.rb', line 101

def nominal_for(class_object)
  unless registered?(class_object)
    raise KeyError, "Rigor::Environment::ClassRegistry has no entry for #{class_object.inspect}"
  end

  @nominals.fetch(class_object.name)
end

#nominal_for_name(name) ⇒ Type::Nominal?

Nil-safe lookup by class name. Accepts Symbol or String. Returns the registered Rigor::Type::Nominal, or nil when the name is unknown. Used by ExpressionTyper to resolve Prism::ConstantReadNode and Prism::ConstantPathNode under the fail-soft policy: unknown names MUST NOT raise and MUST flow through the engine's tracer.

Parameters:

  • name (String, Symbol)

Returns:



113
114
115
116
117
# File 'lib/rigor/environment/class_registry.rb', line 113

def nominal_for_name(name)
  return nil if name.nil?

  @nominals[name.to_s]
end

#normalize_name(name) ⇒ String

Parameters:

  • name (Module, String, Symbol)

Returns:

  • (String)


139
140
141
# File 'lib/rigor/environment/class_registry.rb', line 139

def normalize_name(name)
  name.to_s.delete_prefix("::")
end

#register(class_object) ⇒ void

This method returns an undefined value.

Parameters:

  • class_object (Module)

Raises:

  • (ArgumentError)


86
87
88
89
90
91
92
93
# File 'lib/rigor/environment/class_registry.rb', line 86

def register(class_object)
  raise ArgumentError, "expected Class or Module, got #{class_object.class}" unless class_object.is_a?(Module)
  raise ArgumentError, "anonymous class has no name" if class_object.name.nil?

  @nominals[class_object.name] ||= Type::Combinator.nominal_of(class_object)
  @class_objects[class_object.name] ||= class_object
  self
end

#registered?(class_object) ⇒ Boolean

Parameters:

  • class_object (Module)

Returns:

  • (Boolean)


95
96
97
98
99
# File 'lib/rigor/environment/class_registry.rb', line 95

def registered?(class_object)
  return false unless class_object.is_a?(Module) && class_object.name

  @nominals.key?(class_object.name)
end