Ruby: node.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

node.c
Go to the documentation of this file.
1/**********************************************************************
2
3 node.c - ruby node tree
4
5 $Author: mame $
6 created at: 09/12/06 21:23:44 JST
7
8 Copyright (C) 2009 Yusuke Endoh
9
10**********************************************************************/
11
12#include "internal.h"
13#include "internal/hash.h"
14#include "internal/variable.h"
15#include "ruby/ruby.h"
16#include "vm_core.h"
17
18#define NODE_BUF_DEFAULT_LEN 16
19
20#define A(str) rb_str_cat2(buf, (str))
21#define AR(str) rb_str_concat(buf, (str))
22
23#define A_INDENT add_indent(buf, indent)
24#define D_INDENT rb_str_cat2(indent, next_indent)
25#define D_DEDENT rb_str_resize(indent, RSTRING_LEN(indent) - 4)
26#define A_ID(id) add_id(buf, (id))
27#define A_INT(val) rb_str_catf(buf, "%d", (val))
28#define A_LONG(val) rb_str_catf(buf, "%ld", (val))
29#define A_LIT(lit) AR(rb_dump_literal(lit))
30#define A_NODE_HEADER(node, term) \
31 rb_str_catf(buf, "@ %s (line: %d, location: (%d,%d)-(%d,%d))%s"term, \
32 ruby_node_name(nd_type(node)), nd_line(node), \
33 nd_first_lineno(node), nd_first_column(node), \
34 nd_last_lineno(node), nd_last_column(node), \
35 (node->flags & NODE_FL_NEWLINE ? "*" : ""))
36#define A_FIELD_HEADER(len, name, term) \
37 rb_str_catf(buf, "+- %.*s:"term, (len), (name))
38#define D_FIELD_HEADER(len, name, term) (A_INDENT, A_FIELD_HEADER(len, name, term))
39
40#define D_NULL_NODE (A_INDENT, A("(null node)\n"))
41#define D_NODE_HEADER(node) (A_INDENT, A_NODE_HEADER(node, "\n"))
42
43#define COMPOUND_FIELD(len, name) \
44 FIELD_BLOCK((D_FIELD_HEADER((len), (name), "\n"), D_INDENT), D_DEDENT)
45
46#define COMPOUND_FIELD1(name, ann) \
47 COMPOUND_FIELD(FIELD_NAME_LEN(name, ann), \
48 FIELD_NAME_DESC(name, ann))
49
50#define FIELD_NAME_DESC(name, ann) name " (" ann ")"
51#define FIELD_NAME_LEN(name, ann) (int)( \
52 comment ? \
53 rb_strlen_lit(FIELD_NAME_DESC(name, ann)) : \
54 rb_strlen_lit(name))
55#define SIMPLE_FIELD(len, name) \
56 FIELD_BLOCK(D_FIELD_HEADER((len), (name), " "), A("\n"))
57
58#define FIELD_BLOCK(init, reset) \
59 for (init, field_flag = 1; \
60 field_flag; /* should be optimized away */ \
61 reset, field_flag = 0)
62
63#define SIMPLE_FIELD1(name, ann) SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
64#define F_CUSTOM1(name, ann) SIMPLE_FIELD1(#name, ann)
65#define F_ID(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
66#define F_GENTRY(name, ann) SIMPLE_FIELD1(#name, ann) A_ID(node->name)
67#define F_INT(name, ann) SIMPLE_FIELD1(#name, ann) A_INT(node->name)
68#define F_LONG(name, ann) SIMPLE_FIELD1(#name, ann) A_LONG(node->name)
69#define F_LIT(name, ann) SIMPLE_FIELD1(#name, ann) A_LIT(node->name)
70#define F_MSG(name, ann, desc) SIMPLE_FIELD1(#name, ann) A(desc)
71
72#define F_NODE(name, ann) \
73 COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, node->name);}
74
75#define ANN(ann) \
76 if (comment) { \
77 A_INDENT; A("| # " ann "\n"); \
78 }
79
80#define LAST_NODE (next_indent = " ")
81
82 VALUE
83 rb_dump_literal(VALUE lit)
84{
85 if (!RB_SPECIAL_CONST_P(lit)) {
86 VALUE str;
87 switch (RB_BUILTIN_TYPE(lit)) {
88 case T_CLASS: case T_MODULE: case T_ICLASS:
89 str = rb_class_path(lit);
90 if (FL_TEST(lit, FL_SINGLETON)) {
91 str = rb_sprintf("<%"PRIsVALUE">", str);
92 }
93 return str;
94 default:
95 break;
96 }
97 }
98 return rb_inspect(lit);
99}
100
101static void
102add_indent(VALUE buf, VALUE indent)
103{
104 AR(indent);
105}
106
107static void
108add_id(VALUE buf, ID id)
109{
110 if (id == 0) {
111 A("(null)");
112 }
113 else {
114 VALUE str = rb_id2str(id);
115 if (str) {
116 A(":"); AR(str);
117 }
118 else {
119 rb_str_catf(buf, "(internal variable: 0x%"PRIsVALUE")", id);
120 }
121 }
122}
123
124 struct add_option_arg {
125 VALUE buf, indent;
126 st_index_t count;
127};
128
129static void dump_node(VALUE, VALUE, int, const NODE *);
130static const char default_indent[] = "| ";
131
132static void
133dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
134{
135 int field_flag;
136 const char *next_indent = default_indent;
137 F_LONG(nd_alen, "length");
138 F_NODE(nd_head, "element");
139 while (node->nd_next && nd_type(node->nd_next) == NODE_LIST) {
140 node = node->nd_next;
141 F_NODE(nd_head, "element");
142 }
143 LAST_NODE;
144 F_NODE(nd_next, "next element");
145}
146
147static void
148dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
149{
150 int field_flag;
151 int i;
152 const char *next_indent = default_indent;
153 enum node_type type;
154
155 if (!node) {
156 D_NULL_NODE;
157 return;
158 }
159
160 D_NODE_HEADER(node);
161
162 type = nd_type(node);
163 switch (type) {
164 case NODE_BLOCK:
165 ANN("statement sequence");
166 ANN("format: [nd_head]; ...; [nd_next]");
167 ANN("example: foo; bar");
168 i = 0;
169 do {
170 A_INDENT;
171 rb_str_catf(buf, "+- nd_head (%s%d):\n",
172 comment ? "statement #" : "", ++i);
173 if (!node->nd_next) LAST_NODE;
174 D_INDENT;
175 dump_node(buf, indent, comment, node->nd_head);
176 D_DEDENT;
177 } while (node->nd_next &&
178 nd_type(node->nd_next) == NODE_BLOCK &&
179 (node = node->nd_next, 1));
180 if (node->nd_next) {
181 LAST_NODE;
182 F_NODE(nd_next, "next block");
183 }
184 return;
185
186 case NODE_IF:
187 ANN("if statement");
188 ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
189 ANN("example: if x == 1 then foo else bar end");
190 F_NODE(nd_cond, "condition expr");
191 F_NODE(nd_body, "then clause");
192 LAST_NODE;
193 F_NODE(nd_else, "else clause");
194 return;
195
196 case NODE_UNLESS:
197 ANN("unless statement");
198 ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
199 ANN("example: unless x == 1 then foo else bar end");
200 F_NODE(nd_cond, "condition expr");
201 F_NODE(nd_body, "then clause");
202 LAST_NODE;
203 F_NODE(nd_else, "else clause");
204 return;
205
206 case NODE_CASE:
207 ANN("case statement");
208 ANN("format: case [nd_head]; [nd_body]; end");
209 ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
210 F_NODE(nd_head, "case expr");
211 LAST_NODE;
212 F_NODE(nd_body, "when clauses");
213 return;
214 case NODE_CASE2:
215 ANN("case statement with no head");
216 ANN("format: case; [nd_body]; end");
217 ANN("example: case; when 1; foo; when 2; bar; else baz; end");
218 F_NODE(nd_head, "case expr");
219 LAST_NODE;
220 F_NODE(nd_body, "when clauses");
221 return;
222 case NODE_CASE3:
223 ANN("case statement (pattern matching)");
224 ANN("format: case [nd_head]; [nd_body]; end");
225 ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
226 F_NODE(nd_head, "case expr");
227 LAST_NODE;
228 F_NODE(nd_body, "in clauses");
229 return;
230
231 case NODE_WHEN:
232 ANN("when clause");
233 ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
234 ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
235 F_NODE(nd_head, "when value");
236 F_NODE(nd_body, "when body");
237 LAST_NODE;
238 F_NODE(nd_next, "next when clause");
239 return;
240
241 case NODE_IN:
242 ANN("in clause");
243 ANN("format: in [nd_head]; [nd_body]; (in or else) [nd_next]");
244 ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
245 F_NODE(nd_head, "in pattern");
246 F_NODE(nd_body, "in body");
247 LAST_NODE;
248 F_NODE(nd_next, "next in clause");
249 return;
250
251 case NODE_WHILE:
252 ANN("while statement");
253 ANN("format: while [nd_cond]; [nd_body]; end");
254 ANN("example: while x == 1; foo; end");
255 goto loop;
256 case NODE_UNTIL:
257 ANN("until statement");
258 ANN("format: until [nd_cond]; [nd_body]; end");
259 ANN("example: until x == 1; foo; end");
260 loop:
261 F_CUSTOM1(nd_state, "begin-end-while?") {
262 A_INT((int)node->nd_state);
263 A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
264 }
265 F_NODE(nd_cond, "condition");
266 LAST_NODE;
267 F_NODE(nd_body, "body");
268 return;
269
270 case NODE_ITER:
271 ANN("method call with block");
272 ANN("format: [nd_iter] { [nd_body] }");
273 ANN("example: 3.times { foo }");
274 goto iter;
275 case NODE_FOR:
276 ANN("for statement");
277 ANN("format: for * in [nd_iter] do [nd_body] end");
278 ANN("example: for i in 1..3 do foo end");
279 iter:
280 F_NODE(nd_iter, "iteration receiver");
281 LAST_NODE;
282 F_NODE(nd_body, "body");
283 return;
284
285 case NODE_FOR_MASGN:
286 ANN("vars of for statement with masgn");
287 ANN("format: for [nd_var] in ... do ... end");
288 ANN("example: for x, y in 1..3 do foo end");
289 LAST_NODE;
290 F_NODE(nd_var, "var");
291 return;
292
293 case NODE_BREAK:
294 ANN("break statement");
295 ANN("format: break [nd_stts]");
296 ANN("example: break 1");
297 goto jump;
298 case NODE_NEXT:
299 ANN("next statement");
300 ANN("format: next [nd_stts]");
301 ANN("example: next 1");
302 goto jump;
303 case NODE_RETURN:
304 ANN("return statement");
305 ANN("format: return [nd_stts]");
306 ANN("example: return 1");
307 jump:
308 LAST_NODE;
309 F_NODE(nd_stts, "value");
310 return;
311
312 case NODE_REDO:
313 ANN("redo statement");
314 ANN("format: redo");
315 ANN("example: redo");
316 return;
317
318 case NODE_RETRY:
319 ANN("retry statement");
320 ANN("format: retry");
321 ANN("example: retry");
322 return;
323
324 case NODE_BEGIN:
325 ANN("begin statement");
326 ANN("format: begin; [nd_body]; end");
327 ANN("example: begin; 1; end");
328 LAST_NODE;
329 F_NODE(nd_body, "body");
330 return;
331
332 case NODE_RESCUE:
333 ANN("rescue clause");
334 ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
335 ANN("example: begin; foo; rescue; bar; else; baz; end");
336 F_NODE(nd_head, "body");
337 F_NODE(nd_resq, "rescue clause list");
338 LAST_NODE;
339 F_NODE(nd_else, "rescue else clause");
340 return;
341
342 case NODE_RESBODY:
343 ANN("rescue clause (cont'd)");
344 ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
345 ANN("example: begin; foo; rescue; bar; else; baz; end");
346 F_NODE(nd_args, "rescue exceptions");
347 F_NODE(nd_body, "rescue clause");
348 LAST_NODE;
349 F_NODE(nd_head, "next rescue clause");
350 return;
351
352 case NODE_ENSURE:
353 ANN("ensure clause");
354 ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
355 ANN("example: begin; foo; ensure; bar; end");
356 F_NODE(nd_head, "body");
357 LAST_NODE;
358 F_NODE(nd_ensr, "ensure clause");
359 return;
360
361 case NODE_AND:
362 ANN("&& operator");
363 ANN("format: [nd_1st] && [nd_2nd]");
364 ANN("example: foo && bar");
365 goto andor;
366 case NODE_OR:
367 ANN("|| operator");
368 ANN("format: [nd_1st] || [nd_2nd]");
369 ANN("example: foo || bar");
370 andor:
371 while (1) {
372 F_NODE(nd_1st, "left expr");
373 if (!node->nd_2nd || nd_type(node->nd_2nd) != (int)type)
374 break;
375 node = node->nd_2nd;
376 }
377 LAST_NODE;
378 F_NODE(nd_2nd, "right expr");
379 return;
380
381 case NODE_MASGN:
382 ANN("multiple assignment");
383 ANN("format: [nd_head], [nd_args] = [nd_value]");
384 ANN("example: a, b = foo");
385 F_NODE(nd_value, "rhsn");
386 F_NODE(nd_head, "lhsn");
387 if (NODE_NAMED_REST_P(node->nd_args)) {
388 LAST_NODE;
389 F_NODE(nd_args, "splatn");
390 }
391 else {
392 F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
393 }
394 return;
395
396 case NODE_LASGN:
397 ANN("local variable assignment");
398 ANN("format: [nd_vid](lvar) = [nd_value]");
399 ANN("example: x = foo");
400 F_ID(nd_vid, "local variable");
401 if (NODE_REQUIRED_KEYWORD_P(node)) {
402 F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
403 }
404 else {
405 LAST_NODE;
406 F_NODE(nd_value, "rvalue");
407 }
408 return;
409 case NODE_DASGN:
410 ANN("dynamic variable assignment (out of current scope)");
411 ANN("format: [nd_vid](dvar) = [nd_value]");
412 ANN("example: x = nil; 1.times { x = foo }");
413 F_ID(nd_vid, "local variable");
414 LAST_NODE;
415 F_NODE(nd_value, "rvalue");
416 return;
417 case NODE_DASGN_CURR:
418 ANN("dynamic variable assignment (in current scope)");
419 ANN("format: [nd_vid](current dvar) = [nd_value]");
420 ANN("example: 1.times { x = foo }");
421 F_ID(nd_vid, "local variable");
422 if (NODE_REQUIRED_KEYWORD_P(node)) {
423 F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
424 }
425 else {
426 LAST_NODE;
427 F_NODE(nd_value, "rvalue");
428 }
429 return;
430 case NODE_IASGN:
431 ANN("instance variable assignment");
432 ANN("format: [nd_vid](ivar) = [nd_value]");
433 ANN("example: @x = foo");
434 F_ID(nd_vid, "instance variable");
435 LAST_NODE;
436 F_NODE(nd_value, "rvalue");
437 return;
438 case NODE_CVASGN:
439 ANN("class variable assignment");
440 ANN("format: [nd_vid](cvar) = [nd_value]");
441 ANN("example: @@x = foo");
442 F_ID(nd_vid, "class variable");
443 LAST_NODE;
444 F_NODE(nd_value, "rvalue");
445 return;
446 case NODE_GASGN:
447 ANN("global variable assignment");
448 ANN("format: [nd_entry](gvar) = [nd_value]");
449 ANN("example: $x = foo");
450 F_GENTRY(nd_entry, "global variable");
451 LAST_NODE;
452 F_NODE(nd_value, "rvalue");
453 return;
454
455 case NODE_CDECL:
456 ANN("constant declaration");
457 ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
458 ANN("example: X = foo");
459 if (node->nd_vid) {
460 F_ID(nd_vid, "constant");
461 F_MSG(nd_else, "extension", "not used");
462 }
463 else {
464 F_MSG(nd_vid, "constant", "0 (see extension field)");
465 F_NODE(nd_else, "extension");
466 }
467 LAST_NODE;
468 F_NODE(nd_value, "rvalue");
469 return;
470
471 case NODE_OP_ASGN1:
472 ANN("array assignment with operator");
473 ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
474 ANN("example: ary[1] += foo");
475 F_NODE(nd_recv, "receiver");
476 F_ID(nd_mid, "operator");
477 F_NODE(nd_args->nd_head, "index");
478 LAST_NODE;
479 F_NODE(nd_args->nd_body, "rvalue");
480 return;
481
482 case NODE_OP_ASGN2:
483 ANN("attr assignment with operator");
484 ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
485 ANN(" where [attr]: [nd_next->nd_vid]");
486 ANN("example: struct.field += foo");
487 F_NODE(nd_recv, "receiver");
488 F_CUSTOM1(nd_next->nd_vid, "attr") {
489 if (node->nd_next->nd_aid) A("? ");
490 A_ID(node->nd_next->nd_vid);
491 }
492 F_ID(nd_next->nd_mid, "operator");
493 LAST_NODE;
494 F_NODE(nd_value, "rvalue");
495 return;
496
497 case NODE_OP_ASGN_AND:
498 ANN("assignment with && operator");
499 ANN("format: [nd_head] &&= [nd_value]");
500 ANN("example: foo &&= bar");
501 goto asgn_andor;
502 case NODE_OP_ASGN_OR:
503 ANN("assignment with || operator");
504 ANN("format: [nd_head] ||= [nd_value]");
505 ANN("example: foo ||= bar");
506 asgn_andor:
507 F_NODE(nd_head, "variable");
508 LAST_NODE;
509 F_NODE(nd_value, "rvalue");
510 return;
511
512 case NODE_OP_CDECL:
513 ANN("constant declaration with operator");
514 ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
515 ANN("example: A::B ||= 1");
516 F_NODE(nd_head, "constant");
517 F_ID(nd_aid, "operator");
518 LAST_NODE;
519 F_NODE(nd_value, "rvalue");
520 return;
521
522 case NODE_CALL:
523 ANN("method invocation");
524 ANN("format: [nd_recv].[nd_mid]([nd_args])");
525 ANN("example: obj.foo(1)");
526 F_ID(nd_mid, "method id");
527 F_NODE(nd_recv, "receiver");
528 LAST_NODE;
529 F_NODE(nd_args, "arguments");
530 return;
531
532 case NODE_OPCALL:
533 ANN("method invocation");
534 ANN("format: [nd_recv] [nd_mid] [nd_args]");
535 ANN("example: foo + bar");
536 F_ID(nd_mid, "method id");
537 F_NODE(nd_recv, "receiver");
538 LAST_NODE;
539 F_NODE(nd_args, "arguments");
540 return;
541
542 case NODE_FCALL:
543 ANN("function call");
544 ANN("format: [nd_mid]([nd_args])");
545 ANN("example: foo(1)");
546 F_ID(nd_mid, "method id");
547 LAST_NODE;
548 F_NODE(nd_args, "arguments");
549 return;
550
551 case NODE_VCALL:
552 ANN("function call with no argument");
553 ANN("format: [nd_mid]");
554 ANN("example: foo");
555 F_ID(nd_mid, "method id");
556 return;
557
558 case NODE_QCALL:
559 ANN("safe method invocation");
560 ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
561 ANN("example: obj&.foo(1)");
562 F_ID(nd_mid, "method id");
563 F_NODE(nd_recv, "receiver");
564 LAST_NODE;
565 F_NODE(nd_args, "arguments");
566 return;
567
568 case NODE_SUPER:
569 ANN("super invocation");
570 ANN("format: super [nd_args]");
571 ANN("example: super 1");
572 LAST_NODE;
573 F_NODE(nd_args, "arguments");
574 return;
575
576 case NODE_ZSUPER:
577 ANN("super invocation with no argument");
578 ANN("format: super");
579 ANN("example: super");
580 return;
581
582 case NODE_LIST:
583 ANN("list constructor");
584 ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
585 ANN("example: [1, 2, 3]");
586 goto ary;
587 case NODE_VALUES:
588 ANN("return arguments");
589 ANN("format: [ [nd_head], [nd_next].. ] (length: [nd_alen])");
590 ANN("example: return 1, 2, 3");
591 ary:
592 dump_array(buf, indent, comment, node);
593 return;
594
595 case NODE_ZLIST:
596 ANN("empty list constructor");
597 ANN("format: []");
598 ANN("example: []");
599 return;
600
601 case NODE_HASH:
602 if (!node->nd_brace) {
603 ANN("keyword arguments");
604 ANN("format: nd_head");
605 ANN("example: a: 1, b: 2");
606 }
607 else {
608 ANN("hash constructor");
609 ANN("format: { [nd_head] }");
610 ANN("example: { 1 => 2, 3 => 4 }");
611 }
612 F_CUSTOM1(nd_brace, "keyword arguments or hash literal") {
613 switch (node->nd_brace) {
614 case 0: A("0 (keyword argument)"); break;
615 case 1: A("1 (hash literal)"); break;
616 }
617 }
618 LAST_NODE;
619 F_NODE(nd_head, "contents");
620 return;
621
622 case NODE_YIELD:
623 ANN("yield invocation");
624 ANN("format: yield [nd_head]");
625 ANN("example: yield 1");
626 LAST_NODE;
627 F_NODE(nd_head, "arguments");
628 return;
629
630 case NODE_LVAR:
631 ANN("local variable reference");
632 ANN("format: [nd_vid](lvar)");
633 ANN("example: x");
634 F_ID(nd_vid, "local variable");
635 return;
636 case NODE_DVAR:
637 ANN("dynamic variable reference");
638 ANN("format: [nd_vid](dvar)");
639 ANN("example: 1.times { x = 1; x }");
640 F_ID(nd_vid, "local variable");
641 return;
642 case NODE_IVAR:
643 ANN("instance variable reference");
644 ANN("format: [nd_vid](ivar)");
645 ANN("example: @x");
646 F_ID(nd_vid, "instance variable");
647 return;
648 case NODE_CONST:
649 ANN("constant reference");
650 ANN("format: [nd_vid](constant)");
651 ANN("example: X");
652 F_ID(nd_vid, "constant");
653 return;
654 case NODE_CVAR:
655 ANN("class variable reference");
656 ANN("format: [nd_vid](cvar)");
657 ANN("example: @@x");
658 F_ID(nd_vid, "class variable");
659 return;
660
661 case NODE_GVAR:
662 ANN("global variable reference");
663 ANN("format: [nd_entry](gvar)");
664 ANN("example: $x");
665 F_GENTRY(nd_entry, "global variable");
666 return;
667
668 case NODE_NTH_REF:
669 ANN("nth special variable reference");
670 ANN("format: $[nd_nth]");
671 ANN("example: $1, $2, ..");
672 F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
673 return;
674
675 case NODE_BACK_REF:
676 ANN("back special variable reference");
677 ANN("format: $[nd_nth]");
678 ANN("example: $&, $`, $', $+");
679 F_CUSTOM1(nd_nth, "variable") {
680 char name[3];
681 name[0] = '$';
682 name[1] = (char)node->nd_nth;
683 name[2] = '\0';
684 A(name);
685 }
686 return;
687
688 case NODE_MATCH:
689 ANN("match expression (against $_ implicitly)");
690 ANN("format: [nd_lit] (in condition)");
691 ANN("example: if /foo/; foo; end");
692 F_LIT(nd_lit, "regexp");
693 return;
694
695 case NODE_MATCH2:
696 ANN("match expression (regexp first)");
697 ANN("format: [nd_recv] =~ [nd_value]");
698 ANN("example: /foo/ =~ 'foo'");
699 F_NODE(nd_recv, "regexp (receiver)");
700 if (!node->nd_args) LAST_NODE;
701 F_NODE(nd_value, "string (argument)");
702 if (node->nd_args) {
703 LAST_NODE;
704 F_NODE(nd_args, "named captures");
705 }
706 return;
707
708 case NODE_MATCH3:
709 ANN("match expression (regexp second)");
710 ANN("format: [nd_recv] =~ [nd_value]");
711 ANN("example: 'foo' =~ /foo/");
712 F_NODE(nd_recv, "string (receiver)");
713 LAST_NODE;
714 F_NODE(nd_value, "regexp (argument)");
715 return;
716
717 case NODE_LIT:
718 ANN("literal");
719 ANN("format: [nd_lit]");
720 ANN("example: 1, /foo/");
721 goto lit;
722 case NODE_STR:
723 ANN("string literal");
724 ANN("format: [nd_lit]");
725 ANN("example: 'foo'");
726 goto lit;
727 case NODE_XSTR:
728 ANN("xstring literal");
729 ANN("format: [nd_lit]");
730 ANN("example: `foo`");
731 lit:
732 F_LIT(nd_lit, "literal");
733 return;
734
735 case NODE_ONCE:
736 ANN("once evaluation");
737 ANN("format: [nd_body]");
738 ANN("example: /foo#{ bar }baz/o");
739 LAST_NODE;
740 F_NODE(nd_body, "body");
741 return;
742 case NODE_DSTR:
743 ANN("string literal with interpolation");
744 ANN("format: [nd_lit]");
745 ANN("example: \"foo#{ bar }baz\"");
746 goto dlit;
747 case NODE_DXSTR:
748 ANN("xstring literal with interpolation");
749 ANN("format: [nd_lit]");
750 ANN("example: `foo#{ bar }baz`");
751 goto dlit;
752 case NODE_DREGX:
753 ANN("regexp literal with interpolation");
754 ANN("format: [nd_lit]");
755 ANN("example: /foo#{ bar }baz/");
756 goto dlit;
757 case NODE_DSYM:
758 ANN("symbol literal with interpolation");
759 ANN("format: [nd_lit]");
760 ANN("example: :\"foo#{ bar }baz\"");
761 dlit:
762 F_LIT(nd_lit, "preceding string");
763 if (!node->nd_next) return;
764 F_NODE(nd_next->nd_head, "interpolation");
765 LAST_NODE;
766 F_NODE(nd_next->nd_next, "tailing strings");
767 return;
768
769 case NODE_EVSTR:
770 ANN("interpolation expression");
771 ANN("format: \"..#{ [nd_lit] }..\"");
772 ANN("example: \"foo#{ bar }baz\"");
773 LAST_NODE;
774 F_NODE(nd_body, "body");
775 return;
776
777 case NODE_ARGSCAT:
778 ANN("splat argument following arguments");
779 ANN("format: ..(*[nd_head], [nd_body..])");
780 ANN("example: foo(*ary, post_arg1, post_arg2)");
781 F_NODE(nd_head, "preceding array");
782 LAST_NODE;
783 F_NODE(nd_body, "following array");
784 return;
785
786 case NODE_ARGSPUSH:
787 ANN("splat argument following one argument");
788 ANN("format: ..(*[nd_head], [nd_body])");
789 ANN("example: foo(*ary, post_arg)");
790 F_NODE(nd_head, "preceding array");
791 LAST_NODE;
792 F_NODE(nd_body, "following element");
793 return;
794
795 case NODE_SPLAT:
796 ANN("splat argument");
797 ANN("format: *[nd_head]");
798 ANN("example: foo(*ary)");
799 LAST_NODE;
800 F_NODE(nd_head, "splat'ed array");
801 return;
802
803 case NODE_BLOCK_PASS:
804 ANN("arguments with block argument");
805 ANN("format: ..([nd_head], &[nd_body])");
806 ANN("example: foo(x, &blk)");
807 F_NODE(nd_head, "other arguments");
808 LAST_NODE;
809 F_NODE(nd_body, "block argument");
810 return;
811
812 case NODE_DEFN:
813 ANN("method definition");
814 ANN("format: def [nd_mid] [nd_defn]; end");
815 ANN("example: def foo; bar; end");
816 F_ID(nd_mid, "method name");
817 LAST_NODE;
818 F_NODE(nd_defn, "method definition");
819 return;
820
821 case NODE_DEFS:
822 ANN("singleton method definition");
823 ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
824 ANN("example: def obj.foo; bar; end");
825 F_NODE(nd_recv, "receiver");
826 F_ID(nd_mid, "method name");
827 LAST_NODE;
828 F_NODE(nd_defn, "method definition");
829 return;
830
831 case NODE_ALIAS:
832 ANN("method alias statement");
833 ANN("format: alias [nd_1st] [nd_2nd]");
834 ANN("example: alias bar foo");
835 F_NODE(nd_1st, "new name");
836 LAST_NODE;
837 F_NODE(nd_2nd, "old name");
838 return;
839
840 case NODE_VALIAS:
841 ANN("global variable alias statement");
842 ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
843 ANN("example: alias $y $x");
844 F_ID(nd_alias, "new name");
845 F_ID(nd_orig, "old name");
846 return;
847
848 case NODE_UNDEF:
849 ANN("method undef statement");
850 ANN("format: undef [nd_undef]");
851 ANN("example: undef foo");
852 LAST_NODE;
853 F_NODE(nd_undef, "old name");
854 return;
855
856 case NODE_CLASS:
857 ANN("class definition");
858 ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
859 ANN("example: class C2 < C; ..; end");
860 F_NODE(nd_cpath, "class path");
861 F_NODE(nd_super, "superclass");
862 LAST_NODE;
863 F_NODE(nd_body, "class definition");
864 return;
865
866 case NODE_MODULE:
867 ANN("module definition");
868 ANN("format: module [nd_cpath]; [nd_body]; end");
869 ANN("example: module M; ..; end");
870 F_NODE(nd_cpath, "module path");
871 LAST_NODE;
872 F_NODE(nd_body, "module definition");
873 return;
874
875 case NODE_SCLASS:
876 ANN("singleton class definition");
877 ANN("format: class << [nd_recv]; [nd_body]; end");
878 ANN("example: class << obj; ..; end");
879 F_NODE(nd_recv, "receiver");
880 LAST_NODE;
881 F_NODE(nd_body, "singleton class definition");
882 return;
883
884 case NODE_COLON2:
885 ANN("scoped constant reference");
886 ANN("format: [nd_head]::[nd_mid]");
887 ANN("example: M::C");
888 F_ID(nd_mid, "constant name");
889 LAST_NODE;
890 F_NODE(nd_head, "receiver");
891 return;
892
893 case NODE_COLON3:
894 ANN("top-level constant reference");
895 ANN("format: ::[nd_mid]");
896 ANN("example: ::Object");
897 F_ID(nd_mid, "constant name");
898 return;
899
900 case NODE_DOT2:
901 ANN("range constructor (incl.)");
902 ANN("format: [nd_beg]..[nd_end]");
903 ANN("example: 1..5");
904 goto dot;
905 case NODE_DOT3:
906 ANN("range constructor (excl.)");
907 ANN("format: [nd_beg]...[nd_end]");
908 ANN("example: 1...5");
909 goto dot;
910 case NODE_FLIP2:
911 ANN("flip-flop condition (incl.)");
912 ANN("format: [nd_beg]..[nd_end]");
913 ANN("example: if (x==1)..(x==5); foo; end");
914 goto dot;
915 case NODE_FLIP3:
916 ANN("flip-flop condition (excl.)");
917 ANN("format: [nd_beg]...[nd_end]");
918 ANN("example: if (x==1)...(x==5); foo; end");
919 dot:
920 F_NODE(nd_beg, "begin");
921 LAST_NODE;
922 F_NODE(nd_end, "end");
923 return;
924
925 case NODE_SELF:
926 ANN("self");
927 ANN("format: self");
928 ANN("example: self");
929 return;
930
931 case NODE_NIL:
932 ANN("nil");
933 ANN("format: nil");
934 ANN("example: nil");
935 return;
936
937 case NODE_TRUE:
938 ANN("true");
939 ANN("format: true");
940 ANN("example: true");
941 return;
942
943 case NODE_FALSE:
944 ANN("false");
945 ANN("format: false");
946 ANN("example: false");
947 return;
948
949 case NODE_ERRINFO:
950 ANN("virtual reference to $!");
951 ANN("format: rescue => id");
952 ANN("example: rescue => id");
953 return;
954
955 case NODE_DEFINED:
956 ANN("defined? expression");
957 ANN("format: defined?([nd_head])");
958 ANN("example: defined?(foo)");
959 F_NODE(nd_head, "expr");
960 return;
961
962 case NODE_POSTEXE:
963 ANN("post-execution");
964 ANN("format: END { [nd_body] }");
965 ANN("example: END { foo }");
966 LAST_NODE;
967 F_NODE(nd_body, "END clause");
968 return;
969
970 case NODE_ATTRASGN:
971 ANN("attr assignment");
972 ANN("format: [nd_recv].[nd_mid] = [nd_args]");
973 ANN("example: struct.field = foo");
974 F_NODE(nd_recv, "receiver");
975 F_ID(nd_mid, "method name");
976 LAST_NODE;
977 F_NODE(nd_args, "arguments");
978 return;
979
980 case NODE_LAMBDA:
981 ANN("lambda expression");
982 ANN("format: -> [nd_body]");
983 ANN("example: -> { foo }");
984 LAST_NODE;
985 F_NODE(nd_body, "lambda clause");
986 return;
987
988 case NODE_OPT_ARG:
989 ANN("optional arguments");
990 ANN("format: def method_name([nd_body=some], [nd_next..])");
991 ANN("example: def foo(a, b=1, c); end");
992 F_NODE(nd_body, "body");
993 LAST_NODE;
994 F_NODE(nd_next, "next");
995 return;
996
997 case NODE_KW_ARG:
998 ANN("keyword arguments");
999 ANN("format: def method_name([nd_body=some], [nd_next..])");
1000 ANN("example: def foo(a:1, b:2); end");
1001 F_NODE(nd_body, "body");
1002 LAST_NODE;
1003 F_NODE(nd_next, "next");
1004 return;
1005
1006 case NODE_POSTARG:
1007 ANN("post arguments");
1008 ANN("format: *[nd_1st], [nd_2nd..] = ..");
1009 ANN("example: a, *rest, z = foo");
1010 if (NODE_NAMED_REST_P(node->nd_1st)) {
1011 F_NODE(nd_1st, "rest argument");
1012 }
1013 else {
1014 F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
1015 }
1016 LAST_NODE;
1017 F_NODE(nd_2nd, "post arguments");
1018 return;
1019
1020 case NODE_ARGS:
1021 ANN("method parameters");
1022 ANN("format: def method_name(.., [nd_opt=some], *[nd_rest], [nd_pid], .., &[nd_body])");
1023 ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, &blk); end");
1024 F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
1025 F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
1026 F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
1027 F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
1028 F_ID(nd_ainfo->first_post_arg, "first post argument");
1029 F_CUSTOM1(nd_ainfo->rest_arg, "rest argument") {
1030 if (node->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
1031 A("1 (excessed comma)");
1032 }
1033 else {
1034 A_ID(node->nd_ainfo->rest_arg);
1035 }
1036 }
1037 F_ID(nd_ainfo->block_arg, "block argument");
1038 F_NODE(nd_ainfo->opt_args, "optional arguments");
1039 F_NODE(nd_ainfo->kw_args, "keyword arguments");
1040 LAST_NODE;
1041 F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
1042 return;
1043
1044 case NODE_SCOPE:
1045 ANN("new scope");
1046 ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
1047 F_CUSTOM1(nd_tbl, "local table") {
1048 ID *tbl = node->nd_tbl;
1049 int i;
1050 int size = tbl ? (int)*tbl++ : 0;
1051 if (size == 0) A("(empty)");
1052 for (i = 0; i < size; i++) {
1053 A_ID(tbl[i]); if (i < size - 1) A(",");
1054 }
1055 }
1056 F_NODE(nd_args, "arguments");
1057 LAST_NODE;
1058 F_NODE(nd_body, "body");
1059 return;
1060
1061 case NODE_ARYPTN:
1062 ANN("array pattern");
1063 ANN("format: [nd_pconst]([pre_args], ..., *[rest_arg], [post_args], ...)");
1064 F_NODE(nd_pconst, "constant");
1065 F_NODE(nd_apinfo->pre_args, "pre arguments");
1066 if (NODE_NAMED_REST_P(node->nd_apinfo->rest_arg)) {
1067 F_NODE(nd_apinfo->rest_arg, "rest argument");
1068 }
1069 else {
1070 F_MSG(nd_apinfo->rest_arg, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
1071 }
1072 LAST_NODE;
1073 F_NODE(nd_apinfo->post_args, "post arguments");
1074 return;
1075
1076 case NODE_FNDPTN:
1077 ANN("find pattern");
1078 ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])");
1079 F_NODE(nd_pconst, "constant");
1080 if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) {
1081 F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument");
1082 }
1083 else {
1084 F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
1085 }
1086 F_NODE(nd_fpinfo->args, "arguments");
1087
1088 LAST_NODE;
1089 if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) {
1090 F_NODE(nd_fpinfo->post_rest_arg, "post rest argument");
1091 }
1092 else {
1093 F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
1094 }
1095 return;
1096
1097 case NODE_HSHPTN:
1098 ANN("hash pattern");
1099 ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])");
1100 F_NODE(nd_pconst, "constant");
1101 F_NODE(nd_pkwargs, "keyword arguments");
1102 LAST_NODE;
1103 if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
1104 F_MSG(nd_pkwrestarg, "keyword rest argument", "NODE_SPECIAL_NO_REST_KEYWORD (**nil)");
1105 }
1106 else {
1107 F_NODE(nd_pkwrestarg, "keyword rest argument");
1108 }
1109 return;
1110
1111 case NODE_ARGS_AUX:
1112 case NODE_LAST:
1113 break;
1114 }
1115
1116 rb_bug("dump_node: unknown node: %s", ruby_node_name(nd_type(node)));
1117}
1118
1119 VALUE
1120rb_parser_dump_tree(const NODE *node, int comment)
1121{
1122 VALUE buf = rb_str_new_cstr(
1123 "###########################################################\n"
1124 "## Do NOT use this node dump for any purpose other than ##\n"
1125 "## debug and research. Compatibility is not guaranteed. ##\n"
1126 "###########################################################\n\n"
1127 );
1128 dump_node(buf, rb_str_new_cstr("# "), comment, node);
1129 return buf;
1130}
1131
1132/* Setup NODE structure.
1133 * NODE is not an object managed by GC, but it imitates an object
1134 * so that it can work with `RB_TYPE_P(obj, T_NODE)`.
1135 * This dirty hack is needed because Ripper jumbles NODEs and other type
1136 * objects.
1137 */
1138void
1139rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
1140{
1141 n->flags = T_NODE;
1142 nd_init_type(n, type);
1143 n->u1.value = a0;
1144 n->u2.value = a1;
1145 n->u3.value = a2;
1146 n->nd_loc.beg_pos.lineno = 0;
1147 n->nd_loc.beg_pos.column = 0;
1148 n->nd_loc.end_pos.lineno = 0;
1149 n->nd_loc.end_pos.column = 0;
1150}
1151
1152 typedef struct node_buffer_elem_struct {
1153 struct node_buffer_elem_struct *next;
1154 long len;
1155 NODE buf[FLEX_ARY_LEN];
1156} node_buffer_elem_t;
1157
1158 typedef struct {
1159 long idx, len;
1160 node_buffer_elem_t *head;
1161 node_buffer_elem_t *last;
1162} node_buffer_list_t;
1163
1164 struct node_buffer_struct {
1165 node_buffer_list_t unmarkable;
1166 node_buffer_list_t markable;
1167 ID *local_tables;
1168 VALUE mark_hash;
1169};
1170
1171static void
1172init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head)
1173{
1174 nb->idx = 0;
1175 nb->len = NODE_BUF_DEFAULT_LEN;
1176 nb->head = nb->last = head;
1177 nb->head->len = nb->len;
1178 nb->head->next = NULL;
1179}
1180
1181static node_buffer_t *
1182rb_node_buffer_new(void)
1183{
1184 const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
1185 const size_t alloc_size = sizeof(node_buffer_t) + (bucket_size * 2);
1186 STATIC_ASSERT(
1187 integer_overflow,
1188 offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE)
1189 > sizeof(node_buffer_t) + 2 * sizeof(node_buffer_elem_t));
1190 node_buffer_t *nb = ruby_xmalloc(alloc_size);
1191 init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]);
1192 init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
1193 nb->local_tables = 0;
1194 nb->mark_hash = Qnil;
1195 return nb;
1196}
1197
1198static void
1199node_buffer_list_free(node_buffer_list_t * nb)
1200{
1201 node_buffer_elem_t *nbe = nb->head;
1202
1203 while (nbe != nb->last) {
1204 void *buf = nbe;
1205 nbe = nbe->next;
1206 xfree(buf);
1207 }
1208}
1209
1210static void
1211rb_node_buffer_free(node_buffer_t *nb)
1212{
1213 node_buffer_list_free(&nb->unmarkable);
1214 node_buffer_list_free(&nb->markable);
1215 ID * local_table = nb->local_tables;
1216 while (local_table) {
1217 unsigned int size = (unsigned int)*local_table;
1218 ID * next_table = (ID *)local_table[size + 1];
1219 xfree(local_table);
1220 local_table = next_table;
1221 }
1222 xfree(nb);
1223}
1224
1225static NODE *
1226ast_newnode_in_bucket(node_buffer_list_t *nb)
1227{
1228 if (nb->idx >= nb->len) {
1229 long n = nb->len * 2;
1230 node_buffer_elem_t *nbe;
1231 nbe = rb_xmalloc_mul_add(n, sizeof(NODE), offsetof(node_buffer_elem_t, buf));
1232 nbe->len = n;
1233 nb->idx = 0;
1234 nb->len = n;
1235 nbe->next = nb->head;
1236 nb->head = nbe;
1237 }
1238 return &nb->head->buf[nb->idx++];
1239}
1240
1241 RBIMPL_ATTR_PURE()
1242static bool
1243nodetype_markable_p(enum node_type type)
1244{
1245 switch (type) {
1246 case NODE_MATCH:
1247 case NODE_LIT:
1248 case NODE_STR:
1249 case NODE_XSTR:
1250 case NODE_DSTR:
1251 case NODE_DXSTR:
1252 case NODE_DREGX:
1253 case NODE_DSYM:
1254 case NODE_ARGS:
1255 case NODE_ARYPTN:
1256 case NODE_FNDPTN:
1257 return true;
1258 default:
1259 return false;
1260 }
1261}
1262
1263 NODE *
1264rb_ast_newnode(rb_ast_t *ast, enum node_type type)
1265{
1266 node_buffer_t *nb = ast->node_buffer;
1267 node_buffer_list_t *bucket =
1268 (nodetype_markable_p(type) ? &nb->markable : &nb->unmarkable);
1269 return ast_newnode_in_bucket(bucket);
1270}
1271
1272void
1273rb_ast_node_type_change(NODE *n, enum node_type type)
1274{
1275 enum node_type old_type = nd_type(n);
1276 if (nodetype_markable_p(old_type) != nodetype_markable_p(type)) {
1277 rb_bug("node type changed: %s -> %s",
1278 ruby_node_name(old_type), ruby_node_name(type));
1279 }
1280}
1281
1282void
1283rb_ast_add_local_table(rb_ast_t *ast, ID *buf)
1284{
1285 unsigned int size = (unsigned int)*buf;
1286 buf[size + 1] = (ID)ast->node_buffer->local_tables;
1287 ast->node_buffer->local_tables = buf;
1288}
1289
1290void
1291rb_ast_delete_node(rb_ast_t *ast, NODE *n)
1292{
1293 (void)ast;
1294 (void)n;
1295 /* should we implement freelist? */
1296}
1297
1298 rb_ast_t *
1299rb_ast_new(void)
1300{
1301 node_buffer_t *nb = rb_node_buffer_new();
1302 rb_ast_t *ast = (rb_ast_t *)rb_imemo_new(imemo_ast, 0, 0, 0, (VALUE)nb);
1303 return ast;
1304}
1305
1306 typedef void node_itr_t(void *ctx, NODE * node);
1307
1308static void
1309iterate_buffer_elements(node_buffer_elem_t *nbe, long len, node_itr_t *func, void *ctx)
1310{
1311 long cursor;
1312 for (cursor = 0; cursor < len; cursor++) {
1313 func(ctx, &nbe->buf[cursor]);
1314 }
1315}
1316
1317static void
1318iterate_node_values(node_buffer_list_t *nb, node_itr_t * func, void *ctx)
1319{
1320 node_buffer_elem_t *nbe = nb->head;
1321
1322 /* iterate over the head first because it's not full */
1323 iterate_buffer_elements(nbe, nb->idx, func, ctx);
1324
1325 nbe = nbe->next;
1326 while (nbe) {
1327 iterate_buffer_elements(nbe, nbe->len, func, ctx);
1328 nbe = nbe->next;
1329 }
1330}
1331
1332static void
1333mark_ast_value(void *ctx, NODE * node)
1334{
1335 switch (nd_type(node)) {
1336 case NODE_ARGS:
1337 {
1338 struct rb_args_info *args = node->nd_ainfo;
1339 rb_gc_mark_movable(args->imemo);
1340 break;
1341 }
1342 case NODE_MATCH:
1343 case NODE_LIT:
1344 case NODE_STR:
1345 case NODE_XSTR:
1346 case NODE_DSTR:
1347 case NODE_DXSTR:
1348 case NODE_DREGX:
1349 case NODE_DSYM:
1350 rb_gc_mark_movable(node->nd_lit);
1351 break;
1352 case NODE_ARYPTN:
1353 case NODE_FNDPTN:
1354 rb_gc_mark_movable(node->nd_rval);
1355 break;
1356 default:
1357 rb_bug("unreachable node %s", ruby_node_name(nd_type(node)));
1358 }
1359}
1360
1361static void
1362update_ast_value(void *ctx, NODE * node)
1363{
1364 switch (nd_type(node)) {
1365 case NODE_ARGS:
1366 {
1367 struct rb_args_info *args = node->nd_ainfo;
1368 args->imemo = rb_gc_location(args->imemo);
1369 break;
1370 }
1371 case NODE_MATCH:
1372 case NODE_LIT:
1373 case NODE_STR:
1374 case NODE_XSTR:
1375 case NODE_DSTR:
1376 case NODE_DXSTR:
1377 case NODE_DREGX:
1378 case NODE_DSYM:
1379 node->nd_lit = rb_gc_location(node->nd_lit);
1380 break;
1381 case NODE_ARYPTN:
1382 case NODE_FNDPTN:
1383 node->nd_rval = rb_gc_location(node->nd_rval);
1384 break;
1385 default:
1386 rb_bug("unreachable");
1387 }
1388}
1389
1390void
1391rb_ast_update_references(rb_ast_t *ast)
1392{
1393 if (ast->node_buffer) {
1394 node_buffer_t *nb = ast->node_buffer;
1395
1396 iterate_node_values(&nb->markable, update_ast_value, NULL);
1397 }
1398}
1399
1400void
1401rb_ast_mark(rb_ast_t *ast)
1402{
1403 if (ast->node_buffer) rb_gc_mark(ast->node_buffer->mark_hash);
1404 if (ast->body.compile_option) rb_gc_mark(ast->body.compile_option);
1405 if (ast->node_buffer) {
1406 node_buffer_t *nb = ast->node_buffer;
1407
1408 iterate_node_values(&nb->markable, mark_ast_value, NULL);
1409 }
1410}
1411
1412void
1413rb_ast_free(rb_ast_t *ast)
1414{
1415 if (ast->node_buffer) {
1416 rb_node_buffer_free(ast->node_buffer);
1417 ast->node_buffer = 0;
1418 }
1419}
1420
1421static size_t
1422buffer_list_size(node_buffer_list_t *nb)
1423{
1424 size_t size = 0;
1425 node_buffer_elem_t *nbe = nb->head;
1426 while (nbe != nb->last) {
1427 nbe = nbe->next;
1428 size += offsetof(node_buffer_elem_t, buf) + nb->len * sizeof(NODE);
1429 }
1430 return size;
1431}
1432
1433size_t
1434rb_ast_memsize(const rb_ast_t *ast)
1435{
1436 size_t size = 0;
1437 node_buffer_t *nb = ast->node_buffer;
1438
1439 if (nb) {
1440 size += sizeof(node_buffer_t) + offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
1441 size += buffer_list_size(&nb->unmarkable);
1442 size += buffer_list_size(&nb->markable);
1443 }
1444 return size;
1445}
1446
1447void
1448rb_ast_dispose(rb_ast_t *ast)
1449{
1450 rb_ast_free(ast);
1451}
1452
1453void
1454rb_ast_add_mark_object(rb_ast_t *ast, VALUE obj)
1455{
1456 if (NIL_P(ast->node_buffer->mark_hash)) {
1457 RB_OBJ_WRITE(ast, &ast->node_buffer->mark_hash, rb_ident_hash_new());
1458 }
1459 rb_hash_aset(ast->node_buffer->mark_hash, obj, Qtrue);
1460}
offsetof
#define offsetof(p_type, field)
Definition: addrinfo.h:186
FLEX_ARY_LEN
#define FLEX_ARY_LEN
Definition: compilers.h:88
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
FL_SINGLETON
#define FL_SINGLETON
Definition: fl_type.h:49
PRIsVALUE
#define PRIsVALUE
Definition: function.c:10
rb_gc_location
VALUE rb_gc_location(VALUE value)
Definition: gc.c:9003
rb_gc_mark_movable
void rb_gc_mark_movable(VALUE ptr)
Definition: gc.c:6106
rb_xmalloc_mul_add
void * rb_xmalloc_mul_add(size_t x, size_t y, size_t z)
Definition: gc.c:10920
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
ruby_xmalloc
void * ruby_xmalloc(size_t size)
Allocates a storage instance.
Definition: gc.c:12795
rb_imemo_new
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
Definition: gc.c:2412
FL_TEST
#define FL_TEST
Definition: fl_type.h:130
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:768
rb_ident_hash_new
VALUE rb_ident_hash_new(void)
Definition: hash.c:4443
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:585
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2901
imemo_ast
@ imemo_ast
Definition: imemo.h:44
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: string.h:219
rb_class_path
VALUE rb_class_path(VALUE)
Definition: variable.c:169
hash.h
Internal header for Hash.
STATIC_ASSERT
#define STATIC_ASSERT
Definition: static_assert.h:14
internal.h
size
voidpf void uLong size
Definition: ioapi.h:138
int
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
buf
voidpf void * buf
Definition: ioapi.h:138
ruby_node_name
const char * ruby_node_name(int node)
Definition: iseq.c:2593
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
name
const char * name
Definition: nkf.c:208
rb_node_init
void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
Definition: node.c:1139
F_NODE
#define F_NODE(name, ann)
Definition: node.c:72
rb_parser_dump_tree
VALUE rb_parser_dump_tree(const NODE *node, int comment)
Definition: node.c:1120
rb_dump_literal
VALUE rb_dump_literal(VALUE lit)
Definition: node.c:83
F_CUSTOM1
#define F_CUSTOM1(name, ann)
Definition: node.c:64
rb_ast_dispose
void rb_ast_dispose(rb_ast_t *ast)
Definition: node.c:1448
node_buffer_elem_t
struct node_buffer_elem_struct node_buffer_elem_t
D_NODE_HEADER
#define D_NODE_HEADER(node)
Definition: node.c:41
rb_ast_new
rb_ast_t * rb_ast_new(void)
Definition: node.c:1299
A_ID
#define A_ID(id)
Definition: node.c:26
F_LONG
#define F_LONG(name, ann)
Definition: node.c:68
rb_ast_add_mark_object
void rb_ast_add_mark_object(rb_ast_t *ast, VALUE obj)
Definition: node.c:1454
A_INDENT
#define A_INDENT
Definition: node.c:23
rb_ast_newnode
NODE * rb_ast_newnode(rb_ast_t *ast, enum node_type type)
Definition: node.c:1264
A_LONG
#define A_LONG(val)
Definition: node.c:28
rb_ast_add_local_table
void rb_ast_add_local_table(rb_ast_t *ast, ID *buf)
Definition: node.c:1283
D_DEDENT
#define D_DEDENT
Definition: node.c:25
F_ID
#define F_ID(name, ann)
Definition: node.c:65
rb_ast_update_references
void rb_ast_update_references(rb_ast_t *ast)
Definition: node.c:1391
F_GENTRY
#define F_GENTRY(name, ann)
Definition: node.c:66
rb_ast_mark
void rb_ast_mark(rb_ast_t *ast)
Definition: node.c:1401
A
#define A(str)
Definition: node.c:20
rb_ast_memsize
size_t rb_ast_memsize(const rb_ast_t *ast)
Definition: node.c:1434
F_INT
#define F_INT(name, ann)
Definition: node.c:67
node_itr_t
void node_itr_t(void *ctx, NODE *node)
Definition: node.c:1306
rb_ast_node_type_change
void rb_ast_node_type_change(NODE *n, enum node_type type)
Definition: node.c:1273
NODE_BUF_DEFAULT_LEN
#define NODE_BUF_DEFAULT_LEN
Definition: node.c:18
F_LIT
#define F_LIT(name, ann)
Definition: node.c:69
A_INT
#define A_INT(val)
Definition: node.c:27
D_NULL_NODE
#define D_NULL_NODE
Definition: node.c:40
rb_ast_free
void rb_ast_free(rb_ast_t *ast)
Definition: node.c:1413
AR
#define AR(str)
Definition: node.c:21
ANN
#define ANN(ann)
Definition: node.c:75
D_INDENT
#define D_INDENT
Definition: node.c:24
LAST_NODE
#define LAST_NODE
Definition: node.c:80
F_MSG
#define F_MSG(name, ann, desc)
Definition: node.c:70
rb_ast_delete_node
void rb_ast_delete_node(rb_ast_t *ast, NODE *n)
Definition: node.c:1291
nd_fpinfo
#define nd_fpinfo
Definition: node.h:284
nd_pkwrestarg
#define nd_pkwrestarg
Definition: node.h:280
nd_state
#define nd_state
Definition: node.h:265
nd_var
#define nd_var
Definition: node.h:240
nd_cond
#define nd_cond
Definition: node.h:220
nd_pkwargs
#define nd_pkwargs
Definition: node.h:279
nd_vid
#define nd_vid
Definition: node.h:233
nd_mid
#define nd_mid
Definition: node.h:254
NODE
struct RNode NODE
nd_ensr
#define nd_ensr
Definition: node.h:225
nd_resq
#define nd_resq
Definition: node.h:224
nd_end
#define nd_end
Definition: node.h:264
nd_iter
#define nd_iter
Definition: node.h:241
nd_recv
#define nd_recv
Definition: node.h:253
nd_ainfo
#define nd_ainfo
Definition: node.h:256
nd_1st
#define nd_1st
Definition: node.h:227
node_type
node_type
Definition: node.h:21
NODE_OR
@ NODE_OR
Definition: node.h:45
NODE_LVAR
@ NODE_LVAR
Definition: node.h:72
NODE_FOR
@ NODE_FOR
Definition: node.h:34
NODE_OP_ASGN_OR
@ NODE_OP_ASGN_OR
Definition: node.h:57
NODE_SPLAT
@ NODE_SPLAT
Definition: node.h:98
NODE_DEFS
@ NODE_DEFS
Definition: node.h:101
NODE_REDO
@ NODE_REDO
Definition: node.h:38
NODE_IN
@ NODE_IN
Definition: node.h:30
NODE_MATCH
@ NODE_MATCH
Definition: node.h:80
NODE_MATCH2
@ NODE_MATCH2
Definition: node.h:81
NODE_STR
@ NODE_STR
Definition: node.h:84
NODE_DSYM
@ NODE_DSYM
Definition: node.h:121
NODE_DASGN_CURR
@ NODE_DASGN_CURR
Definition: node.h:49
NODE_LIST
@ NODE_LIST
Definition: node.h:66
NODE_CVAR
@ NODE_CVAR
Definition: node.h:77
NODE_NEXT
@ NODE_NEXT
Definition: node.h:37
NODE_MODULE
@ NODE_MODULE
Definition: node.h:106
NODE_ARGSCAT
@ NODE_ARGSCAT
Definition: node.h:96
NODE_DASGN
@ NODE_DASGN
Definition: node.h:48
NODE_LASGN
@ NODE_LASGN
Definition: node.h:47
NODE_AND
@ NODE_AND
Definition: node.h:44
NODE_MASGN
@ NODE_MASGN
Definition: node.h:46
NODE_CLASS
@ NODE_CLASS
Definition: node.h:105
NODE_CVASGN
@ NODE_CVASGN
Definition: node.h:53
NODE_CALL
@ NODE_CALL
Definition: node.h:59
NODE_OP_ASGN2
@ NODE_OP_ASGN2
Definition: node.h:55
NODE_FALSE
@ NODE_FALSE
Definition: node.h:117
NODE_FLIP2
@ NODE_FLIP2
Definition: node.h:112
NODE_EVSTR
@ NODE_EVSTR
Definition: node.h:88
NODE_DVAR
@ NODE_DVAR
Definition: node.h:73
NODE_ATTRASGN
@ NODE_ATTRASGN
Definition: node.h:122
NODE_BEGIN
@ NODE_BEGIN
Definition: node.h:40
NODE_UNTIL
@ NODE_UNTIL
Definition: node.h:32
NODE_FCALL
@ NODE_FCALL
Definition: node.h:61
NODE_MATCH3
@ NODE_MATCH3
Definition: node.h:82
NODE_LAST
@ NODE_LAST
Definition: node.h:127
NODE_SUPER
@ NODE_SUPER
Definition: node.h:64
NODE_CASE2
@ NODE_CASE2
Definition: node.h:27
NODE_DXSTR
@ NODE_DXSTR
Definition: node.h:87
NODE_IASGN
@ NODE_IASGN
Definition: node.h:51
NODE_GASGN
@ NODE_GASGN
Definition: node.h:50
NODE_OP_CDECL
@ NODE_OP_CDECL
Definition: node.h:58
NODE_RESCUE
@ NODE_RESCUE
Definition: node.h:41
NODE_SCOPE
@ NODE_SCOPE
Definition: node.h:22
NODE_SCLASS
@ NODE_SCLASS
Definition: node.h:107
NODE_HASH
@ NODE_HASH
Definition: node.h:69
NODE_YIELD
@ NODE_YIELD
Definition: node.h:71
NODE_LAMBDA
@ NODE_LAMBDA
Definition: node.h:123
NODE_CDECL
@ NODE_CDECL
Definition: node.h:52
NODE_OP_ASGN_AND
@ NODE_OP_ASGN_AND
Definition: node.h:56
NODE_BLOCK
@ NODE_BLOCK
Definition: node.h:23
NODE_TRUE
@ NODE_TRUE
Definition: node.h:116
NODE_ARGS_AUX
@ NODE_ARGS_AUX
Definition: node.h:92
NODE_CASE
@ NODE_CASE
Definition: node.h:26
NODE_ITER
@ NODE_ITER
Definition: node.h:33
NODE_RETRY
@ NODE_RETRY
Definition: node.h:39
NODE_DOT3
@ NODE_DOT3
Definition: node.h:111
NODE_RETURN
@ NODE_RETURN
Definition: node.h:70
NODE_BACK_REF
@ NODE_BACK_REF
Definition: node.h:79
NODE_QCALL
@ NODE_QCALL
Definition: node.h:63
NODE_ENSURE
@ NODE_ENSURE
Definition: node.h:43
NODE_SELF
@ NODE_SELF
Definition: node.h:114
NODE_DOT2
@ NODE_DOT2
Definition: node.h:110
NODE_OPT_ARG
@ NODE_OPT_ARG
Definition: node.h:93
NODE_FNDPTN
@ NODE_FNDPTN
Definition: node.h:126
NODE_LIT
@ NODE_LIT
Definition: node.h:83
NODE_UNDEF
@ NODE_UNDEF
Definition: node.h:104
NODE_FLIP3
@ NODE_FLIP3
Definition: node.h:113
NODE_POSTARG
@ NODE_POSTARG
Definition: node.h:95
NODE_NTH_REF
@ NODE_NTH_REF
Definition: node.h:78
NODE_VCALL
@ NODE_VCALL
Definition: node.h:62
NODE_KW_ARG
@ NODE_KW_ARG
Definition: node.h:94
NODE_DEFN
@ NODE_DEFN
Definition: node.h:100
NODE_GVAR
@ NODE_GVAR
Definition: node.h:74
NODE_ALIAS
@ NODE_ALIAS
Definition: node.h:102
NODE_COLON2
@ NODE_COLON2
Definition: node.h:108
NODE_POSTEXE
@ NODE_POSTEXE
Definition: node.h:120
NODE_IVAR
@ NODE_IVAR
Definition: node.h:75
NODE_ERRINFO
@ NODE_ERRINFO
Definition: node.h:118
NODE_BLOCK_PASS
@ NODE_BLOCK_PASS
Definition: node.h:99
NODE_ZSUPER
@ NODE_ZSUPER
Definition: node.h:65
NODE_DREGX
@ NODE_DREGX
Definition: node.h:89
NODE_DEFINED
@ NODE_DEFINED
Definition: node.h:119
NODE_ONCE
@ NODE_ONCE
Definition: node.h:90
NODE_IF
@ NODE_IF
Definition: node.h:24
NODE_HSHPTN
@ NODE_HSHPTN
Definition: node.h:125
NODE_ZLIST
@ NODE_ZLIST
Definition: node.h:67
NODE_ARYPTN
@ NODE_ARYPTN
Definition: node.h:124
NODE_XSTR
@ NODE_XSTR
Definition: node.h:86
NODE_BREAK
@ NODE_BREAK
Definition: node.h:36
NODE_UNLESS
@ NODE_UNLESS
Definition: node.h:25
NODE_VALIAS
@ NODE_VALIAS
Definition: node.h:103
NODE_WHEN
@ NODE_WHEN
Definition: node.h:29
NODE_CASE3
@ NODE_CASE3
Definition: node.h:28
NODE_COLON3
@ NODE_COLON3
Definition: node.h:109
NODE_CONST
@ NODE_CONST
Definition: node.h:76
NODE_NIL
@ NODE_NIL
Definition: node.h:115
NODE_VALUES
@ NODE_VALUES
Definition: node.h:68
NODE_RESBODY
@ NODE_RESBODY
Definition: node.h:42
NODE_DSTR
@ NODE_DSTR
Definition: node.h:85
NODE_FOR_MASGN
@ NODE_FOR_MASGN
Definition: node.h:35
NODE_WHILE
@ NODE_WHILE
Definition: node.h:31
NODE_ARGSPUSH
@ NODE_ARGSPUSH
Definition: node.h:97
NODE_OP_ASGN1
@ NODE_OP_ASGN1
Definition: node.h:54
NODE_OPCALL
@ NODE_OPCALL
Definition: node.h:60
NODE_ARGS
@ NODE_ARGS
Definition: node.h:91
nd_brace
#define nd_brace
Definition: node.h:276
nd_alias
#define nd_alias
Definition: node.h:272
nd_2nd
#define nd_2nd
Definition: node.h:228
nd_nth
#define nd_nth
Definition: node.h:268
nd_entry
#define nd_entry
Definition: node.h:232
NODE_NAMED_REST_P
#define NODE_NAMED_REST_P(node)
Definition: node.h:388
nd_stts
#define nd_stts
Definition: node.h:230
nd_pconst
#define nd_pconst
Definition: node.h:278
node_buffer_t
struct node_buffer_struct node_buffer_t
Definition: node.h:396
nd_args
#define nd_args
Definition: node.h:255
nd_cpath
#define nd_cpath
Definition: node.h:260
nd_else
#define nd_else
Definition: node.h:222
NODE_SPECIAL_NO_REST_KEYWORD
#define NODE_SPECIAL_NO_REST_KEYWORD
Definition: node.h:390
nd_alen
#define nd_alen
Definition: node.h:217
nd_lit
#define nd_lit
Definition: node.h:246
nd_undef
#define nd_undef
Definition: node.h:274
nd_head
#define nd_head
Definition: node.h:216
NODE_REQUIRED_KEYWORD_P
#define NODE_REQUIRED_KEYWORD_P(node)
Definition: node.h:386
nd_beg
#define nd_beg
Definition: node.h:263
nd_type
#define nd_type(n)
Definition: node.h:188
nd_apinfo
#define nd_apinfo
Definition: node.h:282
nd_super
#define nd_super
Definition: node.h:261
nd_init_type
#define nd_init_type(n, t)
Definition: node.h:191
nd_body
#define nd_body
Definition: node.h:221
nd_value
#define nd_value
Definition: node.h:243
nd_defn
#define nd_defn
Definition: node.h:258
NODE_SPECIAL_EXCESSIVE_COMMA
#define NODE_SPECIAL_EXCESSIVE_COMMA
Definition: node.h:389
nd_next
#define nd_next
Definition: node.h:218
nd_tbl
#define nd_tbl
Definition: node.h:238
nd_aid
#define nd_aid
Definition: node.h:244
nd_orig
#define nd_orig
Definition: node.h:273
RBIMPL_ATTR_PURE
#define RBIMPL_ATTR_PURE()
Wraps (or simulates) __attribute__((pure))
Definition: pure.h:33
NULL
#define NULL
Definition: regenc.h:69
RB_OBJ_WRITE
#define RB_OBJ_WRITE(a, slot, b)
WB for new reference from ‘a’ to ‘b’.
Definition: rgengc.h:107
ruby.h
Qtrue
#define Qtrue
Definition: special_consts.h:52
Qnil
#define Qnil
Definition: special_consts.h:51
NIL_P
#define NIL_P
Definition: special_consts.h:46
rb_str_catf
VALUE rb_str_catf(VALUE, const char *,...)
Definition: sprintf.c:1243
rb_sprintf
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
st_index_t
st_data_t st_index_t
Definition: st.h:50
A
Definition: nested_struct10.c:12
RNode
Definition: node.h:149
RNode::nd_loc
rb_code_location_t nd_loc
Definition: node.h:172
RNode::flags
VALUE flags
Definition: node.h:150
RNode::u2
union RNode::@128 u2
RNode::value
VALUE value
Definition: node.h:154
RNode::u1
union RNode::@127 u1
RNode::u3
union RNode::@129 u3
add_option_arg
Definition: node.c:124
add_option_arg::count
st_index_t count
Definition: node.c:126
add_option_arg::indent
VALUE indent
Definition: node.c:125
add_option_arg::buf
VALUE buf
Definition: node.c:125
node_buffer_elem_struct
Definition: node.c:1152
node_buffer_elem_struct::next
struct node_buffer_elem_struct * next
Definition: node.c:1153
node_buffer_elem_struct::len
long len
Definition: node.c:1154
node_buffer_elem_struct::buf
NODE buf[FLEX_ARY_LEN]
Definition: node.c:1155
node_buffer_list_t
Definition: node.c:1158
node_buffer_list_t::last
node_buffer_elem_t * last
Definition: node.c:1161
node_buffer_list_t::idx
long idx
Definition: node.c:1159
node_buffer_list_t::len
long len
Definition: node.c:1159
node_buffer_list_t::head
node_buffer_elem_t * head
Definition: node.c:1160
node_buffer_struct
Definition: node.c:1164
node_buffer_struct::markable
node_buffer_list_t markable
Definition: node.c:1166
node_buffer_struct::local_tables
ID * local_tables
Definition: node.c:1167
node_buffer_struct::mark_hash
VALUE mark_hash
Definition: node.c:1168
node_buffer_struct::unmarkable
node_buffer_list_t unmarkable
Definition: node.c:1165
rb_args_info
Definition: node.h:436
rb_args_info::imemo
VALUE imemo
Definition: node.h:455
rb_ast_body_struct::compile_option
VALUE compile_option
Definition: node.h:400
rb_ast_struct
Definition: node.h:403
rb_ast_struct::body
rb_ast_body_t body
Definition: node.h:406
rb_ast_struct::node_buffer
node_buffer_t * node_buffer
Definition: node.h:405
rb_code_location_struct::beg_pos
rb_code_position_t beg_pos
Definition: node.h:136
rb_code_location_struct::end_pos
rb_code_position_t end_pos
Definition: node.h:137
rb_code_position_struct::lineno
int lineno
Definition: node.h:131
rb_code_position_struct::column
int column
Definition: node.h:132
next_table
#define next_table
VALUE
unsigned long VALUE
Definition: value.h:38
ID
unsigned long ID
Definition: value.h:39
T_NODE
#define T_NODE
Definition: value_type.h:72
T_MODULE
#define T_MODULE
Definition: value_type.h:69
T_ICLASS
#define T_ICLASS
Definition: value_type.h:65
T_CLASS
#define T_CLASS
Definition: value_type.h:57
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
vm_core.h
xfree
#define xfree
Definition: xmalloc.h:49