ruby-internal 0.8.2 → 0.8.3
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.
- data/{README → README.rdoc} +1 -38
- metadata +3 -27
- data/lib/internal/method/as_code.rb +0 -58
- data/lib/internal/method/as_expression.rb +0 -33
- data/lib/internal/method/origin.rb +0 -29
- data/lib/internal/method/signature.rb +0 -147
- data/lib/internal/method/signature/argument.rb +0 -102
- data/lib/internal/method/signature/iseq.rb +0 -52
- data/lib/internal/method/signature/node.rb +0 -160
- data/lib/internal/method/signature/signature.rb +0 -23
- data/lib/internal/module/as_code.rb +0 -45
- data/lib/internal/node/as_code.rb +0 -233
- data/lib/internal/node/as_expression.rb +0 -619
- data/lib/internal/proc/as_code.rb +0 -23
- data/lib/internal/proc/as_expression.rb +0 -16
- data/lib/internal/proc/signature.rb +0 -184
- data/lib/internal/vm/bytedecoder.rb +0 -866
- data/lib/internal/vm/iseq/as_code.rb +0 -27
- data/lib/internal/vm/iseq/as_expression.rb +0 -26
- data/test/expression_samples.rb +0 -160
- data/test/test_as_code.rb +0 -261
- data/test/test_as_expression.rb +0 -229
- data/test/test_methodsig.rb +0 -267
data/{README → README.rdoc}
RENAMED
@@ -86,43 +86,6 @@ And view class hierarchies:
|
|
86
86
|
+-class = Kernel
|
87
87
|
=> nil
|
88
88
|
|
89
|
-
View method signatures:
|
90
|
-
|
91
|
-
irb(main):015:0> def foo(a, b, *rest, &block); end; method(:foo).signature
|
92
|
-
=> #<MethodSig::Signature:0x4037093c @origin_class=Object, @arg_info={:b=>"b",
|
93
|
-
:block=>"&block", :a=>"a", :rest=>"*rest"}, @name="foo", @arg_names=[:a,
|
94
|
-
:b, :rest, :block]>
|
95
|
-
irb(main):016:0> proc { |x, y, *rest| }.signature
|
96
|
-
=> #<Proc::Signature:0x4036cf30 @args=#<Proc::Arguments:0x4036d020 @rest_arg=2,
|
97
|
-
@multiple_assignment=true, @names=[:x, :y, :rest]>, @arg_info={:x=>"x", :y=>"y",
|
98
|
-
:rest=>"*rest"}>
|
99
|
-
|
100
|
-
And reconstruct compiled methods:
|
101
|
-
|
102
|
-
irb(main):001:0> def foo(a, b, *rest, &block)
|
103
|
-
irb(main):002:1> begin
|
104
|
-
irb(main):003:2* if not a and not b then
|
105
|
-
irb(main):004:3* raise "Need more input!"
|
106
|
-
irb(main):005:3> end
|
107
|
-
irb(main):006:2> return a + b
|
108
|
-
irb(main):007:2> ensure
|
109
|
-
irb(main):008:2* puts "In ensure block"
|
110
|
-
irb(main):009:2> end
|
111
|
-
irb(main):010:1> end
|
112
|
-
=> nil
|
113
|
-
irb(main):011:0> m = method(:foo)
|
114
|
-
=> #<Method: Object#foo>
|
115
|
-
irb(main):012:0> puts m.as_code
|
116
|
-
def foo(a, b, *rest, &block)
|
117
|
-
begin
|
118
|
-
(raise("Need more input!")) if (not a and not b)
|
119
|
-
return a + b
|
120
|
-
ensure
|
121
|
-
puts("In ensure block")
|
122
|
-
end
|
123
|
-
end
|
124
|
-
=> nil
|
125
|
-
|
126
89
|
== YARV support
|
127
90
|
|
128
91
|
Yes, ruby-internal works with YARV, too. The difference when using YARV
|
@@ -186,7 +149,7 @@ iterate over the bytecode sequence:
|
|
186
149
|
#<VM::Instruction::LEAVE:0x40411e24 @operands=[]> 1 []
|
187
150
|
=> nil
|
188
151
|
|
189
|
-
then decompile it:
|
152
|
+
then decompile it (using ruby-decompiler):
|
190
153
|
|
191
154
|
irb(main):005:0> require 'as_expression'
|
192
155
|
=> true
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-internal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -39,34 +39,21 @@ executables:
|
|
39
39
|
extensions:
|
40
40
|
- Rakefile
|
41
41
|
extra_rdoc_files:
|
42
|
-
- README
|
42
|
+
- README.rdoc
|
43
43
|
files:
|
44
44
|
- lib/internal/node/to_a.rb
|
45
|
-
- lib/internal/node/as_code.rb
|
46
45
|
- lib/internal/node/obfusc.rb
|
47
46
|
- lib/internal/node/dump.rb
|
48
47
|
- lib/internal/node/pp.rb
|
49
|
-
- lib/internal/node/as_expression.rb
|
50
48
|
- lib/internal/module.rb
|
51
49
|
- lib/internal/proc.rb
|
52
50
|
- lib/internal/binding.rb
|
53
51
|
- lib/internal/vm/inline_cache.rb
|
54
|
-
- lib/internal/vm/iseq/as_code.rb
|
55
|
-
- lib/internal/vm/iseq/as_expression.rb
|
56
52
|
- lib/internal/vm/instruction.rb
|
57
53
|
- lib/internal/vm/iseq.rb
|
58
54
|
- lib/internal/vm/control_frame.rb
|
59
|
-
- lib/internal/vm/bytedecoder.rb
|
60
55
|
- lib/internal/vm/constants.rb
|
61
56
|
- lib/internal/object.rb
|
62
|
-
- lib/internal/method/origin.rb
|
63
|
-
- lib/internal/method/signature.rb
|
64
|
-
- lib/internal/method/signature/signature.rb
|
65
|
-
- lib/internal/method/signature/argument.rb
|
66
|
-
- lib/internal/method/signature/iseq.rb
|
67
|
-
- lib/internal/method/signature/node.rb
|
68
|
-
- lib/internal/method/as_code.rb
|
69
|
-
- lib/internal/method/as_expression.rb
|
70
57
|
- lib/internal/vm.rb
|
71
58
|
- lib/internal/object/as_code.rb
|
72
59
|
- lib/internal/thread.rb
|
@@ -75,10 +62,6 @@ files:
|
|
75
62
|
- lib/internal/obfusc.rb
|
76
63
|
- lib/internal/debug.rb
|
77
64
|
- lib/internal/tag.rb
|
78
|
-
- lib/internal/module/as_code.rb
|
79
|
-
- lib/internal/proc/signature.rb
|
80
|
-
- lib/internal/proc/as_code.rb
|
81
|
-
- lib/internal/proc/as_expression.rb
|
82
65
|
- lib/internal/method.rb
|
83
66
|
- lib/internal/node.rb
|
84
67
|
- ext/mkmf-ruby-internal.rb
|
@@ -344,17 +327,13 @@ files:
|
|
344
327
|
- example/simple_client.rb
|
345
328
|
- example/triangle_client.rb
|
346
329
|
- example/README
|
347
|
-
- test/test_methodsig.rb
|
348
330
|
- test/test_dump_method.rb
|
349
331
|
- test/test_dump_proc.rb
|
350
332
|
- test/test_proc.rb
|
351
333
|
- test/test_helpers.rb
|
352
334
|
- test/test_method.rb
|
353
|
-
- test/test_as_code.rb
|
354
335
|
- test/node_samples.rb
|
355
336
|
- test/test_node.rb
|
356
|
-
- test/expression_samples.rb
|
357
|
-
- test/test_as_expression.rb
|
358
337
|
- test/test_module.rb
|
359
338
|
- test/test_dump_class.rb
|
360
339
|
- pre-install.rb
|
@@ -370,7 +349,7 @@ files:
|
|
370
349
|
- COPYING
|
371
350
|
- LGPL
|
372
351
|
- LICENSE
|
373
|
-
- README
|
352
|
+
- README.rdoc
|
374
353
|
- TODO
|
375
354
|
- metaconfig
|
376
355
|
- Rakefile
|
@@ -404,14 +383,11 @@ signing_key:
|
|
404
383
|
specification_version: 3
|
405
384
|
summary: A library that provides acccess to the internals of the ruby interpreter
|
406
385
|
test_files:
|
407
|
-
- test/test_methodsig.rb
|
408
386
|
- test/test_dump_method.rb
|
409
387
|
- test/test_dump_proc.rb
|
410
388
|
- test/test_proc.rb
|
411
389
|
- test/test_helpers.rb
|
412
390
|
- test/test_method.rb
|
413
|
-
- test/test_as_code.rb
|
414
391
|
- test/test_node.rb
|
415
|
-
- test/test_as_expression.rb
|
416
392
|
- test/test_module.rb
|
417
393
|
- test/test_dump_class.rb
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'internal/node/as_code'
|
2
|
-
require 'internal/vm/iseq/as_code'
|
3
|
-
require 'internal/method'
|
4
|
-
require 'internal/method/signature'
|
5
|
-
|
6
|
-
module MethodAsCode
|
7
|
-
# Returns a string representation of the method definition/body.
|
8
|
-
#
|
9
|
-
# irb(main):001:0> def foo(a, b, *rest, &block)
|
10
|
-
# irb(main):002:1> begin
|
11
|
-
# irb(main):003:2* if not a and not b then
|
12
|
-
# irb(main):004:3* raise "Need more input!"
|
13
|
-
# irb(main):005:3> end
|
14
|
-
# irb(main):006:2> return a + b
|
15
|
-
# irb(main):007:2> ensure
|
16
|
-
# irb(main):008:2* puts "In ensure block"
|
17
|
-
# irb(main):009:2> end
|
18
|
-
# irb(main):010:1> end
|
19
|
-
# => nil
|
20
|
-
# irb(main):011:0> m = method(:foo)
|
21
|
-
# => #<Method: Object#foo>
|
22
|
-
# irb(main):012:0> puts m.as_code
|
23
|
-
# def foo(a, b, *rest, &block)
|
24
|
-
# begin
|
25
|
-
# (raise("Need more input!")) if (not a and not b)
|
26
|
-
# return a + b
|
27
|
-
# ensure
|
28
|
-
# puts("In ensure block")
|
29
|
-
# end
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
def as_code(indent=0, name=nil)
|
33
|
-
sig = self.signature
|
34
|
-
if self.body.respond_to?(:body) then
|
35
|
-
# YARV
|
36
|
-
body_expression = self.body.body.as_code(indent+1)
|
37
|
-
else
|
38
|
-
# pre-YARV
|
39
|
-
body_expression = self.body ? self.body.as_code(indent+1) : ''
|
40
|
-
end
|
41
|
-
name ||= sig.name
|
42
|
-
s = "#{' '*indent}def #{name}(#{sig.param_list})\n"
|
43
|
-
if body_expression then
|
44
|
-
s += "#{body_expression}\n"
|
45
|
-
end
|
46
|
-
s += "#{' '*indent}end"
|
47
|
-
return s
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
class Method
|
52
|
-
include MethodAsCode
|
53
|
-
end
|
54
|
-
|
55
|
-
class UnboundMethod
|
56
|
-
include MethodAsCode
|
57
|
-
end
|
58
|
-
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require 'internal/node/as_expression'
|
2
|
-
require 'internal/vm/iseq/as_expression'
|
3
|
-
require 'internal/method/signature'
|
4
|
-
require 'internal/method'
|
5
|
-
|
6
|
-
module MethodAsExpression
|
7
|
-
# Return a single-line string representation of a method
|
8
|
-
# TODO: this method would be more aptly named "as_expression_string".
|
9
|
-
def as_expression
|
10
|
-
sig = self.signature
|
11
|
-
if self.body.respond_to?(:body) then
|
12
|
-
# YARV
|
13
|
-
body_expression = self.body.body.as_expression
|
14
|
-
else
|
15
|
-
# pre-YARV
|
16
|
-
body_expression = self.body.as_expression
|
17
|
-
end
|
18
|
-
if body_expression then
|
19
|
-
return "def #{sig.name}(#{sig.param_list}); #{body_expression}; end"
|
20
|
-
else
|
21
|
-
return "def #{sig.name}(#{sig.param_list}); end"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
class Method
|
27
|
-
include MethodAsExpression
|
28
|
-
end
|
29
|
-
|
30
|
-
class UnboundMethod
|
31
|
-
include MethodAsExpression
|
32
|
-
end
|
33
|
-
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module MethodOrigin
|
2
|
-
# An abstraction for a method origin.
|
3
|
-
class Origin
|
4
|
-
attr_reader :file, :line
|
5
|
-
|
6
|
-
def initialize(file, line)
|
7
|
-
@file = file
|
8
|
-
@line = line
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_s
|
12
|
-
return "#{file}:#{line}"
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
# Return a Method::Origin representing where the method was defined.
|
17
|
-
def origin
|
18
|
-
block = body().next
|
19
|
-
return Origin.new(block.nd_file, block.nd_line)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
class Method
|
24
|
-
include MethodOrigin
|
25
|
-
end
|
26
|
-
|
27
|
-
class UnboundMethod
|
28
|
-
include MethodOrigin
|
29
|
-
end
|
@@ -1,147 +0,0 @@
|
|
1
|
-
require 'internal/method'
|
2
|
-
require 'internal/node'
|
3
|
-
require 'internal/node/as_expression'
|
4
|
-
require 'internal/method/signature/argument'
|
5
|
-
require 'internal/method/signature/node'
|
6
|
-
require 'internal/method/signature/signature'
|
7
|
-
|
8
|
-
if defined?(RubyVM) then
|
9
|
-
require 'internal/vm/bytedecoder'
|
10
|
-
require 'internal/method/signature/iseq'
|
11
|
-
end
|
12
|
-
|
13
|
-
module MethodSig
|
14
|
-
# Return the names of the local variables of this method.
|
15
|
-
def local_vars
|
16
|
-
return self.body.local_vars
|
17
|
-
end
|
18
|
-
|
19
|
-
# Return the names of the arguments this method takes, in the order in
|
20
|
-
# which they appear in the argument list.
|
21
|
-
def argument_names
|
22
|
-
return self.body.argument_names
|
23
|
-
end
|
24
|
-
|
25
|
-
def args_node
|
26
|
-
return self.body.args_node
|
27
|
-
end
|
28
|
-
private :args_node
|
29
|
-
|
30
|
-
# If this method has a "rest" argument, that is, it has an argument
|
31
|
-
# that is preceded by an asterisk (*) in the argument list, then
|
32
|
-
# return its index, otherwise return nil.
|
33
|
-
def rest_arg
|
34
|
-
return self.body.rest_arg
|
35
|
-
end
|
36
|
-
|
37
|
-
# If this method has a "block" argument, that is, it has an argument
|
38
|
-
# that is preceded by an ampersand (&) in the argument list, then
|
39
|
-
# return its index, otherwise return nil.
|
40
|
-
def block_arg
|
41
|
-
return self.body.block_arg
|
42
|
-
end
|
43
|
-
|
44
|
-
def set_optional_args(args, args_node, names)
|
45
|
-
self.body.set_optional_args(args, args_node, names)
|
46
|
-
end
|
47
|
-
private :set_optional_args
|
48
|
-
|
49
|
-
# Return a hash mapping each argument name to a description of that
|
50
|
-
# argument.
|
51
|
-
def arguments
|
52
|
-
names = self.argument_names()
|
53
|
-
block_arg = self.block_arg()
|
54
|
-
|
55
|
-
args = {}
|
56
|
-
names.each do |name|
|
57
|
-
args[name] = Argument.new(name, false, false)
|
58
|
-
end
|
59
|
-
|
60
|
-
# Optional args
|
61
|
-
args_node = args_node()
|
62
|
-
set_optional_args(args, args_node, names)
|
63
|
-
|
64
|
-
# Rest arg
|
65
|
-
if self.rest_arg then
|
66
|
-
rest_name = names[rest_arg]
|
67
|
-
args[rest_name] = Argument.new(rest_name, true, false)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Block arg
|
71
|
-
if block_arg then
|
72
|
-
block_name = names[block_arg]
|
73
|
-
args[block_name] = Argument.new(block_name, false, true)
|
74
|
-
end
|
75
|
-
|
76
|
-
return args
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
class Method
|
81
|
-
include MethodSig
|
82
|
-
|
83
|
-
# Return a String representing the method's signature.
|
84
|
-
def signature
|
85
|
-
return Signature.new(
|
86
|
-
attached_class(),
|
87
|
-
method_oid().to_s,
|
88
|
-
argument_names(),
|
89
|
-
arguments())
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
class UnboundMethod
|
94
|
-
include MethodSig
|
95
|
-
|
96
|
-
# Return a String representing the method's signature.
|
97
|
-
def signature
|
98
|
-
return Signature.new(
|
99
|
-
origin_class(),
|
100
|
-
method_oid().to_s,
|
101
|
-
argument_names(),
|
102
|
-
arguments())
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
if __FILE__ == $0 then
|
107
|
-
def foo(); end
|
108
|
-
puts method(:foo).signature
|
109
|
-
|
110
|
-
def foo(foo); end
|
111
|
-
puts method(:foo).signature
|
112
|
-
|
113
|
-
def foo(foo, bar); end
|
114
|
-
puts method(:foo).signature
|
115
|
-
|
116
|
-
def foo(foo=42, bar=10); end
|
117
|
-
puts method(:foo).signature
|
118
|
-
|
119
|
-
def foo(*args); end
|
120
|
-
puts method(:foo).signature
|
121
|
-
|
122
|
-
def foo(foo, bar=42, *args, &block); end
|
123
|
-
puts method(:foo).signature
|
124
|
-
puts method(:foo).origin
|
125
|
-
|
126
|
-
def foo(foo, bar=obj.foo(1, 2, foo(10)), *args, &block); end
|
127
|
-
puts method(:foo).signature
|
128
|
-
|
129
|
-
def foo(foo, bar=obj.foo(1 + 1), *args, &block); end
|
130
|
-
puts method(:foo).signature
|
131
|
-
|
132
|
-
def foo(foo, bar=true ? false : 0, *args, &block); end
|
133
|
-
puts method(:foo).signature
|
134
|
-
|
135
|
-
def foo(foo, bar=true, *args, &block); end
|
136
|
-
puts method(:foo).signature
|
137
|
-
|
138
|
-
def foo(foo, bar=nil, *args, &block); end
|
139
|
-
puts method(:foo).signature
|
140
|
-
|
141
|
-
def foo(foo, bar={1=>2}, *args, &block); end
|
142
|
-
puts method(:foo).signature
|
143
|
-
|
144
|
-
def foo(foo, bar=[1,2], *args, &block); end
|
145
|
-
puts method(:foo).signature
|
146
|
-
end
|
147
|
-
|
@@ -1,102 +0,0 @@
|
|
1
|
-
|
2
|
-
module MethodSig
|
3
|
-
class Argument
|
4
|
-
attr_reader :name
|
5
|
-
|
6
|
-
def required?
|
7
|
-
return !optional?
|
8
|
-
end
|
9
|
-
|
10
|
-
def optional?
|
11
|
-
return rest? || block?
|
12
|
-
end
|
13
|
-
|
14
|
-
def rest?
|
15
|
-
return @is_rest
|
16
|
-
end
|
17
|
-
|
18
|
-
def block?
|
19
|
-
return @is_block
|
20
|
-
end
|
21
|
-
|
22
|
-
def default
|
23
|
-
return nil
|
24
|
-
end
|
25
|
-
|
26
|
-
def initialize(name, is_rest, is_block)
|
27
|
-
@name = name
|
28
|
-
@is_rest = is_rest
|
29
|
-
@is_block = is_block
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_s
|
33
|
-
if @is_rest then
|
34
|
-
prefix = "*"
|
35
|
-
elsif @is_block then
|
36
|
-
prefix = "&"
|
37
|
-
end
|
38
|
-
|
39
|
-
if self.default then
|
40
|
-
suffix = "=#{default()}"
|
41
|
-
end
|
42
|
-
|
43
|
-
return "#{prefix}#{@name}#{suffix}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class OptionalArgument < Argument
|
48
|
-
def optional?
|
49
|
-
return true
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class NodeOptionalArgument < OptionalArgument
|
54
|
-
attr_reader :node_for_default
|
55
|
-
attr_reader :default
|
56
|
-
|
57
|
-
def initialize(name, default, node_for_default, is_rest, is_block)
|
58
|
-
super(name, is_rest, is_block)
|
59
|
-
@default = default
|
60
|
-
@node_for_default = node_for_default
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
class YarvOptionalArgument < OptionalArgument
|
65
|
-
attr_reader :iseq
|
66
|
-
attr_reader :pc_start
|
67
|
-
attr_reader :local_idx
|
68
|
-
|
69
|
-
def initialize(name, iseq, pc_start, local_idx, is_rest, is_block)
|
70
|
-
super(name, is_rest, is_block)
|
71
|
-
@iseq = iseq
|
72
|
-
@pc_start = pc_start
|
73
|
-
@local_idx = local_idx
|
74
|
-
@default = nil
|
75
|
-
end
|
76
|
-
|
77
|
-
def inspect
|
78
|
-
default()
|
79
|
-
super
|
80
|
-
end
|
81
|
-
|
82
|
-
def default
|
83
|
-
return @default if @default
|
84
|
-
|
85
|
-
env = Internal::ByteDecoder::Environment.new(@iseq.local_table())
|
86
|
-
local_table_idx = local_table_idx()
|
87
|
-
@iseq.bytedecode(env, @pc_start) do |instr|
|
88
|
-
RubyVM::Instruction::SETLOCAL === instr &&
|
89
|
-
instr.operands[0] == local_table_idx
|
90
|
-
end
|
91
|
-
expressions = env.expressions + env.stack
|
92
|
-
|
93
|
-
@default = expressions[0].rhs.to_s
|
94
|
-
return @default
|
95
|
-
end
|
96
|
-
|
97
|
-
def local_table_idx
|
98
|
-
return @iseq.local_table.size - @local_idx + 1
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|