police-dataflow 0.0.1 → 0.0.2
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.
- checksums.yaml +15 -0
- data/Gemfile +8 -7
- data/Gemfile.lock +57 -18
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/police/dataflow.rb +2 -1
- data/lib/police/dataflow/core_extensions.rb +18 -4
- data/lib/police/dataflow/gate_profiles/ruby1.9.3 +167 -0
- data/lib/police/dataflow/gating.rb +70 -0
- data/lib/police/dataflow/label.rb +19 -14
- data/lib/police/dataflow/labeling.rb +103 -22
- data/lib/police/dataflow/proxies.rb +33 -5
- data/lib/police/dataflow/proxy_base.rb +80 -40
- data/lib/police/dataflow/proxy_numeric.rb +22 -0
- data/lib/police/dataflow/proxying.rb +215 -40
- data/police-dataflow.gemspec +11 -15
- data/tasks/info.rake +43 -0
- data/test/dataflow/core_extensions_test.rb +8 -8
- data/test/dataflow/labeling_test.rb +324 -15
- data/test/dataflow/proxies_test.rb +7 -11
- data/test/dataflow/proxy_base_test.rb +199 -72
- data/test/dataflow/proxy_numeric_test.rb +45 -0
- data/test/dataflow/proxying_test.rb +333 -80
- data/test/helper.rb +2 -2
- data/test/helpers/hooks_flow_fixture.rb +22 -0
- data/test/helpers/no_flow_fixture.rb +4 -4
- data/test/helpers/proxying_fixture.rb +11 -7
- data/test/helpers/sticky_fixture.rb +14 -0
- metadata +12 -12
- data/lib/police/dataflow/guarding.rb +0 -16
- data/test/helpers/auto_flow_fixture.rb +0 -6
@@ -6,19 +6,22 @@ module DataFlow
|
|
6
6
|
#
|
7
7
|
# ProxyBase is the superclass for all proxy classes, which makes it visible to
|
8
8
|
# application code. For this reason, we avoid defining any methods there.
|
9
|
+
require 'police/vminfo'
|
10
|
+
|
9
11
|
module Proxying
|
10
12
|
# Creates a label-holding proxy for an object.
|
11
13
|
#
|
12
14
|
# @param [Object] proxied the object to be proxied
|
13
|
-
# @param [
|
15
|
+
# @param [Hash<Integer,Hash<Police::DataFlow::Label,Boolean>>] label_set the
|
16
|
+
# set of all labels that will be held by the object's proxy
|
14
17
|
# @return [Police::DataFlow::ProxyBase] an object that can carry labels, and
|
15
18
|
# performs label-propagation as it redirects received messages to the
|
16
19
|
# proxied object
|
17
|
-
def self.proxy(proxied, label_set
|
20
|
+
def self.proxy(proxied, label_set)
|
18
21
|
proxy_class = Police::DataFlow::Proxies.for proxied.class, label_set
|
19
|
-
proxy_class.new proxied, proxy_class, label_set
|
22
|
+
proxy_class.new proxied, proxy_class, label_set
|
20
23
|
end
|
21
|
-
|
24
|
+
|
22
25
|
# Creates proxies for a class' instance methods.
|
23
26
|
#
|
24
27
|
# The proxy methods are defined as instance methods for the proxying class,
|
@@ -29,17 +32,18 @@ module Proxying
|
|
29
32
|
# receive the new proxy method definitions
|
30
33
|
# @param [Class] klass the class whose instance methods will be proxied
|
31
34
|
# @return [NilClass] nil
|
32
|
-
def self.
|
35
|
+
def self.add_instance_methods(proxy_class, klass)
|
33
36
|
# NOTE: this is thread-safe because, at worst, the effort of adding methods
|
34
37
|
# will be re-duplicated
|
35
38
|
klass.public_instance_methods(true).each do |method|
|
36
|
-
|
39
|
+
add_instance_method proxy_class, klass.instance_method(method), :public
|
37
40
|
end
|
38
41
|
klass.protected_instance_methods(true).each do |method|
|
39
|
-
|
42
|
+
add_instance_method proxy_class, klass.instance_method(method),
|
43
|
+
:protected
|
40
44
|
end
|
41
45
|
klass.private_instance_methods(true).each do |method|
|
42
|
-
|
46
|
+
add_instance_method proxy_class, klass.instance_method(method), :private
|
43
47
|
end
|
44
48
|
nil
|
45
49
|
end
|
@@ -50,20 +54,20 @@ module Proxying
|
|
50
54
|
# @param [Method] method_def the definition of the method to be proxied
|
51
55
|
# @param [Symbol] access the proxied method's access level (:public,
|
52
56
|
# :protected, or :private)
|
53
|
-
def self.
|
57
|
+
def self.add_instance_method(proxy_class, method_def, access)
|
54
58
|
# Avoid redefining methods, because that blows up VM caches.
|
55
59
|
if proxy_class.method_defined?(method_def.name) ||
|
56
60
|
proxy_class.private_method_defined?(method_def.name)
|
57
61
|
return
|
58
62
|
end
|
59
|
-
|
63
|
+
|
60
64
|
# Define the method.
|
61
65
|
proxy_class.class_eval proxy_method_definition(
|
62
66
|
proxy_class.__police_classes__, method_def, access)
|
63
67
|
# Set its access level.
|
64
68
|
proxy_class.__send__ access, method_def.name
|
65
69
|
end
|
66
|
-
|
70
|
+
|
67
71
|
# The full definition of a proxy method.
|
68
72
|
#
|
69
73
|
# @param [Array<Police::DataFlow::Label>] label_classes the label classes
|
@@ -75,46 +79,54 @@ module Proxying
|
|
75
79
|
# proxy class to define a proxy for the given method
|
76
80
|
def self.proxy_method_definition(label_classes, method_def, access)
|
77
81
|
# NOTE: it might be tempting to attempt to pass a block to the proxied
|
78
|
-
# method at all times, and try to yield to the original block when
|
79
|
-
# block is invoked; this would work most of the time, but it
|
80
|
-
# break methods such as Enumerable#map and String#scan, whose
|
81
|
-
# changes depending on whether or not a block is passed to
|
82
|
+
# method at all times, and try to yield to the original block when
|
83
|
+
# our block is invoked; this would work most of the time, but it
|
84
|
+
# would break methods such as Enumerable#map and String#scan, whose
|
85
|
+
# behavior changes depending on whether or not a block is passed to
|
86
|
+
# them
|
82
87
|
["def #{method_def.name}(#{proxy_argument_list(method_def, true)})",
|
88
|
+
proxy_sticky_fastpath_check(method_def),
|
89
|
+
proxy_sticky_gathering(method_def),
|
83
90
|
"return_value = if block",
|
84
|
-
proxy_method_call(method_def, access
|
91
|
+
proxy_method_call(method_def, access) + " do |*yield_args|",
|
92
|
+
proxy_yield_sticky_decorating(method_def),
|
85
93
|
proxy_yield_args_decorating(label_classes, method_def),
|
86
94
|
"block_return = yield(*yield_args)",
|
87
95
|
# TODO(pwnall): consider adding a yield value filter
|
88
96
|
"next block_return",
|
89
97
|
"end",
|
90
98
|
"else",
|
91
|
-
proxy_method_call(method_def, access
|
99
|
+
proxy_method_call(method_def, access),
|
92
100
|
"end",
|
93
|
-
|
101
|
+
|
102
|
+
proxy_return_sticky_decorating(method_def),
|
103
|
+
proxy_return_decorating(label_classes, method_def),
|
94
104
|
"return return_value",
|
95
105
|
"end"].join ';'
|
96
106
|
end
|
97
|
-
|
107
|
+
|
98
108
|
# The proxying call to a method.
|
99
109
|
#
|
100
110
|
# @param [Method] method_def the definition of the method to be proxied
|
101
111
|
# @param [Symbol] access the proxied method's access level (:public,
|
102
112
|
# :protected, or :private)
|
103
|
-
# @param [Boolean] include_block if true, the method call passes the block
|
104
|
-
# that the proxy has received; if false, the block is ignored
|
105
113
|
# @return [String] a chunk of Ruby that can be used to call the given method
|
106
114
|
# when defining a proxy for it
|
107
|
-
def self.proxy_method_call(method_def, access
|
108
|
-
arg_list =
|
115
|
+
def self.proxy_method_call(method_def, access)
|
116
|
+
arg_list = proxy_call_argument_list method_def
|
109
117
|
|
110
118
|
if access == :public
|
111
119
|
"@__police_proxied__.#{method_def.name}(#{arg_list})"
|
112
120
|
else
|
113
|
-
|
121
|
+
if arg_list.empty?
|
122
|
+
"@__police_proxied__.__send__(:#{method_def.name})"
|
123
|
+
else
|
124
|
+
"@__police_proxied__.__send__(:#{method_def.name}, #{arg_list})"
|
125
|
+
end
|
114
126
|
end
|
115
127
|
end
|
116
|
-
|
117
|
-
# Code that labels the values yielded by a decorated method to its block.
|
128
|
+
|
129
|
+
# Code that labels the values yielded by a decorated method to its block.
|
118
130
|
#
|
119
131
|
# @param [Array<Police::DataFlow::Label>] label_classes the label classes
|
120
132
|
# supported by the proxy class
|
@@ -126,39 +138,51 @@ module Proxying
|
|
126
138
|
arg_list = proxy_argument_list method_def, false
|
127
139
|
code_lines = ['labels = @__police_labels__']
|
128
140
|
label_classes.each do |label_class|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
141
|
+
if hook = label_class.yield_args_hook(method_name)
|
142
|
+
label_key = label_class.__id__
|
143
|
+
code_lines << "labels[#{label_key}].each { |label, _| " \
|
144
|
+
"label.#{hook}(self, yield_args, #{arg_list}) }"
|
145
|
+
elsif label_class.sticky?
|
146
|
+
label_key = label_class.__id__
|
147
|
+
code_lines << "labels[#{label_key}].each { |label, _| " \
|
148
|
+
"yield_args.map! { |arg| ::Police::DataFlow.label(arg, label) } " \
|
149
|
+
"}"
|
150
|
+
end
|
133
151
|
end
|
134
152
|
(code_lines.length > 1) ? code_lines.join('; ') : ''
|
135
153
|
end
|
136
|
-
|
154
|
+
|
137
155
|
# Code that labels return value of a decorated method.
|
138
156
|
#
|
139
157
|
# @param [Array<Police::DataFlow::Label>] label_classes the label classes
|
140
158
|
# supported by the proxy class
|
141
159
|
# @param [Method] method_def the definition of the method to be proxied
|
142
|
-
# @return [String] a chunk of Ruby that can be used to invoke the return
|
143
|
-
# decorators of the labels held by a labeled object's proxy
|
160
|
+
# @return [String] a chunk of Ruby that can be used to invoke the return
|
161
|
+
# value decorators of the labels held by a labeled object's proxy
|
144
162
|
def self.proxy_return_decorating(label_classes, method_def)
|
145
163
|
method_name = method_def.name
|
146
164
|
arg_list = proxy_argument_list method_def, false
|
147
165
|
code_lines = ['labels = @__police_labels__']
|
148
166
|
label_classes.each do |label_class|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
167
|
+
if hook = label_class.return_hook(method_name)
|
168
|
+
label_key = label_class.__id__
|
169
|
+
code_lines << "labels[#{label_key}].each { |label, _| " \
|
170
|
+
"return_value = label.#{hook}(return_value, self, #{arg_list}) }"
|
171
|
+
elsif label_class.sticky?
|
172
|
+
label_key = label_class.__id__
|
173
|
+
code_lines << "labels[#{label_key}].each { |label, _| " \
|
174
|
+
"return_value = ::Police::DataFlow.label(return_value, label) }"
|
175
|
+
end
|
153
176
|
end
|
154
177
|
(code_lines.length > 1) ? code_lines.join('; ') : ''
|
155
178
|
end
|
156
|
-
|
179
|
+
|
157
180
|
# The list of arguments used to define a proxy for the given method.
|
158
181
|
#
|
159
182
|
# @param [Method] method_def the definition of the method to be proxied
|
160
|
-
# @param [Boolean] captue_block if true, the method captures the block that
|
161
|
-
# receives
|
183
|
+
# @param [Boolean] captue_block if true, the method captures the block that
|
184
|
+
# it receives; this should be true when the returned code is used in
|
185
|
+
# method definitions, and false when it is used in method calls
|
162
186
|
# @return [String] a chunk of Ruby that can be used as the argument list when
|
163
187
|
# defining a proxy for the given method
|
164
188
|
def self.proxy_argument_list(method_def, capture_block)
|
@@ -172,6 +196,157 @@ module Proxying
|
|
172
196
|
arg_list << '&block' if capture_block
|
173
197
|
arg_list.join ', '
|
174
198
|
end
|
199
|
+
|
200
|
+
# The list of arguments used to call a proxied method.
|
201
|
+
#
|
202
|
+
# This assumes that the proxy method definition uses the code retuned by
|
203
|
+
# proxy_argument_list.
|
204
|
+
#
|
205
|
+
# @param [Method] method_def the definition of the method to be proxied;
|
206
|
+
# should match the value passed to proxy_argument_list
|
207
|
+
# @return [String] a chunk of Ruby that can be used as the argument list when
|
208
|
+
# defining a proxy for the given method
|
209
|
+
def self.proxy_call_argument_list(method_def)
|
210
|
+
source = Police::VmInfo.method_source method_def
|
211
|
+
if source == :native || source == :kernel
|
212
|
+
proxy_low_level_call_argument_list method_def
|
213
|
+
else
|
214
|
+
proxy_argument_list method_def, false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# The list of arguments used to call a proxied low-level method.
|
219
|
+
#
|
220
|
+
# Low-level methods don't use Ruby methods to manipulate their arguments, so
|
221
|
+
# they can't work on proxies, and need to receive the proxied objects
|
222
|
+
# as arguments.
|
223
|
+
#
|
224
|
+
# @param [Method] method_def the definition of the method to be proxied;
|
225
|
+
# should match the value passed to {#proxy_argument_list}
|
226
|
+
# @return [String] a chunk of Ruby that can be used as the argument list when
|
227
|
+
# defining a proxy for the given method
|
228
|
+
def self.proxy_low_level_call_argument_list(method_def)
|
229
|
+
arg_list = if method_def.arity >= 0
|
230
|
+
# Fixed number of arguments.
|
231
|
+
(1..method_def.arity).map do |i|
|
232
|
+
"(nil == arg#{i}.__police_labels__) ? arg#{i} : " +
|
233
|
+
"arg#{i}.__police_proxied__"
|
234
|
+
end
|
235
|
+
else
|
236
|
+
# Variable number of arguments.
|
237
|
+
args_mapper = '*(args.map { |a| (nil == a.__police_labels__) ? a : ' +
|
238
|
+
'a.__police_proxied__ })'
|
239
|
+
(1..(-method_def.arity - 1)).map { |i|
|
240
|
+
"(nil == arg#{i}.__police_labels__) ? arg#{i} : " +
|
241
|
+
"arg#{i}.__police_proxied__"
|
242
|
+
} << args_mapper
|
243
|
+
end
|
244
|
+
arg_list.join ', '
|
245
|
+
end
|
246
|
+
|
247
|
+
# Boolean expression deciding if a proxied method received labeled arguments.
|
248
|
+
#
|
249
|
+
# If none of the method's arguments is labeled, the sticky label propagation
|
250
|
+
# logic can be completely bypassed.
|
251
|
+
#
|
252
|
+
# @param [Method] method_def the definition of the method to be proxied;
|
253
|
+
# should match the value passed to {#proxy_argument_list}
|
254
|
+
# @return [String] a chunk of Ruby that sets the 'fast_sticky' local variable
|
255
|
+
# to a truthy value if none of the proxied method's arguments is labeled,
|
256
|
+
# and to a falsey value if at least one argument has a label
|
257
|
+
def self.proxy_sticky_fastpath_check(method_def)
|
258
|
+
# Don't generate anything for zero-argument methods.
|
259
|
+
return '' if method_def.arity == 0
|
260
|
+
|
261
|
+
boolean_list = if method_def.arity > 0
|
262
|
+
# Fixed number of arguments.
|
263
|
+
(1..method_def.arity).map do |i|
|
264
|
+
"(nil == arg#{i}.__police_stickies__)"
|
265
|
+
end
|
266
|
+
else
|
267
|
+
# Variable number of arguments.
|
268
|
+
args_boolean = '(args.all? { |a| nil == a.__police_stickies__ })'
|
269
|
+
(1..(-method_def.arity - 1)).map { |i|
|
270
|
+
"(nil == arg#{i}.__police_stickies__)"
|
271
|
+
} << args_boolean
|
272
|
+
end
|
273
|
+
'fast_sticky = ' + boolean_list.join(' && ')
|
274
|
+
end
|
275
|
+
|
276
|
+
# Code for computing the union of the arguments' sticky labels.
|
277
|
+
#
|
278
|
+
# The code is wrapped in a check that assumes the code returned by
|
279
|
+
# {#proxy_sticky_fastpath_check} was already executed.
|
280
|
+
#
|
281
|
+
# @param [Method] method_def the definition of the method to be proxied;
|
282
|
+
# should match the value passed to {#proxy_argument_list} and
|
283
|
+
# {#proxy_sticky_fastpath_check}
|
284
|
+
# @return [String] a chunk of Ruby that sets the 'sticky_labels' local
|
285
|
+
# variable to a label set that contains all the sticky labels in the
|
286
|
+
# method's arguments
|
287
|
+
def self.proxy_sticky_gathering(method_def)
|
288
|
+
# Don't generate anything for zero-argument methods.
|
289
|
+
return '' if method_def.arity == 0
|
290
|
+
|
291
|
+
code_lines = ['unless fast_sticky', 'sticky_labels = {}']
|
292
|
+
if method_def.arity > 0
|
293
|
+
# Fixed number of arguments.
|
294
|
+
1.upto method_def.arity do |i|
|
295
|
+
code_lines << "unless nil == arg#{i}.__police_stickies__"
|
296
|
+
code_lines << '::Police::DataFlow::Labeling.merge_sets!(' +
|
297
|
+
"sticky_labels, arg#{i}.__police_stickies__)"
|
298
|
+
code_lines << 'end'
|
299
|
+
end
|
300
|
+
else
|
301
|
+
# Variable number of arguments.
|
302
|
+
1.upto(-method_def.arity - 1) do |i|
|
303
|
+
code_lines << "unless nil == arg#{i}.__police_stickies__"
|
304
|
+
code_lines << '::Police::DataFlow::Labeling.merge_sets!(' +
|
305
|
+
"sticky_labels, arg#{i}.__police_stickies__)"
|
306
|
+
code_lines << 'end'
|
307
|
+
end
|
308
|
+
code_lines << 'args.each do |a|'
|
309
|
+
code_lines << 'unless nil == a.__police_stickies__'
|
310
|
+
code_lines << '::Police::DataFlow::Labeling.merge_sets!(' +
|
311
|
+
'sticky_labels, a.__police_stickies__)'
|
312
|
+
code_lines << 'end'
|
313
|
+
code_lines << 'end'
|
314
|
+
end
|
315
|
+
code_lines << 'end'
|
316
|
+
code_lines.join '; '
|
317
|
+
end
|
318
|
+
|
319
|
+
# Code for applying argument sticky labels to a method's yielded arguments.
|
320
|
+
#
|
321
|
+
# This code assumes that the code returned by {#proxy_sticky_fastpath_check}
|
322
|
+
# and {#proxy_sticky_gathering} was already executed.
|
323
|
+
#
|
324
|
+
# @param [Method] method_def the definition of the method to be proxied;
|
325
|
+
# should match the value passed to {#proxy_argument_list} and
|
326
|
+
# {#proxy_sticky_fastpath_check}
|
327
|
+
# @return [String] a chunk of Ruby that sets the 'sticky_labels' local
|
328
|
+
# variable to a label set that contains all the sticky labels in the
|
329
|
+
# method's arguments
|
330
|
+
def self.proxy_yield_sticky_decorating(method_def)
|
331
|
+
# Don't generate anything for zero-argument methods.
|
332
|
+
return '' if method_def.arity == 0
|
333
|
+
|
334
|
+
'unless fast_sticky; ' +
|
335
|
+
'yield_args.map! do |a|; ' +
|
336
|
+
'::Police::DataFlow::Labeling.bulk_sticky_label(a, sticky_labels); ' +
|
337
|
+
'end; ' +
|
338
|
+
'end'
|
339
|
+
end
|
340
|
+
|
341
|
+
def self.proxy_return_sticky_decorating(method_def)
|
342
|
+
# Don't generate anything for zero-argument methods.
|
343
|
+
return '' if method_def.arity == 0
|
344
|
+
|
345
|
+
'unless fast_sticky; ' +
|
346
|
+
'return_value = ::Police::DataFlow::Labeling.bulk_sticky_label(' +
|
347
|
+
'return_value, sticky_labels); ' +
|
348
|
+
'end'
|
349
|
+
end
|
175
350
|
end # namespace Police::DataFlow::Proxying
|
176
351
|
|
177
352
|
end # namespace Police::DataFlow
|
data/police-dataflow.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "police-dataflow"
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Victor Costan"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2013-09-24"
|
13
13
|
s.description = "Pure Ruby implementtion of data flow label propagation."
|
14
14
|
s.email = "victor@costan.us"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -27,36 +27,32 @@ Gem::Specification.new do |s|
|
|
27
27
|
"lib/police-dataflow.rb",
|
28
28
|
"lib/police/dataflow.rb",
|
29
29
|
"lib/police/dataflow/core_extensions.rb",
|
30
|
-
"lib/police/dataflow/
|
30
|
+
"lib/police/dataflow/gate_profiles/ruby1.9.3",
|
31
|
+
"lib/police/dataflow/gating.rb",
|
31
32
|
"lib/police/dataflow/label.rb",
|
32
33
|
"lib/police/dataflow/labeling.rb",
|
33
34
|
"lib/police/dataflow/proxies.rb",
|
34
35
|
"lib/police/dataflow/proxy_base.rb",
|
36
|
+
"lib/police/dataflow/proxy_numeric.rb",
|
35
37
|
"lib/police/dataflow/proxying.rb",
|
36
38
|
"police-dataflow.gemspec",
|
39
|
+
"tasks/info.rake",
|
37
40
|
"test/dataflow/core_extensions_test.rb",
|
38
41
|
"test/dataflow/labeling_test.rb",
|
39
42
|
"test/dataflow/proxies_test.rb",
|
40
43
|
"test/dataflow/proxy_base_test.rb",
|
44
|
+
"test/dataflow/proxy_numeric_test.rb",
|
41
45
|
"test/dataflow/proxying_test.rb",
|
42
46
|
"test/helper.rb",
|
43
|
-
"test/helpers/
|
47
|
+
"test/helpers/hooks_flow_fixture.rb",
|
44
48
|
"test/helpers/no_flow_fixture.rb",
|
45
|
-
"test/helpers/proxying_fixture.rb"
|
49
|
+
"test/helpers/proxying_fixture.rb",
|
50
|
+
"test/helpers/sticky_fixture.rb"
|
46
51
|
]
|
47
52
|
s.homepage = "http://github.com/csail/police"
|
48
53
|
s.licenses = ["MIT"]
|
49
54
|
s.require_paths = ["lib"]
|
50
|
-
s.rubygems_version = "
|
55
|
+
s.rubygems_version = "2.0.7"
|
51
56
|
s.summary = "Data flow label propagation"
|
52
|
-
|
53
|
-
if s.respond_to? :specification_version then
|
54
|
-
s.specification_version = 3
|
55
|
-
|
56
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
57
|
-
else
|
58
|
-
end
|
59
|
-
else
|
60
|
-
end
|
61
57
|
end
|
62
58
|
|
data/tasks/info.rake
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
task :vminfo do
|
2
|
+
require 'police/vminfo'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
modules = Set.new
|
6
|
+
class_methods = {}
|
7
|
+
instance_methods = {}
|
8
|
+
Police::VmInfo.core_modules.sort_by(&:to_s).each do |module_object|
|
9
|
+
methods = []
|
10
|
+
Police::VmInfo.core_class_methods(module_object).sort_by(&:to_s).
|
11
|
+
each do |method|
|
12
|
+
source = Police::VmInfo.method_source(method)
|
13
|
+
next unless source == :native || source == :kernel
|
14
|
+
next if method.arity == 0
|
15
|
+
methods << method.name
|
16
|
+
end
|
17
|
+
unless methods.empty?
|
18
|
+
class_methods[module_object.to_s] = methods.sort
|
19
|
+
modules << module_object.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
methods = []
|
23
|
+
Police::VmInfo.core_instance_methods(module_object).sort_by(&:to_s).
|
24
|
+
each do |method|
|
25
|
+
source = Police::VmInfo.method_source(method)
|
26
|
+
next unless source == :native || source == :kernel
|
27
|
+
next if method.arity == 0
|
28
|
+
methods << method.name
|
29
|
+
end
|
30
|
+
unless methods.empty?
|
31
|
+
instance_methods[module_object.to_s] = methods.sort
|
32
|
+
modules << module_object.to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
profile_path = File.expand_path(
|
37
|
+
"../lib/police/dataflow/gate_profiles/#{Police::VmInfo.signature}",
|
38
|
+
File.dirname(__FILE__))
|
39
|
+
File.open(profile_path, 'w') do |f|
|
40
|
+
f.write YAML.dump(core: modules.to_a.sort, :class => class_methods,
|
41
|
+
instance: instance_methods)
|
42
|
+
end
|
43
|
+
end
|