fastruby 0.0.16 → 0.0.17
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/CHANGELOG +17 -1
- data/Rakefile +1 -1
- data/ext/fastruby_base/fastruby_base.inl +81 -3
- data/lib/fastruby/fastruby_sexp.rb +21 -0
- data/lib/fastruby/getlocals.rb +2 -1
- data/lib/fastruby/object.rb +1 -1
- data/lib/fastruby/sexp_extension.rb +189 -0
- data/lib/fastruby/sexp_extension_edges.rb +210 -0
- data/lib/fastruby/translator/modules/block.rb +29 -22
- data/lib/fastruby/translator/modules/call.rb +211 -34
- data/lib/fastruby/translator/modules/defn.rb +64 -29
- data/lib/fastruby/translator/modules/exceptions.rb +1 -1
- data/lib/fastruby/translator/modules/flow.rb +93 -31
- data/lib/fastruby/translator/modules/iter.rb +277 -340
- data/lib/fastruby/translator/modules/literal.rb +97 -20
- data/lib/fastruby/translator/modules/logical.rb +40 -5
- data/lib/fastruby/translator/modules/method_group.rb +41 -19
- data/lib/fastruby/translator/modules/nonlocal.rb +74 -29
- data/lib/fastruby/translator/modules/variable.rb +151 -42
- data/lib/fastruby/translator/scope_mode_helper.rb +161 -0
- data/lib/fastruby/translator/translator.rb +389 -302
- data/lib/fastruby.rb +1 -1
- data/lib/fastruby.rb~ +36 -0
- data/spec/edges_helper.rb +91 -0
- data/spec/graph/base_spec.rb +35 -0
- data/spec/graph/path_spec.rb +48 -0
- data/spec/graph/vertex_spec.rb +58 -0
- data/spec/ruby/block/proc_as_block_spec.rb +214 -0
- data/spec/ruby/block/redo_spec.rb +133 -0
- data/spec/ruby/defn/single_function_spec.rb +50 -0
- data/spec/scope_mode/base_spec.rb +55 -0
- data/spec/scope_mode/block_spec.rb +105 -0
- data/spec/scope_mode/call_spec.rb +24 -0
- data/spec/scope_mode/exception_spec.rb +34 -0
- data/spec/scope_mode/flow_spec.rb +99 -0
- data/spec/scope_mode/optimization_spec.rb +130 -0
- data/spec/sexp2graph/base_spec.rb +36 -0
- data/spec/sexp2graph/exception_spec.rb +172 -0
- data/spec/sexp2graph/flow_spec.rb +67 -0
- data/spec/sexp2graph/logical_spec.rb +21 -0
- data/spec/sexp2graph/variable_spec.rb +26 -0
- metadata +110 -120
- data/lib/fastruby/self +0 -82
- data/lib/len +0 -280
- data/spec/block/proc_as_block_spec.rb +0 -111
- data/spec/block/redo_spec.rb +0 -67
- /data/spec/{base_spec.rb → ruby/base_spec.rb} +0 -0
- /data/spec/{block → ruby/block}/arguments_spec.rb +0 -0
- /data/spec/{block → ruby/block}/block_as_proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/break_spec.rb +0 -0
- /data/spec/{block → ruby/block}/callcc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/lambda_spec.rb +0 -0
- /data/spec/{block → ruby/block}/next_spec.rb +0 -0
- /data/spec/{block → ruby/block}/proc_spec.rb +0 -0
- /data/spec/{block → ruby/block}/retry_spec.rb +0 -0
- /data/spec/{block_spec.rb → ruby/block_spec.rb} +0 -0
- /data/spec/{call → ruby/call}/base_call_spec.rb +0 -0
- /data/spec/{call → ruby/call}/multiple_args_spec.rb +0 -0
- /data/spec/{control_spec.rb → ruby/control_spec.rb} +0 -0
- /data/spec/{defn → ruby/defn}/default_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/multiple_args_spec.rb +0 -0
- /data/spec/{defn → ruby/defn}/replacement_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/base_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/ensure_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/exc_trap_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/internal_ex_spec.rb +0 -0
- /data/spec/{exception → ruby/exception}/syntaxis_spec.rb +0 -0
- /data/spec/{expression_spec.rb → ruby/expression_spec.rb} +0 -0
- /data/spec/{flow_control → ruby/flow_control}/case_spec.rb +0 -0
- /data/spec/{flow_control → ruby/flow_control}/for_spec.rb +0 -0
- /data/spec/{integrity_spec.rb → ruby/integrity_spec.rb} +0 -0
- /data/spec/{jump → ruby/jump}/next_spec.rb +0 -0
- /data/spec/{literal_spec.rb → ruby/literal_spec.rb} +0 -0
- /data/spec/{module_spec.rb → ruby/module_spec.rb} +0 -0
- /data/spec/{return_spec.rb → ruby/return_spec.rb} +0 -0
- /data/spec/{singleton_spec.rb → ruby/singleton_spec.rb} +0 -0
- /data/spec/{sugar_spec.rb → ruby/sugar_spec.rb} +0 -0
- /data/spec/{variable_spec.rb → ruby/variable_spec.rb} +0 -0
data/CHANGELOG
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
0.0.17 Fixed bug of non-volatile variables on scopes calling setjmp
|
2
|
+
|
3
|
+
Fixed bug of native pointers encoding on 32 bits systems
|
4
|
+
|
5
|
+
peforrmance: implemented linear stack scopes when possible
|
6
|
+
|
7
|
+
performance: refactored C translation to avoid unecessary non-local jumps such return
|
8
|
+
|
9
|
+
performance: refactored C translation to avoid unecessary anonymous C functions
|
10
|
+
|
11
|
+
performance: Implemented direct call to CFUNC methods on ruby1.9
|
12
|
+
|
13
|
+
Added support for single methods (with "no class")
|
14
|
+
|
15
|
+
Fixed bug with default argument initialization and redo
|
16
|
+
|
1
17
|
0.0.16 Limited (see known issues on README) support for ruby1.9-p180 (tested with rvm)
|
2
18
|
|
3
19
|
Support for ruby1.8-p334 (tested with rvm)
|
@@ -82,4 +98,4 @@
|
|
82
98
|
|
83
99
|
0.0.2 Added missing sexp_processor dependency
|
84
100
|
|
85
|
-
0.0.1 First test release
|
101
|
+
0.0.1 First test release
|
data/Rakefile
CHANGED
@@ -37,7 +37,71 @@ struct FASTRUBYTHREADDATA {
|
|
37
37
|
|
38
38
|
#ifdef RUBY_1_9
|
39
39
|
|
40
|
-
|
40
|
+
|
41
|
+
typedef enum {
|
42
|
+
NOEX_PUBLIC = 0x00,
|
43
|
+
NOEX_NOSUPER = 0x01,
|
44
|
+
NOEX_PRIVATE = 0x02,
|
45
|
+
NOEX_PROTECTED = 0x04,
|
46
|
+
NOEX_MASK = 0x06,
|
47
|
+
NOEX_BASIC = 0x08,
|
48
|
+
NOEX_UNDEF = NOEX_NOSUPER,
|
49
|
+
NOEX_MODFUNC = 0x12,
|
50
|
+
NOEX_SUPER = 0x20,
|
51
|
+
NOEX_VCALL = 0x40,
|
52
|
+
NOEX_RESPONDS = 0x80
|
53
|
+
} rb_method_flag_t;
|
54
|
+
|
55
|
+
typedef enum {
|
56
|
+
VM_METHOD_TYPE_ISEQ,
|
57
|
+
VM_METHOD_TYPE_CFUNC,
|
58
|
+
VM_METHOD_TYPE_ATTRSET,
|
59
|
+
VM_METHOD_TYPE_IVAR,
|
60
|
+
VM_METHOD_TYPE_BMETHOD,
|
61
|
+
VM_METHOD_TYPE_ZSUPER,
|
62
|
+
VM_METHOD_TYPE_UNDEF,
|
63
|
+
VM_METHOD_TYPE_NOTIMPLEMENTED,
|
64
|
+
VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
|
65
|
+
VM_METHOD_TYPE_MISSING /* wrapper for method_missing(id) */
|
66
|
+
} rb_method_type_t;
|
67
|
+
|
68
|
+
typedef struct rb_method_cfunc_struct {
|
69
|
+
VALUE (*func)(ANYARGS);
|
70
|
+
int argc;
|
71
|
+
} rb_method_cfunc_t;
|
72
|
+
|
73
|
+
typedef struct rb_method_attr_struct {
|
74
|
+
ID id;
|
75
|
+
VALUE location;
|
76
|
+
} rb_method_attr_t;
|
77
|
+
|
78
|
+
typedef struct rb_iseq_struct rb_iseq_t;
|
79
|
+
|
80
|
+
typedef struct rb_method_definition_struct {
|
81
|
+
rb_method_type_t type; /* method type */
|
82
|
+
ID original_id;
|
83
|
+
union {
|
84
|
+
rb_iseq_t *iseq; /* should be mark */
|
85
|
+
rb_method_cfunc_t cfunc;
|
86
|
+
rb_method_attr_t attr;
|
87
|
+
VALUE proc; /* should be mark */
|
88
|
+
enum method_optimized_type {
|
89
|
+
OPTIMIZED_METHOD_TYPE_SEND,
|
90
|
+
OPTIMIZED_METHOD_TYPE_CALL
|
91
|
+
} optimize_type;
|
92
|
+
} body;
|
93
|
+
int alias_count;
|
94
|
+
} rb_method_definition_t;
|
95
|
+
|
96
|
+
typedef struct rb_method_entry_struct {
|
97
|
+
rb_method_flag_t flag;
|
98
|
+
char mark;
|
99
|
+
rb_method_definition_t *def;
|
100
|
+
ID called_id;
|
101
|
+
VALUE klass; /* should be mark */
|
102
|
+
} rb_method_entry_t;
|
103
|
+
|
104
|
+
rb_method_entry_t* rb_method_entry(VALUE klass, ID id);
|
41
105
|
void* rb_global_entry(ID id);
|
42
106
|
|
43
107
|
typedef struct RNode {
|
@@ -106,6 +170,11 @@ static inline int stack_chunk_get_current_position(struct STACKCHUNK* sc) {
|
|
106
170
|
}
|
107
171
|
}
|
108
172
|
|
173
|
+
typedef struct {
|
174
|
+
int size;
|
175
|
+
void *p1,*p2,*p3,*p4,*p5;
|
176
|
+
VALUE data[0x10000];
|
177
|
+
} generic_scope_t;
|
109
178
|
|
110
179
|
static inline void* stack_chunk_alloc(struct STACKCHUNK* sc, int size){
|
111
180
|
|
@@ -171,6 +240,7 @@ static inline void* stack_chunk_alloc(struct STACKCHUNK* sc, int size){
|
|
171
240
|
address = sc->pages[page]+position_in_page;
|
172
241
|
}
|
173
242
|
|
243
|
+
((generic_scope_t*)address)->size = size;
|
174
244
|
return address;
|
175
245
|
}
|
176
246
|
|
@@ -178,11 +248,19 @@ static inline void stack_chunk_mark(struct STACKCHUNK* sc) {
|
|
178
248
|
// Mark local variables on each allocated page up to current_position
|
179
249
|
int i;
|
180
250
|
|
181
|
-
for (i=0; i<sc->current_position;
|
251
|
+
for (i=0; i<sc->current_position; ) {
|
182
252
|
int position_in_page = i & PAGE_MASK;
|
183
253
|
int page = i / PAGE_SIZE;
|
184
254
|
|
185
|
-
|
255
|
+
generic_scope_t* scope = (void*)&(sc->pages[page][position_in_page]);
|
256
|
+
|
257
|
+
if (scope->size == 0) {
|
258
|
+
i = i + 1;
|
259
|
+
} else {
|
260
|
+
i = i + scope->size;
|
261
|
+
int j;
|
262
|
+
for (j=0;j<scope->size-6;j++) rb_gc_mark(scope->data[j]);
|
263
|
+
}
|
186
264
|
}
|
187
265
|
}
|
188
266
|
|
@@ -21,5 +21,26 @@ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
|
21
21
|
module FastRuby
|
22
22
|
class FastRubySexp < Array
|
23
23
|
alias node_type first
|
24
|
+
|
25
|
+
def walk_tree(&block)
|
26
|
+
each do |subtree|
|
27
|
+
if subtree.instance_of? FastRubySexp
|
28
|
+
subtree.walk_tree(&block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
block.call(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_tree(ndtype = nil)
|
35
|
+
walk_tree do |subtree|
|
36
|
+
if (not block_given?) || yield(subtree)
|
37
|
+
if (not ndtype) || ndtype == subtree.node_type
|
38
|
+
return subtree
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
return nil
|
44
|
+
end
|
24
45
|
end
|
25
46
|
end
|
data/lib/fastruby/getlocals.rb
CHANGED
@@ -50,6 +50,7 @@ module FastRuby
|
|
50
50
|
|
51
51
|
if tree[0] == :block_pass
|
52
52
|
@locals << :__xblock_arguments
|
53
|
+
@locals << :__x_proc
|
53
54
|
end
|
54
55
|
|
55
56
|
tree.select{|subtree| subtree.instance_of? FastRuby::FastRubySexp}.each do |subtree|
|
@@ -63,4 +64,4 @@ module FastRuby
|
|
63
64
|
processor.locals
|
64
65
|
end
|
65
66
|
end
|
66
|
-
end
|
67
|
+
end
|
data/lib/fastruby/object.rb
CHANGED
@@ -19,6 +19,9 @@ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
|
19
19
|
|
20
20
|
=end
|
21
21
|
require "fastruby/fastruby_sexp"
|
22
|
+
require "fastruby/sexp_extension_edges"
|
23
|
+
require "ruby_parser"
|
24
|
+
require "set"
|
22
25
|
|
23
26
|
class Object
|
24
27
|
def to_fastruby_sexp
|
@@ -27,14 +30,200 @@ class Object
|
|
27
30
|
end
|
28
31
|
|
29
32
|
module FastRuby
|
33
|
+
class Graph
|
34
|
+
attr_reader :edges
|
35
|
+
attr_reader :vertexes
|
36
|
+
|
37
|
+
def initialize(hash = {})
|
38
|
+
@edges = []
|
39
|
+
@vertexes = Set.new
|
40
|
+
@vertex_output = Hash.new
|
41
|
+
|
42
|
+
hash.each do |orig,v|
|
43
|
+
v.each do |dest|
|
44
|
+
add_edge(orig,dest)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_edge(orig,dest)
|
50
|
+
@vertexes << orig
|
51
|
+
@vertexes << dest
|
52
|
+
|
53
|
+
@vertex_output[orig] ||= Set.new
|
54
|
+
@vertex_output[orig] << dest
|
55
|
+
|
56
|
+
@edges << [orig,dest]
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_vertex_output(vertex,&blk)
|
60
|
+
outputs = @vertex_output[vertex]
|
61
|
+
if outputs
|
62
|
+
blk ? outputs.each(&blk) : outputs
|
63
|
+
else
|
64
|
+
Set.new
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def each_path_from(vertex, history = [])
|
69
|
+
outputs = each_vertex_output(vertex) - history.select{|h| h[0] == vertex }.map(&:last)
|
70
|
+
outputs.delete(vertex)
|
71
|
+
|
72
|
+
if outputs.count == 0
|
73
|
+
yield [vertex]
|
74
|
+
return
|
75
|
+
end
|
76
|
+
|
77
|
+
outputs.each do |vo|
|
78
|
+
each_path_from(vo,history+[[vertex,vo]]) do |subpath|
|
79
|
+
yield [vertex]+subpath
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
30
85
|
class FastRubySexp
|
31
86
|
def self.from_sexp(value)
|
87
|
+
return nil if value == nil
|
88
|
+
return value if value.kind_of? FastRubySexp
|
89
|
+
|
32
90
|
ary = FastRuby::FastRubySexp.new
|
33
91
|
value.each do |x|
|
34
92
|
ary << x.to_fastruby_sexp
|
35
93
|
end
|
36
94
|
ary
|
37
95
|
end
|
96
|
+
|
97
|
+
def transform(&blk)
|
98
|
+
ret = FastRuby::FastRubySexp.from_sexp( blk.call(self) )
|
99
|
+
|
100
|
+
unless ret
|
101
|
+
ret = FastRuby::FastRubySexp.new
|
102
|
+
each{|st2|
|
103
|
+
if st2.respond_to?(:transform)
|
104
|
+
ret << st2.transform(&blk)
|
105
|
+
else
|
106
|
+
ret << st2
|
107
|
+
end
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
ret
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.parse(code)
|
115
|
+
from_sexp(RubyParser.new.parse(code))
|
116
|
+
end
|
117
|
+
|
118
|
+
def to_graph
|
119
|
+
graph = Graph.new
|
120
|
+
self.edges.each &graph.method(:add_edge)
|
121
|
+
|
122
|
+
if ENV['FASTRUBY_GRAPH_VERTEX_CHECK'] == '1'
|
123
|
+
output_vertexes = [];
|
124
|
+
|
125
|
+
self.walk_tree do |subtree|
|
126
|
+
if graph.each_vertex_output(subtree).count == 0
|
127
|
+
# vertexes with no output
|
128
|
+
unless [:arglist,:scope].include? subtree.node_type
|
129
|
+
output_vertexes << subtree
|
130
|
+
if output_vertexes.count > 1
|
131
|
+
raise RuntimeError, "invalid output vertexes #{output_vertexes.map &:node_type}"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
graph
|
139
|
+
end
|
140
|
+
|
141
|
+
def edges
|
142
|
+
Edges.new(self)
|
143
|
+
end
|
144
|
+
|
145
|
+
def first_tree
|
146
|
+
if respond_to? "first_tree_#{node_type}"
|
147
|
+
send("first_tree_#{node_type}")
|
148
|
+
else
|
149
|
+
return self[1].first_tree if self.count == 2 and self[1].respond_to? :node_type
|
150
|
+
return self[1].first_tree if [:if,:block,:while,:until,:or,:and,:ensure].include? node_type
|
151
|
+
return self[2].first_tree if [:lasgn,:iasgn,:gasgn,:cdecl].include? node_type
|
152
|
+
|
153
|
+
self
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def first_tree_rescue
|
158
|
+
if self[1].node_type == :resbody
|
159
|
+
return self
|
160
|
+
else
|
161
|
+
return self[1].first_tree
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def first_tree_return
|
166
|
+
self[1] ? self[1].first_tree : self
|
167
|
+
end
|
168
|
+
|
169
|
+
alias first_tree_break first_tree_return
|
170
|
+
alias first_tree_next first_tree_return
|
171
|
+
|
172
|
+
def first_tree_yield
|
173
|
+
if self.size > 1
|
174
|
+
self[-1].first_tree
|
175
|
+
else
|
176
|
+
self
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def first_tree_iter
|
181
|
+
call_tree = self[1]
|
182
|
+
recv = call_tree[1]
|
183
|
+
if recv
|
184
|
+
recv.first_tree
|
185
|
+
else
|
186
|
+
args_tree = call_tree[3]
|
187
|
+
if args_tree.size > 1
|
188
|
+
args_tree[1].first_tree
|
189
|
+
else
|
190
|
+
call_tree
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def first_tree_call
|
196
|
+
recv = self[1]
|
197
|
+
if recv
|
198
|
+
recv.first_tree
|
199
|
+
else
|
200
|
+
args_tree = self[3]
|
201
|
+
if args_tree.size > 1
|
202
|
+
args_tree[1].first_tree
|
203
|
+
else
|
204
|
+
self
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def find_break(&blk)
|
210
|
+
subarray = if node_type == :while
|
211
|
+
[]
|
212
|
+
elsif node_type == :iter
|
213
|
+
self[1..-2]
|
214
|
+
elsif node_type == :break
|
215
|
+
blk.call(self)
|
216
|
+
return; nil
|
217
|
+
else
|
218
|
+
self[1..-1]
|
219
|
+
end
|
220
|
+
|
221
|
+
subarray.each do |subtree|
|
222
|
+
if subtree.respond_to? :find_break
|
223
|
+
subtree.find_break(&blk)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
38
227
|
end
|
39
228
|
end
|
40
229
|
|
@@ -0,0 +1,210 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
This file is part of the fastruby project, http://github.com/tario/fastruby
|
4
|
+
|
5
|
+
Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
|
6
|
+
|
7
|
+
fastruby is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the gnu general public license as published by
|
9
|
+
the free software foundation, either version 3 of the license, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
fastruby is distributed in the hope that it will be useful,
|
13
|
+
but without any warranty; without even the implied warranty of
|
14
|
+
merchantability or fitness for a particular purpose. see the
|
15
|
+
gnu general public license for more details.
|
16
|
+
|
17
|
+
you should have received a copy of the gnu general public license
|
18
|
+
along with fastruby. if not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
module FastRuby
|
22
|
+
class FastRubySexp
|
23
|
+
class Edges
|
24
|
+
def initialize(frbsexp)
|
25
|
+
@frbsexp = frbsexp
|
26
|
+
end
|
27
|
+
|
28
|
+
def each(&blk)
|
29
|
+
node_type = @frbsexp.node_type
|
30
|
+
|
31
|
+
@frbsexp.each do|st|
|
32
|
+
next unless FastRubySexp === st
|
33
|
+
st.edges.each(&blk)
|
34
|
+
end
|
35
|
+
|
36
|
+
if respond_to? "edges_#{node_type}"
|
37
|
+
send("edges_#{node_type}", &blk)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def edges_lasgn(&blk)
|
42
|
+
blk.call(@frbsexp[2],@frbsexp)
|
43
|
+
end
|
44
|
+
|
45
|
+
alias edges_gasgn edges_lasgn
|
46
|
+
alias edges_cdecl edges_lasgn
|
47
|
+
alias edges_iasgn edges_lasgn
|
48
|
+
|
49
|
+
def edges_ensure(&blk)
|
50
|
+
if @frbsexp.size > 2
|
51
|
+
@frbsexp[1].walk_tree do |subtree|
|
52
|
+
if subtree.node_type == :call or subtree.node_type == :iter
|
53
|
+
blk.call(subtree,@frbsexp[2].first_tree)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
blk.call(@frbsexp[2],@frbsexp)
|
58
|
+
else
|
59
|
+
blk.call(@frbsexp[1],@frbsexp)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def edges_rescue(&blk)
|
64
|
+
return if @frbsexp[1].node_type == :resbody
|
65
|
+
|
66
|
+
blk.call(@frbsexp[1],@frbsexp)
|
67
|
+
|
68
|
+
exit_tree = nil
|
69
|
+
resbody_array_tree = @frbsexp[2][1]
|
70
|
+
|
71
|
+
if resbody_array_tree.size > 1
|
72
|
+
exit_tree = resbody_array_tree[1].first_tree
|
73
|
+
lasgn_tree = resbody_array_tree.find{|st|
|
74
|
+
if st.respond_to? :node_type
|
75
|
+
st.node_type == :lasgn
|
76
|
+
else
|
77
|
+
false
|
78
|
+
end
|
79
|
+
}
|
80
|
+
|
81
|
+
(1..resbody_array_tree.size-2).each do |i|
|
82
|
+
blk.call(resbody_array_tree[i], resbody_array_tree[i+1].first_tree)
|
83
|
+
|
84
|
+
if lasgn_tree
|
85
|
+
blk.call(resbody_array_tree[i], lasgn_tree.first_tree)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
if @frbsexp[2]
|
90
|
+
if @frbsexp[2][2]
|
91
|
+
blk.call(resbody_array_tree[-1],@frbsexp[2][2].first_tree)
|
92
|
+
else
|
93
|
+
blk.call(resbody_array_tree[-1],@frbsexp)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
blk.call(resbody_array_tree[-1],@frbsexp)
|
97
|
+
end
|
98
|
+
else
|
99
|
+
if @frbsexp[2]
|
100
|
+
if @frbsexp[2][2]
|
101
|
+
exit_tree = @frbsexp[2][2].first_tree
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
unless exit_tree
|
107
|
+
exit_tree = @frbsexp
|
108
|
+
end
|
109
|
+
|
110
|
+
if @frbsexp[2]
|
111
|
+
if @frbsexp[2][2]
|
112
|
+
blk.call(@frbsexp[2][2],@frbsexp)
|
113
|
+
blk.call(@frbsexp[1],exit_tree)
|
114
|
+
retry_tree = @frbsexp[2][2].find_tree(:retry)
|
115
|
+
if retry_tree
|
116
|
+
blk.call(retry_tree,@frbsexp[1].first_tree)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
@frbsexp[1].walk_tree do |subtree|
|
122
|
+
if subtree.node_type == :call or subtree.node_type == :iter
|
123
|
+
blk.call(subtree,exit_tree)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
def edges_or(&blk)
|
130
|
+
(1..@frbsexp.size-2).each do |i|
|
131
|
+
blk.call(@frbsexp[i],@frbsexp[i+1].first_tree)
|
132
|
+
end
|
133
|
+
|
134
|
+
blk.call(@frbsexp[-1],@frbsexp)
|
135
|
+
end
|
136
|
+
alias edges_and edges_or
|
137
|
+
|
138
|
+
def edges_if(&blk)
|
139
|
+
if @frbsexp[2]
|
140
|
+
blk.call(@frbsexp[1],@frbsexp[2].first_tree)
|
141
|
+
blk.call(@frbsexp[2],@frbsexp)
|
142
|
+
end
|
143
|
+
|
144
|
+
if @frbsexp[3]
|
145
|
+
blk.call(@frbsexp[3],@frbsexp)
|
146
|
+
blk.call(@frbsexp[1],@frbsexp[3].first_tree)
|
147
|
+
end
|
148
|
+
|
149
|
+
unless @frbsexp[2] and @frbsexp[3]
|
150
|
+
blk.call(@frbsexp[1],@frbsexp)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def edges_scope(&blk)
|
155
|
+
blk.call(@frbsexp[1], @frbsexp)
|
156
|
+
end
|
157
|
+
|
158
|
+
def edges_while(&blk)
|
159
|
+
if @frbsexp[2]
|
160
|
+
blk.call(@frbsexp[1], @frbsexp[2].first_tree)
|
161
|
+
blk.call(@frbsexp[2], @frbsexp[1].first_tree)
|
162
|
+
@frbsexp[2].find_break do |subtree|
|
163
|
+
blk.call(subtree, @frbsexp)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
blk.call(@frbsexp[1], @frbsexp)
|
168
|
+
end
|
169
|
+
|
170
|
+
alias edges_until edges_while
|
171
|
+
|
172
|
+
def edges_block(&blk)
|
173
|
+
(2..@frbsexp.size-1).each do |i|
|
174
|
+
blk.call(@frbsexp[i-1], @frbsexp[i].first_tree)
|
175
|
+
end
|
176
|
+
blk.call(@frbsexp.last, @frbsexp)
|
177
|
+
end
|
178
|
+
|
179
|
+
def edges_call(&blk)
|
180
|
+
args_tree = @frbsexp[3]
|
181
|
+
|
182
|
+
(2..args_tree.size-1).each do |i|
|
183
|
+
blk.call(args_tree[i-1], args_tree[i])
|
184
|
+
end
|
185
|
+
|
186
|
+
recv_tree = @frbsexp[1]
|
187
|
+
|
188
|
+
if recv_tree
|
189
|
+
if args_tree.size > 1
|
190
|
+
blk.call(recv_tree, args_tree[1])
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
if args_tree.size > 1
|
195
|
+
blk.call(args_tree.last, @frbsexp)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def self.do_nothing_for(*nodename)
|
200
|
+
nodename.each do |nn|
|
201
|
+
define_method("edges_#{nn}") do
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
do_nothing_for(:nil,:lit,:break)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|