rubymirrors 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,7 +16,7 @@ module AbstractReflection
16
16
  def defining_class
17
17
  raise CapabilitiesExceeded
18
18
  end
19
-
19
+
20
20
  # @return [String] The source code of this method
21
21
  def source
22
22
  raise CapabilitiesExceeded
@@ -39,7 +39,7 @@ module AbstractReflection
39
39
 
40
40
  # Queries the method for it's arguments and returns a list of
41
41
  # mirrors that hold name and value information.
42
- #
42
+ #
43
43
  # @return [Array<FieldMirror>]
44
44
  def arguments
45
45
  raise CapabilitiesExceeded
@@ -1,4 +1,5 @@
1
1
  require 'maglev/reflection/core_ext/module'
2
+ require 'maglev/reflection/core_ext/class'
2
3
 
3
4
  module Maglev
4
5
  class Reflection
@@ -0,0 +1,3 @@
1
+ class Class
2
+ primitive '__subclasses', '_subclasses'
3
+ end
@@ -0,0 +1,3 @@
1
+ class Exception
2
+ primitive '__resume', 'resume:'
3
+ end
@@ -15,9 +15,14 @@ class GsNMethod
15
15
  primitive '__ip_steps', '_ipSteps'
16
16
  primitive '__opcode_info_at', '_opcodeInfoAt:'
17
17
  primitive '__in_class', 'inClass'
18
+ primitive '__all_breakpoints_source_offsets', '_allBreakpointsSourceOffsets'
19
+ primitive '__set_break_at', 'setBreakAtStepPoint:'
20
+ primitive '__clear_break_at', 'clearBreakAtStepPoint:'
18
21
  end
19
22
 
20
23
  class UnboundMethod
24
+ primitive '__nonbridge_meth', '_nonBridgeMeth'
25
+
21
26
  def __st_gsmeth
22
27
  @_st_gsmeth
23
28
  end
@@ -37,5 +37,4 @@ class Module
37
37
  primitive '__inst_var_names', 'instVarNames'
38
38
  primitive '__compile_method_category_environment_id', 'compileMethod:category:environmentId:'
39
39
  primitive '__compile_method_category_environment_id', 'compileMethod:category:environmentId:'
40
- primitive '__subclasses', 'subclasses'
41
40
  end
@@ -0,0 +1,21 @@
1
+ require File.expand_path("../method.rb", __FILE__)
2
+ require File.expand_path("../thread.rb", __FILE__)
3
+
4
+ class ExecBlock
5
+ primitive 'shift', 'shift'
6
+ primitive 'reset', 'reset'
7
+ end
8
+
9
+ class Proc
10
+ def __shift
11
+ @_st_block.shift
12
+ end
13
+
14
+ def __reset
15
+ @_st_block.reset
16
+ end
17
+ end
18
+
19
+ class Thread
20
+ primitive 'call', 'call:'
21
+ end
@@ -13,7 +13,8 @@ class Thread
13
13
  # Remove all frames above [Fixnum]
14
14
  primitive '__trim_stack_to_level', '_trimStackToLevel:'
15
15
  # Change temporary at level to value
16
- primitive '__frame_at_temp_named_put', '_frameAt:tempNamed:put:'
16
+ primitive '__frame_at_temp_at_put', '_frameAt:tempAt:put:'
17
+ primitive '__frame_at_offset_of_temp_named', '_frameAt:offsetOfTempNamed:'
17
18
  # => Array
18
19
  # with:
19
20
  # 1 gsMethod
@@ -33,7 +34,7 @@ class Thread
33
34
  primitive 'convert_to_persistable_state', "convertToPersistableState"
34
35
  primitive 'convert_to_runnable_state', 'convertToRunnableState'
35
36
  primitive '__ar_stack', 'arStack'
36
- primitive '__client_data', '_clientData'
37
+ primitive '__client_data', 'clientData'
37
38
  # Private. Returns an Array describing the specified level in the receiver.
38
39
  # aLevel == 1 is top of stack. If aLevel is less than 1 or greater than
39
40
  # stackDepth, returns nil.
@@ -62,6 +63,12 @@ class Thread
62
63
 
63
64
  class_primitive '__installPartialContinuation_atLevel_value', 'installPartialContinuation:atLevel:value:'
64
65
  class_primitive '__partialContinuationFromLevel_to', 'partialContinuationFromLevel:to:'
66
+
67
+ # Re-add behavior which was removed in GS 3.1.0.1
68
+ def __frame_at_temp_named_put(frameidx, tempname, value)
69
+ offset = __frame_at_offset_of_temp_named(frameidx, tempname)
70
+ __frame_at_temp_at_put(frameidx, offset, value)
71
+ end
65
72
  end
66
73
 
67
74
  # require 'maglev/objectlog'
@@ -1,4 +1,5 @@
1
1
  require 'maglev/reflection/core_ext/module'
2
+ require 'maglev/reflection/core_ext/class'
2
3
 
3
4
  module Maglev
4
5
  class Reflection
@@ -113,7 +113,29 @@ module Maglev
113
113
  gsmeth.__in_class.remove_method(selector)
114
114
  end
115
115
 
116
+ def breakpoints
117
+ gsmeth.__all_breakpoints_source_offsets
118
+ end
119
+
120
+ def break(source_offset = 1)
121
+ step_point = find_step_point_just_before(source_offset)
122
+ if gsmeth.__is_method_for_block
123
+ gsmeth.__set_break_at_step_point(step_point)
124
+ else
125
+ @subject.__nonbridge_meth.__set_break_at_step_point(step_point)
126
+ end
127
+ end
128
+
129
+ def clear_break(source_offset)
130
+ gsmeth.__clear_break_at(find_step_point_just_before(source_offset))
131
+ end
132
+
116
133
  private
134
+ def find_step_point_just_before(source_offset)
135
+ nxt = step_offsets.detect {|o| o > source_offset }
136
+ [step_offsets.index(nxt) - 1, 1].max
137
+ end
138
+
117
139
  def wrap_gsmeth(gsmethod)
118
140
  label = gsmethod.__name.to_s
119
141
  cls = gsmethod.__in_class
@@ -0,0 +1,50 @@
1
+ class PartialContinuation
2
+ attr_accessor :markerBlock, :partial
3
+
4
+ def self.currentDomarkerBlock(block, markerBlock)
5
+ if (marker = markerBlock.call).nil?
6
+ raise RuntimeError, 'Marker not found when capturing partial continuation.'
7
+ end
8
+ return block.call to_offset_markerBlock(marker, 1, markerBlock)
9
+ end
10
+
11
+ def self.to_offset_markerBlock(method, offset, &block)
12
+ idx = find_frame_for(method)
13
+ partial = Thread.__partialContinuationFromLevel_to(3 + offset, idx)
14
+ new.tap do |o|
15
+ o.partial = partial
16
+ o.markerBlock = block
17
+ end
18
+ end
19
+
20
+ def self.find_frame_for(method)
21
+ index = 1
22
+ while frame = Thread.current.__frame_contents_at(index) do
23
+ if frame[0] == method
24
+ return level
25
+ else
26
+ level += 1
27
+ end
28
+ end
29
+ nil
30
+ end
31
+
32
+ def call(arg = nil)
33
+ marker = markerBlock.call
34
+ if marker.nil?
35
+ marker = Thread.current.__frame_contents_at(2).first
36
+ frameIndex = 2
37
+ else
38
+ frameIndex = self.class.find_frame_for marker
39
+ end
40
+ Thread.current.__installPartialContinuation_atLevel_value partial, frameIndex, arg
41
+ end
42
+
43
+ alias [] call
44
+ end
45
+
46
+ def test_callcc
47
+ PartialContinuation.currentDomarkerBlock
48
+ currentDo: aBlock
49
+ markerBlock: [ self callbackMarker ]
50
+ end
@@ -23,7 +23,7 @@ module Ruby
23
23
  end
24
24
 
25
25
  def line
26
- source_location.last
26
+ source_location.last - 1
27
27
  end
28
28
 
29
29
  def line=(num)
@@ -77,6 +77,25 @@ module Ruby
77
77
 
78
78
  def source
79
79
  try_send(:source) or raise(CapabilitiesExceeded)
80
+ rescue => e
81
+ e.message
82
+ end
83
+
84
+ def source=(str)
85
+ src = try_send(:source)
86
+ raise "cannot write to source location" unless file and line and File.writable?(file)
87
+
88
+ f = File.read(file).lines.to_a
89
+ srclen = src.lines.to_a.size
90
+ prefix = f[0...line].join
91
+ method_src = f[line...line + srclen].join
92
+ postfix = f[line + srclen..-1].join
93
+ raise "source differs from runtime" unless method_src.strip == src.strip
94
+
95
+ File.open(file, 'w') {|f| f << prefix << str << postfix }
96
+ defining_class.reflectee.class_eval(str, file, line)
97
+ rescue Exception => e
98
+ raise CapabilitiesExceeded, e.message
80
99
  end
81
100
 
82
101
  def step_offsets
@@ -90,10 +109,14 @@ module Ruby
90
109
 
91
110
  offsets = [0]
92
111
  sends.each do |name|
93
- offsets << (source[offsets.last..-1] =~ /#{Regexp.escape(name)}/)
112
+ next_offset = source[offsets.last..-1] =~ /#{Regexp.escape(name)}/
113
+ break unless next_offset
114
+ offsets << next_offset
94
115
  end
95
116
  offsets.shift
96
117
  Hash[*sends.zip(offsets).flatten]
118
+ rescue Exception
119
+ return {}
97
120
  end
98
121
 
99
122
  private
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rubymirrors"
3
- s.version = "0.0.1"
3
+ s.version = "0.0.2"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.authors = ["Tim Felgentreff"]
6
6
  s.email = ["timfelgentreff@gmail.com"]
metadata CHANGED
@@ -1,64 +1,85 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rubymirrors
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Tim Felgentreff
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-11-10 00:00:00 Z
12
+ date: 2012-10-25 00:00:00.000000000 Z
19
13
  dependencies: []
14
+ description: ! '## A mirror API for Ruby
15
+
20
16
 
21
- description: |
22
- ## A mirror API for Ruby
23
-
24
17
  In various [research][p1] [projects][p2] the advantages of having a [mirror
18
+
25
19
  API][p3] to separate reflection from a language implementation have
20
+
26
21
  been discussed, and "industry grade" implementations exist for
22
+
27
23
  [Java][p4] and [C#][p5]. This project aims at providing a number of
24
+
28
25
  specs and classes that document a mirror API for Ruby. The mirror
26
+
29
27
  implementation that is part of this project will use only those
28
+
30
29
  language facilities that are available across Ruby implementations.
30
+
31
31
  The specs, however, will also test behavior that cannot be provided in
32
+
32
33
  such a manner. The idea here is that in time, all implementations
34
+
33
35
  provide their own implementation of the mirror API, and all
36
+
34
37
  implementations collaborate on this one spec.
35
-
38
+
39
+
36
40
  Why do this, you ask? Because Ruby needs tools, and those tools need
41
+
37
42
  to be written in Ruby. If they are not, then people will be excluded from
43
+
38
44
  tinkering with their tools, thus impeding innovation. You only have to
39
- look at Emacs or Smalltalk to see what's possible when programmers can
45
+
46
+ look at Emacs or Smalltalk to see what''s possible when programmers can
47
+
40
48
  extend their tools, all tools, in a language they feel comfortable
49
+
41
50
  in. If we have a standard mirror API, all tools that are written **for**
51
+
42
52
  Ruby, **in** Ruby, can be shared across implementations, while at the same time
53
+
43
54
  allowing language implementers to use the facilities of their platform
55
+
44
56
  to provide optimal reflective capabilities without tying them to
57
+
45
58
  internals.
46
-
47
- [p1]: http://www.cs.virginia.edu/~lorenz/papers/icse03/icse2003.pdf "Pluggable Reflection: Decoupling Meta-Interface and Implementation"
48
- [p2]: http://bracha.org/newspeak-spec.pdf "Newspeak Programming Language Draft Specification, Version 0.06, pages 40 onward"
49
- [p3]: http://www.hpi.uni-potsdam.de/hirschfeld/events/past/media/100105_Bracha_2010_LinguisticReflectionViaMirrors_HPI.mp4 "Linguistic Reflection Via Mirrors"
50
- [p4]: http://bracha.org/mirrors.pdf "Mirrors: Design Principles for Meta-level Facilities of Object-Oriented Programming Languages"
51
- [p5]: http://oreilly.com/catalog/progcsharp/chapter/ch18.html "See esp. 18-3, highlighting how C# reflection works on assembly rather than VM objects"
52
-
53
- email:
59
+
60
+
61
+ [p1]: http://www.cs.virginia.edu/~lorenz/papers/icse03/icse2003.pdf "Pluggable Reflection:
62
+ Decoupling Meta-Interface and Implementation"
63
+
64
+ [p2]: http://bracha.org/newspeak-spec.pdf "Newspeak Programming Language Draft Specification,
65
+ Version 0.06, pages 40 onward"
66
+
67
+ [p3]: http://www.hpi.uni-potsdam.de/hirschfeld/events/past/media/100105_Bracha_2010_LinguisticReflectionViaMirrors_HPI.mp4
68
+ "Linguistic Reflection Via Mirrors"
69
+
70
+ [p4]: http://bracha.org/mirrors.pdf "Mirrors: Design Principles for Meta-level Facilities
71
+ of Object-Oriented Programming Languages"
72
+
73
+ [p5]: http://oreilly.com/catalog/progcsharp/chapter/ch18.html "See esp. 18-3, highlighting
74
+ how C# reflection works on assembly rather than VM objects"
75
+
76
+ '
77
+ email:
54
78
  - timfelgentreff@gmail.com
55
79
  executables: []
56
-
57
80
  extensions: []
58
-
59
81
  extra_rdoc_files: []
60
-
61
- files:
82
+ files:
62
83
  - Gemfile
63
84
  - README.md
64
85
  - Rakefile
@@ -74,11 +95,14 @@ files:
74
95
  - lib/abstract_reflection/thread_mirror.rb
75
96
  - lib/maglev/reflection.rb
76
97
  - lib/maglev/reflection/class_mirror.rb
98
+ - lib/maglev/reflection/core_ext/class.rb
77
99
  - lib/maglev/reflection/core_ext/class_organizer.rb
100
+ - lib/maglev/reflection/core_ext/exception.rb
78
101
  - lib/maglev/reflection/core_ext/maglev.rb
79
102
  - lib/maglev/reflection/core_ext/method.rb
80
103
  - lib/maglev/reflection/core_ext/module.rb
81
104
  - lib/maglev/reflection/core_ext/object.rb
105
+ - lib/maglev/reflection/core_ext/proc.rb
82
106
  - lib/maglev/reflection/core_ext/thread.rb
83
107
  - lib/maglev/reflection/field_mirror.rb
84
108
  - lib/maglev/reflection/field_mirror/fixed_instance_variable_mirror.rb
@@ -86,6 +110,7 @@ files:
86
110
  - lib/maglev/reflection/mirror.rb
87
111
  - lib/maglev/reflection/object_mirror.rb
88
112
  - lib/maglev/reflection/stack_frame_mirror.rb
113
+ - lib/maglev/reflection/support/partial_continuation.rb
89
114
  - lib/maglev/reflection/thread_mirror.rb
90
115
  - lib/rubinius/reflection.rb
91
116
  - lib/ruby/reflection.rb
@@ -120,40 +145,29 @@ files:
120
145
  - spec/thread_spec.rb
121
146
  homepage:
122
147
  licenses: []
123
-
124
- metadata: {}
125
-
126
148
  post_install_message:
127
149
  rdoc_options: []
128
-
129
- require_paths:
150
+ require_paths:
130
151
  - lib
131
- required_ruby_version: !ruby/object:Gem::Requirement
152
+ required_ruby_version: !ruby/object:Gem::Requirement
132
153
  none: false
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- hash: 3
137
- segments:
138
- - 0
139
- version: "0"
140
- required_rubygems_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
159
  none: false
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- hash: 3
146
- segments:
147
- - 0
148
- version: "0"
160
+ requirements:
161
+ - - ! '>='
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
149
164
  requirements: []
150
-
151
165
  rubyforge_project:
152
- rubygems_version: 1.8.10
166
+ rubygems_version: 1.8.23
153
167
  signing_key:
154
- specification_version: 4
168
+ specification_version: 3
155
169
  summary: Mirror API for Ruby
156
- test_files:
170
+ test_files:
157
171
  - spec/class_spec.rb
158
172
  - spec/field_spec.rb
159
173
  - spec/fixtures/class_spec.rb