Ruby  3.1.4p223 (2023-03-30 revision HEAD)
ast.c
1 /* indent-tabs-mode: nil */
2 #include "internal.h"
3 #include "internal/parse.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"
12 
13 #include "builtin.h"
14 
15 static VALUE rb_mAST;
16 static VALUE rb_cNode;
17 
18 struct ASTNodeData {
19  rb_ast_t *ast;
20  const NODE *node;
21 };
22 
23 static void
24 node_gc_mark(void *ptr)
25 {
26  struct ASTNodeData *data = (struct ASTNodeData *)ptr;
27  rb_gc_mark((VALUE)data->ast);
28 }
29 
30 static size_t
31 node_memsize(const void *ptr)
32 {
33  struct ASTNodeData *data = (struct ASTNodeData *)ptr;
34  return rb_ast_memsize(data->ast);
35 }
36 
37 static const rb_data_type_t rb_node_type = {
38  "AST/node",
39  {node_gc_mark, RUBY_TYPED_DEFAULT_FREE, node_memsize,},
40  0, 0,
41  RUBY_TYPED_FREE_IMMEDIATELY,
42 };
43 
44 static VALUE rb_ast_node_alloc(VALUE klass);
45 
46 static void
47 setup_node(VALUE obj, rb_ast_t *ast, const NODE *node)
48 {
49  struct ASTNodeData *data;
50 
51  TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data);
52  data->ast = ast;
53  data->node = node;
54 }
55 
56 static VALUE
57 ast_new_internal(rb_ast_t *ast, const NODE *node)
58 {
59  VALUE obj;
60 
61  obj = rb_ast_node_alloc(rb_cNode);
62  setup_node(obj, ast, node);
63 
64  return obj;
65 }
66 
67 static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines);
68 static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines);
69 
70 static VALUE
71 ast_parse_new(void)
72 {
73  return rb_parser_set_context(rb_parser_new(), NULL, 0);
74 }
75 
76 static VALUE
77 ast_parse_done(rb_ast_t *ast)
78 {
79  if (!ast->body.root) {
80  rb_ast_dispose(ast);
81  rb_exc_raise(GET_EC()->errinfo);
82  }
83 
84  return ast_new_internal(ast, (NODE *)ast->body.root);
85 }
86 
87 static VALUE
88 ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines)
89 {
90  return rb_ast_parse_str(str, keep_script_lines);
91 }
92 
93 static VALUE
94 rb_ast_parse_str(VALUE str, VALUE keep_script_lines)
95 {
96  rb_ast_t *ast = 0;
97 
98  StringValue(str);
99  VALUE vparser = ast_parse_new();
100  if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
101  ast = rb_parser_compile_string_path(vparser, Qnil, str, 1);
102  return ast_parse_done(ast);
103 }
104 
105 static VALUE
106 ast_s_parse_file(rb_execution_context_t *ec, VALUE module, VALUE path, VALUE keep_script_lines)
107 {
108  return rb_ast_parse_file(path, keep_script_lines);
109 }
110 
111 static VALUE
112 rb_ast_parse_file(VALUE path, VALUE keep_script_lines)
113 {
114  VALUE f;
115  rb_ast_t *ast = 0;
116  rb_encoding *enc = rb_utf8_encoding();
117 
118  FilePathValue(path);
119  f = rb_file_open_str(path, "r");
120  rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
121  VALUE vparser = ast_parse_new();
122  if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
123  ast = rb_parser_compile_file_path(vparser, Qnil, f, 1);
124  rb_io_close(f);
125  return ast_parse_done(ast);
126 }
127 
128 static VALUE
129 lex_array(VALUE array, int index)
130 {
131  VALUE str = rb_ary_entry(array, index);
132  if (!NIL_P(str)) {
133  StringValue(str);
134  if (!rb_enc_asciicompat(rb_enc_get(str))) {
135  rb_raise(rb_eArgError, "invalid source encoding");
136  }
137  }
138  return str;
139 }
140 
141 static VALUE
142 rb_ast_parse_array(VALUE array, VALUE keep_script_lines)
143 {
144  rb_ast_t *ast = 0;
145 
146  array = rb_check_array_type(array);
147  VALUE vparser = ast_parse_new();
148  if (RTEST(keep_script_lines)) rb_parser_keep_script_lines(vparser);
149  ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1);
150  return ast_parse_done(ast);
151 }
152 
153 static VALUE node_children(rb_ast_t*, const NODE*);
154 
155 static VALUE
156 node_find(VALUE self, const int node_id)
157 {
158  VALUE ary;
159  long i;
160  struct ASTNodeData *data;
161  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
162 
163  if (nd_node_id(data->node) == node_id) return self;
164 
165  ary = node_children(data->ast, data->node);
166 
167  for (i = 0; i < RARRAY_LEN(ary); i++) {
168  VALUE child = RARRAY_AREF(ary, i);
169 
170  if (CLASS_OF(child) == rb_cNode) {
171  VALUE result = node_find(child, node_id);
172  if (RTEST(result)) return result;
173  }
174  }
175 
176  return Qnil;
177 }
178 
179 extern VALUE rb_e_script;
180 
181 static VALUE
182 script_lines(VALUE path)
183 {
184  VALUE hash, lines;
185  ID script_lines;
186  CONST_ID(script_lines, "SCRIPT_LINES__");
187  if (!rb_const_defined_at(rb_cObject, script_lines)) return Qnil;
188  hash = rb_const_get_at(rb_cObject, script_lines);
189  if (!RB_TYPE_P(hash, T_HASH)) return Qnil;
190  lines = rb_hash_lookup(hash, path);
191  if (!RB_TYPE_P(lines, T_ARRAY)) return Qnil;
192  return lines;
193 }
194 
195 static VALUE
196 ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script_lines)
197 {
198  VALUE node, lines = Qnil;
199  const rb_iseq_t *iseq;
200  int node_id;
201 
202  if (rb_frame_info_p(body)) {
203  iseq = rb_get_iseq_from_frame_info(body);
204  node_id = rb_get_node_id_from_frame_info(body);
205  }
206  else {
207  iseq = NULL;
208 
209  if (rb_obj_is_proc(body)) {
210  iseq = vm_proc_iseq(body);
211 
212  if (!rb_obj_is_iseq((VALUE)iseq)) return Qnil;
213  }
214  else {
215  iseq = rb_method_iseq(body);
216  }
217  if (iseq) {
218  node_id = iseq->body->location.node_id;
219  }
220  }
221 
222  if (!iseq) {
223  return Qnil;
224  }
225  lines = iseq->body->variable.script_lines;
226 
227  VALUE path = rb_iseq_path(iseq);
228  int e_option = RSTRING_LEN(path) == 2 && memcmp(RSTRING_PTR(path), "-e", 2) == 0;
229 
230  if (NIL_P(lines) && rb_iseq_from_eval_p(iseq) && !e_option) {
231  rb_raise(rb_eArgError, "cannot get AST for method defined in eval");
232  }
233 
234  if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) {
235  node = rb_ast_parse_array(lines, keep_script_lines);
236  }
237  else if (e_option) {
238  node = rb_ast_parse_str(rb_e_script, keep_script_lines);
239  }
240  else {
241  node = rb_ast_parse_file(path, keep_script_lines);
242  }
243 
244  return node_find(node, node_id);
245 }
246 
247 static VALUE
248 rb_ast_node_alloc(VALUE klass)
249 {
250  struct ASTNodeData *data;
251  VALUE obj = TypedData_Make_Struct(klass, struct ASTNodeData, &rb_node_type, data);
252 
253  return obj;
254 }
255 
256 static const char*
257 node_type_to_str(const NODE *node)
258 {
259  return (ruby_node_name(nd_type(node)) + rb_strlen_lit("NODE_"));
260 }
261 
262 static VALUE
263 ast_node_type(rb_execution_context_t *ec, VALUE self)
264 {
265  struct ASTNodeData *data;
266  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
267 
268  return rb_sym_intern_ascii_cstr(node_type_to_str(data->node));
269 }
270 
271 static VALUE
272 ast_node_node_id(rb_execution_context_t *ec, VALUE self)
273 {
274  struct ASTNodeData *data;
275  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
276 
277  return INT2FIX(nd_node_id(data->node));
278 }
279 
280 #define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil
281 
282 static VALUE
283 rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...)
284 {
285  va_list ar;
286  VALUE ary;
287  long i;
288 
289  ary = rb_ary_new2(n);
290 
291  va_start(ar, n);
292  for (i=0; i<n; i++) {
293  NODE *node;
294  node = va_arg(ar, NODE *);
295  rb_ary_push(ary, NEW_CHILD(ast, node));
296  }
297  va_end(ar);
298  return ary;
299 }
300 
301 static VALUE
302 dump_block(rb_ast_t *ast, const NODE *node)
303 {
304  VALUE ary = rb_ary_new();
305  do {
306  rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
307  } while (node->nd_next &&
308  nd_type_p(node->nd_next, NODE_BLOCK) &&
309  (node = node->nd_next, 1));
310  if (node->nd_next) {
311  rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
312  }
313 
314  return ary;
315 }
316 
317 static VALUE
318 dump_array(rb_ast_t *ast, const NODE *node)
319 {
320  VALUE ary = rb_ary_new();
321  rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
322 
323  while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
324  node = node->nd_next;
325  rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
326  }
327  rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
328 
329  return ary;
330 }
331 
332 static VALUE
333 var_name(ID id)
334 {
335  if (!id) return Qnil;
336  if (!rb_id2str(id)) return Qnil;
337  return ID2SYM(id);
338 }
339 
340 static VALUE
341 no_name_rest(void)
342 {
343  ID rest;
344  CONST_ID(rest, "NODE_SPECIAL_NO_NAME_REST");
345  return ID2SYM(rest);
346 }
347 
348 static VALUE
349 rest_arg(rb_ast_t *ast, const NODE *rest_arg)
350 {
351  return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest();
352 }
353 
354 static VALUE
355 node_children(rb_ast_t *ast, const NODE *node)
356 {
357  char name[DECIMAL_SIZE_OF_BITS(sizeof(long) * CHAR_BIT) + 2]; /* including '$' */
358 
359  enum node_type type = nd_type(node);
360  switch (type) {
361  case NODE_BLOCK:
362  return dump_block(ast, node);
363  case NODE_IF:
364  return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else);
365  case NODE_UNLESS:
366  return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else);
367  case NODE_CASE:
368  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
369  case NODE_CASE2:
370  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
371  case NODE_CASE3:
372  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
373  case NODE_WHEN:
374  return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next);
375  case NODE_IN:
376  return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next);
377  case NODE_WHILE:
378  case NODE_UNTIL:
379  return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body),
380  RBOOL(node->nd_state));
381  case NODE_ITER:
382  case NODE_FOR:
383  return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body);
384  case NODE_FOR_MASGN:
385  return rb_ary_new_from_node_args(ast, 1, node->nd_var);
386  case NODE_BREAK:
387  case NODE_NEXT:
388  case NODE_RETURN:
389  return rb_ary_new_from_node_args(ast, 1, node->nd_stts);
390  case NODE_REDO:
391  return rb_ary_new_from_node_args(ast, 0);
392  case NODE_RETRY:
393  return rb_ary_new_from_node_args(ast, 0);
394  case NODE_BEGIN:
395  return rb_ary_new_from_node_args(ast, 1, node->nd_body);
396  case NODE_RESCUE:
397  return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_resq, node->nd_else);
398  case NODE_RESBODY:
399  return rb_ary_new_from_node_args(ast, 3, node->nd_args, node->nd_body, node->nd_head);
400  case NODE_ENSURE:
401  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_ensr);
402  case NODE_AND:
403  case NODE_OR:
404  {
405  VALUE ary = rb_ary_new();
406 
407  while (1) {
408  rb_ary_push(ary, NEW_CHILD(ast, node->nd_1st));
409  if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
410  break;
411  node = node->nd_2nd;
412  }
413  rb_ary_push(ary, NEW_CHILD(ast, node->nd_2nd));
414  return ary;
415  }
416  case NODE_MASGN:
417  if (NODE_NAMED_REST_P(node->nd_args)) {
418  return rb_ary_new_from_node_args(ast, 3, node->nd_value, node->nd_head, node->nd_args);
419  }
420  else {
421  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_value),
422  NEW_CHILD(ast, node->nd_head),
423  no_name_rest());
424  }
425  case NODE_LASGN:
426  case NODE_DASGN:
427  case NODE_IASGN:
428  case NODE_CVASGN:
429  case NODE_GASGN:
430  if (NODE_REQUIRED_KEYWORD_P(node)) {
431  return rb_ary_new_from_args(2, var_name(node->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
432  }
433  return rb_ary_new_from_args(2, var_name(node->nd_vid), NEW_CHILD(ast, node->nd_value));
434  case NODE_CDECL:
435  if (node->nd_vid) {
436  return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value));
437  }
438  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_else), ID2SYM(node->nd_else->nd_mid), NEW_CHILD(ast, node->nd_value));
439  case NODE_OP_ASGN1:
440  return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_recv),
441  ID2SYM(node->nd_mid),
442  NEW_CHILD(ast, node->nd_args->nd_head),
443  NEW_CHILD(ast, node->nd_args->nd_body));
444  case NODE_OP_ASGN2:
445  return rb_ary_new_from_args(5, NEW_CHILD(ast, node->nd_recv),
446  RBOOL(node->nd_next->nd_aid),
447  ID2SYM(node->nd_next->nd_vid),
448  ID2SYM(node->nd_next->nd_mid),
449  NEW_CHILD(ast, node->nd_value));
450  case NODE_OP_ASGN_AND:
451  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idANDOP),
452  NEW_CHILD(ast, node->nd_value));
453  case NODE_OP_ASGN_OR:
454  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idOROP),
455  NEW_CHILD(ast, node->nd_value));
456  case NODE_OP_CDECL:
457  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head),
458  ID2SYM(node->nd_aid),
459  NEW_CHILD(ast, node->nd_value));
460  case NODE_CALL:
461  case NODE_OPCALL:
462  case NODE_QCALL:
463  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv),
464  ID2SYM(node->nd_mid),
465  NEW_CHILD(ast, node->nd_args));
466  case NODE_FCALL:
467  return rb_ary_new_from_args(2, ID2SYM(node->nd_mid),
468  NEW_CHILD(ast, node->nd_args));
469  case NODE_VCALL:
470  return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
471  case NODE_SUPER:
472  return rb_ary_new_from_node_args(ast, 1, node->nd_args);
473  case NODE_ZSUPER:
474  return rb_ary_new_from_node_args(ast, 0);
475  case NODE_LIST:
476  case NODE_VALUES:
477  return dump_array(ast, node);
478  case NODE_ZLIST:
479  return rb_ary_new_from_node_args(ast, 0);
480  case NODE_HASH:
481  return rb_ary_new_from_node_args(ast, 1, node->nd_head);
482  case NODE_YIELD:
483  return rb_ary_new_from_node_args(ast, 1, node->nd_head);
484  case NODE_LVAR:
485  case NODE_DVAR:
486  return rb_ary_new_from_args(1, var_name(node->nd_vid));
487  case NODE_IVAR:
488  case NODE_CONST:
489  case NODE_CVAR:
490  case NODE_GVAR:
491  return rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
492  case NODE_NTH_REF:
493  snprintf(name, sizeof(name), "$%ld", node->nd_nth);
494  return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
495  case NODE_BACK_REF:
496  name[0] = '$';
497  name[1] = (char)node->nd_nth;
498  name[2] = '\0';
499  return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
500  case NODE_MATCH2:
501  if (node->nd_args) {
502  return rb_ary_new_from_node_args(ast, 3, node->nd_recv, node->nd_value, node->nd_args);
503  }
504  return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
505  case NODE_MATCH3:
506  return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
507  case NODE_MATCH:
508  case NODE_LIT:
509  case NODE_STR:
510  case NODE_XSTR:
511  return rb_ary_new_from_args(1, node->nd_lit);
512  case NODE_ONCE:
513  return rb_ary_new_from_node_args(ast, 1, node->nd_body);
514  case NODE_DSTR:
515  case NODE_DXSTR:
516  case NODE_DREGX:
517  case NODE_DSYM:
518  {
519  NODE *n = node->nd_next;
520  VALUE head = Qnil, next = Qnil;
521  if (n) {
522  head = NEW_CHILD(ast, n->nd_head);
523  next = NEW_CHILD(ast, n->nd_next);
524  }
525  return rb_ary_new_from_args(3, node->nd_lit, head, next);
526  }
527  case NODE_EVSTR:
528  return rb_ary_new_from_node_args(ast, 1, node->nd_body);
529  case NODE_ARGSCAT:
530  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
531  case NODE_ARGSPUSH:
532  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
533  case NODE_SPLAT:
534  return rb_ary_new_from_node_args(ast, 1, node->nd_head);
535  case NODE_BLOCK_PASS:
536  return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
537  case NODE_DEFN:
538  return rb_ary_new_from_args(2, ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn));
539  case NODE_DEFS:
540  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn));
541  case NODE_ALIAS:
542  return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
543  case NODE_VALIAS:
544  return rb_ary_new_from_args(2, ID2SYM(node->nd_alias), ID2SYM(node->nd_orig));
545  case NODE_UNDEF:
546  return rb_ary_new_from_node_args(ast, 1, node->nd_undef);
547  case NODE_CLASS:
548  return rb_ary_new_from_node_args(ast, 3, node->nd_cpath, node->nd_super, node->nd_body);
549  case NODE_MODULE:
550  return rb_ary_new_from_node_args(ast, 2, node->nd_cpath, node->nd_body);
551  case NODE_SCLASS:
552  return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_body);
553  case NODE_COLON2:
554  return rb_ary_new_from_args(2, NEW_CHILD(ast, node->nd_head), ID2SYM(node->nd_mid));
555  case NODE_COLON3:
556  return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
557  case NODE_DOT2:
558  case NODE_DOT3:
559  case NODE_FLIP2:
560  case NODE_FLIP3:
561  return rb_ary_new_from_node_args(ast, 2, node->nd_beg, node->nd_end);
562  case NODE_SELF:
563  return rb_ary_new_from_node_args(ast, 0);
564  case NODE_NIL:
565  return rb_ary_new_from_node_args(ast, 0);
566  case NODE_TRUE:
567  return rb_ary_new_from_node_args(ast, 0);
568  case NODE_FALSE:
569  return rb_ary_new_from_node_args(ast, 0);
570  case NODE_ERRINFO:
571  return rb_ary_new_from_node_args(ast, 0);
572  case NODE_DEFINED:
573  return rb_ary_new_from_node_args(ast, 1, node->nd_head);
574  case NODE_POSTEXE:
575  return rb_ary_new_from_node_args(ast, 1, node->nd_body);
576  case NODE_ATTRASGN:
577  return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_args));
578  case NODE_LAMBDA:
579  return rb_ary_new_from_node_args(ast, 1, node->nd_body);
580  case NODE_OPT_ARG:
581  return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next);
582  case NODE_KW_ARG:
583  return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next);
584  case NODE_POSTARG:
585  if (NODE_NAMED_REST_P(node->nd_1st)) {
586  return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
587  }
588  return rb_ary_new_from_args(2, no_name_rest(),
589  NEW_CHILD(ast, node->nd_2nd));
590  case NODE_ARGS:
591  {
592  struct rb_args_info *ainfo = node->nd_ainfo;
593  return rb_ary_new_from_args(10,
594  INT2NUM(ainfo->pre_args_num),
595  NEW_CHILD(ast, ainfo->pre_init),
596  NEW_CHILD(ast, ainfo->opt_args),
597  var_name(ainfo->first_post_arg),
598  INT2NUM(ainfo->post_args_num),
599  NEW_CHILD(ast, ainfo->post_init),
600  (ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA
601  ? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA"))
602  : var_name(ainfo->rest_arg)),
603  (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_args)),
604  (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_rest_arg)),
605  var_name(ainfo->block_arg));
606  }
607  case NODE_SCOPE:
608  {
609  rb_ast_id_table_t *tbl = node->nd_tbl;
610  int i, size = tbl ? tbl->size : 0;
611  VALUE locals = rb_ary_new_capa(size);
612  for (i = 0; i < size; i++) {
613  rb_ary_push(locals, var_name(tbl->ids[i]));
614  }
615  return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, node->nd_args), NEW_CHILD(ast, node->nd_body));
616  }
617  case NODE_ARYPTN:
618  {
619  struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
620  VALUE rest = rest_arg(ast, apinfo->rest_arg);
621  return rb_ary_new_from_args(4,
622  NEW_CHILD(ast, node->nd_pconst),
623  NEW_CHILD(ast, apinfo->pre_args),
624  rest,
625  NEW_CHILD(ast, apinfo->post_args));
626  }
627  case NODE_FNDPTN:
628  {
629  struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo;
630  VALUE pre_rest = rest_arg(ast, fpinfo->pre_rest_arg);
631  VALUE post_rest = rest_arg(ast, fpinfo->post_rest_arg);
632  return rb_ary_new_from_args(4,
633  NEW_CHILD(ast, node->nd_pconst),
634  pre_rest,
635  NEW_CHILD(ast, fpinfo->args),
636  post_rest);
637  }
638  case NODE_HSHPTN:
639  {
640  VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
641  NEW_CHILD(ast, node->nd_pkwrestarg);
642 
643  return rb_ary_new_from_args(3,
644  NEW_CHILD(ast, node->nd_pconst),
645  NEW_CHILD(ast, node->nd_pkwargs),
646  kwrest);
647  }
648  case NODE_ARGS_AUX:
649  case NODE_LAST:
650  break;
651  }
652 
653  rb_bug("node_children: unknown node: %s", ruby_node_name(type));
654 }
655 
656 static VALUE
657 ast_node_children(rb_execution_context_t *ec, VALUE self)
658 {
659  struct ASTNodeData *data;
660  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
661 
662  return node_children(data->ast, data->node);
663 }
664 
665 static VALUE
666 ast_node_first_lineno(rb_execution_context_t *ec, VALUE self)
667 {
668  struct ASTNodeData *data;
669  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
670 
671  return INT2NUM(nd_first_lineno(data->node));
672 }
673 
674 static VALUE
675 ast_node_first_column(rb_execution_context_t *ec, VALUE self)
676 {
677  struct ASTNodeData *data;
678  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
679 
680  return INT2NUM(nd_first_column(data->node));
681 }
682 
683 static VALUE
684 ast_node_last_lineno(rb_execution_context_t *ec, VALUE self)
685 {
686  struct ASTNodeData *data;
687  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
688 
689  return INT2NUM(nd_last_lineno(data->node));
690 }
691 
692 static VALUE
693 ast_node_last_column(rb_execution_context_t *ec, VALUE self)
694 {
695  struct ASTNodeData *data;
696  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
697 
698  return INT2NUM(nd_last_column(data->node));
699 }
700 
701 static VALUE
702 ast_node_inspect(rb_execution_context_t *ec, VALUE self)
703 {
704  VALUE str;
705  VALUE cname;
706  struct ASTNodeData *data;
707  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
708 
709  cname = rb_class_path(rb_obj_class(self));
710  str = rb_str_new2("#<");
711 
712  rb_str_append(str, cname);
713  rb_str_catf(str, ":%s@%d:%d-%d:%d>",
714  node_type_to_str(data->node),
715  nd_first_lineno(data->node), nd_first_column(data->node),
716  nd_last_lineno(data->node), nd_last_column(data->node));
717 
718  return str;
719 }
720 
721 static VALUE
722 ast_node_script_lines(rb_execution_context_t *ec, VALUE self)
723 {
724  struct ASTNodeData *data;
725  TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
726  VALUE ret = data->ast->body.script_lines;
727  if (!RB_TYPE_P(ret, T_ARRAY)) return Qnil;
728  return ret;
729 }
730 
731 #include "ast.rbinc"
732 
733 void
734 Init_ast(void)
735 {
736  rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
737  rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
738  rb_undef_alloc_func(rb_cNode);
739 }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:869
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
Definition: class.c:972
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1738
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define ID2SYM
Old name of RB_ID2SYM.
Definition: symbol.h:44
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define T_HASH
Old name of RUBY_T_HASH.
Definition: value_type.h:65
#define INT2NUM
Old name of RB_INT2NUM.
Definition: int.h:43
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition: symbol.h:47
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition: array.h:651
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3025
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:675
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1100
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:188
Encoding relates APIs.
VALUE rb_enc_from_encoding(rb_encoding *enc)
Queries the Ruby-level counterpart instance of rb_cEncoding that corresponds to the passed encoding.
Definition: encoding.c:188
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
Definition: encoding.h:782
rb_encoding * rb_utf8_encoding(void)
Queries the encoding that represents UTF-8.
Definition: encoding.c:1527
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
Definition: encoding.c:1072
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1102
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
Definition: array.c:989
VALUE rb_ary_new(void)
Allocates a new, empty array.
Definition: array.c:750
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
Definition: array.c:744
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
Definition: array.c:1308
VALUE rb_ary_new_from_args(long n,...)
Constructs an array from the passed objects.
Definition: array.c:756
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
Definition: array.c:1679
void rb_gc_mark(VALUE obj)
Marks an object.
Definition: gc.c:6775
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
Definition: hash.c:2108
VALUE rb_file_open_str(VALUE fname, const char *fmode)
Identical to rb_file_open(), except it takes the pathname as a Ruby's string instead of C's.
Definition: io.c:6675
VALUE rb_io_close(VALUE io)
Closes the IO.
Definition: io.c:5234
VALUE rb_obj_is_proc(VALUE recv)
Queries if the given object is a proc.
Definition: proc.c:175
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition: string.c:3317
#define rb_strlen_lit(str)
Length of a string literal.
Definition: string.h:1756
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
Definition: string.c:952
VALUE rb_const_get_at(VALUE space, ID name)
Identical to rb_const_defined_at(), except it returns the actual defined value.
Definition: variable.c:2739
int rb_const_defined_at(VALUE space, ID name)
Identical to rb_const_defined(), except it doesn't look for parent classes.
Definition: variable.c:3043
VALUE rb_class_path(VALUE mod)
Identical to rb_mod_name(), except it returns #<Class: ...> style inspection for anonymous modules.
Definition: variable.c:172
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
Definition: vm_method.c:1117
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
Definition: symbol.c:782
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
Definition: symbol.c:935
#define DECIMAL_SIZE_OF_BITS(n)
an approximation of ceil(n * log10(2)), up to 65536 at least
Definition: util.h:37
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
Definition: sprintf.c:1241
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:56
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:68
#define RARRAY_AREF(a, i)
Definition: rarray.h:588
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:72
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:497
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:483
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
Definition: rtypeddata.h:79
#define TypedData_Get_Struct(obj, type, data_type, sval)
Obtains a C struct from inside of a wrapper Ruby object.
Definition: rtypeddata.h:507
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
Definition: rtypeddata.h:489
#define FilePathValue(v)
Ensures that the parameter object is a path.
Definition: ruby.h:90
#define RTEST
This is an old name of RB_TEST.
Definition: node.h:155
This is the struct that holds necessary info for a struct.
Definition: rtypeddata.h:190
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:375