[前][次][番号順一覧][スレッド一覧]

ruby-changes:51398

From: nobu <ko1@a...>
Date: Thu, 7 Jun 2018 23:46:29 +0900 (JST)
Subject: [ruby-changes:51398] nobu:r63604 (trunk): ast.c: refine AST#children

nobu	2018-06-07 23:46:25 +0900 (Thu, 07 Jun 2018)

  New Revision: 63604

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=63604

  Log:
    ast.c: refine AST#children
    
    * ast.c (node_children): refined RubyVM::AST#children to include
      symbols (variables, methods, classes, etc).

  Modified files:
    trunk/ast.c
    trunk/test/ruby/test_ast.rb
Index: ast.c
===================================================================
--- ast.c	(revision 63603)
+++ ast.c	(revision 63604)
@@ -1,6 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/ast.c#L1
 /* indent-tabs-mode: nil */
 #include "ruby.h"
 #include "ruby/encoding.h"
+#include "ruby/util.h"
 #include "internal.h"
 #include "node.h"
 #include "vm_core.h"
@@ -176,8 +177,18 @@ dump_array(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L177
 }
 
 static VALUE
+var_name(ID id)
+{
+    if (!id) return Qnil;
+    if (!rb_id2str(id)) return Qnil;
+    return ID2SYM(id);
+}
+
+static VALUE
 node_children(rb_ast_t *ast, NODE *node)
 {
+    char name[DECIMAL_SIZE_OF_BITS(sizeof(long) * CHAR_BIT) + 2]; /* including '$' */
+
     enum node_type type = nd_type(node);
     switch (type) {
       case NODE_BLOCK:
@@ -253,36 +264,47 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L264
       case NODE_CVASGN:
       asgn:
         if (NODE_REQUIRED_KEYWORD_P(node)) {
-            return rb_ary_new_from_node_args(ast, 0);
+            return rb_ary_new_from_args(1, var_name(node->nd_vid));
         }
-        return rb_ary_new_from_node_args(ast, 1, node->nd_value);
+        return rb_ary_new_from_args(2, var_name(node->nd_vid), NEW_CHILD(ast, node->nd_value));
       case NODE_GASGN:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_value);
+        goto asgn;
       case NODE_CDECL:
         if (node->nd_vid) {
-            return rb_ary_new_from_node_args(ast, 1, node->nd_value);
+            return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value));
         }
-        return rb_ary_new_from_node_args(ast, 2, node->nd_else, node->nd_value);
+        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));
       case NODE_OP_ASGN1:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_recv, node->nd_args->nd_head, node->nd_args->nd_body);
+        return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_recv),
+                                    ID2SYM(node->nd_mid),
+                                    NEW_CHILD(ast, node->nd_args->nd_head),
+                                    NEW_CHILD(ast, node->nd_args->nd_body));
       case NODE_OP_ASGN2:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
+        return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_recv),
+                                    node->nd_next->nd_aid ? Qtrue : Qfalse,
+                                    ID2SYM(node->nd_next->nd_vid),
+                                    NEW_CHILD(ast, node->nd_value));
       case NODE_OP_ASGN_AND:
-        goto asgn_andor;
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idANDOP),
+                                    NEW_CHILD(ast, node->nd_value));
       case NODE_OP_ASGN_OR:
-      asgn_andor:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_value);
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idOROP),
+                                    NEW_CHILD(ast, node->nd_value));
       case NODE_OP_CDECL:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_value);
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head),
+                                    ID2SYM(node->nd_aid),
+                                    NEW_CHILD(ast, node->nd_value));
       case NODE_CALL:
       case NODE_OPCALL:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_args);
+      case NODE_QCALL:
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv),
+                                    ID2SYM(node->nd_vid),
+                                    NEW_CHILD(ast, node->nd_args));
       case NODE_FCALL:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_args);
+        return rb_ary_new_from_args(2, ID2SYM(node->nd_vid),
+                                    NEW_CHILD(ast, node->nd_args));
       case NODE_VCALL:
-        return rb_ary_new_from_node_args(ast, 0);
-      case NODE_QCALL:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_args);
+        return rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
       case NODE_SUPER:
         return rb_ary_new_from_node_args(ast, 1, node->nd_args);
       case NODE_ZSUPER:
@@ -299,23 +321,23 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L321
       case NODE_YIELD:
         return rb_ary_new_from_node_args(ast, 1, node->nd_head);
       case NODE_LVAR:
-        return rb_ary_new_from_node_args(ast, 0);
       case NODE_DVAR:
-        return rb_ary_new_from_node_args(ast, 0);
+        return rb_ary_new_from_args(1, var_name(node->nd_vid));
       case NODE_IVAR:
-        return rb_ary_new_from_node_args(ast, 0);
       case NODE_CONST:
-        return rb_ary_new_from_node_args(ast, 0);
       case NODE_CVAR:
-        return rb_ary_new_from_node_args(ast, 0);
       case NODE_GVAR:
-        return rb_ary_new_from_node_args(ast, 0);
+        return rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
       case NODE_NTH_REF:
-        return rb_ary_new_from_node_args(ast, 0);
+        snprintf(name, sizeof(name), "$%ld", node->nd_nth);
+        return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
       case NODE_BACK_REF:
-        return rb_ary_new_from_node_args(ast, 0);
+        name[0] = '$';
+        name[1] = (char)node->nd_nth;
+        name[2] = '\0';
+        return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
       case NODE_MATCH:
-        return rb_ary_new_from_node_args(ast, 0);
+        goto lit;
       case NODE_MATCH2:
         if (node->nd_args) {
             return rb_ary_new_from_node_args(ast, 3, node->nd_recv, node->nd_value, node->nd_args);
@@ -329,7 +351,7 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L351
         goto lit;
       case NODE_XSTR:
       lit:
-        return rb_ary_new_from_node_args(ast, 0);
+        return rb_ary_new_from_args(1, node->nd_lit);
       case NODE_ONCE:
         return rb_ary_new_from_node_args(ast, 1, node->nd_body);
       case NODE_DSTR:
@@ -358,7 +380,7 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L380
       case NODE_ALIAS:
         return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
       case NODE_VALIAS:
-        return rb_ary_new_from_node_args(ast, 0);
+        return rb_ary_new_from_args(2, ID2SYM(node->nd_alias), ID2SYM(node->nd_orig));
       case NODE_UNDEF:
         return rb_ary_new_from_node_args(ast, 1, node->nd_undef);
       case NODE_CLASS:
@@ -368,9 +390,9 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L390
       case NODE_SCLASS:
         return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_body);
       case NODE_COLON2:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_head);
+        return rb_ary_new_from_args(2, NEW_CHILD(ast, node->nd_head), ID2SYM(node->nd_mid));
       case NODE_COLON3:
-        return rb_ary_new_from_node_args(ast, 0);
+        return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
       case NODE_DOT2:
         goto dot;
       case NODE_DOT3:
@@ -395,7 +417,7 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L417
       case NODE_POSTEXE:
         return rb_ary_new_from_node_args(ast, 1, node->nd_body);
       case NODE_ATTRASGN:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_args);
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_args));
       case NODE_LAMBDA:
         return rb_ary_new_from_node_args(ast, 1, node->nd_body);
       case NODE_OPT_ARG:
@@ -408,9 +430,30 @@ node_children(rb_ast_t *ast, NODE *node) https://github.com/ruby/ruby/blob/trunk/ast.c#L430
         }
         return rb_ary_new_from_node_args(ast, 1, node->nd_2nd);
       case NODE_ARGS:
-        return rb_ary_new_from_node_args(ast, 5, node->nd_ainfo->pre_init, node->nd_ainfo->post_init, node->nd_ainfo->opt_args, node->nd_ainfo->kw_args, node->nd_ainfo->kw_rest_arg);
+        {
+            struct rb_args_info *ainfo = node->nd_ainfo;
+            return rb_ary_new_from_args(10,
+                                        INT2NUM(ainfo->pre_args_num),
+                                        NEW_CHILD(ast, ainfo->pre_init),
+                                        NEW_CHILD(ast, ainfo->opt_args),
+                                        var_name(ainfo->first_post_arg),
+                                        INT2NUM(ainfo->post_args_num),
+                                        NEW_CHILD(ast, ainfo->post_init),
+                                        var_name(ainfo->rest_arg),
+                                        NEW_CHILD(ast, ainfo->kw_args),
+                                        NEW_CHILD(ast, ainfo->kw_rest_arg),
+                                        var_name(ainfo->block_arg));
+        }
       case NODE_SCOPE:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_args, node->nd_body);
+        {
+            ID *tbl = node->nd_tbl;
+            int i, size = tbl ? (int)*tbl++ : 0;
+            VALUE locals = rb_ary_new_capa(size);
+            for (i = 0; i < size; i++) {
+                rb_ary_push(locals, var_name(tbl[i]));
+            }
+            return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, node->nd_args), NEW_CHILD(ast, node->nd_body));
+        }
       case NODE_ARGS_AUX:
       case NODE_LAST:
         break;
Index: test/ruby/test_ast.rb
===================================================================
--- test/ruby/test_ast.rb	(revision 63603)
+++ test/ruby/test_ast.rb	(revision 63604)
@@ -72,7 +72,7 @@ class TestAst < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L72
 
     def validate_range0(node)
       beg_pos, end_pos = node.beg_pos, node.end_pos
-      children = node.children.compact
+      children = node.children.grep(RubyVM::AST)
 
       return true if children.empty?
       # These NODE_D* has NODE_ARRAY as nd_next->nd_next whose last locations
@@ -100,7 +100,7 @@ class TestAst < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L100
 
     def validate_not_cared0(node)
       beg_pos, end_pos = node.beg_pos, node.end_pos
-      children = node.children.compact
+      children = node.children.grep(RubyVM::AST)
 
       @errors << { type: :first_lineno, node: node } if beg_pos.lineno == 0
       @errors << { type: :first_column, node: node } if beg_pos.column == -1
@@ -134,18 +134,18 @@ class TestAst < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L134
   def test_column_with_long_heredoc_identifier
     term = "A"*257
     ast = RubyVM::AST.parse("<<-#{term}\n""ddddddd\n#{term}\n")
-    node = ast.children[1]
+    node = ast.children[2]
     assert_equal("NODE_STR", node.type)
     assert_equal(0, node.first_column)
   end
 
   def test_column_of_heredoc
-    node = RubyVM::AST.parse("<<-SRC\nddddddd\nSRC\n").children[1]
+    node = RubyVM::AST.parse("<<-SRC\nddddddd\nSRC\n").children[2]
     assert_equal("NODE_STR", node.type)
     assert_equal(0, node.first_column)
     assert_equal(6, node.last_column)
 
-    node = RubyVM::AST.parse("<<SRC\nddddddd\nSRC\n").children[1]
+    node = RubyVM::AST.parse("<<SRC\nddddddd\nSRC\n").children[2]
     assert_equal("NODE_STR", node.type)
     assert_equal(0, node.first_column)
     assert_equal(5, node.last_column)
@@ -171,4 +171,11 @@ class TestAst < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_ast.rb#L171
       end;
     end
   end
+
+  def test_scope_local_variables
+    node = RubyVM::AST.parse("x = 0")
+    lv, _, body = *node.children
+    assert_equal([:x], lv)
+    assert_equal("NODE_LASGN", body.type)
+  end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]