Tempfile document updated.
[ruby.git] / ast.c
blob12b3996f94b7ac9340bb74ccd5901adbbdc12860
1 /* indent-tabs-mode: nil */
2 #include "internal.h"
3 #include "internal/ruby_parser.h"
4 #include "internal/symbol.h"
5 #include "internal/warnings.h"
6 #include "iseq.h"
7 #include "node.h"
8 #include "ruby.h"
9 #include "ruby/encoding.h"
10 #include "ruby/util.h"
11 #include "vm_core.h"
13 #include "builtin.h"
15 static VALUE rb_mAST;
16 static VALUE rb_cNode;
18 struct ASTNodeData {
19 VALUE ast_value;
20 const NODE *node;
23 static void
24 node_gc_mark(void *ptr)
26 struct ASTNodeData *data = (struct ASTNodeData *)ptr;
27 rb_gc_mark(data->ast_value);
30 static size_t
31 node_memsize(const void *ptr)
33 struct ASTNodeData *data = (struct ASTNodeData *)ptr;
34 rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value);
36 return sizeof(struct ASTNodeData) + rb_ast_memsize(ast);
39 static const rb_data_type_t rb_node_type = {
40 "AST/node",
41 {node_gc_mark, RUBY_TYPED_DEFAULT_FREE, node_memsize,},
42 0, 0,
43 RUBY_TYPED_FREE_IMMEDIATELY,
46 static VALUE rb_ast_node_alloc(VALUE klass);
48 static void
49 setup_node(VALUE obj, VALUE ast_value, const NODE *node)
51 struct ASTNodeData *data;
53 TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data);
54 data->ast_value = ast_value;
55 data->node = node;
58 static VALUE
59 ast_new_internal(VALUE ast_value, const NODE *node)
61 VALUE obj;
63 obj = rb_ast_node_alloc(rb_cNode);
64 setup_node(obj, ast_value, node);
66 return obj;
69 static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
70 static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens);
72 static VALUE
73 ast_parse_new(void)
75 return rb_parser_set_context(rb_parser_new(), NULL, 0);
78 static VALUE
79 ast_parse_done(VALUE ast_value)
81 rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
83 if (!ast->body.root) {
84 rb_ast_dispose(ast);
85 rb_exc_raise(GET_EC()->errinfo);
88 return ast_new_internal(ast_value, (NODE *)ast->body.root);
91 static VALUE
92 ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
94 return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
97 static VALUE
98 rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
100 VALUE ast_value;
102 StringValue(str);
103 VALUE vparser = ast_parse_new();
104 if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
105 if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
106 if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
107 ast_value = rb_parser_compile_string_path(vparser, Qnil, str, 1);
108 return ast_parse_done(ast_value);
111 static VALUE
112 ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
114 return rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
117 static VALUE
118 rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
120 VALUE f;
121 VALUE ast_value = Qnil;
122 rb_encoding *enc = rb_utf8_encoding();
124 f = rb_file_open_str(path, "r");
125 rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
126 VALUE vparser = ast_parse_new();
127 if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
128 if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
129 if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
130 ast_value = rb_parser_compile_file_path(vparser, Qnil, f, 1);
131 rb_io_close(f);
132 return ast_parse_done(ast_value);
135 static VALUE
136 rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
138 VALUE ast_value = Qnil;
140 array = rb_check_array_type(array);
141 VALUE vparser = ast_parse_new();
142 if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
143 if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
144 if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
145 ast_value = rb_parser_compile_array(vparser, Qnil, array, 1);
146 return ast_parse_done(ast_value);
149 static VALUE node_children(VALUE, const NODE*);
151 static VALUE
152 node_find(VALUE self, const int node_id)
154 VALUE ary;
155 long i;
156 struct ASTNodeData *data;
157 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
159 if (nd_node_id(data->node) == node_id) return self;
161 ary = node_children(data->ast_value, data->node);
163 for (i = 0; i < RARRAY_LEN(ary); i++) {
164 VALUE child = RARRAY_AREF(ary, i);
166 if (CLASS_OF(child) == rb_cNode) {
167 VALUE result = node_find(child, node_id);
168 if (RTEST(result)) return result;
172 return Qnil;
175 extern VALUE rb_e_script;
177 static VALUE
178 node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location)
180 int node_id;
182 if (!rb_frame_info_p(location)) {
183 rb_raise(rb_eTypeError, "Thread::Backtrace::Location object expected");
186 node_id = rb_get_node_id_from_frame_info(location);
187 if (node_id == -1) {
188 return Qnil;
191 return INT2NUM(node_id);
194 static VALUE
195 ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
197 VALUE node, lines = Qnil;
198 const rb_iseq_t *iseq;
199 int node_id;
201 if (rb_frame_info_p(body)) {
202 iseq = rb_get_iseq_from_frame_info(body);
203 node_id = rb_get_node_id_from_frame_info(body);
205 else {
206 iseq = NULL;
208 if (rb_obj_is_proc(body)) {
209 iseq = vm_proc_iseq(body);
211 if (!rb_obj_is_iseq((VALUE)iseq)) return Qnil;
213 else {
214 iseq = rb_method_iseq(body);
216 if (iseq) {
217 node_id = ISEQ_BODY(iseq)->location.node_id;
221 if (!iseq) {
222 return Qnil;
225 if (ISEQ_BODY(iseq)->prism) {
226 rb_raise(rb_eRuntimeError, "cannot get AST for ISEQ compiled by prism");
229 lines = ISEQ_BODY(iseq)->variable.script_lines;
231 VALUE path = rb_iseq_path(iseq);
232 int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0;
234 if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) {
235 rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
238 if (!NIL_P(lines)) {
239 node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens);
241 else if (e_option) {
242 node = rb_ast_parse_str(rb_e_script, keep_script_lines, error_tolerant, keep_tokens);
244 else {
245 node = rb_ast_parse_file(path, keep_script_lines, error_tolerant, keep_tokens);
248 return node_find(node, node_id);
251 static VALUE
252 rb_ast_node_alloc(VALUE klass)
254 struct ASTNodeData *data;
255 VALUE obj = TypedData_Make_Struct(klass, struct ASTNodeData, &rb_node_type, data);
257 return obj;
260 static const char*
261 node_type_to_str(const NODE *node)
263 return (ruby_node_name(nd_type(node)) + rb_strlen_lit("NODE_"));
266 static VALUE
267 ast_node_type(rb_execution_context_t *ec, VALUE self)
269 struct ASTNodeData *data;
270 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
272 return rb_sym_intern_ascii_cstr(node_type_to_str(data->node));
275 static VALUE
276 ast_node_node_id(rb_execution_context_t *ec, VALUE self)
278 struct ASTNodeData *data;
279 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
281 return INT2FIX(nd_node_id(data->node));
284 #define NEW_CHILD(ast_value, node) (node ? ast_new_internal(ast_value, node) : Qnil)
286 static VALUE
287 rb_ary_new_from_node_args(VALUE ast_value, long n, ...)
289 va_list ar;
290 VALUE ary;
291 long i;
293 ary = rb_ary_new2(n);
295 va_start(ar, n);
296 for (i=0; i<n; i++) {
297 NODE *node;
298 node = va_arg(ar, NODE *);
299 rb_ary_push(ary, NEW_CHILD(ast_value, node));
301 va_end(ar);
302 return ary;
305 static VALUE
306 dump_block(VALUE ast_value, const struct RNode_BLOCK *node)
308 VALUE ary = rb_ary_new();
309 do {
310 rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
311 } while (node->nd_next &&
312 nd_type_p(node->nd_next, NODE_BLOCK) &&
313 (node = RNODE_BLOCK(node->nd_next), 1));
314 if (node->nd_next) {
315 rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
318 return ary;
321 static VALUE
322 dump_array(VALUE ast_value, const struct RNode_LIST *node)
324 VALUE ary = rb_ary_new();
325 rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
327 while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
328 node = RNODE_LIST(node->nd_next);
329 rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head));
331 rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next));
333 return ary;
336 static VALUE
337 var_name(ID id)
339 if (!id) return Qnil;
340 if (!rb_id2str(id)) return Qnil;
341 return ID2SYM(id);
344 static VALUE
345 no_name_rest(void)
347 ID rest;
348 CONST_ID(rest, "NODE_SPECIAL_NO_NAME_REST");
349 return ID2SYM(rest);
352 static VALUE
353 rest_arg(VALUE ast_value, const NODE *rest_arg)
355 return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast_value, rest_arg) : no_name_rest();
358 static VALUE
359 node_children(VALUE ast_value, const NODE *node)
361 char name[sizeof("$") + DECIMAL_SIZE_OF(long)];
363 enum node_type type = nd_type(node);
364 switch (type) {
365 case NODE_BLOCK:
366 return dump_block(ast_value, RNODE_BLOCK(node));
367 case NODE_IF:
368 return rb_ary_new_from_node_args(ast_value, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else);
369 case NODE_UNLESS:
370 return rb_ary_new_from_node_args(ast_value, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else);
371 case NODE_CASE:
372 return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body);
373 case NODE_CASE2:
374 return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body);
375 case NODE_CASE3:
376 return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body);
377 case NODE_WHEN:
378 return rb_ary_new_from_node_args(ast_value, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next);
379 case NODE_IN:
380 return rb_ary_new_from_node_args(ast_value, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next);
381 case NODE_WHILE:
382 case NODE_UNTIL:
383 return rb_ary_push(rb_ary_new_from_node_args(ast_value, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body),
384 RBOOL(RNODE_WHILE(node)->nd_state));
385 case NODE_ITER:
386 case NODE_FOR:
387 return rb_ary_new_from_node_args(ast_value, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body);
388 case NODE_FOR_MASGN:
389 return rb_ary_new_from_node_args(ast_value, 1, RNODE_FOR_MASGN(node)->nd_var);
390 case NODE_BREAK:
391 return rb_ary_new_from_node_args(ast_value, 1, RNODE_BREAK(node)->nd_stts);
392 case NODE_NEXT:
393 return rb_ary_new_from_node_args(ast_value, 1, RNODE_NEXT(node)->nd_stts);
394 case NODE_RETURN:
395 return rb_ary_new_from_node_args(ast_value, 1, RNODE_RETURN(node)->nd_stts);
396 case NODE_REDO:
397 return rb_ary_new_from_node_args(ast_value, 0);
398 case NODE_RETRY:
399 return rb_ary_new_from_node_args(ast_value, 0);
400 case NODE_BEGIN:
401 return rb_ary_new_from_node_args(ast_value, 1, RNODE_BEGIN(node)->nd_body);
402 case NODE_RESCUE:
403 return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
404 case NODE_RESBODY:
405 return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next);
406 case NODE_ENSURE:
407 return rb_ary_new_from_node_args(ast_value, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
408 case NODE_AND:
409 case NODE_OR:
411 VALUE ary = rb_ary_new();
413 while (1) {
414 rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_1st));
415 if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type))
416 break;
417 node = RNODE_AND(node)->nd_2nd;
419 rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_2nd));
420 return ary;
422 case NODE_MASGN:
423 if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) {
424 return rb_ary_new_from_node_args(ast_value, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args);
426 else {
427 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_value),
428 NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_head),
429 no_name_rest());
431 case NODE_LASGN:
432 if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node)->nd_value)) {
433 return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
435 return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_LASGN(node)->nd_value));
436 case NODE_DASGN:
437 if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node)->nd_value)) {
438 return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
440 return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_DASGN(node)->nd_value));
441 case NODE_IASGN:
442 return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_IASGN(node)->nd_value));
443 case NODE_CVASGN:
444 return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CVASGN(node)->nd_value));
445 case NODE_GASGN:
446 return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_GASGN(node)->nd_value));
447 case NODE_CDECL:
448 if (RNODE_CDECL(node)->nd_vid) {
449 return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
451 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value));
452 case NODE_OP_ASGN1:
453 return rb_ary_new_from_args(4, NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_recv),
454 ID2SYM(RNODE_OP_ASGN1(node)->nd_mid),
455 NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_index),
456 NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_rvalue));
457 case NODE_OP_ASGN2:
458 return rb_ary_new_from_args(5, NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_recv),
459 RBOOL(RNODE_OP_ASGN2(node)->nd_aid),
460 ID2SYM(RNODE_OP_ASGN2(node)->nd_vid),
461 ID2SYM(RNODE_OP_ASGN2(node)->nd_mid),
462 NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_value));
463 case NODE_OP_ASGN_AND:
464 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP),
465 NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_value));
466 case NODE_OP_ASGN_OR:
467 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP),
468 NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_value));
469 case NODE_OP_CDECL:
470 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_head),
471 ID2SYM(RNODE_OP_CDECL(node)->nd_aid),
472 NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_value));
473 case NODE_CALL:
474 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CALL(node)->nd_recv),
475 ID2SYM(RNODE_CALL(node)->nd_mid),
476 NEW_CHILD(ast_value, RNODE_CALL(node)->nd_args));
477 case NODE_OPCALL:
478 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_recv),
479 ID2SYM(RNODE_OPCALL(node)->nd_mid),
480 NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_args));
481 case NODE_QCALL:
482 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_recv),
483 ID2SYM(RNODE_QCALL(node)->nd_mid),
484 NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_args));
485 case NODE_FCALL:
486 return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid),
487 NEW_CHILD(ast_value, RNODE_FCALL(node)->nd_args));
488 case NODE_VCALL:
489 return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid));
490 case NODE_SUPER:
491 return rb_ary_new_from_node_args(ast_value, 1, RNODE_SUPER(node)->nd_args);
492 case NODE_ZSUPER:
493 return rb_ary_new_from_node_args(ast_value, 0);
494 case NODE_LIST:
495 return dump_array(ast_value, RNODE_LIST(node));
496 case NODE_ZLIST:
497 return rb_ary_new_from_node_args(ast_value, 0);
498 case NODE_HASH:
499 return rb_ary_new_from_node_args(ast_value, 1, RNODE_HASH(node)->nd_head);
500 case NODE_YIELD:
501 return rb_ary_new_from_node_args(ast_value, 1, RNODE_YIELD(node)->nd_head);
502 case NODE_LVAR:
503 return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid));
504 case NODE_DVAR:
505 return rb_ary_new_from_args(1, var_name(RNODE_DVAR(node)->nd_vid));
506 case NODE_IVAR:
507 return rb_ary_new_from_args(1, ID2SYM(RNODE_IVAR(node)->nd_vid));
508 case NODE_CONST:
509 return rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid));
510 case NODE_CVAR:
511 return rb_ary_new_from_args(1, ID2SYM(RNODE_CVAR(node)->nd_vid));
512 case NODE_GVAR:
513 return rb_ary_new_from_args(1, ID2SYM(RNODE_GVAR(node)->nd_vid));
514 case NODE_NTH_REF:
515 snprintf(name, sizeof(name), "$%ld", RNODE_NTH_REF(node)->nd_nth);
516 return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
517 case NODE_BACK_REF:
518 name[0] = '$';
519 name[1] = (char)RNODE_BACK_REF(node)->nd_nth;
520 name[2] = '\0';
521 return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
522 case NODE_MATCH:
523 return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
524 case NODE_MATCH2:
525 if (RNODE_MATCH2(node)->nd_args) {
526 return rb_ary_new_from_node_args(ast_value, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args);
528 return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value);
529 case NODE_MATCH3:
530 return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value);
531 case NODE_STR:
532 case NODE_XSTR:
533 return rb_ary_new_from_args(1, rb_node_str_string_val(node));
534 case NODE_INTEGER:
535 return rb_ary_new_from_args(1, rb_node_integer_literal_val(node));
536 case NODE_FLOAT:
537 return rb_ary_new_from_args(1, rb_node_float_literal_val(node));
538 case NODE_RATIONAL:
539 return rb_ary_new_from_args(1, rb_node_rational_literal_val(node));
540 case NODE_IMAGINARY:
541 return rb_ary_new_from_args(1, rb_node_imaginary_literal_val(node));
542 case NODE_REGX:
543 return rb_ary_new_from_args(1, rb_node_regx_string_val(node));
544 case NODE_ONCE:
545 return rb_ary_new_from_node_args(ast_value, 1, RNODE_ONCE(node)->nd_body);
546 case NODE_DSTR:
547 case NODE_DXSTR:
548 case NODE_DREGX:
549 case NODE_DSYM:
551 struct RNode_LIST *n = RNODE_DSTR(node)->nd_next;
552 VALUE head = Qnil, next = Qnil;
553 if (n) {
554 head = NEW_CHILD(ast_value, n->nd_head);
555 next = NEW_CHILD(ast_value, n->nd_next);
557 return rb_ary_new_from_args(3, rb_node_dstr_string_val(node), head, next);
559 case NODE_SYM:
560 return rb_ary_new_from_args(1, rb_node_sym_string_val(node));
561 case NODE_EVSTR:
562 return rb_ary_new_from_node_args(ast_value, 1, RNODE_EVSTR(node)->nd_body);
563 case NODE_ARGSCAT:
564 return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body);
565 case NODE_ARGSPUSH:
566 return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body);
567 case NODE_SPLAT:
568 return rb_ary_new_from_node_args(ast_value, 1, RNODE_SPLAT(node)->nd_head);
569 case NODE_BLOCK_PASS:
570 return rb_ary_new_from_node_args(ast_value, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body);
571 case NODE_DEFN:
572 return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFN(node)->nd_defn));
573 case NODE_DEFS:
574 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_defn));
575 case NODE_ALIAS:
576 return rb_ary_new_from_node_args(ast_value, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd);
577 case NODE_VALIAS:
578 return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig));
579 case NODE_UNDEF:
580 return rb_ary_new_from_node_args(ast_value, 1, RNODE_UNDEF(node)->nd_undef);
581 case NODE_CLASS:
582 return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
583 case NODE_MODULE:
584 return rb_ary_new_from_node_args(ast_value, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body);
585 case NODE_SCLASS:
586 return rb_ary_new_from_node_args(ast_value, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body);
587 case NODE_COLON2:
588 return rb_ary_new_from_args(2, NEW_CHILD(ast_value, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid));
589 case NODE_COLON3:
590 return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid));
591 case NODE_DOT2:
592 case NODE_DOT3:
593 case NODE_FLIP2:
594 case NODE_FLIP3:
595 return rb_ary_new_from_node_args(ast_value, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end);
596 case NODE_SELF:
597 return rb_ary_new_from_node_args(ast_value, 0);
598 case NODE_NIL:
599 return rb_ary_new_from_node_args(ast_value, 0);
600 case NODE_TRUE:
601 return rb_ary_new_from_node_args(ast_value, 0);
602 case NODE_FALSE:
603 return rb_ary_new_from_node_args(ast_value, 0);
604 case NODE_ERRINFO:
605 return rb_ary_new_from_node_args(ast_value, 0);
606 case NODE_DEFINED:
607 return rb_ary_new_from_node_args(ast_value, 1, RNODE_DEFINED(node)->nd_head);
608 case NODE_POSTEXE:
609 return rb_ary_new_from_node_args(ast_value, 1, RNODE_POSTEXE(node)->nd_body);
610 case NODE_ATTRASGN:
611 return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_args));
612 case NODE_LAMBDA:
613 return rb_ary_new_from_node_args(ast_value, 1, RNODE_LAMBDA(node)->nd_body);
614 case NODE_OPT_ARG:
615 return rb_ary_new_from_node_args(ast_value, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next);
616 case NODE_KW_ARG:
617 return rb_ary_new_from_node_args(ast_value, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next);
618 case NODE_POSTARG:
619 if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) {
620 return rb_ary_new_from_node_args(ast_value, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd);
622 return rb_ary_new_from_args(2, no_name_rest(),
623 NEW_CHILD(ast_value, RNODE_POSTARG(node)->nd_2nd));
624 case NODE_ARGS:
626 struct rb_args_info *ainfo = &RNODE_ARGS(node)->nd_ainfo;
627 return rb_ary_new_from_args(10,
628 INT2NUM(ainfo->pre_args_num),
629 NEW_CHILD(ast_value, ainfo->pre_init),
630 NEW_CHILD(ast_value, (NODE *)ainfo->opt_args),
631 var_name(ainfo->first_post_arg),
632 INT2NUM(ainfo->post_args_num),
633 NEW_CHILD(ast_value, ainfo->post_init),
634 (ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA
635 ? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA"))
636 : var_name(ainfo->rest_arg)),
637 (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, (NODE *)ainfo->kw_args)),
638 (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, ainfo->kw_rest_arg)),
639 var_name(ainfo->block_arg));
641 case NODE_SCOPE:
643 rb_ast_id_table_t *tbl = RNODE_SCOPE(node)->nd_tbl;
644 int i, size = tbl ? tbl->size : 0;
645 VALUE locals = rb_ary_new_capa(size);
646 for (i = 0; i < size; i++) {
647 rb_ary_push(locals, var_name(tbl->ids[i]));
649 return rb_ary_new_from_args(3, locals, NEW_CHILD(ast_value, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast_value, RNODE_SCOPE(node)->nd_body));
651 case NODE_ARYPTN:
653 VALUE rest = rest_arg(ast_value, RNODE_ARYPTN(node)->rest_arg);
654 return rb_ary_new_from_args(4,
655 NEW_CHILD(ast_value, RNODE_ARYPTN(node)->nd_pconst),
656 NEW_CHILD(ast_value, RNODE_ARYPTN(node)->pre_args),
657 rest,
658 NEW_CHILD(ast_value, RNODE_ARYPTN(node)->post_args));
660 case NODE_FNDPTN:
662 VALUE pre_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->pre_rest_arg);
663 VALUE post_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->post_rest_arg);
664 return rb_ary_new_from_args(4,
665 NEW_CHILD(ast_value, RNODE_FNDPTN(node)->nd_pconst),
666 pre_rest,
667 NEW_CHILD(ast_value, RNODE_FNDPTN(node)->args),
668 post_rest);
670 case NODE_HSHPTN:
672 VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
673 NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwrestarg);
675 return rb_ary_new_from_args(3,
676 NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pconst),
677 NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwargs),
678 kwrest);
680 case NODE_LINE:
681 return rb_ary_new_from_args(1, rb_node_line_lineno_val(node));
682 case NODE_FILE:
683 return rb_ary_new_from_args(1, rb_node_file_path_val(node));
684 case NODE_ENCODING:
685 return rb_ary_new_from_args(1, rb_node_encoding_val(node));
686 case NODE_ERROR:
687 return rb_ary_new_from_node_args(ast_value, 0);
688 case NODE_ARGS_AUX:
689 case NODE_LAST:
690 break;
693 rb_bug("node_children: unknown node: %s", ruby_node_name(type));
696 static VALUE
697 ast_node_children(rb_execution_context_t *ec, VALUE self)
699 struct ASTNodeData *data;
700 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
702 return node_children(data->ast_value, data->node);
705 static VALUE
706 ast_node_first_lineno(rb_execution_context_t *ec, VALUE self)
708 struct ASTNodeData *data;
709 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
711 return INT2NUM(nd_first_lineno(data->node));
714 static VALUE
715 ast_node_first_column(rb_execution_context_t *ec, VALUE self)
717 struct ASTNodeData *data;
718 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
720 return INT2NUM(nd_first_column(data->node));
723 static VALUE
724 ast_node_last_lineno(rb_execution_context_t *ec, VALUE self)
726 struct ASTNodeData *data;
727 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
729 return INT2NUM(nd_last_lineno(data->node));
732 static VALUE
733 ast_node_last_column(rb_execution_context_t *ec, VALUE self)
735 struct ASTNodeData *data;
736 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
738 return INT2NUM(nd_last_column(data->node));
741 static VALUE
742 ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
744 long i;
745 struct ASTNodeData *data;
746 rb_ast_t *ast;
747 rb_parser_ary_t *parser_tokens;
748 rb_parser_ast_token_t *parser_token;
749 VALUE str, loc, token, all_tokens;
751 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
752 ast = rb_ruby_ast_data_get(data->ast_value);
754 parser_tokens = ast->node_buffer->tokens;
755 if (parser_tokens == NULL) {
756 return Qnil;
759 all_tokens = rb_ary_new2(parser_tokens->len);
760 for (i = 0; i < parser_tokens->len; i++) {
761 parser_token = parser_tokens->data[i];
762 str = rb_str_new(parser_token->str->ptr, parser_token->str->len);
763 loc = rb_ary_new_from_args(4,
764 INT2FIX(parser_token->loc.beg_pos.lineno),
765 INT2FIX(parser_token->loc.beg_pos.column),
766 INT2FIX(parser_token->loc.end_pos.lineno),
767 INT2FIX(parser_token->loc.end_pos.column)
769 token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc);
770 rb_ary_push(all_tokens, token);
772 rb_obj_freeze(all_tokens);
774 return all_tokens;
777 static VALUE
778 ast_node_inspect(rb_execution_context_t *ec, VALUE self)
780 VALUE str;
781 VALUE cname;
782 struct ASTNodeData *data;
783 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
785 cname = rb_class_path(rb_obj_class(self));
786 str = rb_str_new2("#<");
788 rb_str_append(str, cname);
789 rb_str_catf(str, ":%s@%d:%d-%d:%d>",
790 node_type_to_str(data->node),
791 nd_first_lineno(data->node), nd_first_column(data->node),
792 nd_last_lineno(data->node), nd_last_column(data->node));
794 return str;
797 static VALUE
798 ast_node_script_lines(rb_execution_context_t *ec, VALUE self)
800 struct ASTNodeData *data;
801 rb_ast_t *ast;
802 TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
803 ast = rb_ruby_ast_data_get(data->ast_value);
804 rb_parser_ary_t *ret = ast->body.script_lines;
805 return rb_parser_build_script_lines_from(ret);
808 #include "ast.rbinc"
810 void
811 Init_ast(void)
813 rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
814 rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
815 rb_undef_alloc_func(rb_cNode);