Change UNDEF Node to hold their items to keep the original grammar
structure.

For example:

```
undef a, b
```

Before:

```
@ NODE_BLOCK (id: 4, line: 1, location: (1,6)-(1,10))*
+- nd_head (1):
|   @ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,7))
|   +- nd_undef:
|       @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
|       +- string: :a
+- nd_head (2):
    @ NODE_UNDEF (id: 3, line: 1, location: (1,9)-(1,10))
    +- nd_undef:
        @ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
        +- string: :b
```

After:

```
@ NODE_UNDEF (id: 1, line: 1, location: (1,6)-(1,10))*
+- nd_undefs:
    +- length: 2
    +- element (0):
    |   @ NODE_SYM (id: 0, line: 1, location: (1,6)-(1,7))
    |   +- string: :a
    +- element (1):
        @ NODE_SYM (id: 2, line: 1, location: (1,9)-(1,10))
        +- string: :b
```
This commit is contained in:
yui-knk 2024-07-18 13:47:13 +09:00 коммит произвёл Yuichiro Kaneko
Родитель 174c01b80e
Коммит 6be539aab5
6 изменённых файлов: 103 добавлений и 15 удалений

20
ast.c
Просмотреть файл

@ -333,6 +333,24 @@ dump_array(VALUE ast_value, const struct RNode_LIST *node)
return ary;
}
static VALUE
dump_parser_array(VALUE ast_value, rb_parser_ary_t *p_ary)
{
VALUE ary;
if (p_ary->data_type != PARSER_ARY_DATA_NODE) {
rb_bug("unexpected rb_parser_ary_data_type: %d", p_ary->data_type);
}
ary = rb_ary_new();
for (long i = 0; i < p_ary->len; i++) {
rb_ary_push(ary, NEW_CHILD(ast_value, p_ary->data[i]));
}
return ary;
}
static VALUE
var_name(ID id)
{
@ -577,7 +595,7 @@ node_children(VALUE ast_value, const NODE *node)
case NODE_VALIAS:
return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig));
case NODE_UNDEF:
return rb_ary_new_from_node_args(ast_value, 1, RNODE_UNDEF(node)->nd_undef);
return rb_ary_new_from_args(1, dump_parser_array(ast_value, RNODE_UNDEF(node)->nd_undefs));
case NODE_CLASS:
return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
case NODE_MODULE:

Просмотреть файл

@ -10954,10 +10954,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
break;
}
case NODE_UNDEF:{
ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
CHECK(COMPILE(ret, "undef arg", RNODE_UNDEF(node)->nd_undef));
ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
const rb_parser_ary_t *ary = RNODE_UNDEF(node)->nd_undefs;
for (long i = 0; i < ary->len; i++) {
ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
CHECK(COMPILE(ret, "undef arg", ary->data[i]));
ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
if (i < ary->len - 1) {
ADD_INSN(ret, node, pop);
}
}
if (popped) {
ADD_INSN(ret, node, pop);

11
node.c
Просмотреть файл

@ -162,6 +162,14 @@ parser_tokens_free(rb_ast_t *ast, rb_parser_ary_t *tokens)
xfree(tokens);
}
static void
parser_nodes_free(rb_ast_t *ast, rb_parser_ary_t *nodes)
{
/* Do nothing for nodes because nodes are freed when rb_ast_t is freed */
xfree(nodes->data);
xfree(nodes);
}
static void
free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
{
@ -206,6 +214,9 @@ free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
case NODE_IMAGINARY:
xfree(RNODE_IMAGINARY(node)->val);
break;
case NODE_UNDEF:
parser_nodes_free(ast, RNODE_UNDEF(node)->nd_undefs);
break;
default:
break;
}

Просмотреть файл

@ -92,6 +92,9 @@
#define F_NODE2(name, n, ann) \
COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, n);}
#define F_ARRAY(name, type, ann) \
COMPOUND_FIELD1(#name, ann) {dump_parser_array(buf, indent, comment, type(node)->name);}
#define ANN(ann) \
if (comment) { \
A_INDENT; A("| # " ann "\n"); \
@ -164,6 +167,28 @@ dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
F_NODE(nd_next, RNODE_LIST, "next element");
}
static void
dump_parser_array(VALUE buf, VALUE indent, int comment, const rb_parser_ary_t *ary)
{
int field_flag;
const char *next_indent = default_indent;
if (ary->data_type != PARSER_ARY_DATA_NODE) {
rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
}
F_CUSTOM1(length, "length") { A_LONG(ary->len); }
for (long i = 0; i < ary->len; i++) {
if (i == ary->len - 1) LAST_NODE;
A_INDENT;
rb_str_catf(buf, "+- element (%s%ld):\n",
comment ? "statement #" : "", i);
D_INDENT;
dump_node(buf, indent, comment, ary->data[i]);
D_DEDENT;
}
}
static void
dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
{
@ -896,10 +921,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
case NODE_UNDEF:
ANN("method undef statement");
ANN("format: undef [nd_undef]");
ANN("format: undef [nd_undefs]");
ANN("example: undef foo");
LAST_NODE;
F_NODE(nd_undef, RNODE_UNDEF, "old name");
F_ARRAY(nd_undefs, RNODE_UNDEF, "nd_undefs");
return;
case NODE_CLASS:

37
parse.y
Просмотреть файл

@ -2487,7 +2487,6 @@ rb_parser_string_hash_cmp(rb_parser_string_t *str1, rb_parser_string_t *str2)
memcmp(ptr1, ptr2, len1) != 0);
}
#ifndef RIPPER
static void
rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len)
{
@ -2503,7 +2502,7 @@ rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len)
/*
* Do not call this directly.
* Use rb_parser_ary_new_capa_for_script_line() or rb_parser_ary_new_capa_for_ast_token() instead.
* Use rb_parser_ary_new_capa_for_XXX() instead.
*/
static rb_parser_ary_t *
parser_ary_new_capa(rb_parser_t *p, long len)
@ -2524,6 +2523,7 @@ parser_ary_new_capa(rb_parser_t *p, long len)
return ary;
}
#ifndef RIPPER
static rb_parser_ary_t *
rb_parser_ary_new_capa_for_script_line(rb_parser_t *p, long len)
{
@ -2539,10 +2539,19 @@ rb_parser_ary_new_capa_for_ast_token(rb_parser_t *p, long len)
ary->data_type = PARSER_ARY_DATA_AST_TOKEN;
return ary;
}
#endif
static rb_parser_ary_t *
rb_parser_ary_new_capa_for_node(rb_parser_t *p, long len)
{
rb_parser_ary_t *ary = parser_ary_new_capa(p, len);
ary->data_type = PARSER_ARY_DATA_NODE;
return ary;
}
/*
* Do not call this directly.
* Use rb_parser_ary_push_script_line() or rb_parser_ary_push_ast_token() instead.
* Use rb_parser_ary_push_XXX() instead.
*/
static rb_parser_ary_t *
parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val)
@ -2554,6 +2563,7 @@ parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val)
return ary;
}
#ifndef RIPPER
static rb_parser_ary_t *
rb_parser_ary_push_ast_token(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ast_token_t *val)
{
@ -2571,7 +2581,18 @@ rb_parser_ary_push_script_line(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_s
}
return parser_ary_push(p, ary, val);
}
#endif
static rb_parser_ary_t *
rb_parser_ary_push_node(rb_parser_t *p, rb_parser_ary_t *ary, NODE *val)
{
if (ary->data_type != PARSER_ARY_DATA_NODE) {
rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
}
return parser_ary_push(p, ary, val);
}
#ifndef RIPPER
static void
rb_parser_ast_token_free(rb_parser_t *p, rb_parser_ast_token_t *token)
{
@ -2593,6 +2614,9 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
case PARSER_ARY_DATA_SCRIPT_LINE:
foreach_ary(data) {rb_parser_string_free(p, *data);}
break;
case PARSER_ARY_DATA_NODE:
/* Do nothing because nodes are freed when rb_ast_t is freed */
break;
default:
rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
break;
@ -3774,8 +3798,8 @@ undef_list : fitem
}
| undef_list ',' {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
NODE *undef = NEW_UNDEF($4, &@4);
$$ = block_append(p, $1, undef);
nd_set_last_loc($1, @4.end_pos);
rb_parser_ary_push_node(p, RNODE_UNDEF($1)->nd_undefs, $4);
/*% ripper: rb_ary_push($:1, $:4) %*/
}
;
@ -12286,7 +12310,8 @@ static rb_node_undef_t *
rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc)
{
rb_node_undef_t *n = NODE_NEWNODE(NODE_UNDEF, rb_node_undef_t, loc);
n->nd_undef = nd_undef;
n->nd_undefs = rb_parser_ary_new_capa_for_node(p, 1);
rb_parser_ary_push_node(p, n->nd_undefs, nd_undef);
return n;
}

Просмотреть файл

@ -225,7 +225,8 @@ typedef void* rb_parser_ary_data;
enum rb_parser_ary_data_type {
PARSER_ARY_DATA_AST_TOKEN = 1,
PARSER_ARY_DATA_SCRIPT_LINE
PARSER_ARY_DATA_SCRIPT_LINE,
PARSER_ARY_DATA_NODE
};
typedef struct rb_parser_ary {
@ -885,7 +886,7 @@ typedef struct RNode_VALIAS {
typedef struct RNode_UNDEF {
NODE node;
struct RNode *nd_undef;
rb_parser_ary_t *nd_undefs;
} rb_node_undef_t;
typedef struct RNode_CLASS {