rubymirrors 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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