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