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.
-
#custom?(klass) ⇒ Boolean
Check whether this class was explicitly passed to #define.
-
#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
The block must be convertible to a shareable proc.
Returns a new instance of ClassMirror.
23 24 25 26 27 28 29 30 |
# 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 @custom = Strict::Map.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.
54 55 56 57 58 59 60 |
# File 'lib/farce/class_mirror.rb', line 54 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 |
#custom?(klass) ⇒ Boolean
Check whether this class was explicitly passed to #define. Automatically created ancestors and inherited definitions do not count.
87 |
# File 'lib/farce/class_mirror.rb', line 87 def custom?(klass) = @custom.key?(klass) |
#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.
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/farce/class_mirror.rb', line 71 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 = define_mirror(klass) mirror.include(mixin) if mixin @cache.clear @custom[klass] = true mirror end |