ParseTree 1.1.0
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/History.txt +15 -0
- data/Makefile +25 -0
- data/Manifest.txt +14 -0
- data/README.txt +104 -0
- data/composite_sexp_processor.rb +24 -0
- data/parse_tree.rb +545 -0
- data/parse_tree_abc +62 -0
- data/parse_tree_show +28 -0
- data/sexp_processor.rb +301 -0
- data/something.rb +162 -0
- data/test_all.rb +7 -0
- data/test_composite_sexp_processor.rb +69 -0
- data/test_parse_tree.rb +275 -0
- data/test_sexp_processor.rb +382 -0
- metadata +55 -0
data/History.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
*** 1.1.0 / 2004-11-12
|
2
|
+
|
3
|
+
+ 2 minor enhancement
|
4
|
+
+ Added SexpProcessor and CompositeSexpProcessor
|
5
|
+
+ Allowed show.rb to read from standard input.
|
6
|
+
+ 3 bug fixes
|
7
|
+
+ Fixed makefile issues for BSD's make - so dumb.
|
8
|
+
+ Added super as a call in abc.rb's metrics
|
9
|
+
+ Commented out a compiler flag to work with GCC 2.95.
|
10
|
+
|
11
|
+
|
12
|
+
*** 1.0.0 / 2004-11-06
|
13
|
+
|
14
|
+
+ 1 major enhancement
|
15
|
+
+ Birthday!
|
data/Makefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
RUBY?=ruby
|
2
|
+
RUBY_FLAGS?=-w -I.
|
3
|
+
RUBY_LIB?=$(shell $(RUBY) -rrbconfig -e 'include Config; print CONFIG["sitelibdir"]')
|
4
|
+
PREFIX?=/usr/local
|
5
|
+
|
6
|
+
all test:
|
7
|
+
$(RUBY) $(RUBY_FLAGS) test_all.rb
|
8
|
+
|
9
|
+
# we only install test_sexp_processor.rb to help make ruby_to_c's
|
10
|
+
# subclass tests work.
|
11
|
+
|
12
|
+
install:
|
13
|
+
cp -f parse_tree.rb test_sexp_processor.rb sexp_processor.rb composite_sexp_processor.rb $(RUBY_LIB)
|
14
|
+
cp -f parse_tree_show $(PREFIX)/bin
|
15
|
+
cp -f parse_tree_abc $(PREFIX)/bin
|
16
|
+
chmod 444 $(RUBY_LIB)/parse_tree.rb $(RUBY_LIB)/sexp_processor.rb $(RUBY_LIB)/composite_sexp_processor.rb $(RUBY_LIB)/test_sexp_processor.rb
|
17
|
+
chmod 555 $(PREFIX)/bin/parse_tree_show $(PREFIX)/bin/parse_tree_abc
|
18
|
+
|
19
|
+
uninstall:
|
20
|
+
rm -f $(RUBY_LIB)/parse_tree.rb $(RUBY_LIB)/sexp_processor.rb $(RUBY_LIB)/composite_sexp_processor.rb $(RUBY_LIB)/test_sexp_processor.rb
|
21
|
+
rm -f $(PREFIX)/bin/parse_tree_show $(PREFIX)/bin/parse_tree_abc
|
22
|
+
|
23
|
+
clean:
|
24
|
+
-rm *~ diff.txt
|
25
|
+
-rm -r $$HOME/.ruby_inline
|
data/Manifest.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
History.txt
|
2
|
+
Makefile
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
composite_sexp_processor.rb
|
6
|
+
parse_tree.rb
|
7
|
+
parse_tree_abc
|
8
|
+
parse_tree_show
|
9
|
+
sexp_processor.rb
|
10
|
+
something.rb
|
11
|
+
test_all.rb
|
12
|
+
test_composite_sexp_processor.rb
|
13
|
+
test_parse_tree.rb
|
14
|
+
test_sexp_processor.rb
|
data/README.txt
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
ParseTree
|
2
|
+
http://www.zenspider.com/ZSS/Products/ParseTree/
|
3
|
+
support@zenspider.com
|
4
|
+
|
5
|
+
** DESCRIPTION:
|
6
|
+
|
7
|
+
ParseTree is a C extension (using RubyInline) that extracts the parse
|
8
|
+
tree for an entire class or a specific method and returns it as a
|
9
|
+
s-expression (aka sexp) using ruby's arrays, strings, symbols, and
|
10
|
+
integers.
|
11
|
+
|
12
|
+
As an example:
|
13
|
+
|
14
|
+
def conditional1(arg1)
|
15
|
+
if arg1 == 0 then
|
16
|
+
return 1
|
17
|
+
end
|
18
|
+
return 0
|
19
|
+
end
|
20
|
+
|
21
|
+
becomes:
|
22
|
+
|
23
|
+
[:defn,
|
24
|
+
"conditional1",
|
25
|
+
[:scope,
|
26
|
+
[:block,
|
27
|
+
[:args, "arg1"],
|
28
|
+
[:if,
|
29
|
+
[:call, [:lvar, "arg1"], "==", [:array, [:lit, 0]]],
|
30
|
+
[:return, [:lit, 1]],
|
31
|
+
nil],
|
32
|
+
[:return, [:lit, 0]]]]]
|
33
|
+
|
34
|
+
** FEATURES/PROBLEMS:
|
35
|
+
|
36
|
+
+ Uses RubyInline, so it just drops in.
|
37
|
+
+ Includes SexpProcessor and CompositeSexpProcessor.
|
38
|
+
+ Allows you to write very clean filters.
|
39
|
+
+ Includes show.rb, which lets you quickly snoop code.
|
40
|
+
+ Includes abc.rb, which lets you get abc metrics on code.
|
41
|
+
+ abc metrics = numbers of assignments, branches, and calls.
|
42
|
+
+ whitespace independent metric for method complexity.
|
43
|
+
+ Only works on methods in classes/modules, not arbitrary code.
|
44
|
+
+ Does not work on the core classes, as they are not ruby (yet).
|
45
|
+
|
46
|
+
** SYNOPSYS:
|
47
|
+
|
48
|
+
sexp_array = ParseTree.new.parse_tree(klass)
|
49
|
+
|
50
|
+
or:
|
51
|
+
|
52
|
+
class MyProcessor < SexpProcessor
|
53
|
+
def initialize
|
54
|
+
super
|
55
|
+
self.strict = false
|
56
|
+
end
|
57
|
+
def process_lit(exp)
|
58
|
+
val = exp.shift
|
59
|
+
return val
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
or:
|
64
|
+
|
65
|
+
% ./parse_tree_show myfile.rb
|
66
|
+
|
67
|
+
or:
|
68
|
+
|
69
|
+
% ./parse_tree_abc myfile.rb
|
70
|
+
|
71
|
+
** REQUIREMENTS:
|
72
|
+
|
73
|
+
+ RubyInline 3 or better.
|
74
|
+
|
75
|
+
** INSTALL:
|
76
|
+
|
77
|
+
+ sudo make install
|
78
|
+
+ renames show.rb to parse_tree_show
|
79
|
+
+ renames abc.rb to parse_tree_abc
|
80
|
+
|
81
|
+
** LICENSE:
|
82
|
+
|
83
|
+
(The MIT License)
|
84
|
+
|
85
|
+
Copyright (c) 2001-2004 Ryan Davis, Zen Spider Software
|
86
|
+
|
87
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
88
|
+
a copy of this software and associated documentation files (the
|
89
|
+
"Software"), to deal in the Software without restriction, including
|
90
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
91
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
92
|
+
permit persons to whom the Software is furnished to do so, subject to
|
93
|
+
the following conditions:
|
94
|
+
|
95
|
+
The above copyright notice and this permission notice shall be
|
96
|
+
included in all copies or substantial portions of the Software.
|
97
|
+
|
98
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
99
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
100
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
101
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
102
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
103
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
104
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'sexp_processor'
|
2
|
+
|
3
|
+
class CompositeSexpProcessor < SexpProcessor
|
4
|
+
|
5
|
+
attr_reader :processors
|
6
|
+
|
7
|
+
def initialize(*processors)
|
8
|
+
super
|
9
|
+
@processors = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(processor)
|
13
|
+
raise ArgumentError, "Can only add sexp processors" unless
|
14
|
+
SexpProcessor === processor
|
15
|
+
@processors << processor
|
16
|
+
end
|
17
|
+
|
18
|
+
def process(exp)
|
19
|
+
@processors.each do |processor|
|
20
|
+
exp = processor.process(exp)
|
21
|
+
end
|
22
|
+
exp
|
23
|
+
end
|
24
|
+
end
|
data/parse_tree.rb
ADDED
@@ -0,0 +1,545 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
require_gem 'RubyInline'
|
6
|
+
rescue LoadError
|
7
|
+
require 'inline'
|
8
|
+
end
|
9
|
+
|
10
|
+
class ParseTree
|
11
|
+
|
12
|
+
VERSION = '1.1.0'
|
13
|
+
|
14
|
+
inline do |builder|
|
15
|
+
builder.add_type_converter("VALUE", '', '')
|
16
|
+
builder.add_type_converter("NODE *", '(NODE *)', '(VALUE)')
|
17
|
+
builder.include '"intern.h"'
|
18
|
+
builder.include '"node.h"'
|
19
|
+
builder.include '"st.h"'
|
20
|
+
builder.add_compile_flags "-Wall"
|
21
|
+
builder.add_compile_flags "-W"
|
22
|
+
builder.add_compile_flags "-Wpointer-arith"
|
23
|
+
builder.add_compile_flags "-Wcast-qual"
|
24
|
+
builder.add_compile_flags "-Wcast-align"
|
25
|
+
builder.add_compile_flags "-Wwrite-strings"
|
26
|
+
builder.add_compile_flags "-Wmissing-noreturn"
|
27
|
+
builder.add_compile_flags "-Werror"
|
28
|
+
# NOTE: this flag doesn't work w/ gcc 2.95.x - the FreeBSD default
|
29
|
+
# builder.add_compile_flags "-Wno-strict-aliasing"
|
30
|
+
# ruby.h screws these up hardcore:
|
31
|
+
# builder.add_compile_flags "-Wundef"
|
32
|
+
# builder.add_compile_flags "-Wconversion"
|
33
|
+
# builder.add_compile_flags "-Wstrict-prototypes"
|
34
|
+
# builder.add_compile_flags "-Wmissing-prototypes"
|
35
|
+
# builder.add_compile_flags "-Wsign-compare",
|
36
|
+
|
37
|
+
builder.prefix %q{
|
38
|
+
static char node_type_string[][60] = {
|
39
|
+
// 00
|
40
|
+
"method", "fbody", "cfunc", "scope", "block",
|
41
|
+
"if", "case", "when", "opt_n", "while",
|
42
|
+
// 10
|
43
|
+
"until", "iter", "for", "break", "next",
|
44
|
+
"redo", "retry", "begin", "rescue", "resbody",
|
45
|
+
// 20
|
46
|
+
"ensure", "and", "or", "not", "masgn",
|
47
|
+
"lasgn", "dasgn", "dasgn_curr", "gasgn", "iasgn",
|
48
|
+
// 30
|
49
|
+
"cdecl", "cvasgn", "cvdecl", "op_asgn1", "op_asgn2",
|
50
|
+
"op_asgn_and", "op_asgn_or", "call", "fcall", "vcall",
|
51
|
+
// 40
|
52
|
+
"super", "zsuper", "array", "zarray", "hash",
|
53
|
+
"return", "yield", "lvar", "dvar", "gvar",
|
54
|
+
// 50
|
55
|
+
"ivar", "const", "cvar", "nth_ref", "back_ref",
|
56
|
+
"match", "match2", "match3", "lit", "str",
|
57
|
+
// 60
|
58
|
+
"dstr", "xstr", "dxstr", "evstr", "dregx",
|
59
|
+
"dregx_once", "args", "argscat", "argspush", "splat",
|
60
|
+
// 70
|
61
|
+
"to_ary", "svalue", "block_arg", "block_pass", "defn",
|
62
|
+
"defs", "alias", "valias", "undef", "class",
|
63
|
+
// 80
|
64
|
+
"module", "sclass", "colon2", "colon3", "cref",
|
65
|
+
"dot2", "dot3", "flip2", "flip3", "attrset",
|
66
|
+
// 90
|
67
|
+
"self", "nil", "true", "false", "defined",
|
68
|
+
// 95
|
69
|
+
"newline", "postexe",
|
70
|
+
#ifdef C_ALLOCA
|
71
|
+
"alloca",
|
72
|
+
#endif
|
73
|
+
"dmethod", "bmethod",
|
74
|
+
// 100 / 99
|
75
|
+
"memo", "ifunc", "dsym", "attrasgn",
|
76
|
+
// 104 / 103
|
77
|
+
"last"
|
78
|
+
};
|
79
|
+
}
|
80
|
+
|
81
|
+
builder.c_raw %q^
|
82
|
+
// FIX!!!
|
83
|
+
static ID *dump_local_tbl;
|
84
|
+
|
85
|
+
static void add_to_parse_tree(VALUE ary, NODE * n) {
|
86
|
+
NODE * volatile node = n;
|
87
|
+
NODE * volatile contnode = NULL;
|
88
|
+
VALUE old_ary = Qnil;
|
89
|
+
VALUE current;
|
90
|
+
VALUE node_name;
|
91
|
+
|
92
|
+
if (!node) return;
|
93
|
+
|
94
|
+
again:
|
95
|
+
|
96
|
+
if (node) {
|
97
|
+
node_name = ID2SYM(rb_intern(node_type_string[nd_type(node)]));
|
98
|
+
} else {
|
99
|
+
node_name = ID2SYM(rb_intern("ICKY"));
|
100
|
+
}
|
101
|
+
|
102
|
+
current = rb_ary_new();
|
103
|
+
rb_ary_push(ary, current);
|
104
|
+
rb_ary_push(current, node_name);
|
105
|
+
|
106
|
+
again_no_block:
|
107
|
+
|
108
|
+
switch (nd_type(node)) {
|
109
|
+
|
110
|
+
case NODE_BLOCK:
|
111
|
+
if (contnode) {
|
112
|
+
add_to_parse_tree(current, node);
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
|
116
|
+
contnode = node->nd_next;
|
117
|
+
|
118
|
+
// NOTE: this will break the moment there is a block w/in a block
|
119
|
+
old_ary = ary;
|
120
|
+
ary = current;
|
121
|
+
node = node->nd_head;
|
122
|
+
goto again;
|
123
|
+
break;
|
124
|
+
|
125
|
+
case NODE_FBODY:
|
126
|
+
case NODE_DEFINED:
|
127
|
+
add_to_parse_tree(current, node->nd_head);
|
128
|
+
break;
|
129
|
+
|
130
|
+
case NODE_COLON2:
|
131
|
+
add_to_parse_tree(current, node->nd_head);
|
132
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(node->nd_mid)));
|
133
|
+
break;
|
134
|
+
|
135
|
+
case NODE_BEGIN:
|
136
|
+
node = node->nd_body;
|
137
|
+
goto again;
|
138
|
+
|
139
|
+
case NODE_MATCH2:
|
140
|
+
case NODE_MATCH3:
|
141
|
+
add_to_parse_tree(current, node->nd_recv);
|
142
|
+
add_to_parse_tree(current, node->nd_value);
|
143
|
+
break;
|
144
|
+
|
145
|
+
case NODE_OPT_N:
|
146
|
+
add_to_parse_tree(current, node->nd_body);
|
147
|
+
break;
|
148
|
+
|
149
|
+
case NODE_IF:
|
150
|
+
add_to_parse_tree(current, node->nd_cond);
|
151
|
+
if (node->nd_body) {
|
152
|
+
add_to_parse_tree(current, node->nd_body);
|
153
|
+
} else {
|
154
|
+
rb_ary_push(current, Qnil);
|
155
|
+
}
|
156
|
+
if (node->nd_else) {
|
157
|
+
add_to_parse_tree(current, node->nd_else);
|
158
|
+
} else {
|
159
|
+
rb_ary_push(current, Qnil);
|
160
|
+
}
|
161
|
+
break;
|
162
|
+
|
163
|
+
case NODE_CASE:
|
164
|
+
add_to_parse_tree(current, node->nd_head); /* expr */
|
165
|
+
node = node->nd_body;
|
166
|
+
while (node) {
|
167
|
+
add_to_parse_tree(current, node);
|
168
|
+
if (nd_type(node) == NODE_WHEN) { /* when */
|
169
|
+
node = node->nd_next;
|
170
|
+
} else {
|
171
|
+
break; /* else */
|
172
|
+
}
|
173
|
+
if (! node) {
|
174
|
+
rb_ary_push(current, Qnil); /* no else */
|
175
|
+
}
|
176
|
+
}
|
177
|
+
break;
|
178
|
+
|
179
|
+
case NODE_WHEN:
|
180
|
+
add_to_parse_tree(current, node->nd_head); /* args */
|
181
|
+
if (node->nd_body) {
|
182
|
+
add_to_parse_tree(current, node->nd_body); /* body */
|
183
|
+
} else {
|
184
|
+
rb_ary_push(current, Qnil);
|
185
|
+
}
|
186
|
+
break;
|
187
|
+
|
188
|
+
case NODE_WHILE:
|
189
|
+
case NODE_UNTIL:
|
190
|
+
add_to_parse_tree(current, node->nd_cond);
|
191
|
+
add_to_parse_tree(current, node->nd_body);
|
192
|
+
break;
|
193
|
+
|
194
|
+
case NODE_BLOCK_PASS:
|
195
|
+
add_to_parse_tree(current, node->nd_body);
|
196
|
+
add_to_parse_tree(current, node->nd_iter);
|
197
|
+
break;
|
198
|
+
|
199
|
+
case NODE_ITER:
|
200
|
+
case NODE_FOR:
|
201
|
+
add_to_parse_tree(current, node->nd_iter);
|
202
|
+
if (node->nd_var != (NODE *)-1 && node->nd_var != NULL) {
|
203
|
+
add_to_parse_tree(current, node->nd_var);
|
204
|
+
} else {
|
205
|
+
rb_ary_push(current, Qnil);
|
206
|
+
}
|
207
|
+
add_to_parse_tree(current, node->nd_body);
|
208
|
+
break;
|
209
|
+
|
210
|
+
case NODE_BREAK:
|
211
|
+
case NODE_NEXT:
|
212
|
+
case NODE_YIELD:
|
213
|
+
if (node->nd_stts)
|
214
|
+
add_to_parse_tree(current, node->nd_stts);
|
215
|
+
break;
|
216
|
+
|
217
|
+
case NODE_RESCUE:
|
218
|
+
{
|
219
|
+
NODE *resq, *n;
|
220
|
+
int i;
|
221
|
+
|
222
|
+
add_to_parse_tree(current, node->nd_head);
|
223
|
+
resq = node->nd_resq;
|
224
|
+
while (resq) {
|
225
|
+
if (nd_type(resq) == NODE_ARRAY) {
|
226
|
+
n = resq;
|
227
|
+
for (i = 0; i < resq->nd_alen; i++) {
|
228
|
+
add_to_parse_tree(current, n->nd_head);
|
229
|
+
n = n->nd_next;
|
230
|
+
}
|
231
|
+
} else {
|
232
|
+
add_to_parse_tree(current, resq->nd_args);
|
233
|
+
}
|
234
|
+
add_to_parse_tree(current, resq->nd_body);
|
235
|
+
resq = resq->nd_head;
|
236
|
+
}
|
237
|
+
if (node->nd_else) {
|
238
|
+
add_to_parse_tree(current, node->nd_else);
|
239
|
+
}
|
240
|
+
}
|
241
|
+
break;
|
242
|
+
|
243
|
+
case NODE_ENSURE:
|
244
|
+
add_to_parse_tree(current, node->nd_head);
|
245
|
+
if (node->nd_ensr) {
|
246
|
+
add_to_parse_tree(current, node->nd_ensr);
|
247
|
+
}
|
248
|
+
break;
|
249
|
+
|
250
|
+
case NODE_AND:
|
251
|
+
case NODE_OR:
|
252
|
+
add_to_parse_tree(current, node->nd_1st);
|
253
|
+
add_to_parse_tree(current, node->nd_2nd);
|
254
|
+
break;
|
255
|
+
|
256
|
+
case NODE_NOT:
|
257
|
+
add_to_parse_tree(current, node->nd_body);
|
258
|
+
break;
|
259
|
+
|
260
|
+
case NODE_DOT2:
|
261
|
+
case NODE_DOT3:
|
262
|
+
case NODE_FLIP2:
|
263
|
+
case NODE_FLIP3:
|
264
|
+
add_to_parse_tree(current, node->nd_beg);
|
265
|
+
add_to_parse_tree(current, node->nd_end);
|
266
|
+
break;
|
267
|
+
|
268
|
+
case NODE_RETURN:
|
269
|
+
if (node->nd_stts)
|
270
|
+
add_to_parse_tree(current, node->nd_stts);
|
271
|
+
break;
|
272
|
+
|
273
|
+
case NODE_ARGSCAT:
|
274
|
+
case NODE_ARGSPUSH:
|
275
|
+
add_to_parse_tree(current, node->nd_head);
|
276
|
+
add_to_parse_tree(current, node->nd_body);
|
277
|
+
break;
|
278
|
+
|
279
|
+
case NODE_CALL:
|
280
|
+
case NODE_FCALL:
|
281
|
+
case NODE_VCALL:
|
282
|
+
if (nd_type(node) != NODE_FCALL)
|
283
|
+
add_to_parse_tree(current, node->nd_recv);
|
284
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(node->nd_mid)));
|
285
|
+
if (node->nd_args || nd_type(node) != NODE_FCALL)
|
286
|
+
add_to_parse_tree(current, node->nd_args);
|
287
|
+
break;
|
288
|
+
|
289
|
+
case NODE_SUPER:
|
290
|
+
add_to_parse_tree(current, node->nd_args);
|
291
|
+
break;
|
292
|
+
|
293
|
+
case NODE_DMETHOD:
|
294
|
+
{
|
295
|
+
struct METHOD *data;
|
296
|
+
Data_Get_Struct(node->nd_cval, struct METHOD, data);
|
297
|
+
break;
|
298
|
+
}
|
299
|
+
|
300
|
+
case NODE_SCOPE:
|
301
|
+
dump_local_tbl = node->nd_tbl;
|
302
|
+
add_to_parse_tree(current, node->nd_next);
|
303
|
+
break;
|
304
|
+
|
305
|
+
case NODE_OP_ASGN1:
|
306
|
+
add_to_parse_tree(current, node->nd_recv);
|
307
|
+
add_to_parse_tree(current, node->nd_args->nd_next);
|
308
|
+
add_to_parse_tree(current, node->nd_args->nd_head);
|
309
|
+
break;
|
310
|
+
|
311
|
+
case NODE_OP_ASGN2:
|
312
|
+
add_to_parse_tree(current, node->nd_recv);
|
313
|
+
add_to_parse_tree(current, node->nd_value);
|
314
|
+
break;
|
315
|
+
|
316
|
+
case NODE_OP_ASGN_AND:
|
317
|
+
case NODE_OP_ASGN_OR:
|
318
|
+
add_to_parse_tree(current, node->nd_head);
|
319
|
+
add_to_parse_tree(current, node->nd_value);
|
320
|
+
break;
|
321
|
+
|
322
|
+
case NODE_MASGN:
|
323
|
+
add_to_parse_tree(current, node->nd_head);
|
324
|
+
if (node->nd_args) {
|
325
|
+
if (node->nd_args != (NODE *)-1) {
|
326
|
+
add_to_parse_tree(current, node->nd_args);
|
327
|
+
}
|
328
|
+
}
|
329
|
+
add_to_parse_tree(current, node->nd_value);
|
330
|
+
break;
|
331
|
+
|
332
|
+
case NODE_LASGN:
|
333
|
+
case NODE_IASGN:
|
334
|
+
case NODE_DASGN:
|
335
|
+
case NODE_DASGN_CURR:
|
336
|
+
case NODE_CDECL:
|
337
|
+
case NODE_CVASGN:
|
338
|
+
case NODE_CVDECL:
|
339
|
+
case NODE_GASGN:
|
340
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(node->nd_vid)));
|
341
|
+
add_to_parse_tree(current, node->nd_value);
|
342
|
+
break;
|
343
|
+
|
344
|
+
case NODE_HASH:
|
345
|
+
{
|
346
|
+
NODE *list;
|
347
|
+
|
348
|
+
list = node->nd_head;
|
349
|
+
while (list) {
|
350
|
+
add_to_parse_tree(current, list->nd_head);
|
351
|
+
list = list->nd_next;
|
352
|
+
if (list == 0)
|
353
|
+
rb_bug("odd number list for Hash");
|
354
|
+
add_to_parse_tree(current, list->nd_head);
|
355
|
+
list = list->nd_next;
|
356
|
+
}
|
357
|
+
}
|
358
|
+
break;
|
359
|
+
|
360
|
+
case NODE_ARRAY:
|
361
|
+
while (node) {
|
362
|
+
add_to_parse_tree(current, node->nd_head);
|
363
|
+
node = node->nd_next;
|
364
|
+
}
|
365
|
+
break;
|
366
|
+
|
367
|
+
case NODE_DSTR:
|
368
|
+
case NODE_DXSTR:
|
369
|
+
case NODE_DREGX:
|
370
|
+
case NODE_DREGX_ONCE:
|
371
|
+
{
|
372
|
+
NODE *list = node->nd_next;
|
373
|
+
if (nd_type(node) == NODE_DREGX || nd_type(node) == NODE_DREGX_ONCE) {
|
374
|
+
break;
|
375
|
+
}
|
376
|
+
rb_ary_push(current, rb_str_new3(node->nd_lit));
|
377
|
+
while (list) {
|
378
|
+
if (list->nd_head) {
|
379
|
+
switch (nd_type(list->nd_head)) {
|
380
|
+
case NODE_STR:
|
381
|
+
add_to_parse_tree(current, list->nd_head);
|
382
|
+
break;
|
383
|
+
case NODE_EVSTR:
|
384
|
+
add_to_parse_tree(current, list->nd_head->nd_body);
|
385
|
+
break;
|
386
|
+
default:
|
387
|
+
add_to_parse_tree(current, list->nd_head);
|
388
|
+
break;
|
389
|
+
}
|
390
|
+
}
|
391
|
+
list = list->nd_next;
|
392
|
+
}
|
393
|
+
}
|
394
|
+
break;
|
395
|
+
|
396
|
+
case NODE_DEFN:
|
397
|
+
case NODE_DEFS:
|
398
|
+
if (node->nd_defn) {
|
399
|
+
if (nd_type(node) == NODE_DEFS)
|
400
|
+
add_to_parse_tree(current, node->nd_recv);
|
401
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(node->nd_mid)));
|
402
|
+
add_to_parse_tree(current, node->nd_defn);
|
403
|
+
}
|
404
|
+
break;
|
405
|
+
|
406
|
+
case NODE_CLASS:
|
407
|
+
case NODE_MODULE:
|
408
|
+
rb_ary_push(current, rb_str_new2(rb_id2name((ID)node->nd_cpath->nd_mid)));
|
409
|
+
if (node->nd_super && nd_type(node) == NODE_CLASS) {
|
410
|
+
add_to_parse_tree(current, node->nd_super);
|
411
|
+
}
|
412
|
+
add_to_parse_tree(current, node->nd_body);
|
413
|
+
break;
|
414
|
+
|
415
|
+
case NODE_SCLASS:
|
416
|
+
add_to_parse_tree(current, node->nd_recv);
|
417
|
+
add_to_parse_tree(current, node->nd_body);
|
418
|
+
break;
|
419
|
+
|
420
|
+
case NODE_ARGS:
|
421
|
+
if (dump_local_tbl &&
|
422
|
+
(node->nd_cnt || node->nd_opt || node->nd_rest != -1)) {
|
423
|
+
int i;
|
424
|
+
NODE *optnode;
|
425
|
+
|
426
|
+
for (i = 0; i < node->nd_cnt; i++) {
|
427
|
+
// regular arg names
|
428
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(dump_local_tbl[i + 3])));
|
429
|
+
}
|
430
|
+
|
431
|
+
optnode = node->nd_opt;
|
432
|
+
while (optnode) {
|
433
|
+
// optional arg names
|
434
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(dump_local_tbl[i + 3])));
|
435
|
+
i++;
|
436
|
+
optnode = optnode->nd_next;
|
437
|
+
}
|
438
|
+
if (node->nd_rest != -1) {
|
439
|
+
// *arg name
|
440
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(dump_local_tbl[node->nd_rest + 1])));
|
441
|
+
}
|
442
|
+
optnode = node->nd_opt;
|
443
|
+
//
|
444
|
+
if (optnode) {
|
445
|
+
add_to_parse_tree(current, node->nd_opt);
|
446
|
+
}
|
447
|
+
}
|
448
|
+
break;
|
449
|
+
|
450
|
+
case NODE_LVAR:
|
451
|
+
case NODE_DVAR:
|
452
|
+
case NODE_IVAR:
|
453
|
+
case NODE_CVAR:
|
454
|
+
case NODE_GVAR:
|
455
|
+
case NODE_CONST:
|
456
|
+
case NODE_ATTRSET:
|
457
|
+
rb_ary_push(current, rb_str_new2(rb_id2name(node->nd_vid)));
|
458
|
+
break;
|
459
|
+
|
460
|
+
case NODE_STR:
|
461
|
+
case NODE_LIT:
|
462
|
+
rb_ary_push(current, node->nd_lit);
|
463
|
+
break;
|
464
|
+
|
465
|
+
case NODE_NEWLINE:
|
466
|
+
rb_ary_push(current, INT2FIX(nd_line(node)));
|
467
|
+
rb_ary_push(current, rb_str_new2(node->nd_file));
|
468
|
+
rb_ary_pop(ary); // nuke it for now
|
469
|
+
|
470
|
+
node = node->nd_next;
|
471
|
+
goto again;
|
472
|
+
|
473
|
+
// these are things we know we do not need to translate to C.
|
474
|
+
case NODE_BLOCK_ARG:
|
475
|
+
case NODE_SELF:
|
476
|
+
case NODE_NIL:
|
477
|
+
case NODE_TRUE:
|
478
|
+
case NODE_FALSE:
|
479
|
+
case NODE_ZSUPER:
|
480
|
+
case NODE_BMETHOD:
|
481
|
+
case NODE_REDO:
|
482
|
+
case NODE_RETRY:
|
483
|
+
case NODE_COLON3:
|
484
|
+
case NODE_NTH_REF:
|
485
|
+
case NODE_BACK_REF:
|
486
|
+
case NODE_ZARRAY:
|
487
|
+
case NODE_XSTR:
|
488
|
+
case NODE_UNDEF:
|
489
|
+
case NODE_ALIAS:
|
490
|
+
case NODE_VALIAS:
|
491
|
+
break;
|
492
|
+
|
493
|
+
default:
|
494
|
+
rb_ary_push(current, INT2FIX(-99));
|
495
|
+
rb_ary_push(current, INT2FIX(nd_type(node)));
|
496
|
+
break;
|
497
|
+
}
|
498
|
+
|
499
|
+
// finish:
|
500
|
+
if (contnode) {
|
501
|
+
node = contnode;
|
502
|
+
contnode = NULL;
|
503
|
+
current = ary;
|
504
|
+
ary = old_ary;
|
505
|
+
old_ary = Qnil;
|
506
|
+
goto again_no_block;
|
507
|
+
}
|
508
|
+
}
|
509
|
+
^
|
510
|
+
|
511
|
+
builder.c %q{
|
512
|
+
static VALUE parse_tree_for_method(VALUE klass, VALUE method) {
|
513
|
+
NODE *node = NULL;
|
514
|
+
ID id;
|
515
|
+
VALUE result = rb_ary_new();
|
516
|
+
|
517
|
+
(void) self; // quell warnings
|
518
|
+
|
519
|
+
id = rb_to_id(method);
|
520
|
+
if (st_lookup(RCLASS(klass)->m_tbl, id, (st_data_t *) &node)) {
|
521
|
+
rb_ary_push(result, ID2SYM(rb_intern("defn")));
|
522
|
+
rb_ary_push(result, method);
|
523
|
+
add_to_parse_tree(result, node->nd_body);
|
524
|
+
} else {
|
525
|
+
rb_ary_push(result, Qnil);
|
526
|
+
}
|
527
|
+
|
528
|
+
return result;
|
529
|
+
}
|
530
|
+
}
|
531
|
+
end
|
532
|
+
|
533
|
+
def parse_tree(klass, meth=nil)
|
534
|
+
code = []
|
535
|
+
if meth then
|
536
|
+
code = parse_tree_for_method(klass, meth.to_s)
|
537
|
+
else
|
538
|
+
klass.instance_methods(false).sort.each do |m|
|
539
|
+
code << parse_tree_for_method(klass, m)
|
540
|
+
end
|
541
|
+
end
|
542
|
+
return code
|
543
|
+
end
|
544
|
+
|
545
|
+
end
|