mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
ast.c: refine AST#children
* ast.c (node_children): refined RubyVM::AST#children to include symbols (variables, methods, classes, etc). git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63604 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
69e5eb35d3
commit
daf789b5a5
2 changed files with 88 additions and 38 deletions
109
ast.c
109
ast.c
|
@ -1,6 +1,7 @@
|
|||
/* 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"
|
||||
|
@ -175,9 +176,19 @@ dump_array(rb_ast_t *ast, NODE *node)
|
|||
return ary;
|
||||
}
|
||||
|
||||
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)
|
|||
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_FCALL:
|
||||
return rb_ary_new_from_node_args(ast, 1, 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(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_args(2, ID2SYM(node->nd_vid),
|
||||
NEW_CHILD(ast, node->nd_args));
|
||||
case NODE_VCALL:
|
||||
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)
|
|||
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)
|
|||
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)
|
|||
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)
|
|||
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)
|
|||
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)
|
|||
}
|
||||
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;
|
||||
|
|
|
@ -72,7 +72,7 @@ class TestAst < Test::Unit::TestCase
|
|||
|
||||
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
|
|||
|
||||
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
|
|||
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
|
|||
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
|
||||
|
|
Loading…
Reference in a new issue