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,20 @@
1
+ module Maglev
2
+ ClassOrganizer = __resolve_smalltalk_global(:ClassOrganizer)
3
+ class ClassOrganizer
4
+ # @return [ClassOrganizer] the cached instance or a fresh one
5
+ class_primitive_nobridge 'cached_organizer', 'cachedOrganizer'
6
+ # Clears the cached instance
7
+ class_primitive_nobridge 'clear_cache', 'clearCachedOrganizer'
8
+
9
+ primitive 'all_ruby_classes', '_allRubyClasses'
10
+ primitive 'all_ruby_classes_under', '_allRubyClasses:'
11
+
12
+ # @return [Array<Class>]
13
+ primitive 'implementors_of', 'rubyImplementorsOf:'
14
+ primitive 'implementors_of_in', 'rubyImplementorsOf:in:'
15
+
16
+ # @return [Array<GsNMethod>]
17
+ primitive 'senders_of', 'rubySendersOf:'
18
+ primitive 'senders_of_in', 'rubySendersOf:in:'
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ module Maglev
2
+ class System
3
+ class_primitive 'needs_commit', 'needsCommit'
4
+ end
5
+ end
@@ -0,0 +1,154 @@
1
+ class GsNMethod
2
+ primitive_nobridge '__env_id', 'environmentId'
3
+ primitive_nobridge '__home_method', 'homeMethod'
4
+ primitive_nobridge '__in_class', 'inClass'
5
+ primitive '__is_method_for_block', 'isMethodForBlock'
6
+ primitive '__source_string_for_block', '_sourceStringForBlock'
7
+ primitive '__source_offsets', '_sourceOffsets'
8
+ primitive '__source_offsets_of_sends', '_sourceOffsetsOfSends'
9
+ primitive '__source_offset_first_send_of', '_sourceOffsetOfFirstSendOf:'
10
+ primitive '__set_break_at_step_point', 'setBreakAtStepPoint:'
11
+ primitive '__args_and_temps', 'argsAndTemps'
12
+ primitive '__num_args', 'numArgs'
13
+ primitive '__selector', 'selector'
14
+ primitive '__ruby_opt_args_bits', 'rubyOptArgsBits'
15
+ primitive '__ip_steps', '_ipSteps'
16
+ primitive '__opcode_info_at', '_opcodeInfoAt:'
17
+ primitive '__in_class', 'inClass'
18
+ end
19
+
20
+ class UnboundMethod
21
+ def __st_gsmeth
22
+ @_st_gsmeth
23
+ end
24
+ end
25
+
26
+ class GsNMethodWrapper < UnboundMethod
27
+ def initialize(gsmethod); @_st_gsmeth = gsmethod; end
28
+ def inspect; "#<GsNMethodWrapper: #{self.name}>"; end
29
+ def name; @_st_gsmeth.__name; end
30
+ end
31
+
32
+ # class UnboundMethod
33
+ # def step_offsets
34
+ # @_st_gsmeth.__source_offsets
35
+ # end
36
+
37
+ # def send_offsets
38
+ # @_st_gsmeth.__source_offsets_of_sends
39
+ # end
40
+
41
+ # def break(step_point = 1)
42
+ # if @_st_gsmeth.__is_method_for_block
43
+ # @_st_gsmeth.__set_break_at_step_point(step_point)
44
+ # else
45
+ # self.__nonbridge_meth.__set_break_at_step_point(step_point)
46
+ # end
47
+ # end
48
+
49
+ # def in_class
50
+ # @_st_gsmeth.__in_class
51
+ # end
52
+
53
+ # def file
54
+ # (@_st_gsmeth.__source_location || [])[0]
55
+ # end
56
+
57
+ # def line
58
+ # (@_st_gsmeth.__source_location || [])[1]
59
+ # end
60
+
61
+ # def source
62
+ # if @_st_gsmeth.__is_method_for_block
63
+ # @_st_gsmeth.__source_string_for_block
64
+ # else
65
+ # @_st_gsmeth.__source_string
66
+ # end
67
+ # end
68
+
69
+ # def file=(path)
70
+ # raise TypeError, "cannot modifiy a block method" if is_method_for_block?
71
+ # @_st_gsmeth.__in_class.class_eval(source, path, line)
72
+ # reload
73
+ # end
74
+
75
+ # def line=(num)
76
+ # raise TypeError, "cannot modifiy a block method" if is_method_for_block?
77
+ # @_st_gsmeth.__in_class.class_eval(source, file, num)
78
+ # reload
79
+ # end
80
+
81
+ # def source!(str, file_out = false)
82
+ # raise TypeError, "cannot modifiy a block method" if is_method_for_block?
83
+ # if file.nil? && line.nil? # Smalltalk method
84
+ # in_class.__compile_method_category_environment_id(str,
85
+ # '*maglev-webtools-unclassified', 1)
86
+ # else # Ruby method
87
+ # self.original_source = source
88
+ # self.in_class.class_eval(str, file, line)
89
+ # self.file_out(str) if file_out
90
+ # end
91
+ # reload
92
+ # end
93
+
94
+ # def file_out(source)
95
+ # if !is_def_method? || is_method_for_block?
96
+ # raise StandardError, "not an ordinary method def"
97
+ # end
98
+
99
+ # unless File.writable?(file)
100
+ # raise StandardError, "cannot write to method source file #{file}"
101
+ # end
102
+
103
+ # # Write a new file with updated contents
104
+ # original_contents = File.readlines(file)
105
+ # copy = File.open("#{file}.tmp", 'w+') do |f|
106
+ # f.write(original_contents[0...(line - 1)].join)
107
+ # f.write(original_contents[(line - 1)..-1].join.sub(original_source, source))
108
+ # end
109
+
110
+ # # Rename to original file
111
+ # File.rename("#{file}.tmp", file)
112
+ # end
113
+
114
+ # def reload
115
+ # @_st_gsmeth = in_class.__gs_method(self.name, true)
116
+ # self
117
+ # end
118
+
119
+ # attr_writer :original_source
120
+ # def original_source
121
+ # @original_source || source
122
+ # end
123
+
124
+ # def is_method_for_block?
125
+ # @_st_gsmeth.__is_method_for_block
126
+ # end
127
+
128
+ # def is_def_method?
129
+ # self.original_source =~ /^\s+def\s/
130
+ # end
131
+
132
+ # # Answers whether the method send the specified message.
133
+ # # Accepts the following options:
134
+ # # args => how many arguments in the send (default: 0)
135
+ # # splat => is there a splat argument (default: false)
136
+ # # block => is there a block argument (default: false)
137
+ # # keep => whether to just keep the selector as passed
138
+ # # @return true or false, depending on the result
139
+ # def sends_message?(string, options={})
140
+ # options = {:args => 0, :splat => false,
141
+ # :block => false, :keep => false}.merge(options)
142
+ # unless options[:keep]
143
+ # string = string.to_s + options[:args].to_s +
144
+ # (options[:splat] ? '*' : '_') +
145
+ # (options[:block] ? '&' : '_')
146
+ # end
147
+ # !@_st_gsmeth.__source_offset_first_send_of(string.to_sym).nil?
148
+ # end
149
+
150
+ # def ==(other)
151
+ # false unless other === self.class
152
+ # in_class == other.in_class && name == other.name
153
+ # end
154
+ # end
@@ -0,0 +1,41 @@
1
+ require 'maglev/orderedcollection'
2
+
3
+ class Module
4
+ RubyNameSpace = __resolve_smalltalk_global(:RubyNameSpace)
5
+ RubyTransientNameSpace = __resolve_smalltalk_global(:RubyTransientNameSpace)
6
+
7
+ class RubyNameSpace
8
+ primitive 'parent', 'parent'
9
+ primitive 'my_class', 'myClass'
10
+ primitive 'keys', 'keys'
11
+ primitive 'values', 'values'
12
+ primitive '[]', 'at:'
13
+ end
14
+
15
+ class RubyTransientNameSpace < RubyNameSpace
16
+ primitive 'parent', 'parent'
17
+ primitive 'persistent_copy', 'persistentCopy'
18
+
19
+ def keys
20
+ super + (persistent_copy ? persistent_copy.keys : [])
21
+ end
22
+
23
+ def values
24
+ super.to_a + (persistent_copy ? persistent_copy.values.to_a : [])
25
+ end
26
+
27
+ def [](other)
28
+ super || (persistent_copy ? persistent_copy[other] : nil)
29
+ rescue Exception
30
+ nil
31
+ end
32
+ end
33
+
34
+ primitive '__transient_namespace', 'transientNameSpace:'
35
+ primitive 'singleton_class?', 'isRubySingletonClass'
36
+ primitive '__the_non_meta_class', 'theNonMetaClass'
37
+ primitive '__inst_var_names', 'instVarNames'
38
+ primitive '__compile_method_category_environment_id', 'compileMethod:category:environmentId:'
39
+ primitive '__compile_method_category_environment_id', 'compileMethod:category:environmentId:'
40
+ primitive '__subclasses', 'subclasses'
41
+ end
@@ -0,0 +1,4 @@
1
+ class Object
2
+ primitive '__inst_var_at', 'instVarAt:'
3
+ primitive '__inst_var_at_put', 'instVarAt:Put:'
4
+ end
@@ -0,0 +1,226 @@
1
+ require 'maglev/objectlog'
2
+
3
+ class Thread
4
+ VariableContext = __resolve_smalltalk_global(:VariableContext)
5
+ VariableContext.primitive '[]', 'at:'
6
+ VariableContext.primitive '[]=', 'at:put:'
7
+ VariableContext.primitive 'size', 'size'
8
+
9
+ # => GsNMethod
10
+ primitive '__method_at', 'methodAt:'
11
+ # => Fixnum
12
+ primitive '__stack_depth', 'stackDepth'
13
+ # Remove all frames above [Fixnum]
14
+ primitive '__trim_stack_to_level', '_trimStackToLevel:'
15
+ # Change temporary at level to value
16
+ primitive '__frame_at_temp_named_put', '_frameAt:tempNamed:put:'
17
+ # => Array
18
+ # with:
19
+ # 1 gsMethod
20
+ # 2 self
21
+ # 4 selector
22
+ # 5 quickStepPoint (offset into sourceOffsets)
23
+ # 6 sourceOffsets (the points where each step would be at)
24
+ # 7 argAndTempNames
25
+ # 8 argAndTempValues (maybe smaller or larger than argAndTempNames)
26
+ # 9 sourceString
27
+ # 10 ipOffset
28
+ # 11 markerOrException
29
+ primitive '__gsi_debugger_detailed_report_at', '_gsiDebuggerDetailedReportAt:'
30
+ # Stepping
31
+ primitive '__step_over_in_frame', '_stepOverInFrame:'
32
+ # Persistence conversions
33
+ primitive 'convert_to_persistable_state', "convertToPersistableState"
34
+ primitive 'convert_to_runnable_state', 'convertToRunnableState'
35
+ primitive '__ar_stack', 'arStack'
36
+ primitive '__client_data', '_clientData'
37
+ # Private. Returns an Array describing the specified level in the receiver.
38
+ # aLevel == 1 is top of stack. If aLevel is less than 1 or greater than
39
+ # stackDepth, returns nil.
40
+ # The result Array contains:
41
+ # offset item
42
+ # ----- -----
43
+ # 0 gsMethod
44
+ # 1 ipOffset
45
+ # 2 frameOffset (zero-based)
46
+ # 3 varContext
47
+ # 4 saveProtectedMode
48
+ # 5 markerOrException
49
+ # 6 nil (not used)
50
+ # 7 self (possibly nil in a ComplexBlock)
51
+ # 8 argAndTempNames (an Array of Symbols or Strings)
52
+ # 9 receiver
53
+ # 10 arguments and temps, if any
54
+ primitive '__frame_contents_at', '_frameContentsAt:'
55
+ class_primitive '__frame_contents_at', '_frameContentsAt:'
56
+ primitive '__run' , 'rubyRun'
57
+ primitive '__wakeup', 'rubyResume'
58
+ primitive '__value', 'value:'
59
+ primitive '_report', '_reportOfSize:'
60
+ primitive '__is_continuation', 'isContinuation'
61
+ primitive '__is_partial_continuation', 'isPartialContinuation'
62
+
63
+ class_primitive '__installPartialContinuation_atLevel_value', 'installPartialContinuation:atLevel:value:'
64
+ class_primitive '__partialContinuationFromLevel_to', 'partialContinuationFromLevel:to:'
65
+ end
66
+
67
+ # require 'maglev/objectlog'
68
+
69
+ # class Thread
70
+ # # => GsNMethod
71
+ # primitive '__method_at', 'methodAt:'
72
+ # # => Fixnum
73
+ # primitive '__stack_depth', 'stackDepth'
74
+ # # Remove all frames above [Fixnum]
75
+ # primitive '__trim_stack_to_level', '_trimStackToLevel:'
76
+ # # Change temporary at level to value
77
+ # primitive '__frame_at_temp_named_put', '_frameAt:tempNamed:put:'
78
+ # # => Array
79
+ # # with:
80
+ # # 1 gsMethod
81
+ # # 2 self
82
+ # # 4 selector
83
+ # # 5 quickStepPoint (offset into sourceOffsets)
84
+ # # 6 sourceOffsets (the points where each step would be at)
85
+ # # 7 argAndTempNames
86
+ # # 8 argAndTempValues (maybe smaller or larger than argAndTempNames)
87
+ # # 9 sourceString
88
+ # # 10 ipOffset
89
+ # # 11 markerOrException
90
+ # primitive '__gsi_debugger_detailed_report_at', '_gsiDebuggerDetailedReportAt:'
91
+ # # Stepping
92
+ # primitive '__step_over_in_frame', '_stepOverInFrame:'
93
+ # # Persistence conversions
94
+ # primitive 'convert_to_persistable_state', "convertToPersistableState"
95
+ # primitive 'convert_to_runnable_state', 'convertToRunnableState'
96
+ # primitive '__ar_stack', 'arStack'
97
+ # primitive '__client_data', '_clientData'
98
+ # # Private. Returns an Array describing the specified level in the receiver.
99
+ # # aLevel == 1 is top of stack. If aLevel is less than 1 or greater than
100
+ # # stackDepth, returns nil.
101
+ # # The result Array contains:
102
+ # # offset item
103
+ # # ----- -----
104
+ # # 0 gsMethod
105
+ # # 1 ipOffset
106
+ # # 2 frameOffset (zero-based)
107
+ # # 3 varContext
108
+ # # 4 saveProtectedMode
109
+ # # 5 markerOrException
110
+ # # 6 nil (not used)
111
+ # # 7 self (possibly nil in a ComplexBlock)
112
+ # # 8 argAndTempNames (an Array of Symbols or Strings)
113
+ # # 9 receiver
114
+ # # 10 arguments and temps, if any
115
+ # primitive '__frame_contents_at', '_frameContentsAt:'
116
+ # primitive '__run' , 'rubyRun'
117
+ # primitive '__wakeup', 'rubyResume'
118
+ # primitive '__value', 'value:'
119
+
120
+ # # Resuming a continuation is only possible through this method
121
+ # def run_callcc(ret_val = nil)
122
+ # __value(ret_val)
123
+ # end
124
+
125
+ # def run
126
+ # if in_persistable_state?
127
+ # raise RuntimeError, "You have to call #resume_continuation on the ObjectLogEntry for this Thread"
128
+ # end
129
+ # __run
130
+ # end
131
+
132
+ # def wakeup
133
+ # if in_persistable_state?
134
+ # raise RuntimeError, "You have to call #resume_continuation on the ObjectLogEntry for this Thread"
135
+ # end
136
+ # __wakeup
137
+ # end
138
+
139
+ # # Simple check whether the thread looks like as if it is in a persistable (i.e.
140
+ # # non-runnable) state
141
+ # def in_persistable_state?
142
+ # return true if thread_data.nil?
143
+ # thread_data.collect(&:class).collect(&:name).include? :RubyPersistableCompilerState
144
+ # end
145
+
146
+ # # Saves the Thread to the ObjectLog.
147
+ # #
148
+ # # @param [String] message the message under which to save the entry,
149
+ # # defaults to inspect and timestamp
150
+ # # @param [Boolean] force_commit whether or not to force a commit.
151
+ # # Defaults to nil, which means it'll commit if the session is clean or raise
152
+ # # an error. Pass true to forcibly abort and commit only the log entry, pass
153
+ # # false to only commit if the session is clean.
154
+ # # @return [DebuggerLogEntry] the saved entry
155
+ # # @raise [RuntimeError] raised if the session is dirty but no force_commit
156
+ # # option has been passed
157
+ # def save(message = nil, force_commit = nil)
158
+ # if Maglev.needs_commit and force_commit.nil?
159
+ # raise RuntimeError, "Saving exception to ObjectLog, discarding transaction"
160
+ # end
161
+ # message ||= "#{inspect}-#{DateTime.now}"
162
+ # Maglev.abort_transaction if force_commit || !Maglev.needs_commit
163
+ # DebuggerLogEntry.create_continuation_labeled(message)
164
+ # Maglev.commit_transaction if force_commit || !Maglev.needs_commit
165
+ # self
166
+ # end
167
+
168
+ # # Remove Thread from ObjectLog
169
+ # def delete
170
+ # if Maglev::System.needs_commit
171
+ # raise Exception, "Abort would loose data. Commit your data and try again"
172
+ # end
173
+ # Maglev.abort_transaction
174
+ # ObjectLogEntry.object_log.delete(@log_entry)
175
+ # Maglev.commit_transaction
176
+ # end
177
+
178
+ # def stack
179
+ # self.__stack_depth.times.collect do |idx|
180
+ # Frame.new(self.__method_at(idx + 1), idx + 1, self)
181
+ # end
182
+ # end
183
+
184
+ # def step(symbol = :over)
185
+ # case symbol
186
+ # when :into
187
+ # self.__step_over_in_frame(0)
188
+ # when :over
189
+ # self.__step_over_in_frame(1)
190
+ # when :through
191
+ # raise NotImplementedError, "not implemented yet"
192
+ # when Fixnum
193
+ # self.__step_over_in_frame(symbol)
194
+ # end
195
+ # end
196
+
197
+ # primitive '_report', '_reportOfSize:'
198
+ # def report(depth = self.__stack_depth)
199
+ # _report(depth)
200
+ # end
201
+
202
+ # # The list of saved threads in the ObjectLog
203
+ # def self.saved_errors
204
+ # ObjectLog.errors
205
+ # end
206
+
207
+ # def raw_stack
208
+ # self.__ar_stack || begin # Force data into cache, if neccessary
209
+ # self.stack
210
+ # self.__ar_stack
211
+ # end
212
+ # end
213
+
214
+ # def thread_data
215
+ # self.__client_data
216
+ # end
217
+
218
+ # def compiler_state
219
+ # self.__client_data.first
220
+ # end
221
+
222
+ # VariableContext = __resolve_smalltalk_global(:VariableContext)
223
+ # VariableContext.primitive '[]', 'at:'
224
+ # VariableContext.primitive '[]=', 'at:put:'
225
+ # VariableContext.primitive 'size', 'size'
226
+ # end