rubymirrors 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. data/Gemfile +7 -0
  2. data/README.md +30 -0
  3. data/Rakefile +13 -0
  4. data/lib/abstract_reflection.rb +112 -0
  5. data/lib/abstract_reflection/class_mirror.rb +150 -0
  6. data/lib/abstract_reflection/compiler_mirror.rb +31 -0
  7. data/lib/abstract_reflection/field_mirror.rb +35 -0
  8. data/lib/abstract_reflection/gc_mirror.rb +19 -0
  9. data/lib/abstract_reflection/method_mirror.rb +253 -0
  10. data/lib/abstract_reflection/mirror.rb +108 -0
  11. data/lib/abstract_reflection/object_mirror.rb +48 -0
  12. data/lib/abstract_reflection/stack_frame_mirror.rb +61 -0
  13. data/lib/abstract_reflection/thread_mirror.rb +64 -0
  14. data/lib/maglev/reflection.rb +49 -0
  15. data/lib/maglev/reflection/class_mirror.rb +157 -0
  16. data/lib/maglev/reflection/core_ext/class_organizer.rb +20 -0
  17. data/lib/maglev/reflection/core_ext/maglev.rb +5 -0
  18. data/lib/maglev/reflection/core_ext/method.rb +154 -0
  19. data/lib/maglev/reflection/core_ext/module.rb +41 -0
  20. data/lib/maglev/reflection/core_ext/object.rb +4 -0
  21. data/lib/maglev/reflection/core_ext/thread.rb +226 -0
  22. data/lib/maglev/reflection/field_mirror.rb +39 -0
  23. data/lib/maglev/reflection/field_mirror/fixed_instance_variable_mirror.rb +25 -0
  24. data/lib/maglev/reflection/method_mirror.rb +149 -0
  25. data/lib/maglev/reflection/mirror.rb +6 -0
  26. data/lib/maglev/reflection/object_mirror.rb +18 -0
  27. data/lib/maglev/reflection/stack_frame_mirror.rb +104 -0
  28. data/lib/maglev/reflection/thread_mirror.rb +116 -0
  29. data/lib/rubinius/reflection.rb +6 -0
  30. data/lib/ruby/reflection.rb +74 -0
  31. data/lib/ruby/reflection/class_mirror.rb +89 -0
  32. data/lib/ruby/reflection/field_mirror.rb +32 -0
  33. data/lib/ruby/reflection/field_mirror/class_variable_mirror.rb +25 -0
  34. data/lib/ruby/reflection/field_mirror/constant_mirror.rb +36 -0
  35. data/lib/ruby/reflection/field_mirror/instance_variable_mirror.rb +25 -0
  36. data/lib/ruby/reflection/method_mirror.rb +122 -0
  37. data/lib/ruby/reflection/mirror.rb +12 -0
  38. data/lib/ruby/reflection/object_mirror.rb +25 -0
  39. data/lib/ruby/reflection/stack_frame_mirror.rb +49 -0
  40. data/lib/ruby/reflection/support/shift_reset.rb +29 -0
  41. data/lib/ruby/reflection/thread_mirror.rb +47 -0
  42. data/rubymirrors.gemspec +12 -0
  43. data/spec/class_spec.rb +92 -0
  44. data/spec/field_spec.rb +119 -0
  45. data/spec/fixtures/class_spec.rb +29 -0
  46. data/spec/fixtures/field_spec.rb +9 -0
  47. data/spec/fixtures/method_spec.rb +14 -0
  48. data/spec/fixtures/object_spec.rb +5 -0
  49. data/spec/fixtures/reflect_spec.rb +14 -0
  50. data/spec/fixtures/stack_frame_spec.rb +5 -0
  51. data/spec/fixtures/thread_spec.rb +5 -0
  52. data/spec/frame_spec.rb +80 -0
  53. data/spec/method_spec.rb +166 -0
  54. data/spec/object_spec.rb +18 -0
  55. data/spec/reflection_spec.rb +74 -0
  56. data/spec/spec_helper.rb +16 -0
  57. data/spec/spec_helper/mspec_patch.rb +29 -0
  58. data/spec/spec_helper/multiple_reflections.rb +14 -0
  59. data/spec/thread_spec.rb +142 -0
  60. metadata +173 -0
@@ -0,0 +1,108 @@
1
+ module AbstractReflection
2
+ # The basic mirror. This is the lib code. It is also the factory to
3
+ # use for creating new mirrors on any kind of object. Its #reflect
4
+ # class method will return an appropriate mirror for a given object,
5
+ # provided one has been registered. The [ObjectMirror] class should
6
+ # have been registered as the fallback case for any kind of object,
7
+ # but that may depend on the specific API implementation.
8
+ module Mirror
9
+ module ClassMethods
10
+ @@mirrors = []
11
+
12
+ # Reflect on the passed object. This is the default factory for
13
+ # creating new mirrors, and it will try and find the appropriate
14
+ # mirror from the list of registered mirrors.
15
+ #
16
+ # @param [Object] the object to reflect upon. This need not be the
17
+ # actual object represented - it can itself be just a
18
+ # representation. It is really up to the mirror to decide what to
19
+ # do with it
20
+ # @param [Reflection] the instance of a Reflection this mirror was
21
+ # spawned in.
22
+ def reflect(obj, reflection)
23
+ target_mirror = nil
24
+ @@mirrors.detect {|klass| target_mirror = klass.mirror_class(obj) }
25
+ raise CapabilitiesExceeded if target_mirror.nil?
26
+ target_mirror.new(obj, reflection)
27
+ end
28
+
29
+ # The constructor, sets the @reflection instance variable before
30
+ # calling initialize.
31
+ def new(obj, reflection)
32
+ basic_new_object = allocate
33
+ basic_new_object.reflection = reflection
34
+ basic_new_object.send(:initialize, obj)
35
+ basic_new_object
36
+ end
37
+
38
+ # Decides whether the given class can reflect on [obj]
39
+ # @param [Object] the object to reflect upon
40
+ # @return [true, false]
41
+ def reflects?(obj)
42
+ @reflected_modules.any? { |mod| mod === obj }
43
+ end
44
+
45
+ # A shortcut to define reflects? behavior.
46
+ # @param [Module] the module whose instances this mirror reflects
47
+ def reflect!(*modules)
48
+ @reflected_modules = modules
49
+ register_mirror self
50
+ end
51
+
52
+ # Some objects may be more useful with a specialized kind of
53
+ # mirror. This method can be used to register new mirror
54
+ # classes. If used within a module, each class that includes
55
+ # that specific module is registered upon inclusion.
56
+ #
57
+ # @param [Module] The class or module to register
58
+ #
59
+ # @return [Mirror] returns self
60
+ def register_mirror(klass)
61
+ @@mirrors.unshift klass
62
+ @@mirrors.uniq!
63
+ self
64
+ end
65
+
66
+ # @param [Object] the object to reflect upon
67
+ #
68
+ # @return [Mirror, NilClass] the class to instantiate as mirror,
69
+ # using #new, or nil, if non is known
70
+ def mirror_class(obj)
71
+ self if reflects?(obj)
72
+ end
73
+
74
+ # Only define this once, and always get the ClassMethods from
75
+ # the current module. When [Mirror] is included in another
76
+ # module, this will enable that module to also define ClassMethods
77
+ # to mix in when included. Additionally, if [Mirror] had registered
78
+ # itself for matching specific objects, this registration is forwarded
79
+ # to the class.
80
+ def included(base)
81
+ base.extend(const_get("ClassMethods")) if const_defined?("ClassMethods")
82
+ base.const_set(:CapabilitiesExceeded, CapabilitiesExceeded)
83
+ end
84
+ end
85
+
86
+ extend ClassMethods
87
+ attr_accessor :reflection
88
+
89
+ def initialize(obj)
90
+ @subject = obj
91
+ end
92
+
93
+ # A generic representation of the object under observation.
94
+ def name
95
+ @subject.inspect
96
+ end
97
+
98
+ # The equivalent to #==/#eql? for comparison of mirrors against objects
99
+ def mirrors?(other)
100
+ @subject == other
101
+ end
102
+
103
+ # Accessor to the reflected object
104
+ def reflectee
105
+ @subject
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,48 @@
1
+ module AbstractReflection
2
+ # A mirror class. It is the most generic mirror and should be able
3
+ # to reflect on any object you can get at in a given system.
4
+ module ObjectMirror
5
+ include Mirror
6
+
7
+ # @return [FieldMirror] the instance variables of the object
8
+ def variables
9
+ raise CapabilitiesExceeded
10
+ end
11
+
12
+ # @return [FieldMirror] the class variables of the object or its class
13
+ def class_variables
14
+ raise CapabilitiesExceeded
15
+ end
16
+
17
+ # @return [ClassMirror] the a class mirror on the runtime class object
18
+ def target_class
19
+ raise CapabilitiesExceeded
20
+ end
21
+
22
+ # Searches the system for other objects that have references to
23
+ # this one.
24
+ #
25
+ # @return [Array<ObjectMirror>]
26
+ def objects_with_references
27
+ end
28
+
29
+ # Returns the transitive closure (the full object tree under this
30
+ # object, without duplicates).
31
+ #
32
+ # @return [Hash<ObjectMirror => Hash<...,...>>] nested hashes
33
+ def transitive_closure
34
+ end
35
+
36
+ # Searches for a reference path from this object to another given
37
+ # object.
38
+ #
39
+ # @return [Array<ObjectMirror>, NilClass] the object path or nil, if none
40
+ def path_to(obj)
41
+ end
42
+
43
+ # The instance_eval known from Ruby. Should return the result or a
44
+ # representation thereof.
45
+ def instance_eval
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,61 @@
1
+ module AbstractReflection
2
+ module StackFrameMirror
3
+ include Mirror
4
+
5
+ def restart
6
+ raise CapabilitiesExceeded
7
+ end
8
+
9
+ def pop
10
+ raise CapabilitiesExceeded
11
+ end
12
+
13
+ def step(length = :over)
14
+ raise CapabilitiesExceeded
15
+ end
16
+
17
+ def receiver
18
+ raise CapabilitiesExceeded
19
+ end
20
+
21
+ def self
22
+ raise CapabilitiesExceeded
23
+ end
24
+
25
+ def selector
26
+ raise CapabilitiesExceeded
27
+ end
28
+
29
+ def ip_offset
30
+ raise CapabilitiesExceeded
31
+ end
32
+
33
+ def step_offset
34
+ raise CapabilitiesExceeded
35
+ end
36
+
37
+ def source_offset
38
+ raise CapabilitiesExceeded
39
+ end
40
+
41
+ def arguments
42
+ raise CapabilitiesExceeded
43
+ end
44
+
45
+ def locals
46
+ raise CapabilitiesExceeded
47
+ end
48
+
49
+ def variable_context
50
+ raise CapabilitiesExceeded
51
+ end
52
+
53
+ def binding
54
+ raise CapabilitiesExceeded
55
+ end
56
+
57
+ def method
58
+ raise CapabilitiesExceeded
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,64 @@
1
+ module AbstractReflection
2
+ module ThreadMirror
3
+ include Mirror
4
+
5
+ def stop
6
+ raise CapabilitiesExceeded
7
+ end
8
+
9
+ def run
10
+ raise CapabilitiesExceeded
11
+ end
12
+
13
+ def kill
14
+ raise CapabilitiesExceeded
15
+ end
16
+
17
+ def return_value
18
+ raise CapabilitiesExceeded
19
+ end
20
+
21
+ def status
22
+ raise CapabilitiesExceeded
23
+ end
24
+
25
+ def stack
26
+ raise CapabilitiesExceeded
27
+ end
28
+
29
+ def step(length = :over)
30
+ raise CapabilitiesExceeded
31
+ end
32
+
33
+ def breakpoints
34
+ raise CapabilitiesExceeded
35
+ end
36
+
37
+ def thread_data
38
+ raise CapabilitiesExceeded
39
+ end
40
+
41
+ def compiler
42
+ raise CapabilitiesExceeded
43
+ end
44
+
45
+ # Installs an exception block in the thread. This is no rescue,
46
+ # the block will be executed for the given exception type, but it
47
+ # will not prevent the exception from propagating through the
48
+ # thread.
49
+ #
50
+ # @param [Exception, Array<Exception>] the exception(s) to rescue
51
+ # @param [Block] the exception handler
52
+ def handle_exception(e = Exception, &block)
53
+ raise CapabilitiesExceeded
54
+ end
55
+
56
+ def reset
57
+ raise CapabilitiesExceeded
58
+ end
59
+
60
+ def shift
61
+ raise CapabilitiesExceeded
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,49 @@
1
+ require 'ruby/reflection'
2
+ require 'maglev/reflection/core_ext/class_organizer'
3
+
4
+ module Maglev
5
+ class Reflection < Ruby::Reflection
6
+ def modules
7
+ mirror_modules_satisfying {|m| Module === m && !(Class === m) }
8
+ end
9
+
10
+ def classes
11
+ mirror_modules_satisfying {|m| Class === m }
12
+ end
13
+
14
+ def implementations_of(str)
15
+ if sym = Symbol.__existing_symbol(str.to_s)
16
+ class_list = ClassOrganizer.cached_organizer.implementors_of sym
17
+ class_list.collect {|cls| self.reflect(cls).method sym }
18
+ else
19
+ []
20
+ end
21
+ end
22
+
23
+ def senders_of(str)
24
+ if sym = Symbol.__existing_symbol(str.to_s)
25
+ meth_list = ClassOrganizer.cached_organizer.senders_of sym
26
+ meth_list.collect do |m|
27
+ self.reflect(m.__in_class).method m.__name
28
+ end
29
+ else
30
+ []
31
+ end
32
+ end
33
+
34
+ private
35
+ def mirror_modules_satisfying
36
+ modules = self.reflect(Object).each_module
37
+ modules = modules.select {|m| yield m }
38
+ modules.collect {|m| self.reflect m }
39
+ end
40
+ end
41
+ end
42
+
43
+ require 'maglev/reflection/mirror'
44
+ require 'maglev/reflection/object_mirror'
45
+ require 'maglev/reflection/field_mirror'
46
+ require 'maglev/reflection/thread_mirror'
47
+ require 'maglev/reflection/stack_frame_mirror'
48
+ require 'maglev/reflection/class_mirror'
49
+ require 'maglev/reflection/method_mirror'
@@ -0,0 +1,157 @@
1
+ require 'maglev/reflection/core_ext/module'
2
+
3
+ module Maglev
4
+ class Reflection
5
+ class ClassMirror < ObjectMirror
6
+ include AbstractReflection::ClassMirror
7
+ reflect! Module
8
+
9
+ def singleton_instance
10
+ raise TypeError, "not a singleton class" unless self.singleton_class?
11
+ if self.inspect =~ /^#<Class:.*>$/
12
+
13
+ else
14
+ raise NotImplementedError, "not implemented yet"
15
+ end
16
+ end
17
+
18
+ def singleton_class
19
+ reflection.reflect @subject.singleton_class
20
+ end
21
+
22
+ def singleton_class?
23
+ self.name =~ /^\#<Class:.*>$/
24
+ end
25
+
26
+ def compile_method(source, selector = nil)
27
+ meth_dict = instance_methods(false) + methods(false)
28
+ if selector || (md = /^\s*def\s+(?:self\.)?([^;\( \n]+)/.match(source))
29
+ selector = selector || md[1]
30
+ begin
31
+ method(selector).source!(source, true)
32
+ rescue NameError, TypeError
33
+ class_eval(source)
34
+ end
35
+ else
36
+ class_eval(source)
37
+ end
38
+ new_meth_dict = instance_methods(false) + methods(false)
39
+ new_method_selector = if new_meth_dict > meth_dict
40
+ (new_meth_dict - meth_dict).first
41
+ else
42
+ selector
43
+ end
44
+ method(new_method_selector) if new_method_selector
45
+ end
46
+
47
+ def instance_variables
48
+ if (fixed_ivs = @subject.__inst_var_names).empty?
49
+ raise AbstractReflection::CapabilitiesExceeded
50
+ else
51
+ field_mirrors fixed_ivs
52
+ end
53
+ end
54
+
55
+ def class_variables
56
+ field_mirrors @subject.class_variables
57
+ end
58
+
59
+ def class_instance_variables
60
+ field_mirrors @subject.instance_variables
61
+ end
62
+
63
+ def nested_classes
64
+ constants.collect(&:value).select {|c| ClassMirror === c }
65
+ end
66
+
67
+ def source_files
68
+ method_objects = @subject.instance_methods(false).collect do |name|
69
+ @subject.instance_method(name)
70
+ end
71
+ method_objects += @subject.methods(false).collect do |name|
72
+ @subject.method(name)
73
+ end
74
+ method_objects.collect(&:source_location).collect(&:first).uniq
75
+ end
76
+
77
+ def mixins
78
+ mirrors @subject.ancestors.reject {|m| m.is_a? Class }
79
+ end
80
+
81
+ def superclass
82
+ self.class.new @subject.superclass
83
+ end
84
+
85
+ def subclasses
86
+ ary = []
87
+ each_module do |m|
88
+ ary << m if m.superclass && m.superclass.mirrors?(@subject)
89
+ end
90
+ ary
91
+ end
92
+
93
+ def ancestors
94
+ mirrors @subject.ancestors
95
+ end
96
+
97
+ def constant(str)
98
+ path = str.to_s.split("::")
99
+ c = path[0..-2].inject(@subject) {|klass,str| klass.const_get(str) }
100
+ field_mirror c, path.last
101
+ rescue NameError
102
+ nil
103
+ end
104
+
105
+ def constants
106
+ field_mirrors (@subject.constants - @subject.instance_variables)
107
+ end
108
+
109
+ def method(name)
110
+ reflection.reflect @subject.instance_method(name.to_s)
111
+ end
112
+
113
+ def methods
114
+ @subject.instance_methods(false)
115
+ end
116
+
117
+ def nesting
118
+ ary = [@subject]
119
+ while (ns = ary.last.__transient_namespace(1)) &&
120
+ (par = ns.parent) &&
121
+ (nxt = par.my_class)
122
+ break if nxt.nil? || nxt == Object
123
+ ary << nxt
124
+ end
125
+ ary
126
+ end
127
+
128
+ # Maglev specific, not public reflection API.
129
+ #
130
+ # Traverse the Ruby namespace hierarchy and execute block for
131
+ # all classes and modules. Returns an IdentitySet of all
132
+ # classes and modules found. Skips autoloads (i.e., does not
133
+ # trigger them and does not yield them to the block).
134
+ #
135
+ # @param [Module] klass The Class or Module object to start traversal.
136
+ # Default is Object.
137
+ #
138
+ # @param [IdentitySet] rg The recursion guard used to prevent infinite
139
+ # loops; also used as return value.
140
+ #
141
+ # @return [IdentitySet] An IdentitySet of all the Classes and Modules
142
+ # registered in the Ruby namespace
143
+ #
144
+ def each_module(from=Object, rg=IdentitySet.new, &block)
145
+ unless rg.include?(from)
146
+ rg.add from
147
+ yield reflection.reflect(from) if block
148
+ if ns = from.__transient_namespace(1)
149
+ ns.values.each {|c| each_module(c, rg, &block) if Module === c }
150
+ end
151
+ end
152
+ rg
153
+ end
154
+
155
+ end
156
+ end
157
+ end