Class: Farce::ClassMirror
- Inherits:
-
Object
- Object
- Farce::ClassMirror
- Includes:
- Shareable::Tracked
- Defined in:
- lib/farce/class_mirror.rb
Overview
Map Ruby classes to a parallel inheritance hierarchy. Undefined classes use the nearest defined ancestor's mirror. An optional block turns each lookup into a cached value for that source class.
Instance Method Summary collapse
-
#[](klass) ⇒ Object
Look up a mirror or the cached result of the constructor block.
-
#define(klass) { ... } ⇒ Class
Define or extend a mirror class from the main Ractor.
-
#initialize(base_class = Class.new) {|mirror, klass| ... } ⇒ ClassMirror
constructor
A new instance of ClassMirror.
Methods included from Shareable
Constructor Details
#initialize(base_class = Class.new) {|mirror, klass| ... } ⇒ ClassMirror
Note:
The block must be convertible to a shareable proc.
Returns a new instance of ClassMirror.
23 24 25 26 27 28 29 |
# File 'lib/farce/class_mirror.rb', line 23 def initialize(base_class = Class.new, &) raise TypeError, "Class expected, got #{base_class.class}" unless base_class.is_a?(Class) @mapping = Strict::Map.new({ BasicObject => base_class }) @cache = Strict::WeakKeyMap.new @callback = block_given? ? Ractor.shareable_proc(&) : nil super() end |
Instance Method Details
#[](klass) ⇒ Object
Look up a mirror or the cached result of the constructor block.
52 53 54 55 56 57 58 |
# File 'lib/farce/class_mirror.rb', line 52 def [](klass) raise TypeError, "Class expected, got #{klass.class}" unless klass.is_a?(Class) @cache.store_if_absent(klass) do result = lookup(klass) @callback ? @callback.call(result, klass) : result end end |
#define(klass) { ... } ⇒ Class
Define or extend a mirror class from the main Ractor.
Missing ancestors are defined automatically. The block defines methods
in an included module, so super can call earlier definitions.
Existing lookup results are invalidated after each definition.
69 70 71 72 73 74 75 76 77 78 |
# File 'lib/farce/class_mirror.rb', line 69 def define(klass, &) check_frozen! raise Ractor::IsolationError, "must be called from main Ractor" unless Ractor.main? raise TypeError, "Class expected, got #{klass.class}" unless klass.is_a?(Class) mixin = Module.new(&) if block_given? mirror = @mapping.store_if_absent(klass) { Class.new(define(klass.superclass)) } mirror.include(mixin) if mixin @cache.clear mirror end |