Change RNode structure from union to struct
authoryui-knk <[email protected]>
Tue, 22 Aug 2023 01:26:38 +0000 (22 10:26 +0900)
committerYuichiro Kaneko <[email protected]>
Thu, 28 Sep 2023 02:58:10 +0000 (28 11:58 +0900)
All kind of AST nodes use same struct RNode, which has u1, u2, u3 union members
for holding different kind of data.
This has two problems.

1. Low flexibility of data structure

Some nodes, for example NODE_TRUE, don’t use u1, u2, u3. On the other hand,
NODE_OP_ASGN2 needs more than three union members. However they use same
structure definition, need to allocate three union members for NODE_TRUE and
need to separate NODE_OP_ASGN2 into another node.
This change removes the restriction so make it possible to
change data structure by each node type.

2. No compile time check for union member access

It’s developer’s responsibility for using correct member for each node type when it’s union.
This change clarifies which node has which type of fields and enables compile time check.

This commit also changes node_buffer_elem_struct buf management to handle
different size data with alignment.

12 files changed:
ast.c
compile.c
ext/objspace/objspace.c
ext/ripper/ripper_init.c.tmpl
node.c
node.h
node_dump.c
parse.y
parser_node.h
ruby_parser.c
rubyparser.h
vm.c

diff --git a/ast.c b/ast.c
index 4bd3784..cdd2269 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -331,14 +331,14 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...)
 }
 
 static VALUE
-dump_block(rb_ast_t *ast, const NODE *node)
+dump_block(rb_ast_t *ast, const struct RNode_BLOCK *node)
 {
     VALUE ary = rb_ary_new();
     do {
         rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
     } while (node->nd_next &&
         nd_type_p(node->nd_next, NODE_BLOCK) &&
-        (node = node->nd_next, 1));
+        (node = RNODE_BLOCK(node->nd_next), 1));
     if (node->nd_next) {
         rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
     }
@@ -347,13 +347,13 @@ dump_block(rb_ast_t *ast, const NODE *node)
 }
 
 static VALUE
-dump_array(rb_ast_t *ast, const NODE *node)
+dump_array(rb_ast_t *ast, const struct RNode_LIST *node)
 {
     VALUE ary = rb_ary_new();
     rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
 
     while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
-        node = node->nd_next;
+        node = RNODE_LIST(node->nd_next);
         rb_ary_push(ary, NEW_CHILD(ast, node->nd_head));
     }
     rb_ary_push(ary, NEW_CHILD(ast, node->nd_next));
@@ -391,67 +391,67 @@ node_children(rb_ast_t *ast, const NODE *node)
     enum node_type type = nd_type(node);
     switch (type) {
       case NODE_BLOCK:
-        return dump_block(ast, node);
+        return dump_block(ast, RNODE_BLOCK(node));
       case NODE_IF:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else);
       case NODE_UNLESS:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else);
       case NODE_CASE:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body);
       case NODE_CASE2:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body);
       case NODE_CASE3:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body);
       case NODE_WHEN:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next);
       case NODE_IN:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next);
       case NODE_WHILE:
       case NODE_UNTIL:
-        return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body),
-                           RBOOL(node->nd_state));
+        return rb_ary_push(rb_ary_new_from_node_args(ast, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body),
+                           RBOOL(RNODE_WHILE(node)->nd_state));
       case NODE_ITER:
       case NODE_FOR:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body);
       case NODE_FOR_MASGN:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_var);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_FOR_MASGN(node)->nd_var);
       case NODE_BREAK:
       case NODE_NEXT:
       case NODE_RETURN:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_stts);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_BREAK(node)->nd_stts);
       case NODE_REDO:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_RETRY:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_BEGIN:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_BEGIN(node)->nd_body);
       case NODE_RESCUE:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_resq, node->nd_else);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
       case NODE_RESBODY:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_args, node->nd_body, node->nd_head);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_head);
       case NODE_ENSURE:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_ensr);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
       case NODE_AND:
       case NODE_OR:
         {
             VALUE ary = rb_ary_new();
 
             while (1) {
-                rb_ary_push(ary, NEW_CHILD(ast, node->nd_1st));
-                if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
+                rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_1st));
+                if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type))
                     break;
-                node = node->nd_2nd;
+                node = RNODE_AND(node)->nd_2nd;
             }
-            rb_ary_push(ary, NEW_CHILD(ast, node->nd_2nd));
+            rb_ary_push(ary, NEW_CHILD(ast, RNODE_AND(node)->nd_2nd));
             return ary;
         }
       case NODE_MASGN:
-        if (NODE_NAMED_REST_P(node->nd_args)) {
-            return rb_ary_new_from_node_args(ast, 3, node->nd_value, node->nd_head, node->nd_args);
+        if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) {
+            return rb_ary_new_from_node_args(ast, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args);
         }
         else {
-            return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_value),
-                                        NEW_CHILD(ast, node->nd_head),
+            return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_MASGN(node)->nd_value),
+                                        NEW_CHILD(ast, RNODE_MASGN(node)->nd_head),
                                         no_name_rest());
         }
       case NODE_LASGN:
@@ -459,138 +459,141 @@ node_children(rb_ast_t *ast, const NODE *node)
       case NODE_IASGN:
       case NODE_CVASGN:
       case NODE_GASGN:
-        if (NODE_REQUIRED_KEYWORD_P(node)) {
-            return rb_ary_new_from_args(2, var_name(node->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
+        if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node))) {
+            return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD")));
         }
-        return rb_ary_new_from_args(2, var_name(node->nd_vid), NEW_CHILD(ast, node->nd_value));
+        return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast, RNODE_LASGN(node)->nd_value));
       case NODE_CDECL:
-        if (node->nd_vid) {
-            return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value));
+        if (RNODE_CDECL(node)->nd_vid) {
+            return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast, RNODE_CDECL(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));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast, RNODE_CDECL(node)->nd_value));
       case NODE_OP_ASGN1:
-        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));
+        return rb_ary_new_from_args(4, NEW_CHILD(ast, RNODE_OP_ASGN1(node)->nd_recv),
+                                    ID2SYM(RNODE_OP_ASGN1(node)->nd_mid),
+                                    NEW_CHILD(ast, RNODE_ARGSCAT(RNODE_OP_ASGN1(node)->nd_args)->nd_head),
+                                    NEW_CHILD(ast, RNODE_ARGSCAT(RNODE_OP_ASGN1(node)->nd_args)->nd_body));
       case NODE_OP_ASGN2:
-        return rb_ary_new_from_args(5, NEW_CHILD(ast, node->nd_recv),
-                                    RBOOL(node->nd_next->nd_aid),
-                                    ID2SYM(node->nd_next->nd_vid),
-                                    ID2SYM(node->nd_next->nd_mid),
-                                    NEW_CHILD(ast, node->nd_value));
+        // NODE_OP_ASGN2 has NODE_OP_ASGN2 in its nd_next, however nd_next
+        // has different structure, whose u1 is ID attr, u2 is ID op, u3 is bool.
+        // See: NEW_OP_ASGN2
+        return rb_ary_new_from_args(5, NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_recv),
+                                    RBOOL(RNODE_OP_ASGN22(RNODE_OP_ASGN2(node)->nd_next)->nd_aid),
+                                    ID2SYM(RNODE_OP_ASGN22(RNODE_OP_ASGN2(node)->nd_next)->nd_vid),
+                                    ID2SYM(RNODE_OP_ASGN22(RNODE_OP_ASGN2(node)->nd_next)->nd_mid),
+                                    NEW_CHILD(ast, RNODE_OP_ASGN2(node)->nd_value));
       case NODE_OP_ASGN_AND:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idANDOP),
-                                    NEW_CHILD(ast, node->nd_value));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP),
+                                    NEW_CHILD(ast, RNODE_OP_ASGN_AND(node)->nd_value));
       case NODE_OP_ASGN_OR:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idOROP),
-                                    NEW_CHILD(ast, node->nd_value));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP),
+                                    NEW_CHILD(ast, RNODE_OP_ASGN_OR(node)->nd_value));
       case NODE_OP_CDECL:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head),
-                                    ID2SYM(node->nd_aid),
-                                    NEW_CHILD(ast, node->nd_value));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_head),
+                                    ID2SYM(RNODE_OP_CDECL(node)->nd_aid),
+                                    NEW_CHILD(ast, RNODE_OP_CDECL(node)->nd_value));
       case NODE_CALL:
       case NODE_OPCALL:
       case NODE_QCALL:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv),
-                                    ID2SYM(node->nd_mid),
-                                    NEW_CHILD(ast, node->nd_args));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_CALL(node)->nd_recv),
+                                    ID2SYM(RNODE_CALL(node)->nd_mid),
+                                    NEW_CHILD(ast, RNODE_CALL(node)->nd_args));
       case NODE_FCALL:
-        return rb_ary_new_from_args(2, ID2SYM(node->nd_mid),
-                                    NEW_CHILD(ast, node->nd_args));
+        return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid),
+                                    NEW_CHILD(ast, RNODE_FCALL(node)->nd_args));
       case NODE_VCALL:
-        return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
+        return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid));
       case NODE_SUPER:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_args);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_SUPER(node)->nd_args);
       case NODE_ZSUPER:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_LIST:
       case NODE_VALUES:
-        return dump_array(ast, node);
+        return dump_array(ast, RNODE_LIST(node));
       case NODE_ZLIST:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_HASH:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_head);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_HASH(node)->nd_head);
       case NODE_YIELD:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_head);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_YIELD(node)->nd_head);
       case NODE_LVAR:
       case NODE_DVAR:
-        return rb_ary_new_from_args(1, var_name(node->nd_vid));
+        return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid));
       case NODE_IVAR:
       case NODE_CONST:
       case NODE_CVAR:
       case NODE_GVAR:
-        return rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
+        return rb_ary_new_from_args(1, ID2SYM(RNODE_IVAR(node)->nd_vid));
       case NODE_NTH_REF:
-        snprintf(name, sizeof(name), "$%ld", node->nd_nth);
+        snprintf(name, sizeof(name), "$%ld", RNODE_NTH_REF(node)->nd_nth);
         return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
       case NODE_BACK_REF:
         name[0] = '$';
-        name[1] = (char)node->nd_nth;
+        name[1] = (char)RNODE_BACK_REF(node)->nd_nth;
         name[2] = '\0';
         return rb_ary_new_from_args(1, ID2SYM(rb_intern(name)));
       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);
+        if (RNODE_MATCH2(node)->nd_args) {
+            return rb_ary_new_from_node_args(ast, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args);
         }
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value);
       case NODE_MATCH3:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value);
       case NODE_MATCH:
       case NODE_LIT:
       case NODE_STR:
       case NODE_XSTR:
-        return rb_ary_new_from_args(1, node->nd_lit);
+        return rb_ary_new_from_args(1, RNODE_LIT(node)->nd_lit);
       case NODE_ONCE:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_ONCE(node)->nd_body);
       case NODE_DSTR:
       case NODE_DXSTR:
       case NODE_DREGX:
       case NODE_DSYM:
         {
-            NODE *n = node->nd_next;
+            struct RNode_LIST *n = RNODE_DSTR(node)->nd_next;
             VALUE head = Qnil, next = Qnil;
             if (n) {
                 head = NEW_CHILD(ast, n->nd_head);
                 next = NEW_CHILD(ast, n->nd_next);
             }
-            return rb_ary_new_from_args(3, node->nd_lit, head, next);
+            return rb_ary_new_from_args(3, RNODE_DSTR(node)->nd_lit, head, next);
         }
       case NODE_EVSTR:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_EVSTR(node)->nd_body);
       case NODE_ARGSCAT:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body);
       case NODE_ARGSPUSH:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body);
       case NODE_SPLAT:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_head);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_SPLAT(node)->nd_head);
       case NODE_BLOCK_PASS:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body);
       case NODE_DEFN:
-        return rb_ary_new_from_args(2, ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn));
+        return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFN(node)->nd_defn));
       case NODE_DEFS:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast, RNODE_DEFS(node)->nd_defn));
       case NODE_ALIAS:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd);
       case NODE_VALIAS:
-        return rb_ary_new_from_args(2, ID2SYM(node->nd_alias), ID2SYM(node->nd_orig));
+        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, 1, node->nd_undef);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_UNDEF(node)->nd_undef);
       case NODE_CLASS:
-        return rb_ary_new_from_node_args(ast, 3, node->nd_cpath, node->nd_super, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
       case NODE_MODULE:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_cpath, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body);
       case NODE_SCLASS:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body);
       case NODE_COLON2:
-        return rb_ary_new_from_args(2, NEW_CHILD(ast, node->nd_head), ID2SYM(node->nd_mid));
+        return rb_ary_new_from_args(2, NEW_CHILD(ast, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid));
       case NODE_COLON3:
-        return rb_ary_new_from_args(1, ID2SYM(node->nd_mid));
+        return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid));
       case NODE_DOT2:
       case NODE_DOT3:
       case NODE_FLIP2:
       case NODE_FLIP3:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_beg, node->nd_end);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end);
       case NODE_SELF:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_NIL:
@@ -602,26 +605,26 @@ node_children(rb_ast_t *ast, const NODE *node)
       case NODE_ERRINFO:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_DEFINED:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_head);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_DEFINED(node)->nd_head);
       case NODE_POSTEXE:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_POSTEXE(node)->nd_body);
       case NODE_ATTRASGN:
-        return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_args));
+        return rb_ary_new_from_args(3, NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast, RNODE_ATTRASGN(node)->nd_args));
       case NODE_LAMBDA:
-        return rb_ary_new_from_node_args(ast, 1, node->nd_body);
+        return rb_ary_new_from_node_args(ast, 1, RNODE_LAMBDA(node)->nd_body);
       case NODE_OPT_ARG:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next);
       case NODE_KW_ARG:
-        return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next);
+        return rb_ary_new_from_node_args(ast, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next);
       case NODE_POSTARG:
-        if (NODE_NAMED_REST_P(node->nd_1st)) {
-            return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd);
+        if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) {
+            return rb_ary_new_from_node_args(ast, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd);
         }
         return rb_ary_new_from_args(2, no_name_rest(),
-                                    NEW_CHILD(ast, node->nd_2nd));
+                                    NEW_CHILD(ast, RNODE_POSTARG(node)->nd_2nd));
       case NODE_ARGS:
         {
-            struct rb_args_info *ainfo = node->nd_ainfo;
+            struct rb_args_info *ainfo = RNODE_ARGS(node)->nd_ainfo;
             return rb_ary_new_from_args(10,
                                         INT2NUM(ainfo->pre_args_num),
                                         NEW_CHILD(ast, ainfo->pre_init),
@@ -638,48 +641,52 @@ node_children(rb_ast_t *ast, const NODE *node)
         }
       case NODE_SCOPE:
         {
-            rb_ast_id_table_t *tbl = node->nd_tbl;
+            rb_ast_id_table_t *tbl = RNODE_SCOPE(node)->nd_tbl;
             int i, size = tbl ? tbl->size : 0;
             VALUE locals = rb_ary_new_capa(size);
             for (i = 0; i < size; i++) {
                 rb_ary_push(locals, var_name(tbl->ids[i]));
             }
-            return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, node->nd_args), NEW_CHILD(ast, node->nd_body));
+            return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast, RNODE_SCOPE(node)->nd_body));
         }
       case NODE_ARYPTN:
         {
-            struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
+            struct rb_ary_pattern_info *apinfo = RNODE_ARYPTN(node)->nd_apinfo;
             VALUE rest = rest_arg(ast, apinfo->rest_arg);
             return rb_ary_new_from_args(4,
-                                        NEW_CHILD(ast, node->nd_pconst),
+                                        NEW_CHILD(ast, RNODE_ARYPTN(node)->nd_pconst),
                                         NEW_CHILD(ast, apinfo->pre_args),
                                         rest,
                                         NEW_CHILD(ast, apinfo->post_args));
         }
       case NODE_FNDPTN:
         {
-            struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo;
+            struct rb_fnd_pattern_info *fpinfo = RNODE_FNDPTN(node)->nd_fpinfo;
             VALUE pre_rest = rest_arg(ast, fpinfo->pre_rest_arg);
             VALUE post_rest = rest_arg(ast, fpinfo->post_rest_arg);
             return rb_ary_new_from_args(4,
-                                        NEW_CHILD(ast, node->nd_pconst),
+                                        NEW_CHILD(ast, RNODE_FNDPTN(node)->nd_pconst),
                                         pre_rest,
                                         NEW_CHILD(ast, fpinfo->args),
                                         post_rest);
         }
       case NODE_HSHPTN:
         {
-            VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
-                                                                                 NEW_CHILD(ast, node->nd_pkwrestarg);
+            VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) :
+                                                                                 NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwrestarg);
 
             return rb_ary_new_from_args(3,
-                                        NEW_CHILD(ast, node->nd_pconst),
-                                        NEW_CHILD(ast, node->nd_pkwargs),
+                                        NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pconst),
+                                        NEW_CHILD(ast, RNODE_HSHPTN(node)->nd_pkwargs),
                                         kwrest);
         }
       case NODE_ERROR:
         return rb_ary_new_from_node_args(ast, 0);
       case NODE_ARGS_AUX:
+      case NODE_DEF_TEMP:
+      case NODE_DEF_TEMP2:
+      case NODE_RIPPER:
+      case NODE_RIPPER_VALUES:
       case NODE_LAST:
         break;
     }
index c7bc538..c286df0 100644 (file)
--- a/compile.c
+++ b/compile.c
@@ -333,10 +333,10 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NOD
   (debug_compile("== " desc "\n", \
                  iseq_compile_each(iseq, (anchor), (node), (popped))))
 
-#define COMPILE_RECV(anchor, desc, node) \
+#define COMPILE_RECV(anchor, desc, node, recv) \
     (private_recv_p(node) ? \
      (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \
-     COMPILE(anchor, desc, node->nd_recv) ? 0 : -1)
+     COMPILE(anchor, desc, recv) ? 0 : -1)
 
 #define OPERAND_AT(insn, idx) \
   (((INSN*)(insn))->operands[(idx)])
@@ -753,8 +753,8 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
     /* assume node is T_NODE */
     else if (nd_type_p(node, NODE_SCOPE)) {
         /* iseq type of top, method, class, block */
-        iseq_set_local_table(iseq, node->nd_tbl);
-        iseq_set_arguments(iseq, ret, node->nd_args);
+        iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl);
+        iseq_set_arguments(iseq, ret, RNODE_SCOPE(node)->nd_args);
 
         switch (ISEQ_BODY(iseq)->type) {
           case ISEQ_TYPE_BLOCK:
@@ -769,7 +769,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
                 NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1);
                 ADD_INSN (ret, &dummy_line_node, nop);
                 ADD_LABEL(ret, start);
-                CHECK(COMPILE(ret, "block body", node->nd_body));
+                CHECK(COMPILE(ret, "block body", RNODE_SCOPE(node)->nd_body));
                 ADD_LABEL(ret, end);
                 ADD_TRACE(ret, RUBY_EVENT_B_RETURN);
                 ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno;
@@ -782,23 +782,23 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
           case ISEQ_TYPE_CLASS:
             {
                 ADD_TRACE(ret, RUBY_EVENT_CLASS);
-                CHECK(COMPILE(ret, "scoped node", node->nd_body));
+                CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body));
                 ADD_TRACE(ret, RUBY_EVENT_END);
                 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
                 break;
             }
           case ISEQ_TYPE_METHOD:
             {
-                ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
+                ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
                 ADD_TRACE(ret, RUBY_EVENT_CALL);
-                CHECK(COMPILE(ret, "scoped node", node->nd_body));
-                ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body;
+                CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body));
+                ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body;
                 ADD_TRACE(ret, RUBY_EVENT_RETURN);
                 ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node);
                 break;
             }
           default: {
-            CHECK(COMPILE(ret, "scoped node", node->nd_body));
+            CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body));
             break;
           }
         }
@@ -1817,14 +1817,14 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
 
     while (node) {
         kw++;
-        node = node->nd_next;
+        node = RNODE_KW_ARG(node)->nd_next;
     }
     arg_size += kw;
     keyword->bits_start = arg_size++;
 
     node = args->kw_args;
     while (node) {
-        const NODE *val_node = node->nd_body->nd_value;
+        const NODE *val_node = RNODE_LASGN(RNODE_KW_ARG(node)->nd_body)->nd_value;
         VALUE dv;
 
         if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) {
@@ -1833,7 +1833,7 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
         else {
             switch (nd_type(val_node)) {
               case NODE_LIT:
-                dv = val_node->nd_lit;
+                dv = RNODE_LIT(val_node)->nd_lit;
                 break;
               case NODE_NIL:
                 dv = Qnil;
@@ -1853,12 +1853,12 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
             rb_ary_push(default_values, dv);
         }
 
-        node = node->nd_next;
+        node = RNODE_KW_ARG(node)->nd_next;
     }
 
     keyword->num = kw;
 
-    if (args->kw_rest_arg->nd_vid != 0) {
+    if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) {
         keyword->rest_start = arg_size++;
         body->param.flags.has_kwrest = TRUE;
     }
@@ -1889,7 +1889,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
 
     if (node_args) {
         struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
-        struct rb_args_info *args = node_args->nd_ainfo;
+        struct rb_args_info *args = RNODE_ARGS(node_args)->nd_ainfo;
         ID rest_id = 0;
         int last_comma = 0;
         ID block_id = 0;
@@ -1920,8 +1920,8 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
                 label = NEW_LABEL(nd_line(node));
                 rb_ary_push(labels, (VALUE)label | 1);
                 ADD_LABEL(optargs, label);
-                NO_CHECK(COMPILE_POPPED(optargs, "optarg", node->nd_body));
-                node = node->nd_next;
+                NO_CHECK(COMPILE_POPPED(optargs, "optarg", RNODE_OPT_ARG(node)->nd_body));
+                node = RNODE_OPT_ARG(node)->nd_next;
                 i += 1;
             }
 
@@ -4023,16 +4023,16 @@ all_string_result_p(const NODE *node)
       case NODE_STR: case NODE_DSTR:
         return TRUE;
       case NODE_IF: case NODE_UNLESS:
-        if (!node->nd_body || !node->nd_else) return FALSE;
-        if (all_string_result_p(node->nd_body))
-            return all_string_result_p(node->nd_else);
+        if (!RNODE_IF(node)->nd_body || !RNODE_IF(node)->nd_else) return FALSE;
+        if (all_string_result_p(RNODE_IF(node)->nd_body))
+            return all_string_result_p(RNODE_IF(node)->nd_else);
         return FALSE;
       case NODE_AND: case NODE_OR:
-        if (!node->nd_2nd)
-            return all_string_result_p(node->nd_1st);
-        if (!all_string_result_p(node->nd_1st))
+        if (!RNODE_AND(node)->nd_2nd)
+            return all_string_result_p(RNODE_AND(node)->nd_1st);
+        if (!all_string_result_p(RNODE_AND(node)->nd_1st))
             return FALSE;
-        return all_string_result_p(node->nd_2nd);
+        return all_string_result_p(RNODE_AND(node)->nd_2nd);
       default:
         return FALSE;
     }
@@ -4041,8 +4041,8 @@ all_string_result_p(const NODE *node)
 static int
 compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp)
 {
-    const NODE *list = node->nd_next;
-    VALUE lit = node->nd_lit;
+    const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
+    VALUE lit = RNODE_DSTR(node)->nd_lit;
     LINK_ELEMENT *first_lit = 0;
     int cnt = 0;
 
@@ -4063,7 +4063,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons
     while (list) {
         const NODE *const head = list->nd_head;
         if (nd_type_p(head, NODE_STR)) {
-            lit = rb_fstring(head->nd_lit);
+            lit = rb_fstring(RNODE_STR(head)->nd_lit);
             ADD_INSN1(ret, head, putobject, lit);
             RB_OBJ_WRITTEN(iseq, Qundef, lit);
             lit = Qnil;
@@ -4072,7 +4072,7 @@ compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cons
             CHECK(COMPILE(ret, "each string", head));
         }
         cnt++;
-        list = list->nd_next;
+        list = (struct RNode_LIST *)list->nd_next;
     }
     if (NIL_P(lit) && first_lit) {
         ELEM_REMOVE(first_lit);
@@ -4087,12 +4087,12 @@ static int
 compile_block(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped)
 {
     while (node && nd_type_p(node, NODE_BLOCK)) {
-        CHECK(COMPILE_(ret, "BLOCK body", node->nd_head,
-                       (node->nd_next ? 1 : popped)));
-        node = node->nd_next;
+        CHECK(COMPILE_(ret, "BLOCK body", RNODE_BLOCK(node)->nd_head,
+                       (RNODE_BLOCK(node)->nd_next ? 1 : popped)));
+        node = RNODE_BLOCK(node)->nd_next;
     }
     if (node) {
-        CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped));
+        CHECK(COMPILE_(ret, "BLOCK next", RNODE_BLOCK(node)->nd_next, popped));
     }
     return COMPILE_OK;
 }
@@ -4101,8 +4101,8 @@ static int
 compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
 {
     int cnt;
-    if (!node->nd_next) {
-        VALUE lit = rb_fstring(node->nd_lit);
+    if (!RNODE_DSTR(node)->nd_next) {
+        VALUE lit = rb_fstring(RNODE_DSTR(node)->nd_lit);
         ADD_INSN1(ret, node, putstring, lit);
         RB_OBJ_WRITTEN(iseq, Qundef, lit);
     }
@@ -4118,7 +4118,7 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
 {
     int cnt;
     CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
-    ADD_INSN2(ret, node, toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt));
+    ADD_INSN2(ret, node, toregexp, INT2FIX(RNODE_DREGX(node)->nd_cflag), INT2FIX(cnt));
     return COMPILE_OK;
 }
 
@@ -4136,7 +4136,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
     ADD_INSNL(ret, node, branchif, lend);
 
     /* *flip == 0 */
-    CHECK(COMPILE(ret, "flip2 beg", node->nd_beg));
+    CHECK(COMPILE(ret, "flip2 beg", RNODE_FLIP2(node)->nd_beg));
     ADD_INSNL(ret, node, branchunless, else_label);
     ADD_INSN1(ret, node, putobject, Qtrue);
     ADD_INSN1(ret, node, setspecial, key);
@@ -4146,7 +4146,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
 
     /* *flip == 1 */
     ADD_LABEL(ret, lend);
-    CHECK(COMPILE(ret, "flip2 end", node->nd_end));
+    CHECK(COMPILE(ret, "flip2 end", RNODE_FLIP2(node)->nd_end));
     ADD_INSNL(ret, node, branchunless, then_label);
     ADD_INSN1(ret, node, putobject, Qfalse);
     ADD_INSN1(ret, node, setspecial, key);
@@ -4195,8 +4195,8 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
   again:
     switch (nd_type(cond)) {
       case NODE_AND:
-        CHECK(ok = compile_logical(iseq, ret, cond->nd_1st, NULL, else_label));
-        cond = cond->nd_2nd;
+        CHECK(ok = compile_logical(iseq, ret, RNODE_AND(cond)->nd_1st, NULL, else_label));
+        cond = RNODE_AND(cond)->nd_2nd;
         if (ok == COMPILE_SINGLE) {
             INIT_ANCHOR(ignore);
             ret = ignore;
@@ -4204,8 +4204,8 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
         }
         goto again;
       case NODE_OR:
-        CHECK(ok = compile_logical(iseq, ret, cond->nd_1st, then_label, NULL));
-        cond = cond->nd_2nd;
+        CHECK(ok = compile_logical(iseq, ret, RNODE_OR(cond)->nd_1st, then_label, NULL));
+        cond = RNODE_OR(cond)->nd_2nd;
         if (ok == COMPILE_SINGLE) {
             INIT_ANCHOR(ignore);
             ret = ignore;
@@ -4277,7 +4277,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
 static int
 keyword_node_p(const NODE *const node)
 {
-    return nd_type_p(node, NODE_HASH) && (node->nd_brace & HASH_BRACE) != HASH_BRACE;
+    return nd_type_p(node, NODE_HASH) && (RNODE_HASH(node)->nd_brace & HASH_BRACE) != HASH_BRACE;
 }
 
 static int
@@ -4290,22 +4290,22 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
     RUBY_ASSERT(kw_arg_ptr != NULL);
     RUBY_ASSERT(flag != NULL);
 
-    if (root_node->nd_head && nd_type_p(root_node->nd_head, NODE_LIST)) {
-        const NODE *node = root_node->nd_head;
+    if (RNODE_HASH(root_node)->nd_head && nd_type_p(RNODE_HASH(root_node)->nd_head, NODE_LIST)) {
+        const NODE *node = RNODE_HASH(root_node)->nd_head;
         int seen_nodes = 0;
 
         while (node) {
-            const NODE *key_node = node->nd_head;
+            const NODE *key_node = RNODE_LIST(node)->nd_head;
             seen_nodes++;
 
             assert(nd_type_p(node, NODE_LIST));
-            if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(key_node->nd_lit)) {
+            if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(RNODE_LIT(key_node)->nd_lit)) {
                 /* can be keywords */
             }
             else {
                 if (flag) {
                     *flag |= VM_CALL_KW_SPLAT;
-                    if (seen_nodes > 1 || node->nd_next->nd_next) {
+                    if (seen_nodes > 1 || RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
                         /* A new hash will be created for the keyword arguments
                          * in this case, so mark the method as passing mutable
                          * keyword splat.
@@ -4315,14 +4315,14 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
                 }
                 return FALSE;
             }
-            node = node->nd_next; /* skip value node */
-            node = node->nd_next;
+            node = RNODE_LIST(node)->nd_next; /* skip value node */
+            node = RNODE_LIST(node)->nd_next;
         }
 
         /* may be keywords */
-        node = root_node->nd_head;
+        node = RNODE_HASH(root_node)->nd_head;
         {
-            int len = (int)node->nd_alen / 2;
+            int len = (int)RNODE_LIST(node)->as.nd_alen / 2;
             struct rb_callinfo_kwarg *kw_arg =
                 rb_xmalloc_mul_add(len, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg));
             VALUE *keywords = kw_arg->keywords;
@@ -4331,10 +4331,10 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
 
             *kw_arg_ptr = kw_arg;
 
-            for (i=0; node != NULL; i++, node = node->nd_next->nd_next) {
-                const NODE *key_node = node->nd_head;
-                const NODE *val_node = node->nd_next->nd_head;
-                keywords[i] = key_node->nd_lit;
+            for (i=0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
+                const NODE *key_node = RNODE_LIST(node)->nd_head;
+                const NODE *val_node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
+                keywords[i] = RNODE_LIT(key_node)->nd_lit;
                 NO_CHECK(COMPILE(ret, "keyword values", val_node));
             }
             assert(i == len);
@@ -4349,17 +4349,17 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, NODE **k
 {
     int len = 0;
 
-    for (; node; len++, node = node->nd_next) {
+    for (; node; len++, node = RNODE_LIST(node)->nd_next) {
         if (CPDEBUG > 0) {
             EXPECT_NODE("compile_args", node, NODE_LIST, -1);
         }
 
-        if (node->nd_next == NULL && keyword_node_p(node->nd_head)) { /* last node is kwnode */
-            *kwnode_ptr = node->nd_head;
+        if (RNODE_LIST(node)->nd_next == NULL && keyword_node_p(RNODE_LIST(node)->nd_head)) { /* last node is kwnode */
+            *kwnode_ptr = RNODE_LIST(node)->nd_head;
         }
         else {
-            RUBY_ASSERT(!keyword_node_p(node->nd_head));
-            NO_CHECK(COMPILE_(ret, "array element", node->nd_head, FALSE));
+            RUBY_ASSERT(!keyword_node_p(RNODE_LIST(node)->nd_head));
+            NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, FALSE));
         }
     }
 
@@ -4396,15 +4396,15 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
         if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
             VALUE lit;
             VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
-            lit = rb_str_dup(node->nd_lit);
+            lit = rb_str_dup(RNODE_STR(node)->nd_lit);
             rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
             return rb_str_freeze(lit);
         }
         else {
-            return rb_fstring(node->nd_lit);
+            return rb_fstring(RNODE_STR(node)->nd_lit);
         }
       default:
-        return node->nd_lit;
+        return RNODE_LIT(node)->nd_lit;
     }
 }
 
@@ -4423,8 +4423,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
     EXPECT_NODE("compile_array", node, NODE_LIST, -1);
 
     if (popped) {
-        for (; node; node = node->nd_next) {
-            NO_CHECK(COMPILE_(ret, "array element", node->nd_head, popped));
+        for (; node; node = RNODE_LIST(node)->nd_next) {
+            NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, popped));
         }
         return 1;
     }
@@ -4483,10 +4483,10 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
         int count = 1;
 
         /* pre-allocation check (this branch can be omittable) */
-        if (static_literal_node_p(node->nd_head, iseq)) {
+        if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq)) {
             /* count the elements that are optimizable */
-            const NODE *node_tmp = node->nd_next;
-            for (; node_tmp && static_literal_node_p(node_tmp->nd_head, iseq); node_tmp = node_tmp->nd_next)
+            const NODE *node_tmp = RNODE_LIST(node)->nd_next;
+            for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq); node_tmp = RNODE_LIST(node_tmp)->nd_next)
                 count++;
 
             if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) {
@@ -4494,8 +4494,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
                 VALUE ary = rb_ary_hidden_new(count);
 
                 /* Create a hidden array */
-                for (; count; count--, node = node->nd_next)
-                    rb_ary_push(ary, static_literal_value(node->nd_head, iseq));
+                for (; count; count--, node = RNODE_LIST(node)->nd_next)
+                    rb_ary_push(ary, static_literal_value(RNODE_LIST(node)->nd_head, iseq));
                 OBJ_FREEZE(ary);
 
                 /* Emit optimized code */
@@ -4513,15 +4513,15 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
         }
 
         /* Base case: Compile "count" elements */
-        for (; count; count--, node = node->nd_next) {
+        for (; count; count--, node = RNODE_LIST(node)->nd_next) {
             if (CPDEBUG > 0) {
                 EXPECT_NODE("compile_array", node, NODE_LIST, -1);
             }
 
-            NO_CHECK(COMPILE_(ret, "array element", node->nd_head, 0));
+            NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0));
             stack_len++;
 
-            if (!node->nd_next && keyword_node_p(node->nd_head)) {
+            if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
                 /* Reached the end, and the last element is a keyword */
                 FLUSH_CHUNK(newarraykwsplat);
                 return 1;
@@ -4559,7 +4559,7 @@ compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node)
 static inline int
 static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq)
 {
-    return node->nd_head && static_literal_node_p(node->nd_head, iseq) && static_literal_node_p(node->nd_next->nd_head, iseq);
+    return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
 }
 
 static int
@@ -4567,7 +4567,7 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
 {
     const NODE *line_node = node;
 
-    node = node->nd_head;
+    node = RNODE_HASH(node)->nd_head;
 
     if (!node || nd_type_p(node, NODE_ZLIST)) {
         if (!popped) {
@@ -4579,8 +4579,8 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
     EXPECT_NODE("compile_hash", node, NODE_LIST, -1);
 
     if (popped) {
-        for (; node; node = node->nd_next) {
-            NO_CHECK(COMPILE_(ret, "hash element", node->nd_head, popped));
+        for (; node; node = RNODE_LIST(node)->nd_next) {
+            NO_CHECK(COMPILE_(ret, "hash element", RNODE_LIST(node)->nd_head, popped));
         }
         return 1;
     }
@@ -4633,8 +4633,8 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
         /* pre-allocation check (this branch can be omittable) */
         if (static_literal_node_pair_p(node, iseq)) {
             /* count the elements that are optimizable */
-            const NODE *node_tmp = node->nd_next->nd_next;
-            for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = node_tmp->nd_next->nd_next)
+            const NODE *node_tmp = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next;
+            for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = RNODE_LIST(RNODE_LIST(node_tmp)->nd_next)->nd_next)
                 count++;
 
             if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) {
@@ -4642,10 +4642,10 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
                 VALUE ary = rb_ary_hidden_new(count);
 
                 /* Create a hidden hash */
-                for (; count; count--, node = node->nd_next->nd_next) {
+                for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
                     VALUE elem[2];
-                    elem[0] = static_literal_value(node->nd_head, iseq);
-                    elem[1] = static_literal_value(node->nd_next->nd_head, iseq);
+                    elem[0] = static_literal_value(RNODE_LIST(node)->nd_head, iseq);
+                    elem[1] = static_literal_value(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
                     rb_ary_cat(ary, elem, 2);
                 }
                 VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2);
@@ -4672,16 +4672,16 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
         }
 
         /* Base case: Compile "count" elements */
-        for (; count; count--, node = node->nd_next->nd_next) {
+        for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
 
             if (CPDEBUG > 0) {
                 EXPECT_NODE("compile_hash", node, NODE_LIST, -1);
             }
 
-            if (node->nd_head) {
+            if (RNODE_LIST(node)->nd_head) {
                 /* Normal key-value pair */
-                NO_CHECK(COMPILE_(anchor, "hash key element", node->nd_head, 0));
-                NO_CHECK(COMPILE_(anchor, "hash value element", node->nd_next->nd_head, 0));
+                NO_CHECK(COMPILE_(anchor, "hash key element", RNODE_LIST(node)->nd_head, 0));
+                NO_CHECK(COMPILE_(anchor, "hash value element", RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, 0));
                 stack_len += 2;
 
                 /* If there are many pushed elements, flush them to avoid stack overflow */
@@ -4691,10 +4691,10 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
                 /* kwsplat case: foo(..., **kw, ...) */
                 FLUSH_CHUNK();
 
-                const NODE *kw = node->nd_next->nd_head;
-                int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(kw->nd_lit, T_HASH); /* foo(  ..., **{}, ...) */
+                const NODE *kw = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head;
+                int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(RNODE_LIT(kw)->nd_lit, T_HASH); /* foo(  ..., **{}, ...) */
                 int first_kw = first_chunk && stack_len == 0; /* foo(1,2,3, **kw, ...) */
-                int last_kw = !node->nd_next->nd_next;        /* foo(  ..., **kw) */
+                int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next; /* foo(  ..., **kw) */
                 int only_kw = last_kw && first_kw;            /* foo(1,2,3, **kw) */
 
                 if (empty_kw) {
@@ -4757,7 +4757,7 @@ rb_node_case_when_optimizable_literal(const NODE *const node)
 {
     switch (nd_type(node)) {
       case NODE_LIT: {
-        VALUE v = node->nd_lit;
+        VALUE v = RNODE_LIT(node)->nd_lit;
         double ival;
         if (RB_FLOAT_TYPE_P(v) &&
             modf(RFLOAT_VALUE(v), &ival) == 0.0) {
@@ -4778,7 +4778,7 @@ rb_node_case_when_optimizable_literal(const NODE *const node)
       case NODE_FALSE:
         return Qfalse;
       case NODE_STR:
-        return rb_fstring(node->nd_lit);
+        return rb_fstring(RNODE_LIT(node)->nd_lit);
     }
     return Qundef;
 }
@@ -4788,7 +4788,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
           LABEL *l1, int only_special_literals, VALUE literals)
 {
     while (vals) {
-        const NODE *val = vals->nd_head;
+        const NODE *val = RNODE_LIST(vals)->nd_head;
         VALUE lit = rb_node_case_when_optimizable_literal(val);
 
         if (UNDEF_P(lit)) {
@@ -4799,8 +4799,8 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
         }
 
         if (nd_type_p(val, NODE_STR)) {
-            debugp_param("nd_lit", val->nd_lit);
-            lit = rb_fstring(val->nd_lit);
+            debugp_param("nd_lit", RNODE_STR(val)->nd_lit);
+            lit = rb_fstring(RNODE_STR(val)->nd_lit);
             ADD_INSN1(cond_seq, val, putobject, lit);
             RB_OBJ_WRITTEN(iseq, Qundef, lit);
         }
@@ -4812,7 +4812,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
         ADD_INSN1(cond_seq, vals, topn, INT2FIX(1));
         ADD_CALL(cond_seq, vals, idEqq, INT2FIX(1));
         ADD_INSNL(cond_seq, val, branchif, l1);
-        vals = vals->nd_next;
+        vals = RNODE_LIST(vals)->nd_next;
     }
     return only_special_literals;
 }
@@ -4830,19 +4830,19 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals,
         break;
       case NODE_SPLAT:
         ADD_INSN (cond_seq, line_node, dup);
-        CHECK(COMPILE(cond_seq, "when splat", vals->nd_head));
+        CHECK(COMPILE(cond_seq, "when splat", RNODE_SPLAT(vals)->nd_head));
         ADD_INSN1(cond_seq, line_node, splatarray, Qfalse);
         ADD_INSN1(cond_seq, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
         ADD_INSNL(cond_seq, line_node, branchif, l1);
         break;
       case NODE_ARGSCAT:
-        CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
-        CHECK(when_splat_vals(iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals));
+        CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_head, l1, only_special_literals, literals));
+        CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_body, l1, only_special_literals, literals));
         break;
       case NODE_ARGSPUSH:
-        CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals));
+        CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSPUSH(vals)->nd_head, l1, only_special_literals, literals));
         ADD_INSN (cond_seq, line_node, dup);
-        CHECK(COMPILE(cond_seq, "when argspush body", vals->nd_body));
+        CHECK(COMPILE(cond_seq, "when argspush body", RNODE_ARGSPUSH(vals)->nd_body));
         ADD_INSN1(cond_seq, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
         ADD_INSNL(cond_seq, line_node, branchif, l1);
         break;
@@ -5062,7 +5062,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const
         break;
       }
       case NODE_CDECL:
-        if (!node->nd_vid) {
+        if (!RNODE_CDECL(node)->nd_vid) {
             /* Special handling only needed for expr::C, not for C */
             INSN *iobj;
 
@@ -5100,8 +5100,8 @@ static int
 compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *lhsn)
 {
     if (lhsn) {
-        CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next));
-        CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, lhsn->nd_head, NULL, 0));
+        CHECK(compile_massign_opt_lhs(iseq, ret, RNODE_LIST(lhsn)->nd_next));
+        CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, RNODE_LIST(lhsn)->nd_head, NULL, 0));
     }
     return COMPILE_OK;
 }
@@ -5131,29 +5131,29 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
     }
 
     while (lhsn) {
-        const NODE *ln = lhsn->nd_head;
+        const NODE *ln = RNODE_LIST(lhsn)->nd_head;
         switch (nd_type(ln)) {
           case NODE_LASGN:
           case NODE_DASGN:
           case NODE_IASGN:
           case NODE_CVASGN:
-            MEMORY(ln->nd_vid);
+            MEMORY(RNODE_LASGN(ln)->nd_vid);
             break;
           default:
             return 0;
         }
-        lhsn = lhsn->nd_next;
+        lhsn = RNODE_LIST(lhsn)->nd_next;
         llen++;
     }
 
     while (rhsn) {
         if (llen <= rlen) {
-            NO_CHECK(COMPILE_POPPED(ret, "masgn val (popped)", rhsn->nd_head));
+            NO_CHECK(COMPILE_POPPED(ret, "masgn val (popped)", RNODE_LIST(rhsn)->nd_head));
         }
         else {
-            NO_CHECK(COMPILE(ret, "masgn val", rhsn->nd_head));
+            NO_CHECK(COMPILE(ret, "masgn val", RNODE_LIST(rhsn)->nd_head));
         }
-        rhsn = rhsn->nd_next;
+        rhsn = RNODE_LIST(rhsn)->nd_next;
         rlen++;
     }
 
@@ -5170,9 +5170,9 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
 static int
 compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs, LINK_ANCHOR *const lhs, LINK_ANCHOR *const post, const NODE *const node, struct masgn_state *state, int popped)
 {
-    const NODE *rhsn = node->nd_value;
-    const NODE *splatn = node->nd_args;
-    const NODE *lhsn = node->nd_head;
+    const NODE *rhsn = RNODE_MASGN(node)->nd_value;
+    const NODE *splatn = RNODE_MASGN(node)->nd_args;
+    const NODE *lhsn = RNODE_MASGN(node)->nd_head;
     const NODE *lhsn_count = lhsn;
     int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0;
 
@@ -5182,20 +5182,20 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
 
     while (lhsn_count) {
         llen++;
-        lhsn_count = lhsn_count->nd_next;
+        lhsn_count = RNODE_LIST(lhsn_count)->nd_next;
     }
     while (lhsn) {
-        CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, lhsn->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level));
+        CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(lhsn)->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level));
         lpos++;
-        lhsn = lhsn->nd_next;
+        lhsn = RNODE_LIST(lhsn)->nd_next;
     }
 
     if (lhs_splat) {
         if (nd_type_p(splatn, NODE_POSTARG)) {
             /*a, b, *r, p1, p2 */
-            const NODE *postn = splatn->nd_2nd;
-            const NODE *restn = splatn->nd_1st;
-            int plen = (int)postn->nd_alen;
+            const NODE *postn = RNODE_POSTARG(splatn)->nd_2nd;
+            const NODE *restn = RNODE_POSTARG(splatn)->nd_1st;
+            int plen = (int)RNODE_LIST(postn)->as.nd_alen;
             int ppos = 0;
             int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00);
 
@@ -5205,9 +5205,9 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
                 CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, restn, state, 1 + plen + state->lhs_level));
             }
             while (postn) {
-                CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, postn->nd_head, state, (plen - ppos) + state->lhs_level));
+                CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(postn)->nd_head, state, (plen - ppos) + state->lhs_level));
                 ppos++;
-                postn = postn->nd_next;
+                postn = RNODE_LIST(postn)->nd_next;
             }
         }
         else {
@@ -5233,7 +5233,7 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs
 static int
 compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
 {
-    if (!popped || node->nd_args || !compile_massign_opt(iseq, ret, node->nd_value, node->nd_head)) {
+    if (!popped || RNODE_MASGN(node)->nd_args || !compile_massign_opt(iseq, ret, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head)) {
         struct masgn_state state;
         state.lhs_level = popped ? 0 : 1;
         state.nested = 0;
@@ -5282,15 +5282,15 @@ collect_const_segments(rb_iseq_t *iseq, const NODE *node)
     for (;;) {
         switch (nd_type(node)) {
           case NODE_CONST:
-            rb_ary_unshift(arr, ID2SYM(node->nd_vid));
+            rb_ary_unshift(arr, ID2SYM(RNODE_CONST(node)->nd_vid));
             return arr;
           case NODE_COLON3:
-            rb_ary_unshift(arr, ID2SYM(node->nd_mid));
+            rb_ary_unshift(arr, ID2SYM(RNODE_COLON3(node)->nd_mid));
             rb_ary_unshift(arr, ID2SYM(idNULL));
             return arr;
           case NODE_COLON2:
-            rb_ary_unshift(arr, ID2SYM(node->nd_mid));
-            node = node->nd_head;
+            rb_ary_unshift(arr, ID2SYM(RNODE_COLON2(node)->nd_mid));
+            node = RNODE_COLON2(node)->nd_head;
             break;
           default:
             return Qfalse;
@@ -5304,22 +5304,22 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node,
 {
     switch (nd_type(node)) {
       case NODE_CONST:
-        debugi("compile_const_prefix - colon", node->nd_vid);
+        debugi("compile_const_prefix - colon", RNODE_CONST(node)->nd_vid);
         ADD_INSN1(body, node, putobject, Qtrue);
-        ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_vid));
+        ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_CONST(node)->nd_vid));
         break;
       case NODE_COLON3:
-        debugi("compile_const_prefix - colon3", node->nd_mid);
+        debugi("compile_const_prefix - colon3", RNODE_COLON3(node)->nd_mid);
         ADD_INSN(body, node, pop);
         ADD_INSN1(body, node, putobject, rb_cObject);
         ADD_INSN1(body, node, putobject, Qtrue);
-        ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid));
+        ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_COLON3(node)->nd_mid));
         break;
       case NODE_COLON2:
-        CHECK(compile_const_prefix(iseq, node->nd_head, pref, body));
-        debugi("compile_const_prefix - colon2", node->nd_mid);
+        CHECK(compile_const_prefix(iseq, RNODE_COLON2(node)->nd_head, pref, body));
+        debugi("compile_const_prefix - colon2", RNODE_COLON2(node)->nd_mid);
         ADD_INSN1(body, node, putobject, Qfalse);
-        ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid));
+        ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_COLON2(node)->nd_mid));
         break;
       default:
         CHECK(COMPILE(pref, "const colon2 prefix", node));
@@ -5336,9 +5336,9 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath)
         ADD_INSN1(ret, cpath, putobject, rb_cObject);
         return VM_DEFINECLASS_FLAG_SCOPED;
     }
-    else if (cpath->nd_head) {
+    else if (RNODE_COLON2(cpath)->nd_head) {
         /* Bar::Foo */
-        NO_CHECK(COMPILE(ret, "nd_else->nd_head", cpath->nd_head));
+        NO_CHECK(COMPILE(ret, "nd_else->nd_head", RNODE_COLON2(cpath)->nd_head));
         return VM_DEFINECLASS_FLAG_SCOPED;
     }
     else {
@@ -5352,9 +5352,9 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath)
 static inline int
 private_recv_p(const NODE *node)
 {
-    if (nd_type_p(node->nd_recv, NODE_SELF)) {
-        NODE *self = node->nd_recv;
-        return self->nd_state != 0;
+    if (nd_type_p(RNODE_CALL(node)->nd_recv, NODE_SELF)) {
+        NODE *self = RNODE_CALL(node)->nd_recv;
+        return RNODE_SELF(self)->nd_state != 0;
     }
     return 0;
 }
@@ -5396,13 +5396,13 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
         const NODE *vals = node;
 
         do {
-            defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse, false);
+            defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish, Qfalse, false);
 
             if (!lfinish[1]) {
                 lfinish[1] = NEW_LABEL(line);
             }
             ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
-        } while ((vals = vals->nd_next) != NULL);
+        } while ((vals = RNODE_LIST(vals)->nd_next) != NULL);
       }
         /* fall through */
       case NODE_STR:
@@ -5423,47 +5423,47 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
 #define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type))
       case NODE_IVAR:
         ADD_INSN3(ret, line_node, definedivar,
-                  ID2SYM(node->nd_vid), get_ivar_ic_value(iseq,node->nd_vid), PUSH_VAL(DEFINED_IVAR));
+                  ID2SYM(RNODE_IVAR(node)->nd_vid), get_ivar_ic_value(iseq,RNODE_IVAR(node)->nd_vid), PUSH_VAL(DEFINED_IVAR));
         return;
 
       case NODE_GVAR:
         ADD_INSN(ret, line_node, putnil);
         ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_GVAR),
-                  ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_GVAR));
+                  ID2SYM(RNODE_GVAR(node)->nd_vid), PUSH_VAL(DEFINED_GVAR));
         return;
 
       case NODE_CVAR:
         ADD_INSN(ret, line_node, putnil);
         ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CVAR),
-                  ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR));
+                  ID2SYM(RNODE_CVAR(node)->nd_vid), PUSH_VAL(DEFINED_CVAR));
         return;
 
       case NODE_CONST:
         ADD_INSN(ret, line_node, putnil);
         ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST),
-                  ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CONST));
+                  ID2SYM(RNODE_CONST(node)->nd_vid), PUSH_VAL(DEFINED_CONST));
         return;
       case NODE_COLON2:
         if (!lfinish[1]) {
             lfinish[1] = NEW_LABEL(line);
         }
-        defined_expr0(iseq, ret, node->nd_head, lfinish, Qfalse, false);
+        defined_expr0(iseq, ret, RNODE_COLON2(node)->nd_head, lfinish, Qfalse, false);
         ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
-        NO_CHECK(COMPILE(ret, "defined/colon2#nd_head", node->nd_head));
+        NO_CHECK(COMPILE(ret, "defined/colon2#nd_head", RNODE_COLON2(node)->nd_head));
 
-        if (rb_is_const_id(node->nd_mid)) {
+        if (rb_is_const_id(RNODE_COLON2(node)->nd_mid)) {
             ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST_FROM),
-                    ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
+                    ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
         }
         else {
             ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD),
-                    ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
+                    ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_METHOD));
         }
         return;
       case NODE_COLON3:
         ADD_INSN1(ret, line_node, putobject, rb_cObject);
         ADD_INSN3(ret, line_node, defined,
-                  INT2FIX(DEFINED_CONST_FROM), ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST));
+                  INT2FIX(DEFINED_CONST_FROM), ID2SYM(RNODE_COLON3(node)->nd_mid), PUSH_VAL(DEFINED_CONST));
         return;
 
         /* method dispatch */
@@ -5476,7 +5476,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
             (type == NODE_CALL || type == NODE_OPCALL ||
              (type == NODE_ATTRASGN && !private_recv_p(node)));
 
-        if (node->nd_args || explicit_receiver) {
+        if (RNODE_CALL(node)->nd_args || explicit_receiver) {
             if (!lfinish[1]) {
                 lfinish[1] = NEW_LABEL(line);
             }
@@ -5484,31 +5484,31 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
                 lfinish[2] = NEW_LABEL(line);
             }
         }
-        if (node->nd_args) {
-            defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse, false);
+        if (RNODE_CALL(node)->nd_args) {
+            defined_expr0(iseq, ret, RNODE_CALL(node)->nd_args, lfinish, Qfalse, false);
             ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
         }
         if (explicit_receiver) {
-            defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse, true);
-            switch (nd_type(node->nd_recv)) {
+            defined_expr0(iseq, ret, RNODE_CALL(node)->nd_recv, lfinish, Qfalse, true);
+            switch (nd_type(RNODE_CALL(node)->nd_recv)) {
               case NODE_CALL:
               case NODE_OPCALL:
               case NODE_VCALL:
               case NODE_FCALL:
               case NODE_ATTRASGN:
                 ADD_INSNL(ret, line_node, branchunless, lfinish[2]);
-                compile_call(iseq, ret, node->nd_recv, nd_type(node->nd_recv), line_node, 0, true);
+                compile_call(iseq, ret, RNODE_CALL(node)->nd_recv, nd_type(RNODE_CALL(node)->nd_recv), line_node, 0, true);
                 break;
               default:
                 ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
-                NO_CHECK(COMPILE(ret, "defined/recv", node->nd_recv));
+                NO_CHECK(COMPILE(ret, "defined/recv", RNODE_CALL(node)->nd_recv));
                 break;
             }
             if (keep_result) {
                 ADD_INSN(ret, line_node, dup);
             }
             ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD),
-                      ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
+                      ID2SYM(RNODE_CALL(node)->nd_mid), PUSH_VAL(DEFINED_METHOD));
         }
         else {
             ADD_INSN(ret, line_node, putself);
@@ -5516,7 +5516,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
                 ADD_INSN(ret, line_node, dup);
             }
             ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC),
-                      ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD));
+                      ID2SYM(RNODE_CALL(node)->nd_mid), PUSH_VAL(DEFINED_METHOD));
         }
         return;
       }
@@ -5531,7 +5531,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
       case NODE_NTH_REF:
         ADD_INSN(ret, line_node, putnil);
         ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_REF),
-                  INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)),
+                  INT2FIX((RNODE_BACK_REF(node)->nd_nth << 1) | (type == NODE_BACK_REF)),
                   PUSH_VAL(DEFINED_GVAR));
         return;
 
@@ -5607,7 +5607,7 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const
 {
     const int line = nd_line(node);
     const NODE *line_node = node;
-    if (!node->nd_head) {
+    if (!RNODE_DEFINED(node)->nd_head) {
         VALUE str = rb_iseq_defined_string(DEFINED_NIL);
         ADD_INSN1(ret, line_node, putobject, str);
     }
@@ -5617,7 +5617,7 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const
         lfinish[0] = NEW_LABEL(line);
         lfinish[1] = 0;
         lfinish[2] = 0;
-        defined_expr(iseq, ret, node->nd_head, lfinish, needstr);
+        defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr);
         if (lfinish[1]) {
             ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link);
             ADD_INSN(ret, line_node, swap);
@@ -5741,10 +5741,10 @@ check_keyword(const NODE *node)
     /* This check is essentially a code clone of compile_keyword_arg. */
 
     if (nd_type_p(node, NODE_LIST)) {
-        while (node->nd_next) {
-            node = node->nd_next;
+        while (RNODE_LIST(node)->nd_next) {
+            node = RNODE_LIST(node)->nd_next;
         }
-        node = node->nd_head;
+        node = RNODE_LIST(node)->nd_head;
     }
 
     return keyword_node_p(node);
@@ -5756,9 +5756,9 @@ keyword_node_single_splat_p(NODE *kwnode)
 {
     RUBY_ASSERT(keyword_node_p(kwnode));
 
-    NODE *node = kwnode->nd_head;
-    return node->nd_head == NULL &&
-           node->nd_next->nd_next == NULL;
+    NODE *node = RNODE_HASH(kwnode)->nd_head;
+    return RNODE_LIST(node)->nd_head == NULL &&
+           RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next == NULL;
 }
 
 static int
@@ -5788,7 +5788,7 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
       }
       case NODE_SPLAT: {
           // f(*a)
-          NO_CHECK(COMPILE(args, "args (splat)", argn->nd_head));
+          NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
           ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
           if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
           RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
@@ -5796,19 +5796,19 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
       }
       case NODE_ARGSCAT: {
           if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
-          int argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
+          int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
 
-          if (nd_type_p(argn->nd_body, NODE_LIST)) {
-              int rest_len = compile_args(iseq, args, argn->nd_body, &kwnode);
+          if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
+              int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode);
               if (kwnode) rest_len--;
               ADD_INSN1(args, argn, newarray, INT2FIX(rest_len));
           }
           else {
-              RUBY_ASSERT(!check_keyword(argn->nd_body));
-              NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body));
+              RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body));
+              NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSCAT(argn)->nd_body));
           }
 
-          if (nd_type_p(argn->nd_head, NODE_LIST)) {
+          if (nd_type_p(RNODE_ARGSCAT(argn)->nd_head, NODE_LIST)) {
               ADD_INSN1(args, argn, splatarray, Qtrue);
               argc += 1;
           }
@@ -5830,21 +5830,21 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
       }
       case NODE_ARGSPUSH: {
           if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
-          int argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL);
+          int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
 
-          if (nd_type_p(argn->nd_body, NODE_LIST)) {
-              int rest_len = compile_args(iseq, args, argn->nd_body, &kwnode);
+          if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
+              int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode);
               if (kwnode) rest_len--;
               ADD_INSN1(args, argn, newarray, INT2FIX(rest_len));
               ADD_INSN1(args, argn, newarray, INT2FIX(1));
               ADD_INSN(args, argn, concatarray);
           }
           else {
-              if (keyword_node_p(argn->nd_body)) {
-                  kwnode = argn->nd_body;
+              if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) {
+                  kwnode = RNODE_ARGSPUSH(argn)->nd_body;
               }
               else {
-                  NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body));
+                  NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body));
                   ADD_INSN1(args, argn, newarray, INT2FIX(1));
                   ADD_INSN(args, argn, concatarray);
               }
@@ -5877,7 +5877,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
         unsigned int dup_rest = 1;
         DECL_ANCHOR(arg_block);
         INIT_ANCHOR(arg_block);
-        NO_CHECK(COMPILE(arg_block, "block", argn->nd_body));
+        NO_CHECK(COMPILE(arg_block, "block", RNODE_BLOCK_PASS(argn)->nd_body));
 
         *flag |= VM_CALL_ARGS_BLOCKARG;
 
@@ -5891,7 +5891,7 @@ setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
                 dup_rest = 0;
             }
         }
-        ret = INT2FIX(setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords));
+        ret = INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, dup_rest, flag, keywords));
         ADD_SEQ(args, arg_block);
     }
     else {
@@ -5931,19 +5931,19 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
     ADD_INSN(ret, line_node, dup);
     ADD_INSNL(ret, line_node, branchunless, fail_label);
 
-    for (vars = node; vars; vars = vars->nd_next) {
+    for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
         INSN *cap;
-        if (vars->nd_next) {
+        if (RNODE_BLOCK(vars)->nd_next) {
             ADD_INSN(ret, line_node, dup);
         }
         last = ret->last;
-        NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head));
+        NO_CHECK(COMPILE_POPPED(ret, "capture", RNODE_BLOCK(vars)->nd_head));
         last = last->next; /* putobject :var */
         cap = new_insn_send(iseq, line_node, idAREF, INT2FIX(1),
                             NULL, INT2FIX(0), NULL);
         ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap);
 #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0
-        if (!vars->nd_next && vars == node) {
+        if (!RNODE_BLOCK(vars)->nd_next && vars == node) {
             /* only one name */
             DECL_ANCHOR(nom);
 
@@ -5964,9 +5964,9 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
     ADD_INSNL(ret, line_node, jump, end_label);
     ADD_LABEL(ret, fail_label);
     ADD_INSN(ret, line_node, pop);
-    for (vars = node; vars; vars = vars->nd_next) {
+    for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) {
         last = ret->last;
-        NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head));
+        NO_CHECK(COMPILE_POPPED(ret, "capture", RNODE_BLOCK(vars)->nd_head));
         last = last->next; /* putobject :var */
         ((INSN*)last)->insn_id = BIN(putnil);
         ((INSN*)last)->operand_size = 0;
@@ -5980,7 +5980,7 @@ optimizable_range_item_p(const NODE *n)
     if (!n) return FALSE;
     switch (nd_type(n)) {
       case NODE_LIT:
-        return RB_INTEGER_TYPE_P(n->nd_lit);
+        return RB_INTEGER_TYPE_P(RNODE_LIT(n)->nd_lit);
       case NODE_NIL:
         return TRUE;
       default:
@@ -5991,8 +5991,8 @@ optimizable_range_item_p(const NODE *n)
 static int
 compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type)
 {
-    const NODE *const node_body = type == NODE_IF ? node->nd_body : node->nd_else;
-    const NODE *const node_else = type == NODE_IF ? node->nd_else : node->nd_body;
+    const NODE *const node_body = type == NODE_IF ? RNODE_IF(node)->nd_body : RNODE_UNLESS(node)->nd_else;
+    const NODE *const node_else = type == NODE_IF ? RNODE_IF(node)->nd_else : RNODE_UNLESS(node)->nd_body;
 
     const int line = nd_line(node);
     const NODE *line_node = node;
@@ -6005,7 +6005,7 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
     else_label = NEW_LABEL(line);
     end_label = 0;
 
-    compile_branch_condition(iseq, cond_seq, node->nd_cond, then_label, else_label);
+    compile_branch_condition(iseq, cond_seq, RNODE_IF(node)->nd_cond, then_label, else_label);
     ADD_SEQ(ret, cond_seq);
 
     if (then_label->refcnt && else_label->refcnt) {
@@ -6085,11 +6085,11 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
 
     RHASH_TBL_RAW(literals)->type = &cdhash_type;
 
-    CHECK(COMPILE(head, "case base", node->nd_head));
+    CHECK(COMPILE(head, "case base", RNODE_CASE(node)->nd_head));
 
     branches = decl_branch_base(iseq, node, "case");
 
-    node = node->nd_body;
+    node = RNODE_CASE(node)->nd_body;
     EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG);
     type = nd_type(node);
     line = nd_line(node);
@@ -6109,14 +6109,14 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
         add_trace_branch_coverage(
                 iseq,
                 body_seq,
-                node->nd_body ? node->nd_body : node,
+                RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
                 branch_id++,
                 "when",
                 branches);
-        CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped));
+        CHECK(COMPILE_(body_seq, "when body", RNODE_WHEN(node)->nd_body, popped));
         ADD_INSNL(body_seq, line_node, jump, endlabel);
 
-        vals = node->nd_head;
+        vals = RNODE_WHEN(node)->nd_head;
         if (vals) {
             switch (nd_type(vals)) {
               case NODE_LIST:
@@ -6137,7 +6137,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
             EXPECT_NODE_NONULL("NODE_CASE", node, NODE_LIST, COMPILE_NG);
         }
 
-        node = node->nd_next;
+        node = RNODE_WHEN(node)->nd_next;
         if (!node) {
             break;
         }
@@ -6182,7 +6182,7 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
 {
     const NODE *vals;
     const NODE *val;
-    const NODE *node = orig_node->nd_body;
+    const NODE *node = RNODE_CASE2(orig_node)->nd_body;
     LABEL *endlabel;
     DECL_ANCHOR(body_seq);
     VALUE branches = Qfalse;
@@ -6200,14 +6200,14 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
         add_trace_branch_coverage(
                 iseq,
                 body_seq,
-                node->nd_body ? node->nd_body : node,
+                RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node,
                 branch_id++,
                 "when",
                 branches);
-        CHECK(COMPILE_(body_seq, "when", node->nd_body, popped));
+        CHECK(COMPILE_(body_seq, "when", RNODE_WHEN(node)->nd_body, popped));
         ADD_INSNL(body_seq, node, jump, endlabel);
 
-        vals = node->nd_head;
+        vals = RNODE_WHEN(node)->nd_head;
         if (!vals) {
             EXPECT_NODE_NONULL("NODE_WHEN", node, NODE_LIST, COMPILE_NG);
         }
@@ -6215,12 +6215,12 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
           case NODE_LIST:
             while (vals) {
                 LABEL *lnext;
-                val = vals->nd_head;
+                val = RNODE_LIST(vals)->nd_head;
                 lnext = NEW_LABEL(nd_line(val));
                 debug_compile("== when2\n", (void)0);
                 CHECK(compile_branch_condition(iseq, ret, val, l1, lnext));
                 ADD_LABEL(ret, lnext);
-                vals = vals->nd_next;
+                vals = RNODE_LIST(vals)->nd_next;
             }
             break;
           case NODE_SPLAT:
@@ -6234,7 +6234,7 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
           default:
             UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG);
         }
-        node = node->nd_next;
+        node = RNODE_WHEN(node)->nd_next;
     }
     /* else */
     add_trace_branch_coverage(
@@ -6326,10 +6326,10 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
          * match_failed:
          *   goto unmatched
          */
-        struct rb_ary_pattern_info *apinfo = node->nd_apinfo;
+        struct rb_ary_pattern_info *apinfo = RNODE_ARYPTN(node)->nd_apinfo;
         const NODE *args = apinfo->pre_args;
-        const int pre_args_num = apinfo->pre_args ? rb_long2int(apinfo->pre_args->nd_alen) : 0;
-        const int post_args_num = apinfo->post_args ? rb_long2int(apinfo->post_args->nd_alen) : 0;
+        const int pre_args_num = apinfo->pre_args ? rb_long2int(RNODE_LIST(apinfo->pre_args)->as.nd_alen) : 0;
+        const int post_args_num = apinfo->post_args ? rb_long2int(RNODE_LIST(apinfo->post_args)->as.nd_alen) : 0;
 
         const int min_argc = pre_args_num + post_args_num;
         const int use_rest_num = apinfo->rest_arg && (NODE_NAMED_REST_P(apinfo->rest_arg) ||
@@ -6370,8 +6370,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
             ADD_INSN(ret, line_node, dup);
             ADD_INSN1(ret, line_node, putobject, INT2FIX(i));
             ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (2)
-            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false));
-            args = args->nd_next;
+            CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false));
+            args = RNODE_LIST(args)->nd_next;
         }
 
         if (apinfo->rest_arg) {
@@ -6408,8 +6408,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
             ADD_SEND(ret, line_node, idPLUS, INT2FIX(1));
 
             ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (4)
-            CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false));
-            args = args->nd_next;
+            CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false));
+            args = RNODE_LIST(args)->nd_next;
         }
 
         ADD_INSN(ret, line_node, pop);
@@ -6487,9 +6487,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
          * match_failed:
          *   goto unmatched
          */
-        struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo;
+        struct rb_fnd_pattern_info *fpinfo = RNODE_FNDPTN(node)->nd_fpinfo;
         const NODE *args = fpinfo->args;
-        const int args_num = fpinfo->args ? rb_long2int(fpinfo->args->nd_alen) : 0;
+        const int args_num = fpinfo->args ? rb_long2int(RNODE_LIST(fpinfo->args)->as.nd_alen) : 0;
 
         LABEL *match_failed, *type_error, *deconstruct, *deconstructed;
         match_failed = NEW_LABEL(line);
@@ -6542,8 +6542,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
                 }
                 ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (5)
 
-                CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (5) */, false));
-                args = args->nd_next;
+                CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (5) */, false));
+                args = RNODE_LIST(args)->nd_next;
             }
 
             if (NODE_NAMED_REST_P(fpinfo->pre_rest_arg)) {
@@ -6674,12 +6674,12 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
         match_failed = NEW_LABEL(line);
         type_error = NEW_LABEL(line);
 
-        if (node->nd_pkwargs && !node->nd_pkwrestarg) {
-            const NODE *kw_args = node->nd_pkwargs->nd_head;
-            keys = rb_ary_new_capa(kw_args ? kw_args->nd_alen/2 : 0);
+        if (RNODE_HSHPTN(node)->nd_pkwargs && !RNODE_HSHPTN(node)->nd_pkwrestarg) {
+            const NODE *kw_args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
+            keys = rb_ary_new_capa(kw_args ? RNODE_LIST(kw_args)->as.nd_alen/2 : 0);
             while (kw_args) {
-                rb_ary_push(keys, kw_args->nd_head->nd_lit);
-                kw_args = kw_args->nd_next->nd_next;
+                rb_ary_push(keys, RNODE_LIT(RNODE_LIST(kw_args)->nd_head)->nd_lit);
+                kw_args = RNODE_LIST(RNODE_LIST(kw_args)->nd_next)->nd_next;
             }
         }
 
@@ -6706,28 +6706,28 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
         ADD_INSN1(ret, line_node, checktype, INT2FIX(T_HASH));
         ADD_INSNL(ret, line_node, branchunless, type_error);
 
-        if (node->nd_pkwrestarg) {
+        if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
             ADD_SEND(ret, line_node, rb_intern("dup"), INT2FIX(0));
         }
 
-        if (node->nd_pkwargs) {
+        if (RNODE_HSHPTN(node)->nd_pkwargs) {
             int i;
             int keys_num;
             const NODE *args;
-            args = node->nd_pkwargs->nd_head;
+            args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head;
             if (args) {
                 DECL_ANCHOR(match_values);
                 INIT_ANCHOR(match_values);
-                keys_num = rb_long2int(args->nd_alen) / 2;
+                keys_num = rb_long2int(RNODE_LIST(args)->as.nd_alen) / 2;
                 for (i = 0; i < keys_num; i++) {
-                    NODE *key_node = args->nd_head;
-                    NODE *value_node = args->nd_next->nd_head;
+                    NODE *key_node = RNODE_LIST(args)->nd_head;
+                    NODE *value_node = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_head;
                     VALUE key;
 
                     if (!nd_type_p(key_node, NODE_LIT)) {
                         UNKNOWN_NODE("NODE_IN", key_node, COMPILE_NG);
                     }
-                    key = key_node->nd_lit;
+                    key = RNODE_LIT(key_node)->nd_lit;
 
                     ADD_INSN(ret, line_node, dup);
                     ADD_INSN1(ret, line_node, putobject, key);
@@ -6756,9 +6756,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
 
                     ADD_INSN(match_values, line_node, dup);
                     ADD_INSN1(match_values, line_node, putobject, key);
-                    ADD_SEND(match_values, line_node, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); // (8)
+                    ADD_SEND(match_values, line_node, RNODE_HSHPTN(node)->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); // (8)
                     CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (8) */, false));
-                    args = args->nd_next->nd_next;
+                    args = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_next;
                 }
                 ADD_SEQ(ret, match_values);
             }
@@ -6772,8 +6772,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
             ADD_INSNL(ret, line_node, branchunless, match_failed);
         }
 
-        if (node->nd_pkwrestarg) {
-            if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
+        if (RNODE_HSHPTN(node)->nd_pkwrestarg) {
+            if (RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
                 ADD_INSN(ret, line_node, dup);
                 ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (10)
                 if (in_single_pattern) {
@@ -6783,7 +6783,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
             }
             else {
                 ADD_INSN(ret, line_node, dup); // (11)
-                CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (11) */, false));
+                CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_HSHPTN(node)->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (11) */, false));
             }
         }
 
@@ -6840,7 +6840,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
         break;
       case NODE_LASGN: {
         struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
-        ID id = node->nd_vid;
+        ID id = RNODE_LASGN(node)->nd_vid;
         int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id);
 
         if (in_alt_pattern) {
@@ -6858,7 +6858,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
       }
       case NODE_DASGN: {
         int idx, lv, ls;
-        ID id = node->nd_vid;
+        ID id = RNODE_DASGN(node)->nd_vid;
 
         idx = get_dyna_var_idx(iseq, id, &lv, &ls);
 
@@ -6884,8 +6884,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
       case NODE_UNLESS: {
         LABEL *match_failed;
         match_failed = unmatched;
-        CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
-        CHECK(COMPILE(ret, "case in if", node->nd_cond));
+        CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_IF(node)->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache));
+        CHECK(COMPILE(ret, "case in if", RNODE_IF(node)->nd_cond));
         if (in_single_pattern) {
             LABEL *match_succeeded;
             match_succeeded = NEW_LABEL(line);
@@ -6922,15 +6922,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
         LABEL *match_failed;
         match_failed = NEW_LABEL(line);
 
-        n = node->nd_head;
-        if (! (nd_type_p(n, NODE_LIST) && n->nd_alen == 2)) {
+        n = RNODE_HASH(node)->nd_head;
+        if (! (nd_type_p(n, NODE_LIST) && RNODE_LIST(n)->as.nd_alen == 2)) {
             COMPILE_ERROR(ERROR_ARGS "unexpected node");
             return COMPILE_NG;
         }
 
         ADD_INSN(ret, line_node, dup); // (1)
-        CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (1) */, use_deconstructed_cache));
-        CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index, false));
+        CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(n)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (1) */, use_deconstructed_cache));
+        CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index, false));
         ADD_INSN(ret, line_node, putnil);
 
         ADD_LABEL(ret, match_failed);
@@ -6944,13 +6944,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
         fin = NEW_LABEL(line);
 
         ADD_INSN(ret, line_node, dup); // (1)
-        CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, in_single_pattern, true, base_index + 1 /* (1) */, use_deconstructed_cache));
+        CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_1st, match_succeeded, fin, in_single_pattern, true, base_index + 1 /* (1) */, use_deconstructed_cache));
         ADD_LABEL(ret, match_succeeded);
         ADD_INSN(ret, line_node, pop);
         ADD_INSNL(ret, line_node, jump, matched);
         ADD_INSN(ret, line_node, putnil);
         ADD_LABEL(ret, fin);
-        CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, in_single_pattern, true, base_index, use_deconstructed_cache));
+        CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_2nd, matched, unmatched, in_single_pattern, true, base_index, use_deconstructed_cache));
         break;
       }
       default:
@@ -6973,9 +6973,9 @@ iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
 {
     const NODE *line_node = node;
 
-    if (node->nd_pconst) {
+    if (RNODE_ARYPTN(node)->nd_pconst) {
         ADD_INSN(ret, line_node, dup); // (1)
-        CHECK(COMPILE(ret, "constant", node->nd_pconst)); // (2)
+        CHECK(COMPILE(ret, "constant", RNODE_ARYPTN(node)->nd_pconst)); // (2)
         if (in_single_pattern) {
             ADD_INSN1(ret, line_node, dupn, INT2FIX(2));
         }
@@ -7178,12 +7178,12 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
 
     branches = decl_branch_base(iseq, node, "case");
 
-    node = node->nd_body;
+    node = RNODE_CASE3(node)->nd_body;
     EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG);
     type = nd_type(node);
     line = nd_line(node);
     line_node = node;
-    single_pattern = !node->nd_next;
+    single_pattern = !RNODE_IN(node)->nd_next;
 
     endlabel = NEW_LABEL(line);
     elselabel = NEW_LABEL(line);
@@ -7197,7 +7197,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
     }
     ADD_INSN(head, line_node, putnil); /* allocate stack for cached #deconstruct value */
 
-    CHECK(COMPILE(head, "case base", orig_node->nd_head));
+    CHECK(COMPILE(head, "case base", RNODE_CASE3(orig_node)->nd_head));
 
     ADD_SEQ(ret, head);        /* case VAL */
 
@@ -7213,14 +7213,14 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
         add_trace_branch_coverage(
             iseq,
             body_seq,
-            node->nd_body ? node->nd_body : node,
+            RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node,
             branch_id++,
             "in",
             branches);
-        CHECK(COMPILE_(body_seq, "in body", node->nd_body, popped));
+        CHECK(COMPILE_(body_seq, "in body", RNODE_IN(node)->nd_body, popped));
         ADD_INSNL(body_seq, line_node, jump, endlabel);
 
-        pattern = node->nd_head;
+        pattern = RNODE_IN(node)->nd_head;
         if (pattern) {
             int pat_line = nd_line(pattern);
             LABEL *next_pat = NEW_LABEL(pat_line);
@@ -7235,7 +7235,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
             return COMPILE_NG;
         }
 
-        node = node->nd_next;
+        node = RNODE_IN(node)->nd_next;
         if (!node) {
             break;
         }
@@ -7360,7 +7360,7 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
     ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0;
     push_ensure_entry(iseq, &enl, NULL, NULL);
 
-    if (node->nd_state == 1) {
+    if (RNODE_WHILE(node)->nd_state == 1) {
         ADD_INSNL(ret, line_node, jump, next_label);
     }
     else {
@@ -7379,27 +7379,27 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
     add_trace_branch_coverage(
         iseq,
         ret,
-        node->nd_body ? node->nd_body : node,
+        RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node,
         0,
         "body",
         branches);
-    CHECK(COMPILE_POPPED(ret, "while body", node->nd_body));
+    CHECK(COMPILE_POPPED(ret, "while body", RNODE_WHILE(node)->nd_body));
     ADD_LABEL(ret, next_label);        /* next */
 
     if (type == NODE_WHILE) {
-        compile_branch_condition(iseq, ret, node->nd_cond,
+        compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
                                  redo_label, end_label);
     }
     else {
         /* until */
-        compile_branch_condition(iseq, ret, node->nd_cond,
+        compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
                                  end_label, redo_label);
     }
 
     ADD_LABEL(ret, end_label);
     ADD_ADJUST_RESTORE(ret, adjust_label);
 
-    if (UNDEF_P(node->nd_state)) {
+    if (UNDEF_P(RNODE_WHILE(node)->nd_state)) {
         /* ADD_INSN(ret, line_node, putundef); */
         COMPILE_ERROR(ERROR_ARGS "unsupported: putundef");
         return COMPILE_NG;
@@ -7441,18 +7441,18 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
 
     ADD_LABEL(ret, retry_label);
     if (nd_type_p(node, NODE_FOR)) {
-        CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter));
+        CHECK(COMPILE(ret, "iter caller (for)", RNODE_FOR(node)->nd_iter));
 
         ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
-            NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
+            NEW_CHILD_ISEQ(RNODE_FOR(node)->nd_body, make_name_for_block(iseq),
                            ISEQ_TYPE_BLOCK, line);
         ADD_SEND_WITH_BLOCK(ret, line_node, idEach, INT2FIX(0), child_iseq);
     }
     else {
         ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq =
-            NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq),
+            NEW_CHILD_ISEQ(RNODE_ITER(node)->nd_body, make_name_for_block(iseq),
                            ISEQ_TYPE_BLOCK, line);
-        CHECK(COMPILE(ret, "iter caller", node->nd_iter));
+        CHECK(COMPILE(ret, "iter caller", RNODE_ITER(node)->nd_iter));
     }
 
     {
@@ -7496,7 +7496,7 @@ compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod
      * (args.length == 1 && Array.try_convert(args[0])) || args
      */
     const NODE *line_node = node;
-    const NODE *var = node->nd_var;
+    const NODE *var = RNODE_FOR_MASGN(node)->nd_var;
     LABEL *not_single = NEW_LABEL(nd_line(var));
     LABEL *not_ary = NEW_LABEL(nd_line(var));
     CHECK(COMPILE(ret, "for var", var));
@@ -7531,7 +7531,7 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
         LABEL *splabel = NEW_LABEL(0);
         ADD_LABEL(ret, splabel);
         ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
-        CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts,
+        CHECK(COMPILE_(ret, "break val (while/until)", RNODE_BREAK(node)->nd_stts,
                        ISEQ_COMPILE_DATA(iseq)->loopval_popped));
         add_ensure_iseq(ret, iseq, 0);
         ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
@@ -7566,7 +7566,7 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
             }
 
             /* escape from block */
-            CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
+            CHECK(COMPILE(ret, "break val (block)", RNODE_BREAK(node)->nd_stts));
             ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_BREAK));
             if (popped) {
                 ADD_INSN(ret, line_node, pop);
@@ -7589,7 +7589,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
         LABEL *splabel = NEW_LABEL(0);
         debugs("next in while loop\n");
         ADD_LABEL(ret, splabel);
-        CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts));
+        CHECK(COMPILE(ret, "next val/valid syntax?", RNODE_NEXT(node)->nd_stts));
         add_ensure_iseq(ret, iseq, 0);
         ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label);
         ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
@@ -7603,7 +7603,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
         debugs("next in block\n");
         ADD_LABEL(ret, splabel);
         ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label);
-        CHECK(COMPILE(ret, "next val", node->nd_stts));
+        CHECK(COMPILE(ret, "next val", RNODE_NEXT(node)->nd_stts));
         add_ensure_iseq(ret, iseq, 0);
         ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
         ADD_ADJUST_RESTORE(ret, splabel);
@@ -7638,7 +7638,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
             ip = ISEQ_BODY(ip)->parent_iseq;
         }
         if (ip != 0) {
-            CHECK(COMPILE(ret, "next val", node->nd_stts));
+            CHECK(COMPILE(ret, "next val", RNODE_NEXT(node)->nd_stts));
             ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_NEXT));
 
             if (popped) {
@@ -7750,7 +7750,7 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     LABEL *lstart = NEW_LABEL(line);
     LABEL *lend = NEW_LABEL(line);
     LABEL *lcont = NEW_LABEL(line);
-    const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq,
+    const rb_iseq_t *rescue = NEW_CHILD_ISEQ(RNODE_RESCUE(node)->nd_resq,
                                              rb_str_concat(rb_str_new2("rescue in "),
                                                            ISEQ_BODY(iseq)->location.label),
                                              ISEQ_TYPE_RESCUE, line);
@@ -7762,14 +7762,14 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue;
     ISEQ_COMPILE_DATA(iseq)->in_rescue = true;
     {
-        CHECK(COMPILE(ret, "rescue head", node->nd_head));
+        CHECK(COMPILE(ret, "rescue head", RNODE_RESCUE(node)->nd_head));
     }
     ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;
 
     ADD_LABEL(ret, lend);
-    if (node->nd_else) {
+    if (RNODE_RESCUE(node)->nd_else) {
         ADD_INSN(ret, line_node, pop);
-        CHECK(COMPILE(ret, "rescue else", node->nd_else));
+        CHECK(COMPILE(ret, "rescue else", RNODE_RESCUE(node)->nd_else));
     }
     ADD_INSN(ret, line_node, nop);
     ADD_LABEL(ret, lcont);
@@ -7797,16 +7797,16 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
         label_miss = NEW_LABEL(line);
         label_hit = NEW_LABEL(line);
 
-        narg = resq->nd_args;
+        narg = RNODE_RESBODY(resq)->nd_args;
         if (narg) {
             switch (nd_type(narg)) {
               case NODE_LIST:
                 while (narg) {
                     ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0);
-                    CHECK(COMPILE(ret, "rescue arg", narg->nd_head));
+                    CHECK(COMPILE(ret, "rescue arg", RNODE_LIST(narg)->nd_head));
                     ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
                     ADD_INSNL(ret, line_node, branchif, label_hit);
-                    narg = narg->nd_next;
+                    narg = RNODE_LIST(narg)->nd_next;
                 }
                 break;
               case NODE_SPLAT:
@@ -7831,14 +7831,14 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
         ADD_LABEL(ret, label_hit);
         ADD_TRACE(ret, RUBY_EVENT_RESCUE);
 
-        if (nd_type(resq->nd_body) == NODE_BEGIN && resq->nd_body->nd_body == NULL) {
+        if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL) {
             // empty body
-            int lineno = nd_line(resq->nd_body);
+            int lineno = nd_line(RNODE_RESBODY(resq)->nd_body);
             NODE dummy_line_node = generate_dummy_line_node(lineno, -1);
             ADD_INSN(ret, &dummy_line_node, putnil);
         }
         else {
-            CHECK(COMPILE(ret, "resbody body", resq->nd_body));
+            CHECK(COMPILE(ret, "resbody body", RNODE_RESBODY(resq)->nd_body));
         }
 
         if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) {
@@ -7846,7 +7846,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
         }
         ADD_INSN(ret, line_node, leave);
         ADD_LABEL(ret, label_miss);
-        resq = resq->nd_head;
+        resq = RNODE_RESBODY(resq)->nd_head;
     }
     return COMPILE_OK;
 }
@@ -7857,7 +7857,7 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     const int line = nd_line(node);
     const NODE *line_node = node;
     DECL_ANCHOR(ensr);
-    const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr,
+    const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr,
                                              rb_str_concat(rb_str_new2 ("ensure in "), ISEQ_BODY(iseq)->location.label),
                                              ISEQ_TYPE_ENSURE, line);
     LABEL *lstart = NEW_LABEL(line);
@@ -7870,17 +7870,17 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     struct ensure_range *erange;
 
     INIT_ANCHOR(ensr);
-    CHECK(COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr));
+    CHECK(COMPILE_POPPED(ensr, "ensure ensr", RNODE_ENSURE(node)->nd_ensr));
     last = ensr->last;
     last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
 
     er.begin = lstart;
     er.end = lend;
     er.next = 0;
-    push_ensure_entry(iseq, &enl, &er, node->nd_ensr);
+    push_ensure_entry(iseq, &enl, &er, RNODE_ENSURE(node)->nd_ensr);
 
     ADD_LABEL(ret, lstart);
-    CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave)));
+    CHECK(COMPILE_(ret, "ensure head", RNODE_ENSURE(node)->nd_head, (popped | last_leave)));
     ADD_LABEL(ret, lend);
     ADD_SEQ(ret, ensr);
     if (!popped && last_leave) ADD_INSN(ret, line_node, putnil);
@@ -7909,7 +7909,7 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
         enum rb_iseq_type type = ISEQ_BODY(iseq)->type;
         const rb_iseq_t *is = iseq;
         enum rb_iseq_type t = type;
-        const NODE *retval = node->nd_stts;
+        const NODE *retval = RNODE_RETURN(node)->nd_stts;
         LABEL *splabel = 0;
 
         while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) {
@@ -8018,13 +8018,13 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
     /* optimization shortcut
      *   "literal".freeze -> opt_str_freeze("literal")
      */
-    if (node->nd_recv && nd_type_p(node->nd_recv, NODE_STR) &&
-        (node->nd_mid == idFreeze || node->nd_mid == idUMinus) &&
-        node->nd_args == NULL &&
+    if (RNODE_CALL(node)->nd_recv && nd_type_p(RNODE_CALL(node)->nd_recv, NODE_STR) &&
+        (RNODE_CALL(node)->nd_mid == idFreeze || RNODE_CALL(node)->nd_mid == idUMinus) &&
+        RNODE_CALL(node)->nd_args == NULL &&
         ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
         ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
-        VALUE str = rb_fstring(node->nd_recv->nd_lit);
-        if (node->nd_mid == idUMinus) {
+        VALUE str = rb_fstring(RNODE_STR(RNODE_CALL(node)->nd_recv)->nd_lit);
+        if (RNODE_CALL(node)->nd_mid == idUMinus) {
             ADD_INSN2(ret, line_node, opt_str_uminus, str,
                       new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
         }
@@ -8041,14 +8041,14 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
     /* optimization shortcut
      *   obj["literal"] -> opt_aref_with(obj, "literal")
      */
-    if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
-        nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 1 &&
-        nd_type_p(node->nd_args->nd_head, NODE_STR) &&
+    if (RNODE_CALL(node)->nd_mid == idAREF && !private_recv_p(node) && RNODE_CALL(node)->nd_args &&
+        nd_type_p(RNODE_CALL(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_CALL(node)->nd_args)->as.nd_alen == 1 &&
+        nd_type_p(RNODE_LIST(RNODE_CALL(node)->nd_args)->nd_head, NODE_STR) &&
         ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
         !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
         ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
-        VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
-        CHECK(COMPILE(ret, "recv", node->nd_recv));
+        VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(RNODE_CALL(node)->nd_args)->nd_head)->nd_lit);
+        CHECK(COMPILE(ret, "recv", RNODE_CALL(node)->nd_recv));
         ADD_INSN2(ret, line_node, opt_aref_with, str,
                   new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
         RB_OBJ_WRITTEN(iseq, Qundef, str);
@@ -8091,12 +8091,12 @@ iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid)
         if (recv) {
             switch (nd_type(recv)) {
               case NODE_VCALL:
-                if (recv->nd_mid == rb_intern("__builtin")) {
+                if (RNODE_VCALL(recv)->nd_mid == rb_intern("__builtin")) {
                     return name;
                 }
                 break;
               case NODE_CONST:
-                if (recv->nd_vid == rb_intern("Primitive")) {
+                if (RNODE_CONST(recv)->nd_vid == rb_intern("Primitive")) {
                     return name;
                 }
                 break;
@@ -8186,13 +8186,13 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
     if (!node) goto no_arg;
     while (node) {
         if (!nd_type_p(node, NODE_LIST)) goto bad_arg;
-        const NODE *next = node->nd_next;
+        const NODE *next = RNODE_LIST(node)->nd_next;
 
-        node = node->nd_head;
+        node = RNODE_LIST(node)->nd_head;
         if (!node) goto no_arg;
         if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
 
-        symbol = node->nd_lit;
+        symbol = RNODE_LIT(node)->nd_lit;
         if (!SYMBOL_P(symbol)) goto non_symbol_arg;
 
         string = rb_sym_to_s(symbol);
@@ -8226,11 +8226,11 @@ compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, c
 {
     if (!node) goto no_arg;
     if (!nd_type_p(node, NODE_LIST)) goto bad_arg;
-    if (node->nd_next) goto too_many_arg;
-    node = node->nd_head;
+    if (RNODE_LIST(node)->nd_next) goto too_many_arg;
+    node = RNODE_LIST(node)->nd_head;
     if (!node) goto no_arg;
     if (!nd_type_p(node, NODE_LIT)) goto bad_arg;
-    VALUE name = node->nd_lit;
+    VALUE name = RNODE_LIT(node)->nd_lit;
     if (!SYMBOL_P(name)) goto non_symbol_arg;
     if (!popped) {
         compile_lvar(iseq, ret, line_node, SYM2ID(name));
@@ -8254,8 +8254,8 @@ static NODE *
 mandatory_node(const rb_iseq_t *iseq, const NODE *cond_node)
 {
     const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node;
-    if (nd_type(node) == NODE_IF && node->nd_cond == cond_node) {
-        return node->nd_body;
+    if (nd_type(node) == NODE_IF && RNODE_IF(node)->nd_cond == cond_node) {
+        return RNODE_IF(node)->nd_body;
     }
     else {
         rb_bug("mandatory_node: can't find mandatory node");
@@ -8269,8 +8269,11 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
     struct rb_args_info args = {
         .pre_args_num = ISEQ_BODY(iseq)->param.lead_num,
     };
-    NODE args_node;
-    rb_node_init(&args_node, NODE_ARGS, 0, 0, (VALUE)&args);
+    rb_node_args_t args_node;
+    rb_node_init(RNODE(&args_node), NODE_ARGS);
+    args_node.not_used = 0;
+    args_node.not_used2 = 0;
+    args_node.nd_ainfo = &args;
 
     // local table without non-mandatory parameters
     const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num;
@@ -8291,11 +8294,14 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
         tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size];
     }
 
-    NODE scope_node;
-    rb_node_init(&scope_node, NODE_SCOPE, (VALUE)tbl, (VALUE)mandatory_node(iseq, node), (VALUE)&args_node);
+    rb_node_scope_t scope_node;
+    rb_node_init(RNODE(&scope_node), NODE_SCOPE);
+    scope_node.nd_tbl = tbl;
+    scope_node.nd_body = mandatory_node(iseq, node);
+    scope_node.nd_args = RNODE(&args_node);
 
     rb_ast_body_t ast = {
-        .root = &scope_node,
+        .root = RNODE(&scope_node),
         .frozen_string_literal = -1,
         .coverage_enabled = -1,
         .script_lines = ISEQ_BODY(iseq)->variable.script_lines,
@@ -8315,7 +8321,7 @@ static int
 compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped,
                               const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func)
 {
-    NODE *args_node = node->nd_args;
+    NODE *args_node = RNODE_QCALL(node)->nd_args;
 
     if (parent_block != NULL) {
         COMPILE_ERROR(ERROR_ARGS_AT(line_node) "should not call builtins here.");
@@ -8418,7 +8424,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
      */
     DECL_ANCHOR(recv);
     DECL_ANCHOR(args);
-    ID mid = node->nd_mid;
+    ID mid = RNODE_CALL(node)->nd_mid;
     VALUE argc;
     unsigned int flag = 0;
     struct rb_callinfo_kwarg *keywords = NULL;
@@ -8497,7 +8503,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
 
     const char *builtin_func;
     if (UNLIKELY(iseq_has_builtin_function_table(iseq)) &&
-        (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) {
+        (builtin_func = iseq_builtin_function_name(type, RNODE_CALL(node)->nd_recv, mid)) != NULL) {
         return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func);
     }
 
@@ -8507,16 +8513,16 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
             int idx, level;
 
             if (mid == idCall &&
-                nd_type_p(node->nd_recv, NODE_LVAR) &&
-                iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) {
-                ADD_INSN2(recv, node->nd_recv, getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
+                nd_type_p(RNODE_CALL(node)->nd_recv, NODE_LVAR) &&
+                iseq_block_param_id_p(iseq, RNODE_LVAR(RNODE_CALL(node)->nd_recv)->nd_vid, &idx, &level)) {
+                ADD_INSN2(recv, RNODE_CALL(node)->nd_recv, getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
             }
             else if (private_recv_p(node)) {
                 ADD_INSN(recv, node, putself);
                 flag |= VM_CALL_FCALL;
             }
             else {
-                CHECK(COMPILE(recv, "recv", node->nd_recv));
+                CHECK(COMPILE(recv, "recv", RNODE_CALL(node)->nd_recv));
             }
 
             if (type == NODE_QCALL) {
@@ -8530,7 +8536,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
 
     /* args */
     if (type != NODE_VCALL) {
-        argc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+        argc = setup_args(iseq, args, RNODE_CALL(node)->nd_args, &flag, &keywords);
         CHECK(!NIL_P(argc));
     }
     else {
@@ -8567,7 +8573,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     VALUE argc;
     unsigned int flag = 0;
     int asgnflag = 0;
-    ID id = node->nd_mid;
+    ID id = RNODE_OP_ASGN1(node)->nd_mid;
     int boff = 0;
 
     /*
@@ -8596,9 +8602,9 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     if (!popped) {
         ADD_INSN(ret, node, putnil);
     }
-    asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node);
+    asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node, RNODE_OP_ASGN1(node)->nd_recv);
     CHECK(asgnflag != -1);
-    switch (nd_type(node->nd_args->nd_head)) {
+    switch (nd_type(RNODE_OP_ASGN1(node)->nd_args->nd_head)) {
       case NODE_ZLIST:
         argc = INT2FIX(0);
         break;
@@ -8606,7 +8612,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         boff = 1;
         /* fall through */
       default:
-        argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL);
+        argc = setup_args(iseq, ret, RNODE_OP_ASGN1(node)->nd_args->nd_head, &flag, NULL);
         CHECK(!NIL_P(argc));
     }
     ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff));
@@ -8634,7 +8640,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         }
         ADD_INSN(ret, node, pop);
 
-        CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
+        CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", RNODE_OP_ASGN1(node)->nd_args->nd_body));
         if (!popped) {
             ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
         }
@@ -8668,7 +8674,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         ADD_LABEL(ret, lfin);
     }
     else {
-        CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body));
+        CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", RNODE_OP_ASGN1(node)->nd_args->nd_body));
         ADD_SEND(ret, node, id, INT2FIX(1));
         if (!popped) {
             ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff));
@@ -8702,8 +8708,8 @@ static int
 compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
 {
     const int line = nd_line(node);
-    ID atype = node->nd_next->nd_mid;
-    ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid);
+    ID atype = RNODE_OP_ASGN2(node)->nd_next->nd_mid;
+    ID vid = RNODE_OP_ASGN2(node)->nd_next->nd_vid, aid = rb_id_attrset(vid);
     int asgnflag;
     LABEL *lfin = NEW_LABEL(line);
     LABEL *lcfin = NEW_LABEL(line);
@@ -8761,9 +8767,9 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
 
     */
 
-    asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node);
+    asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node, RNODE_OP_ASGN2(node)->nd_recv);
     CHECK(asgnflag != -1);
-    if (node->nd_next->nd_aid) {
+    if (RNODE_OP_ASGN2(node)->nd_next->nd_aid) {
         lskip = NEW_LABEL(line);
         ADD_INSN(ret, node, dup);
         ADD_INSNL(ret, node, branchnil, lskip);
@@ -8784,7 +8790,7 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         if (!popped) {
             ADD_INSN(ret, node, pop);
         }
-        CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
+        CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
         if (!popped) {
             ADD_INSN(ret, node, swap);
             ADD_INSN1(ret, node, topn, INT2FIX(1));
@@ -8800,7 +8806,7 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         ADD_LABEL(ret, lfin);
     }
     else {
-        CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value));
+        CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value));
         ADD_SEND(ret, node, atype, INT2FIX(1));
         if (!popped) {
             ADD_INSN(ret, node, swap);
@@ -8826,21 +8832,21 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     LABEL *lassign = 0;
     ID mid;
 
-    switch (nd_type(node->nd_head)) {
+    switch (nd_type(RNODE_OP_CDECL(node)->nd_head)) {
       case NODE_COLON3:
         ADD_INSN1(ret, node, putobject, rb_cObject);
         break;
       case NODE_COLON2:
-        CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head));
+        CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", RNODE_COLON2(RNODE_OP_CDECL(node)->nd_head)->nd_head));
         break;
       default:
         COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL",
-                      ruby_node_name(nd_type(node->nd_head)));
+                      ruby_node_name(nd_type(RNODE_OP_CDECL(node)->nd_head)));
         return COMPILE_NG;
     }
-    mid = node->nd_head->nd_mid;
+    mid = RNODE_COLON2(RNODE_OP_CDECL(node)->nd_head)->nd_mid;
     /* cref */
-    if (node->nd_aid == idOROP) {
+    if (RNODE_OP_CDECL(node)->nd_aid == idOROP) {
         lassign = NEW_LABEL(line);
         ADD_INSN(ret, node, dup); /* cref cref */
         ADD_INSN3(ret, node, defined, INT2FIX(DEFINED_CONST_FROM),
@@ -8851,17 +8857,17 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     ADD_INSN1(ret, node, putobject, Qtrue);
     ADD_INSN1(ret, node, getconstant, ID2SYM(mid)); /* cref obj */
 
-    if (node->nd_aid == idOROP || node->nd_aid == idANDOP) {
+    if (RNODE_OP_CDECL(node)->nd_aid == idOROP || RNODE_OP_CDECL(node)->nd_aid == idANDOP) {
         lfin = NEW_LABEL(line);
         if (!popped) ADD_INSN(ret, node, dup); /* cref [obj] obj */
-        if (node->nd_aid == idOROP)
+        if (RNODE_OP_CDECL(node)->nd_aid == idOROP)
             ADD_INSNL(ret, node, branchif, lfin);
         else /* idANDOP */
             ADD_INSNL(ret, node, branchunless, lfin);
         /* cref [obj] */
         if (!popped) ADD_INSN(ret, node, pop); /* cref */
         if (lassign) ADD_LABEL(ret, lassign);
-        CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
+        CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
         /* cref value */
         if (popped)
             ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */
@@ -8875,9 +8881,9 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
         ADD_INSN(ret, node, pop); /* [value] */
     }
     else {
-        CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value));
+        CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", RNODE_OP_CDECL(node)->nd_value));
         /* cref obj value */
-        ADD_CALL(ret, node, node->nd_aid, INT2FIX(1));
+        ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1));
         /* cref value */
         ADD_INSN(ret, node, swap); /* value cref */
         if (!popped) {
@@ -8896,11 +8902,11 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     LABEL *lfin = NEW_LABEL(line);
     LABEL *lassign;
 
-    if (type == NODE_OP_ASGN_OR && !nd_type_p(node->nd_head, NODE_IVAR)) {
+    if (type == NODE_OP_ASGN_OR && !nd_type_p(RNODE_OP_ASGN_OR(node)->nd_head, NODE_IVAR)) {
         LABEL *lfinish[2];
         lfinish[0] = lfin;
         lfinish[1] = 0;
-        defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
+        defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish, Qfalse);
         lassign = lfinish[1];
         if (!lassign) {
             lassign = NEW_LABEL(line);
@@ -8911,7 +8917,7 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
         lassign = NEW_LABEL(line);
     }
 
-    CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head));
+    CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", RNODE_OP_ASGN_OR(node)->nd_head));
 
     if (!popped) {
         ADD_INSN(ret, node, dup);
@@ -8929,7 +8935,7 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     }
 
     ADD_LABEL(ret, lassign);
-    CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value, popped));
+    CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", RNODE_OP_ASGN_OR(node)->nd_value, popped));
     ADD_LABEL(ret, lfin);
     return COMPILE_OK;
 }
@@ -8947,7 +8953,7 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
     INIT_ANCHOR(args);
     ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
     if (type == NODE_SUPER) {
-        VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords);
+        VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords);
         CHECK(!NIL_P(vargc));
         argc = FIX2INT(vargc);
     }
@@ -9079,8 +9085,8 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
       default: /* valid */;
     }
 
-    if (node->nd_head) {
-        argc = setup_args(iseq, args, node->nd_head, &flag, &keywords);
+    if (RNODE_YIELD(node)->nd_head) {
+        argc = setup_args(iseq, args, RNODE_YIELD(node)->nd_head, &flag, &keywords);
         CHECK(!NIL_P(argc));
     }
     else {
@@ -9114,17 +9120,17 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
     INIT_ANCHOR(val);
     switch ((int)type) {
       case NODE_MATCH:
-        ADD_INSN1(recv, node, putobject, node->nd_lit);
+        ADD_INSN1(recv, node, putobject, RNODE_MATCH(node)->nd_lit);
         ADD_INSN2(val, node, getspecial, INT2FIX(0),
                   INT2FIX(0));
         break;
       case NODE_MATCH2:
-        CHECK(COMPILE(recv, "receiver", node->nd_recv));
-        CHECK(COMPILE(val, "value", node->nd_value));
+        CHECK(COMPILE(recv, "receiver", RNODE_MATCH2(node)->nd_recv));
+        CHECK(COMPILE(val, "value", RNODE_MATCH2(node)->nd_value));
         break;
       case NODE_MATCH3:
-        CHECK(COMPILE(recv, "receiver", node->nd_value));
-        CHECK(COMPILE(val, "value", node->nd_recv));
+        CHECK(COMPILE(recv, "receiver", RNODE_MATCH3(node)->nd_value));
+        CHECK(COMPILE(val, "value", RNODE_MATCH3(node)->nd_recv));
         break;
     }
 
@@ -9132,8 +9138,8 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
     ADD_SEQ(ret, val);
     ADD_SEND(ret, node, idEqTilde, INT2FIX(1));
 
-    if (node->nd_args) {
-        compile_named_capture_assign(iseq, ret, node->nd_args);
+    if (RNODE_MATCH2(node)->nd_args) {
+        compile_named_capture_assign(iseq, ret, RNODE_MATCH2(node)->nd_args);
     }
 
     if (popped) {
@@ -9145,7 +9151,7 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
 static int
 compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
 {
-    if (rb_is_const_id(node->nd_mid)) {
+    if (rb_is_const_id(RNODE_COLON2(node)->nd_mid)) {
         /* constant */
         VALUE segments;
         if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache &&
@@ -9175,8 +9181,8 @@ compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
     else {
         /* function call */
         ADD_CALL_RECEIVER(ret, node);
-        CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head));
-        ADD_CALL(ret, node, node->nd_mid, INT2FIX(1));
+        CHECK(COMPILE(ret, "colon2#nd_head", RNODE_COLON2(node)->nd_head));
+        ADD_CALL(ret, node, RNODE_COLON2(node)->nd_mid, INT2FIX(1));
     }
     if (popped) {
         ADD_INSN(ret, node, pop);
@@ -9187,19 +9193,19 @@ compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
 static int
 compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
 {
-    debugi("colon3#nd_mid", node->nd_mid);
+    debugi("colon3#nd_mid", RNODE_COLON3(node)->nd_mid);
 
     /* add cache insn */
     if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
         ISEQ_BODY(iseq)->ic_size++;
-        VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(node->nd_mid));
+        VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(RNODE_COLON3(node)->nd_mid));
         ADD_INSN1(ret, node, opt_getconstant_path, segments);
         RB_OBJ_WRITTEN(iseq, Qundef, segments);
     }
     else {
         ADD_INSN1(ret, node, putobject, rb_cObject);
         ADD_INSN1(ret, node, putobject, Qtrue);
-        ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_mid));
+        ADD_INSN1(ret, node, getconstant, ID2SYM(RNODE_COLON3(node)->nd_mid));
     }
 
     if (popped) {
@@ -9212,13 +9218,13 @@ static int
 compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const int excl)
 {
     VALUE flag = INT2FIX(excl);
-    const NODE *b = node->nd_beg;
-    const NODE *e = node->nd_end;
+    const NODE *b = RNODE_DOT2(node)->nd_beg;
+    const NODE *e = RNODE_DOT2(node)->nd_end;
 
     if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) {
         if (!popped) {
-            VALUE bv = nd_type_p(b, NODE_LIT) ? b->nd_lit : Qnil;
-            VALUE ev = nd_type_p(e, NODE_LIT) ? e->nd_lit : Qnil;
+            VALUE bv = nd_type_p(b, NODE_LIT) ? RNODE_LIT(b)->nd_lit : Qnil;
+            VALUE ev = nd_type_p(e, NODE_LIT) ? RNODE_LIT(e)->nd_lit : Qnil;
             VALUE val = rb_range_new(bv, ev, excl);
             ADD_INSN1(ret, node, putobject, val);
             RB_OBJ_WRITTEN(iseq, Qundef, val);
@@ -9267,7 +9273,7 @@ compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
 {
     struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
     LABEL *end_label = NEW_LABEL(nd_line(node));
-    const NODE *default_value = node->nd_body->nd_value;
+    const NODE *default_value = RNODE_DASGN(RNODE_KW_ARG(node)->nd_body)->nd_value;
 
     if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) {
         /* required argument. do nothing */
@@ -9291,7 +9297,7 @@ compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
 
         ADD_INSN2(ret, node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx));
         ADD_INSNL(ret, node, branchif, end_label);
-        CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body));
+        CHECK(COMPILE_POPPED(ret, "keyword default argument", RNODE_KW_ARG(node)->nd_body));
         ADD_LABEL(ret, end_label);
     }
     return COMPILE_OK;
@@ -9303,7 +9309,7 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     DECL_ANCHOR(recv);
     DECL_ANCHOR(args);
     unsigned int flag = 0;
-    ID mid = node->nd_mid;
+    ID mid = RNODE_ATTRASGN(node)->nd_mid;
     VALUE argc;
     LABEL *else_label = NULL;
     VALUE branches = Qfalse;
@@ -9311,16 +9317,16 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
     /* optimization shortcut
      *   obj["literal"] = value -> opt_aset_with(obj, "literal", value)
      */
-    if (mid == idASET && !private_recv_p(node) && node->nd_args &&
-        nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 2 &&
-        nd_type_p(node->nd_args->nd_head, NODE_STR) &&
+    if (mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args &&
+        nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 &&
+        nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) &&
         ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
         !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal &&
         ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
     {
-        VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
-        CHECK(COMPILE(ret, "recv", node->nd_recv));
-        CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head));
+        VALUE str = rb_fstring(RNODE_STR(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head)->nd_lit);
+        CHECK(COMPILE(ret, "recv", RNODE_ATTRASGN(node)->nd_recv));
+        CHECK(COMPILE(ret, "value", RNODE_LIST(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_next)->nd_head));
         if (!popped) {
             ADD_INSN(ret, node, swap);
             ADD_INSN1(ret, node, topn, INT2FIX(1));
@@ -9334,10 +9340,10 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
 
     INIT_ANCHOR(recv);
     INIT_ANCHOR(args);
-    argc = setup_args(iseq, args, node->nd_args, &flag, NULL);
+    argc = setup_args(iseq, args, RNODE_ATTRASGN(node)->nd_args, &flag, NULL);
     CHECK(!NIL_P(argc));
 
-    int asgnflag = COMPILE_RECV(recv, "recv", node);
+    int asgnflag = COMPILE_RECV(recv, "recv", node, RNODE_ATTRASGN(node)->nd_recv);
     CHECK(asgnflag != -1);
     flag |= (unsigned int)asgnflag;
 
@@ -9474,7 +9480,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         CHECK(compile_retry(iseq, ret, node, popped));
         break;
       case NODE_BEGIN:{
-        CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped));
+        CHECK(COMPILE_(ret, "NODE_BEGIN", RNODE_BEGIN(node)->nd_body, popped));
         break;
       }
       case NODE_RESCUE:
@@ -9490,7 +9496,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       case NODE_AND:
       case NODE_OR:{
         LABEL *end_label = NEW_LABEL(line);
-        CHECK(COMPILE(ret, "nd_1st", node->nd_1st));
+        CHECK(COMPILE(ret, "nd_1st", RNODE_OR(node)->nd_1st));
         if (!popped) {
             ADD_INSN(ret, node, dup);
         }
@@ -9503,7 +9509,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         if (!popped) {
             ADD_INSN(ret, node, pop);
         }
-        CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped));
+        CHECK(COMPILE_(ret, "nd_2nd", RNODE_OR(node)->nd_2nd, popped));
         ADD_LABEL(ret, end_label);
         break;
       }
@@ -9514,11 +9520,11 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
 
       case NODE_LASGN:{
-        ID id = node->nd_vid;
+        ID id = RNODE_LASGN(node)->nd_vid;
         int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id);
 
         debugs("lvar: %s idx: %d\n", rb_id2name(id), idx);
-        CHECK(COMPILE(ret, "rvalue", node->nd_value));
+        CHECK(COMPILE(ret, "rvalue", RNODE_LASGN(node)->nd_value));
 
         if (!popped) {
             ADD_INSN(ret, node, dup);
@@ -9528,8 +9534,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
       case NODE_DASGN: {
         int idx, lv, ls;
-        ID id = node->nd_vid;
-        CHECK(COMPILE(ret, "dvalue", node->nd_value));
+        ID id = RNODE_DASGN(node)->nd_vid;
+        CHECK(COMPILE(ret, "dvalue", RNODE_DASGN(node)->nd_value));
         debugi("dassn id", rb_id2str(id) ? id : '*');
 
         if (!popped) {
@@ -9547,27 +9553,27 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_GASGN:{
-        CHECK(COMPILE(ret, "lvalue", node->nd_value));
+        CHECK(COMPILE(ret, "lvalue", RNODE_GASGN(node)->nd_value));
 
         if (!popped) {
             ADD_INSN(ret, node, dup);
         }
-        ADD_INSN1(ret, node, setglobal, ID2SYM(node->nd_vid));
+        ADD_INSN1(ret, node, setglobal, ID2SYM(RNODE_GASGN(node)->nd_vid));
         break;
       }
       case NODE_IASGN:{
-        CHECK(COMPILE(ret, "lvalue", node->nd_value));
+        CHECK(COMPILE(ret, "lvalue", RNODE_IASGN(node)->nd_value));
         if (!popped) {
             ADD_INSN(ret, node, dup);
         }
         ADD_INSN2(ret, node, setinstancevariable,
-                  ID2SYM(node->nd_vid),
-                  get_ivar_ic_value(iseq,node->nd_vid));
+                  ID2SYM(RNODE_IASGN(node)->nd_vid),
+                  get_ivar_ic_value(iseq,RNODE_IASGN(node)->nd_vid));
         break;
       }
       case NODE_CDECL:{
-        if (node->nd_vid) {
-            CHECK(COMPILE(ret, "lvalue", node->nd_value));
+        if (RNODE_CDECL(node)->nd_vid) {
+            CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
 
             if (!popped) {
                 ADD_INSN(ret, node, dup);
@@ -9575,11 +9581,11 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
 
             ADD_INSN1(ret, node, putspecialobject,
                       INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
-            ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_vid));
+            ADD_INSN1(ret, node, setconstant, ID2SYM(RNODE_CDECL(node)->nd_vid));
         }
         else {
-            compile_cpath(ret, iseq, node->nd_else);
-            CHECK(COMPILE(ret, "lvalue", node->nd_value));
+            compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else);
+            CHECK(COMPILE(ret, "lvalue", RNODE_CDECL(node)->nd_value));
             ADD_INSN(ret, node, swap);
 
             if (!popped) {
@@ -9587,18 +9593,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
                 ADD_INSN(ret, node, swap);
             }
 
-            ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_else->nd_mid));
+            ADD_INSN1(ret, node, setconstant, ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid));
         }
         break;
       }
       case NODE_CVASGN:{
-        CHECK(COMPILE(ret, "cvasgn val", node->nd_value));
+        CHECK(COMPILE(ret, "cvasgn val", RNODE_CVASGN(node)->nd_value));
         if (!popped) {
             ADD_INSN(ret, node, dup);
         }
         ADD_INSN2(ret, node, setclassvariable,
-                  ID2SYM(node->nd_vid),
-                  get_cvar_ic_value(iseq,node->nd_vid));
+                  ID2SYM(RNODE_CVASGN(node)->nd_vid),
+                  get_cvar_ic_value(iseq, RNODE_CVASGN(node)->nd_vid));
         break;
       }
       case NODE_OP_ASGN1:
@@ -9646,10 +9652,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
             COMPILE_ERROR(ERROR_ARGS "NODE_VALUES: must not be popped");
         }
         while (n) {
-            CHECK(COMPILE(ret, "values item", n->nd_head));
-            n = n->nd_next;
+            CHECK(COMPILE(ret, "values item", RNODE_VALUES(n)->nd_head));
+            n = RNODE_VALUES(n)->nd_next;
         }
-        ADD_INSN1(ret, node, newarray, INT2FIX(node->nd_alen));
+        ADD_INSN1(ret, node, newarray, INT2FIX(RNODE_VALUES(node)->nd_alen));
         break;
       }
       case NODE_HASH:
@@ -9663,18 +9669,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       case NODE_LVAR:{
         if (!popped) {
-            compile_lvar(iseq, ret, node, node->nd_vid);
+            compile_lvar(iseq, ret, node, RNODE_LVAR(node)->nd_vid);
         }
         break;
       }
       case NODE_DVAR:{
         int lv, idx, ls;
-        debugi("nd_vid", node->nd_vid);
+        debugi("nd_vid", RNODE_DVAR(node)->nd_vid);
         if (!popped) {
-            idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
+            idx = get_dyna_var_idx(iseq, RNODE_DVAR(node)->nd_vid, &lv, &ls);
             if (idx < 0) {
                 COMPILE_ERROR(ERROR_ARGS "unknown dvar (%"PRIsVALUE")",
-                              rb_id2str(node->nd_vid));
+                              rb_id2str(RNODE_DVAR(node)->nd_vid));
                 goto ng;
             }
             ADD_GETLOCAL(ret, node, ls - idx, lv);
@@ -9682,34 +9688,34 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_GVAR:{
-        ADD_INSN1(ret, node, getglobal, ID2SYM(node->nd_vid));
+        ADD_INSN1(ret, node, getglobal, ID2SYM(RNODE_GVAR(node)->nd_vid));
         if (popped) {
             ADD_INSN(ret, node, pop);
         }
         break;
       }
       case NODE_IVAR:{
-        debugi("nd_vid", node->nd_vid);
+        debugi("nd_vid", RNODE_IVAR(node)->nd_vid);
         if (!popped) {
             ADD_INSN2(ret, node, getinstancevariable,
-                      ID2SYM(node->nd_vid),
-                      get_ivar_ic_value(iseq,node->nd_vid));
+                      ID2SYM(RNODE_IVAR(node)->nd_vid),
+                      get_ivar_ic_value(iseq, RNODE_IVAR(node)->nd_vid));
         }
         break;
       }
       case NODE_CONST:{
-        debugi("nd_vid", node->nd_vid);
+        debugi("nd_vid", RNODE_CONST(node)->nd_vid);
 
         if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
             body->ic_size++;
-            VALUE segments = rb_ary_new_from_args(1, ID2SYM(node->nd_vid));
+            VALUE segments = rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid));
             ADD_INSN1(ret, node, opt_getconstant_path, segments);
             RB_OBJ_WRITTEN(iseq, Qundef, segments);
         }
         else {
             ADD_INSN(ret, node, putnil);
             ADD_INSN1(ret, node, putobject, Qtrue);
-            ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid));
+            ADD_INSN1(ret, node, getconstant, ID2SYM(RNODE_CONST(node)->nd_vid));
         }
 
         if (popped) {
@@ -9720,26 +9726,26 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       case NODE_CVAR:{
         if (!popped) {
             ADD_INSN2(ret, node, getclassvariable,
-                      ID2SYM(node->nd_vid),
-                      get_cvar_ic_value(iseq,node->nd_vid));
+                      ID2SYM(RNODE_CVAR(node)->nd_vid),
+                      get_cvar_ic_value(iseq, RNODE_CVAR(node)->nd_vid));
         }
         break;
       }
       case NODE_NTH_REF:{
         if (!popped) {
-            if (!node->nd_nth) {
+            if (!RNODE_NTH_REF(node)->nd_nth) {
                 ADD_INSN(ret, node, putnil);
                 break;
             }
             ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~'  */,
-                      INT2FIX(node->nd_nth << 1));
+                      INT2FIX(RNODE_NTH_REF(node)->nd_nth << 1));
         }
         break;
       }
       case NODE_BACK_REF:{
         if (!popped) {
             ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */,
-                      INT2FIX(0x01 | (node->nd_nth << 1)));
+                      INT2FIX(0x01 | (RNODE_BACK_REF(node)->nd_nth << 1)));
         }
         break;
       }
@@ -9749,17 +9755,17 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         CHECK(compile_match(iseq, ret, node, popped, type));
         break;
       case NODE_LIT:{
-        debugp_param("lit", node->nd_lit);
+        debugp_param("lit", RNODE_LIT(node)->nd_lit);
         if (!popped) {
-            ADD_INSN1(ret, node, putobject, node->nd_lit);
-            RB_OBJ_WRITTEN(iseq, Qundef, node->nd_lit);
+            ADD_INSN1(ret, node, putobject, RNODE_LIT(node)->nd_lit);
+            RB_OBJ_WRITTEN(iseq, Qundef, RNODE_LIT(node)->nd_lit);
         }
         break;
       }
       case NODE_STR:{
-        debugp_param("nd_lit", node->nd_lit);
+        debugp_param("nd_lit", RNODE_STR(node)->nd_lit);
         if (!popped) {
-            VALUE lit = node->nd_lit;
+            VALUE lit = RNODE_STR(node)->nd_lit;
             if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
                 lit = rb_fstring(lit);
                 ADD_INSN1(ret, node, putstring, lit);
@@ -9791,7 +9797,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
       case NODE_XSTR:{
         ADD_CALL_RECEIVER(ret, node);
-        VALUE str = rb_fstring(node->nd_lit);
+        VALUE str = rb_fstring(RNODE_XSTR(node)->nd_lit);
         ADD_INSN1(ret, node, putobject, str);
         RB_OBJ_WRITTEN(iseq, Qundef, str);
         ADD_CALL(ret, node, idBackquote, INT2FIX(1));
@@ -9812,7 +9818,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_EVSTR:
-        CHECK(compile_evstr(iseq, ret, node->nd_body, popped));
+        CHECK(compile_evstr(iseq, ret, RNODE_EVSTR(node)->nd_body, popped));
         break;
       case NODE_DREGX:{
         compile_dregx(iseq, ret, node);
@@ -9825,7 +9831,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       case NODE_ONCE:{
         int ic_index = body->ise_size++;
         const rb_iseq_t *block_iseq;
-        block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
+        block_iseq = NEW_CHILD_ISEQ(RNODE_ONCE(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line);
 
         ADD_INSN2(ret, node, once, block_iseq, INT2FIX(ic_index));
         RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block_iseq);
@@ -9837,36 +9843,36 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
       case NODE_ARGSCAT:{
         if (popped) {
-            CHECK(COMPILE(ret, "argscat head", node->nd_head));
+            CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head));
             ADD_INSN1(ret, node, splatarray, Qfalse);
             ADD_INSN(ret, node, pop);
-            CHECK(COMPILE(ret, "argscat body", node->nd_body));
+            CHECK(COMPILE(ret, "argscat body", RNODE_ARGSCAT(node)->nd_body));
             ADD_INSN1(ret, node, splatarray, Qfalse);
             ADD_INSN(ret, node, pop);
         }
         else {
-            CHECK(COMPILE(ret, "argscat head", node->nd_head));
-            CHECK(COMPILE(ret, "argscat body", node->nd_body));
+            CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head));
+            CHECK(COMPILE(ret, "argscat body", RNODE_ARGSCAT(node)->nd_body));
             ADD_INSN(ret, node, concatarray);
         }
         break;
       }
       case NODE_ARGSPUSH:{
         if (popped) {
-            CHECK(COMPILE(ret, "argspush head", node->nd_head));
+            CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head));
             ADD_INSN1(ret, node, splatarray, Qfalse);
             ADD_INSN(ret, node, pop);
-            CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped));
+            CHECK(COMPILE_(ret, "argspush body", RNODE_ARGSPUSH(node)->nd_body, popped));
         }
         else {
-            CHECK(COMPILE(ret, "argspush head", node->nd_head));
-            CHECK(compile_array_1(iseq, ret, node->nd_body));
+            CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head));
+            CHECK(compile_array_1(iseq, ret, RNODE_ARGSPUSH(node)->nd_body));
             ADD_INSN(ret, node, concatarray);
         }
         break;
       }
       case NODE_SPLAT:{
-        CHECK(COMPILE(ret, "splat", node->nd_head));
+        CHECK(COMPILE(ret, "splat", RNODE_SPLAT(node)->nd_head));
         ADD_INSN1(ret, node, splatarray, Qtrue);
 
         if (popped) {
@@ -9875,8 +9881,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_DEFN:{
-        ID mid = node->nd_mid;
-        const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn,
+        ID mid = RNODE_DEFN(node)->nd_mid;
+        const rb_iseq_t *method_iseq = NEW_ISEQ(RNODE_DEFN(node)->nd_defn,
                                                 rb_id2str(mid),
                                                 ISEQ_TYPE_METHOD, line);
 
@@ -9891,13 +9897,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_DEFS:{
-        ID mid = node->nd_mid;
-        const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(node->nd_defn,
+        ID mid = RNODE_DEFS(node)->nd_mid;
+        const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(RNODE_DEFS(node)->nd_defn,
                                                            rb_id2str(mid),
                                                            ISEQ_TYPE_METHOD, line);
 
         debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq));
-        CHECK(COMPILE(ret, "defs: recv", node->nd_recv));
+        CHECK(COMPILE(ret, "defs: recv", RNODE_DEFS(node)->nd_recv));
         ADD_INSN2(ret, node, definesmethod, ID2SYM(mid), singleton_method_iseq);
         RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_method_iseq);
 
@@ -9909,8 +9915,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       case NODE_ALIAS:{
         ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
         ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
-        CHECK(COMPILE(ret, "alias arg1", node->nd_1st));
-        CHECK(COMPILE(ret, "alias arg2", node->nd_2nd));
+        CHECK(COMPILE(ret, "alias arg1", RNODE_ALIAS(node)->nd_1st));
+        CHECK(COMPILE(ret, "alias arg2", RNODE_ALIAS(node)->nd_2nd));
         ADD_SEND(ret, node, id_core_set_method_alias, INT2FIX(3));
 
         if (popped) {
@@ -9920,8 +9926,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
       case NODE_VALIAS:{
         ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
-        ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_alias));
-        ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_orig));
+        ADD_INSN1(ret, node, putobject, ID2SYM(RNODE_VALIAS(node)->nd_alias));
+        ADD_INSN1(ret, node, putobject, ID2SYM(RNODE_VALIAS(node)->nd_orig));
         ADD_SEND(ret, node, id_core_set_variable_alias, INT2FIX(2));
 
         if (popped) {
@@ -9932,7 +9938,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       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", node->nd_undef));
+        CHECK(COMPILE(ret, "undef arg", RNODE_UNDEF(node)->nd_undef));
         ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
 
         if (popped) {
@@ -9941,15 +9947,15 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_CLASS:{
-        const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body,
-                                                     rb_str_freeze(rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
+        const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(RNODE_CLASS(node)->nd_body,
+                                                     rb_str_freeze(rb_sprintf("<class:%"PRIsVALUE">", rb_id2str(RNODE_COLON2(RNODE_CLASS(node)->nd_cpath)->nd_mid))),
                                                      ISEQ_TYPE_CLASS, line);
         const int flags = VM_DEFINECLASS_TYPE_CLASS |
-            (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
-            compile_cpath(ret, iseq, node->nd_cpath);
+            (RNODE_CLASS(node)->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) |
+            compile_cpath(ret, iseq, RNODE_CLASS(node)->nd_cpath);
 
-        CHECK(COMPILE(ret, "super", node->nd_super));
-        ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags));
+        CHECK(COMPILE(ret, "super", RNODE_CLASS(node)->nd_super));
+        ADD_INSN3(ret, node, defineclass, ID2SYM(RNODE_COLON2(RNODE_CLASS(node)->nd_cpath)->nd_mid), class_iseq, INT2FIX(flags));
         RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)class_iseq);
 
         if (popped) {
@@ -9958,14 +9964,14 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       }
       case NODE_MODULE:{
-        const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body,
-                                                      rb_str_freeze(rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(node->nd_cpath->nd_mid))),
+        const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(RNODE_MODULE(node)->nd_body,
+                                                      rb_str_freeze(rb_sprintf("<module:%"PRIsVALUE">", rb_id2str(RNODE_COLON2(RNODE_MODULE(node)->nd_cpath)->nd_mid))),
                                                       ISEQ_TYPE_CLASS, line);
         const int flags = VM_DEFINECLASS_TYPE_MODULE |
-            compile_cpath(ret, iseq, node->nd_cpath);
+            compile_cpath(ret, iseq, RNODE_MODULE(node)->nd_cpath);
 
         ADD_INSN (ret, node, putnil); /* dummy */
-        ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags));
+        ADD_INSN3(ret, node, defineclass, ID2SYM(RNODE_COLON2(RNODE_MODULE(node)->nd_cpath)->nd_mid), module_iseq, INT2FIX(flags));
         RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)module_iseq);
 
         if (popped) {
@@ -9975,10 +9981,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
       }
       case NODE_SCLASS:{
         ID singletonclass;
-        const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_lit("singleton class"),
+        const rb_iseq_t *singleton_class = NEW_ISEQ(RNODE_SCLASS(node)->nd_body, rb_fstring_lit("singleton class"),
                                                     ISEQ_TYPE_CLASS, line);
 
-        CHECK(COMPILE(ret, "sclass#recv", node->nd_recv));
+        CHECK(COMPILE(ret, "sclass#recv", RNODE_SCLASS(node)->nd_recv));
         ADD_INSN (ret, node, putnil);
         CONST_ID(singletonclass, "singletonclass");
         ADD_INSN3(ret, node, defineclass,
@@ -10056,7 +10062,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
          */
         int is_index = body->ise_size++;
         struct rb_iseq_new_with_callback_callback_func *ifunc =
-            rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body);
+            rb_iseq_new_with_callback_new_callback(build_postexe_iseq, RNODE_POSTEXE(node)->nd_body);
         const rb_iseq_t *once_iseq =
             new_child_iseq_with_callback(iseq, ifunc,
                                  rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
@@ -10087,7 +10093,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
         break;
       case NODE_LAMBDA:{
         /* compile same as lambda{...} */
-        const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
+        const rb_iseq_t *block = NEW_CHILD_ISEQ(RNODE_LAMBDA(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line);
         VALUE argc = INT2FIX(0);
 
         ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
index e8762d1..94ae2d5 100644 (file)
@@ -493,6 +493,10 @@ count_nodes(int argc, VALUE *argv, VALUE os)
                 COUNT_NODE(NODE_ARYPTN);
                 COUNT_NODE(NODE_FNDPTN);
                 COUNT_NODE(NODE_HSHPTN);
+                COUNT_NODE(NODE_DEF_TEMP);
+                COUNT_NODE(NODE_DEF_TEMP2);
+                COUNT_NODE(NODE_RIPPER);
+                COUNT_NODE(NODE_RIPPER_VALUES);
                 COUNT_NODE(NODE_ERROR);
 #undef COUNT_NODE
               case NODE_LAST: break;
index 0008eb9..fc399f4 100644 (file)
@@ -14,7 +14,6 @@
 #include "ripper_init.h"
 
 #define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),rb_ruby_parser_enc(p))
-#define NODE_RIPPER NODE_CDECL
 #define RIPPER_VERSION "0.1.0"
 
 ID id_warn, id_warning, id_gets, id_assoc;
@@ -62,7 +61,7 @@ ripper_get_id(VALUE v)
     if (!RB_TYPE_P(v, T_NODE)) return 0;
     nd = (NODE *)v;
     if (!nd_type_p(nd, NODE_RIPPER)) return 0;
-    return nd->nd_vid;
+    return RNODE_RIPPER(nd)->nd_vid;
 }
 
 VALUE
@@ -73,7 +72,7 @@ ripper_get_value(VALUE v)
     if (!RB_TYPE_P(v, T_NODE)) return v;
     nd = (NODE *)v;
     if (!nd_type_p(nd, NODE_RIPPER)) return Qnil;
-    return nd->nd_rval;
+    return RNODE_RIPPER(nd)->nd_rval;
 }
 
 static VALUE
diff --git a/node.c b/node.c
index c4bf0b8..1f0e457 100644 (file)
--- a/node.c
+++ b/node.c
 #include "internal/parse.h"
 #define T_NODE 0x1b
 
+#else
+
+#include "internal.h"
+#include "internal/hash.h"
+#include "internal/variable.h"
+#include "ruby/ruby.h"
+#include "vm_core.h"
+
+#endif
+
+#define NODE_BUF_DEFAULT_SIZE (sizeof(struct RNode) * 16)
+
+static void
+init_node_buffer_elem(node_buffer_elem_t *nbe, size_t allocated, void *xmalloc(size_t))
+{
+    nbe->allocated = allocated;
+    nbe->used = 0;
+    nbe->len = 0;
+    nbe->nodes = xmalloc(allocated / sizeof(struct RNode) * sizeof(struct RNode *)); /* All node requires at least RNode */
+}
+
+static void
+init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head, void *xmalloc(size_t))
+{
+    init_node_buffer_elem(head, NODE_BUF_DEFAULT_SIZE, xmalloc);
+    nb->head = nb->last = head;
+    nb->head->next = NULL;
+}
+
+#ifdef UNIVERSAL_PARSER
+#define ruby_xmalloc config->malloc
+#define Qnil config->qnil
+#endif
+
+#ifdef UNIVERSAL_PARSER
+static node_buffer_t *
+rb_node_buffer_new(rb_parser_config_t *config)
+#else
+static node_buffer_t *
+rb_node_buffer_new(void)
+#endif
+{
+    const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_SIZE;
+    const size_t alloc_size = sizeof(node_buffer_t) + (bucket_size * 2);
+    STATIC_ASSERT(
+        integer_overflow,
+        offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_SIZE
+        > sizeof(node_buffer_t) + 2 * sizeof(node_buffer_elem_t));
+    node_buffer_t *nb = ruby_xmalloc(alloc_size);
+    init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1], ruby_xmalloc);
+    init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size), ruby_xmalloc);
+    nb->local_tables = 0;
+    nb->mark_hash = Qnil;
+    nb->tokens = Qnil;
+#ifdef UNIVERSAL_PARSER
+    nb->config = config;
+#endif
+    return nb;
+}
+
+#ifdef UNIVERSAL_PARSER
+#undef ruby_xmalloc
 #define ruby_xmalloc ast->node_buffer->config->malloc
 #undef xfree
 #define xfree ast->node_buffer->config->free
 #define rb_gc_mark ast->node_buffer->config->gc_mark
 #define rb_gc_location ast->node_buffer->config->gc_location
 #define rb_gc_mark_movable ast->node_buffer->config->gc_mark_movable
+#undef Qnil
 #define Qnil ast->node_buffer->config->qnil
 #define Qtrue ast->node_buffer->config->qtrue
 #define NIL_P ast->node_buffer->config->nil_p
 #define rb_hash_aset ast->node_buffer->config->hash_aset
 #define RB_OBJ_WRITE(old, slot, young) ast->node_buffer->config->obj_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young))
-
-#else
-
-#include "internal.h"
-#include "internal/hash.h"
-#include "internal/variable.h"
-#include "ruby/ruby.h"
-#include "vm_core.h"
-
 #endif
 
-#define NODE_BUF_DEFAULT_LEN 16
-
-typedef void node_itr_t(rb_ast_t *ast, void *ctx, NODE * node);
+typedef void node_itr_t(rb_ast_t *ast, void *ctx, NODE *node);
 static void iterate_node_values(rb_ast_t *ast, node_buffer_list_t *nb, node_itr_t * func, void *ctx);
 
 /* Setup NODE structure.
@@ -54,18 +106,15 @@ static void iterate_node_values(rb_ast_t *ast, node_buffer_list_t *nb, node_itr_
  * objects.
  */
 void
-rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
+rb_node_init(NODE *n, enum node_type type)
 {
-    n->flags = T_NODE;
-    nd_init_type(n, type);
-    n->u1.value = a0;
-    n->u2.value = a1;
-    n->u3.value = a2;
-    n->nd_loc.beg_pos.lineno = 0;
-    n->nd_loc.beg_pos.column = 0;
-    n->nd_loc.end_pos.lineno = 0;
-    n->nd_loc.end_pos.column = 0;
-    n->node_id = -1;
+    RNODE(n)->flags = T_NODE;
+    nd_init_type(RNODE(n), type);
+    RNODE(n)->nd_loc.beg_pos.lineno = 0;
+    RNODE(n)->nd_loc.beg_pos.column = 0;
+    RNODE(n)->nd_loc.end_pos.lineno = 0;
+    RNODE(n)->nd_loc.end_pos.column = 0;
+    RNODE(n)->node_id = -1;
 }
 
 const char *
@@ -96,61 +145,12 @@ ruby_node_name(int node)
 #endif
 
 static void
-init_node_buffer_list(node_buffer_list_t * nb, node_buffer_elem_t *head)
-{
-    nb->idx = 0;
-    nb->len = NODE_BUF_DEFAULT_LEN;
-    nb->head = nb->last = head;
-    nb->head->len = nb->len;
-    nb->head->next = NULL;
-}
-
-#ifdef UNIVERSAL_PARSER
-static node_buffer_t *
-rb_node_buffer_new(rb_parser_config_t *config)
-{
-    const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
-    const size_t alloc_size = sizeof(node_buffer_t) + (bucket_size * 2);
-    STATIC_ASSERT(
-        integer_overflow,
-        offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE)
-        > sizeof(node_buffer_t) + 2 * sizeof(node_buffer_elem_t));
-    node_buffer_t *nb = config->malloc(alloc_size);
-    init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]);
-    init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
-    nb->local_tables = 0;
-    nb->mark_hash = config->qnil;
-    nb->tokens = config->qnil;
-    nb->config = config;
-    return nb;
-}
-#else
-static node_buffer_t *
-rb_node_buffer_new(void)
-{
-    const size_t bucket_size = offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
-    const size_t alloc_size = sizeof(node_buffer_t) + (bucket_size * 2);
-    STATIC_ASSERT(
-        integer_overflow,
-        offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE)
-        > sizeof(node_buffer_t) + 2 * sizeof(node_buffer_elem_t));
-    node_buffer_t *nb = ruby_xmalloc(alloc_size);
-    init_node_buffer_list(&nb->unmarkable, (node_buffer_elem_t*)&nb[1]);
-    init_node_buffer_list(&nb->markable, (node_buffer_elem_t*)((size_t)nb->unmarkable.head + bucket_size));
-    nb->local_tables = 0;
-    nb->mark_hash = Qnil;
-    nb->tokens = Qnil;
-    return nb;
-}
-#endif
-
-static void
 node_buffer_list_free(rb_ast_t *ast, node_buffer_list_t * nb)
 {
     node_buffer_elem_t *nbe = nb->head;
-
     while (nbe != nb->last) {
         void *buf = nbe;
+        xfree(nbe->nodes);
         nbe = nbe->next;
         xfree(buf);
     }
@@ -165,17 +165,17 @@ struct rb_ast_local_table_link {
 };
 
 static void
-free_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
+free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
 {
     switch (nd_type(node)) {
       case NODE_ARGS:
-        xfree(node->nd_ainfo);
+        xfree(RNODE_ARGS(node)->nd_ainfo);
         break;
       case NODE_ARYPTN:
-        xfree(node->nd_apinfo);
+        xfree(RNODE_ARYPTN(node)->nd_apinfo);
         break;
       case NODE_FNDPTN:
-        xfree(node->nd_fpinfo);
+        xfree(RNODE_FNDPTN(node)->nd_fpinfo);
         break;
     }
 }
@@ -195,20 +195,31 @@ rb_node_buffer_free(rb_ast_t *ast, node_buffer_t *nb)
     xfree(nb);
 }
 
+#define buf_add_offset(nbe, offset) ((char *)(nbe->buf) + (offset))
+
 static NODE *
-ast_newnode_in_bucket(rb_ast_t *ast, node_buffer_list_t *nb)
+ast_newnode_in_bucket(rb_ast_t *ast, node_buffer_list_t *nb, size_t size, size_t alignment)
 {
-    if (nb->idx >= nb->len) {
-        long n = nb->len * 2;
+    size_t padding;
+    NODE *ptr;
+
+    padding = alignment - (size_t)buf_add_offset(nb->head, nb->head->used) % alignment;
+    padding = padding == alignment ? 0 : padding;
+
+    if (nb->head->used + size + padding > nb->head->allocated) {
+        size_t n = nb->head->allocated * 2;
         node_buffer_elem_t *nbe;
-        nbe = rb_xmalloc_mul_add(n, sizeof(NODE), offsetof(node_buffer_elem_t, buf));
-        nbe->len = n;
-        nb->idx = 0;
-        nb->len = n;
+        nbe = rb_xmalloc_mul_add(n, sizeof(char *), offsetof(node_buffer_elem_t, buf));
+        init_node_buffer_elem(nbe, n, ruby_xmalloc);
         nbe->next = nb->head;
         nb->head = nbe;
+        padding = 0; /* malloc returns aligned address then no need to add padding */
     }
-    return &nb->head->buf[nb->idx++];
+
+    ptr = (NODE *)buf_add_offset(nb->head, nb->head->used + padding);
+    nb->head->used += (size + padding);
+    nb->head->nodes[nb->head->len++] = ptr;
+    return ptr;
 }
 
 RBIMPL_ATTR_PURE()
@@ -231,12 +242,12 @@ nodetype_markable_p(enum node_type type)
 }
 
 NODE *
-rb_ast_newnode(rb_ast_t *ast, enum node_type type)
+rb_ast_newnode(rb_ast_t *ast, enum node_type type, size_t size, size_t alignment)
 {
     node_buffer_t *nb = ast->node_buffer;
     node_buffer_list_t *bucket =
         (nodetype_markable_p(type) ? &nb->markable : &nb->unmarkable);
-    return ast_newnode_in_bucket(ast, bucket);
+    return ast_newnode_in_bucket(ast, bucket, size, alignment);
 }
 
 #if RUBY_DEBUG
@@ -306,7 +317,7 @@ iterate_buffer_elements(rb_ast_t *ast, node_buffer_elem_t *nbe, long len, node_i
 {
     long cursor;
     for (cursor = 0; cursor < len; cursor++) {
-        func(ast, ctx, &nbe->buf[cursor]);
+        func(ast, ctx, nbe->nodes[cursor]);
     }
 }
 
@@ -315,10 +326,6 @@ iterate_node_values(rb_ast_t *ast, node_buffer_list_t *nb, node_itr_t * func, vo
 {
     node_buffer_elem_t *nbe = nb->head;
 
-    /* iterate over the head first because it's not full */
-    iterate_buffer_elements(ast, nbe, nb->idx, func, ctx);
-
-    nbe = nbe->next;
     while (nbe) {
         iterate_buffer_elements(ast, nbe, nbe->len, func, ctx);
         nbe = nbe->next;
@@ -326,7 +333,7 @@ iterate_node_values(rb_ast_t *ast, node_buffer_list_t *nb, node_itr_t * func, vo
 }
 
 static void
-mark_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
+mark_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
 {
 #ifdef UNIVERSAL_PARSER
     bug_report_func rb_bug = ast->node_buffer->config->bug;
@@ -341,7 +348,7 @@ mark_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
       case NODE_DXSTR:
       case NODE_DREGX:
       case NODE_DSYM:
-        rb_gc_mark_movable(node->nd_lit);
+        rb_gc_mark_movable(RNODE_LIT(node)->nd_lit);
         break;
       default:
         rb_bug("unreachable node %s", ruby_node_name(nd_type(node)));
@@ -349,7 +356,7 @@ mark_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
 }
 
 static void
-update_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
+update_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
 {
 #ifdef UNIVERSAL_PARSER
     bug_report_func rb_bug = ast->node_buffer->config->bug;
@@ -364,7 +371,7 @@ update_ast_value(rb_ast_t *ast, void *ctx, NODE * node)
       case NODE_DXSTR:
       case NODE_DREGX:
       case NODE_DSYM:
-        node->nd_lit = rb_gc_location(node->nd_lit);
+        RNODE_LIT(node)->nd_lit = rb_gc_location(RNODE_LIT(node)->nd_lit);
         break;
       default:
         rb_bug("unreachable");
@@ -418,8 +425,8 @@ buffer_list_size(node_buffer_list_t *nb)
     size_t size = 0;
     node_buffer_elem_t *nbe = nb->head;
     while (nbe != nb->last) {
+        size += offsetof(node_buffer_elem_t, buf) + nbe->used;
         nbe = nbe->next;
-        size += offsetof(node_buffer_elem_t, buf) + nb->len * sizeof(NODE);
     }
     return size;
 }
@@ -431,7 +438,7 @@ rb_ast_memsize(const rb_ast_t *ast)
     node_buffer_t *nb = ast->node_buffer;
 
     if (nb) {
-        size += sizeof(node_buffer_t) + offsetof(node_buffer_elem_t, buf) + NODE_BUF_DEFAULT_LEN * sizeof(NODE);
+        size += sizeof(node_buffer_t);
         size += buffer_list_size(&nb->unmarkable);
         size += buffer_list_size(&nb->markable);
     }
diff --git a/node.h b/node.h
index 645f935..79c0c67 100644 (file)
--- a/node.h
+++ b/node.h
@@ -19,12 +19,14 @@ typedef void (*bug_report_func)(const char *fmt, ...);
 
 typedef struct node_buffer_elem_struct {
     struct node_buffer_elem_struct *next;
-    long len;
-    NODE buf[FLEX_ARY_LEN];
+    long len; /* Length of nodes */
+    size_t allocated; /* Total memory size of allocated buf */
+    size_t used; /* Current usage of buf */
+    NODE **nodes; /* Array of node pointers */
+    NODE *buf[FLEX_ARY_LEN];
 } node_buffer_elem_t;
 
 typedef struct {
-    long idx, len;
     node_buffer_elem_t *head;
     node_buffer_elem_t *last;
 } node_buffer_list_t;
@@ -59,14 +61,14 @@ VALUE rb_ast_tokens(rb_ast_t *ast);
 void rb_ast_node_type_change(NODE *n, enum node_type type);
 #endif
 const char *ruby_node_name(int node);
-void rb_node_init(NODE *n, enum node_type type, VALUE a0, VALUE a1, VALUE a2);
+void rb_node_init(NODE *n, enum node_type type);
 
 void rb_ast_mark(rb_ast_t*);
 void rb_ast_update_references(rb_ast_t*);
 void rb_ast_free(rb_ast_t*);
 void rb_ast_add_mark_object(rb_ast_t*, VALUE);
 void rb_ast_set_tokens(rb_ast_t*, VALUE);
-NODE *rb_ast_newnode(rb_ast_t*, enum node_type type);
+NODE *rb_ast_newnode(rb_ast_t*, enum node_type type, size_t size, size_t alignment);
 void rb_ast_delete_node(rb_ast_t*, NODE *n);
 rb_ast_id_table_t *rb_ast_new_local_table(rb_ast_t*, int);
 rb_ast_id_table_t *rb_ast_resize_latest_local_table(rb_ast_t*, int);
@@ -100,21 +102,21 @@ RUBY_SYMBOL_EXPORT_END
 #define NODE_SPECIAL_EXCESSIVE_COMMA   ((ID)1)
 #define NODE_SPECIAL_NO_REST_KEYWORD   ((NODE *)-1)
 
-#define nd_first_column(n) ((int)((n)->nd_loc.beg_pos.column))
-#define nd_set_first_column(n, v) ((n)->nd_loc.beg_pos.column = (v))
-#define nd_first_lineno(n) ((int)((n)->nd_loc.beg_pos.lineno))
-#define nd_set_first_lineno(n, v) ((n)->nd_loc.beg_pos.lineno = (v))
-#define nd_first_loc(n) ((n)->nd_loc.beg_pos)
+#define nd_first_column(n) ((int)(RNODE(n)->nd_loc.beg_pos.column))
+#define nd_set_first_column(n, v) (RNODE(n)->nd_loc.beg_pos.column = (v))
+#define nd_first_lineno(n) ((int)(RNODE(n)->nd_loc.beg_pos.lineno))
+#define nd_set_first_lineno(n, v) (RNODE(n)->nd_loc.beg_pos.lineno = (v))
+#define nd_first_loc(n) (RNODE(n)->nd_loc.beg_pos)
 #define nd_set_first_loc(n, v) (nd_first_loc(n) = (v))
 
-#define nd_last_column(n) ((int)((n)->nd_loc.end_pos.column))
-#define nd_set_last_column(n, v) ((n)->nd_loc.end_pos.column = (v))
-#define nd_last_lineno(n) ((int)((n)->nd_loc.end_pos.lineno))
-#define nd_set_last_lineno(n, v) ((n)->nd_loc.end_pos.lineno = (v))
-#define nd_last_loc(n) ((n)->nd_loc.end_pos)
+#define nd_last_column(n) ((int)(RNODE(n)->nd_loc.end_pos.column))
+#define nd_set_last_column(n, v) (RNODE(n)->nd_loc.end_pos.column = (v))
+#define nd_last_lineno(n) ((int)(RNODE(n)->nd_loc.end_pos.lineno))
+#define nd_set_last_lineno(n, v) (RNODE(n)->nd_loc.end_pos.lineno = (v))
+#define nd_last_loc(n) (RNODE(n)->nd_loc.end_pos)
 #define nd_set_last_loc(n, v) (nd_last_loc(n) = (v))
-#define nd_node_id(n) ((n)->node_id)
-#define nd_set_node_id(n,id) ((n)->node_id = (id))
+#define nd_node_id(n) (RNODE(n)->node_id)
+#define nd_set_node_id(n,id) (RNODE(n)->node_id = (id))
 
 static inline bool
 nd_type_p(const NODE *n, enum node_type t)
index c13403d..e4862da 100644 (file)
 
 #define SIMPLE_FIELD1(name, ann)    SIMPLE_FIELD(FIELD_NAME_LEN(name, ann), FIELD_NAME_DESC(name, ann))
 #define F_CUSTOM1(name, ann)       SIMPLE_FIELD1(#name, ann)
-#define F_ID(name, ann)            SIMPLE_FIELD1(#name, ann) A_ID(node->name)
-#define F_INT(name, ann)           SIMPLE_FIELD1(#name, ann) A_INT(node->name)
-#define F_LONG(name, ann)          SIMPLE_FIELD1(#name, ann) A_LONG(node->name)
-#define F_LIT(name, ann)           SIMPLE_FIELD1(#name, ann) A_LIT(node->name)
+#define F_ID(name, type, ann)      SIMPLE_FIELD1(#name, ann) A_ID(type(node)->name)
+#define F_INT(name, type, ann)     SIMPLE_FIELD1(#name, ann) A_INT(type(node)->name)
+#define F_LONG(name, type, ann)            SIMPLE_FIELD1(#name, ann) A_LONG(type(node)->name)
+#define F_LIT(name, type, ann)     SIMPLE_FIELD1(#name, ann) A_LIT(type(node)->name)
 #define F_MSG(name, ann, desc)     SIMPLE_FIELD1(#name, ann) A(desc)
 
-#define F_NODE(name, ann) \
-    COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, node->name);}
+#define F_NODE(name, type, ann) \
+    COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, type(node)->name);}
+
+#define F_NODE2(name, n, ann) \
+    COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, n);}
 
 #define ANN(ann) \
     if (comment) { \
@@ -131,14 +134,14 @@ dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
 {
     int field_flag;
     const char *next_indent = default_indent;
-    F_LONG(nd_alen, "length");
-    F_NODE(nd_head, "element");
-    while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) {
-        node = node->nd_next;
-        F_NODE(nd_head, "element");
+    F_LONG(as.nd_alen, RNODE_LIST, "length");
+    F_NODE(nd_head, RNODE_LIST, "element");
+    while (RNODE_LIST(node)->nd_next && nd_type_p(RNODE_LIST(node)->nd_next, NODE_LIST)) {
+        node = RNODE_LIST(node)->nd_next;
+        F_NODE(nd_head, RNODE_LIST, "element");
     }
     LAST_NODE;
-    F_NODE(nd_next, "next element");
+    F_NODE(nd_next, RNODE_LIST, "next element");
 }
 
 static void
@@ -167,16 +170,16 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
             A_INDENT;
             rb_str_catf(buf, "+- nd_head (%s%d):\n",
                         comment ? "statement #" : "", ++i);
-            if (!node->nd_next) LAST_NODE;
+            if (!RNODE_BLOCK(node)->nd_next) LAST_NODE;
             D_INDENT;
-            dump_node(buf, indent, comment, node->nd_head);
+            dump_node(buf, indent, comment, RNODE_BLOCK(node)->nd_head);
             D_DEDENT;
-        } while (node->nd_next &&
-                 nd_type_p(node->nd_next, NODE_BLOCK) &&
-                 (node = node->nd_next, 1));
-        if (node->nd_next) {
+        } while (RNODE_BLOCK(node)->nd_next &&
+                 nd_type_p(RNODE_BLOCK(node)->nd_next, NODE_BLOCK) &&
+                 (node = RNODE_BLOCK(node)->nd_next, 1));
+        if (RNODE_BLOCK(node)->nd_next) {
             LAST_NODE;
-            F_NODE(nd_next, "next block");
+            F_NODE(nd_next, RNODE_BLOCK, "next block");
         }
         return;
 
@@ -184,65 +187,65 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("if statement");
         ANN("format: if [nd_cond] then [nd_body] else [nd_else] end");
         ANN("example: if x == 1 then foo else bar end");
-        F_NODE(nd_cond, "condition expr");
-        F_NODE(nd_body, "then clause");
+        F_NODE(nd_cond, RNODE_IF, "condition expr");
+        F_NODE(nd_body, RNODE_IF, "then clause");
         LAST_NODE;
-        F_NODE(nd_else, "else clause");
+        F_NODE(nd_else, RNODE_IF, "else clause");
         return;
 
       case NODE_UNLESS:
         ANN("unless statement");
         ANN("format: unless [nd_cond] then [nd_body] else [nd_else] end");
         ANN("example: unless x == 1 then foo else bar end");
-        F_NODE(nd_cond, "condition expr");
-        F_NODE(nd_body, "then clause");
+        F_NODE(nd_cond, RNODE_UNLESS, "condition expr");
+        F_NODE(nd_body, RNODE_UNLESS, "then clause");
         LAST_NODE;
-        F_NODE(nd_else, "else clause");
+        F_NODE(nd_else, RNODE_UNLESS, "else clause");
         return;
 
       case NODE_CASE:
         ANN("case statement");
         ANN("format: case [nd_head]; [nd_body]; end");
         ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
-        F_NODE(nd_head, "case expr");
+        F_NODE(nd_head, RNODE_CASE, "case expr");
         LAST_NODE;
-        F_NODE(nd_body, "when clauses");
+        F_NODE(nd_body, RNODE_CASE, "when clauses");
         return;
       case NODE_CASE2:
         ANN("case statement with no head");
         ANN("format: case; [nd_body]; end");
         ANN("example: case; when 1; foo; when 2; bar; else baz; end");
-        F_NODE(nd_head, "case expr");
+        F_NODE(nd_head, RNODE_CASE2, "case expr");
         LAST_NODE;
-        F_NODE(nd_body, "when clauses");
+        F_NODE(nd_body, RNODE_CASE2, "when clauses");
         return;
       case NODE_CASE3:
         ANN("case statement (pattern matching)");
         ANN("format: case [nd_head]; [nd_body]; end");
         ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
-        F_NODE(nd_head, "case expr");
+        F_NODE(nd_head, RNODE_CASE3, "case expr");
         LAST_NODE;
-        F_NODE(nd_body, "in clauses");
+        F_NODE(nd_body, RNODE_CASE3, "in clauses");
         return;
 
       case NODE_WHEN:
         ANN("when clause");
         ANN("format: when [nd_head]; [nd_body]; (when or else) [nd_next]");
         ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
-        F_NODE(nd_head, "when value");
-        F_NODE(nd_body, "when body");
+        F_NODE(nd_head, RNODE_WHEN, "when value");
+        F_NODE(nd_body, RNODE_WHEN, "when body");
         LAST_NODE;
-        F_NODE(nd_next, "next when clause");
+        F_NODE(nd_next, RNODE_WHEN, "next when clause");
         return;
 
       case NODE_IN:
         ANN("in clause");
         ANN("format: in [nd_head]; [nd_body]; (in or else) [nd_next]");
         ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
-        F_NODE(nd_head, "in pattern");
-        F_NODE(nd_body, "in body");
+        F_NODE(nd_head, RNODE_IN, "in pattern");
+        F_NODE(nd_body, RNODE_IN, "in body");
         LAST_NODE;
-        F_NODE(nd_next, "next in clause");
+        F_NODE(nd_next, RNODE_IN, "next in clause");
         return;
 
       case NODE_WHILE:
@@ -256,12 +259,12 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("example: until x == 1; foo; end");
       loop:
         F_CUSTOM1(nd_state, "begin-end-while?") {
-            A_INT((int)node->nd_state);
-            A((node->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
+            A_INT((int)RNODE_WHILE(node)->nd_state);
+            A((RNODE_WHILE(node)->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
         }
-        F_NODE(nd_cond, "condition");
+        F_NODE(nd_cond, RNODE_WHILE, "condition");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_WHILE, "body");
         return;
 
       case NODE_ITER:
@@ -274,9 +277,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: for * in [nd_iter] do [nd_body] end");
         ANN("example: for i in 1..3 do foo end");
       iter:
-        F_NODE(nd_iter, "iteration receiver");
+        F_NODE(nd_iter, RNODE_ITER, "iteration receiver");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_ITER, "body");
         return;
 
       case NODE_FOR_MASGN:
@@ -284,7 +287,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: for [nd_var] in ... do ... end");
         ANN("example: for x, y in 1..3 do foo end");
         LAST_NODE;
-        F_NODE(nd_var, "var");
+        F_NODE(nd_var, RNODE_FOR_MASGN, "var");
         return;
 
       case NODE_BREAK:
@@ -303,7 +306,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("example: return 1");
       jump:
         LAST_NODE;
-        F_NODE(nd_stts, "value");
+        F_NODE(nd_stts, RNODE_BREAK, "value");
         return;
 
       case NODE_REDO:
@@ -323,36 +326,36 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: begin; [nd_body]; end");
         ANN("example: begin; 1; end");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_BEGIN, "body");
         return;
 
       case NODE_RESCUE:
         ANN("rescue clause");
         ANN("format: begin; [nd_body]; (rescue) [nd_resq]; else [nd_else]; end");
         ANN("example: begin; foo; rescue; bar; else; baz; end");
-        F_NODE(nd_head, "body");
-        F_NODE(nd_resq, "rescue clause list");
+        F_NODE(nd_head, RNODE_RESCUE, "body");
+        F_NODE(nd_resq, RNODE_RESCUE, "rescue clause list");
         LAST_NODE;
-        F_NODE(nd_else, "rescue else clause");
+        F_NODE(nd_else, RNODE_RESCUE, "rescue else clause");
         return;
 
       case NODE_RESBODY:
         ANN("rescue clause (cont'd)");
         ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
         ANN("example: begin; foo; rescue; bar; else; baz; end");
-        F_NODE(nd_args, "rescue exceptions");
-        F_NODE(nd_body, "rescue clause");
+        F_NODE(nd_args, RNODE_RESBODY, "rescue exceptions");
+        F_NODE(nd_body, RNODE_RESBODY, "rescue clause");
         LAST_NODE;
-        F_NODE(nd_head, "next rescue clause");
+        F_NODE(nd_head, RNODE_RESBODY, "next rescue clause");
         return;
 
       case NODE_ENSURE:
         ANN("ensure clause");
         ANN("format: begin; [nd_head]; ensure; [nd_ensr]; end");
         ANN("example: begin; foo; ensure; bar; end");
-        F_NODE(nd_head, "body");
+        F_NODE(nd_head, RNODE_ENSURE, "body");
         LAST_NODE;
-        F_NODE(nd_ensr, "ensure clause");
+        F_NODE(nd_ensr, RNODE_ENSURE, "ensure clause");
         return;
 
       case NODE_AND:
@@ -366,24 +369,24 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("example: foo || bar");
       andor:
         while (1) {
-            F_NODE(nd_1st, "left expr");
-            if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type))
+            F_NODE(nd_1st, RNODE_AND, "left expr");
+            if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type))
                 break;
-            node = node->nd_2nd;
+            node = RNODE_AND(node)->nd_2nd;
         }
         LAST_NODE;
-        F_NODE(nd_2nd, "right expr");
+        F_NODE(nd_2nd, RNODE_AND, "right expr");
         return;
 
       case NODE_MASGN:
         ANN("multiple assignment");
         ANN("format: [nd_head], [nd_args] = [nd_value]");
         ANN("example: a, b = foo");
-        F_NODE(nd_value, "rhsn");
-        F_NODE(nd_head, "lhsn");
-        if (NODE_NAMED_REST_P(node->nd_args)) {
+        F_NODE(nd_value, RNODE_MASGN, "rhsn");
+        F_NODE(nd_head, RNODE_MASGN, "lhsn");
+        if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) {
             LAST_NODE;
-            F_NODE(nd_args, "splatn");
+            F_NODE(nd_args, RNODE_MASGN, "splatn");
         }
         else {
             F_MSG(nd_args, "splatn", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
@@ -394,13 +397,13 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("local variable assignment");
         ANN("format: [nd_vid](lvar) = [nd_value]");
         ANN("example: x = foo");
-        F_ID(nd_vid, "local variable");
-        if (NODE_REQUIRED_KEYWORD_P(node)) {
+        F_ID(nd_vid, RNODE_LASGN, "local variable");
+        if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node))) {
             F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
         }
         else {
             LAST_NODE;
-            F_NODE(nd_value, "rvalue");
+            F_NODE(nd_value, RNODE_LASGN, "rvalue");
         }
         return;
       case NODE_DASGN:
@@ -408,65 +411,65 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_vid](dvar) = [nd_value]");
         ANN("example: x = nil; 1.times { x = foo }");
         ANN("example: 1.times { x = foo }");
-        F_ID(nd_vid, "local variable");
-        if (NODE_REQUIRED_KEYWORD_P(node)) {
+        F_ID(nd_vid, RNODE_DASGN, "local variable");
+        if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node))) {
             F_MSG(nd_value, "rvalue", "NODE_SPECIAL_REQUIRED_KEYWORD (required keyword argument)");
         }
         else {
             LAST_NODE;
-            F_NODE(nd_value, "rvalue");
+            F_NODE(nd_value, RNODE_DASGN, "rvalue");
         }
         return;
       case NODE_IASGN:
         ANN("instance variable assignment");
         ANN("format: [nd_vid](ivar) = [nd_value]");
         ANN("example: @x = foo");
-        F_ID(nd_vid, "instance variable");
+        F_ID(nd_vid, RNODE_IASGN, "instance variable");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_IASGN, "rvalue");
         return;
       case NODE_CVASGN:
         ANN("class variable assignment");
         ANN("format: [nd_vid](cvar) = [nd_value]");
         ANN("example: @@x = foo");
-        F_ID(nd_vid, "class variable");
+        F_ID(nd_vid, RNODE_CVASGN, "class variable");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_CVASGN, "rvalue");
         return;
       case NODE_GASGN:
         ANN("global variable assignment");
         ANN("format: [nd_vid](gvar) = [nd_value]");
         ANN("example: $x = foo");
-        F_ID(nd_vid, "global variable");
+        F_ID(nd_vid, RNODE_GASGN, "global variable");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_GASGN, "rvalue");
         return;
 
       case NODE_CDECL:
         ANN("constant declaration");
         ANN("format: [nd_else]::[nd_vid](constant) = [nd_value]");
         ANN("example: X = foo");
-        if (node->nd_vid) {
-            F_ID(nd_vid, "constant");
+        if (RNODE_CDECL(node)->nd_vid) {
+            F_ID(nd_vid, RNODE_CDECL, "constant");
             F_MSG(nd_else, "extension", "not used");
         }
         else {
             F_MSG(nd_vid, "constant", "0 (see extension field)");
-            F_NODE(nd_else, "extension");
+            F_NODE(nd_else, RNODE_CDECL, "extension");
         }
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_CDECL, "rvalue");
         return;
 
       case NODE_OP_ASGN1:
         ANN("array assignment with operator");
         ANN("format: [nd_recv] [ [nd_args->nd_head] ] [nd_mid]= [nd_args->nd_body]");
         ANN("example: ary[1] += foo");
-        F_NODE(nd_recv, "receiver");
-        F_ID(nd_mid, "operator");
-        F_NODE(nd_args->nd_head, "index");
+        F_NODE(nd_recv, RNODE_OP_ASGN1, "receiver");
+        F_ID(nd_mid, RNODE_OP_ASGN1, "operator");
+        F_NODE(nd_args->nd_head, RNODE_OP_ASGN1, "index");
         LAST_NODE;
-        F_NODE(nd_args->nd_body, "rvalue");
+        F_NODE(nd_args->nd_body, RNODE_OP_ASGN1, "rvalue");
         return;
 
       case NODE_OP_ASGN2:
@@ -474,14 +477,14 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_recv].[attr] [nd_next->nd_mid]= [nd_value]");
         ANN("          where [attr]: [nd_next->nd_vid]");
         ANN("example: struct.field += foo");
-        F_NODE(nd_recv, "receiver");
+        F_NODE(nd_recv, RNODE_OP_ASGN2, "receiver");
         F_CUSTOM1(nd_next->nd_vid, "attr") {
-            if (node->nd_next->nd_aid) A("? ");
-            A_ID(node->nd_next->nd_vid);
+            if (RNODE_OP_ASGN2(node)->nd_next->nd_aid) A("? ");
+            A_ID(RNODE_OP_ASGN2(node)->nd_next->nd_vid);
         }
-        F_ID(nd_next->nd_mid, "operator");
+        F_ID(nd_next->nd_mid, RNODE_OP_ASGN2, "operator");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_OP_ASGN2, "rvalue");
         return;
 
       case NODE_OP_ASGN_AND:
@@ -494,65 +497,65 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_head] ||= [nd_value]");
         ANN("example: foo ||= bar");
       asgn_andor:
-        F_NODE(nd_head, "variable");
+        F_NODE(nd_head, RNODE_OP_ASGN_AND, "variable");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_OP_ASGN_AND, "rvalue");
         return;
 
       case NODE_OP_CDECL:
         ANN("constant declaration with operator");
         ANN("format: [nd_head](constant) [nd_aid]= [nd_value]");
         ANN("example: A::B ||= 1");
-        F_NODE(nd_head, "constant");
-        F_ID(nd_aid, "operator");
+        F_NODE(nd_head, RNODE_OP_CDECL, "constant");
+        F_ID(nd_aid, RNODE_OP_CDECL, "operator");
         LAST_NODE;
-        F_NODE(nd_value, "rvalue");
+        F_NODE(nd_value, RNODE_OP_CDECL, "rvalue");
         return;
 
       case NODE_CALL:
         ANN("method invocation");
         ANN("format: [nd_recv].[nd_mid]([nd_args])");
         ANN("example: obj.foo(1)");
-        F_ID(nd_mid, "method id");
-        F_NODE(nd_recv, "receiver");
+        F_ID(nd_mid, RNODE_CALL, "method id");
+        F_NODE(nd_recv, RNODE_CALL, "receiver");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_CALL, "arguments");
         return;
 
       case NODE_OPCALL:
         ANN("method invocation");
         ANN("format: [nd_recv] [nd_mid] [nd_args]");
         ANN("example: foo + bar");
-        F_ID(nd_mid, "method id");
-        F_NODE(nd_recv, "receiver");
+        F_ID(nd_mid, RNODE_OPCALL, "method id");
+        F_NODE(nd_recv, RNODE_OPCALL, "receiver");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_OPCALL, "arguments");
         return;
 
       case NODE_FCALL:
         ANN("function call");
         ANN("format: [nd_mid]([nd_args])");
         ANN("example: foo(1)");
-        F_ID(nd_mid, "method id");
+        F_ID(nd_mid, RNODE_FCALL, "method id");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_FCALL, "arguments");
         return;
 
       case NODE_VCALL:
         ANN("function call with no argument");
         ANN("format: [nd_mid]");
         ANN("example: foo");
-        F_ID(nd_mid, "method id");
+        F_ID(nd_mid, RNODE_VCALL, "method id");
         return;
 
       case NODE_QCALL:
         ANN("safe method invocation");
         ANN("format: [nd_recv]&.[nd_mid]([nd_args])");
         ANN("example: obj&.foo(1)");
-        F_ID(nd_mid, "method id");
-        F_NODE(nd_recv, "receiver");
+        F_ID(nd_mid, RNODE_QCALL, "method id");
+        F_NODE(nd_recv, RNODE_QCALL, "receiver");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_QCALL, "arguments");
         return;
 
       case NODE_SUPER:
@@ -560,7 +563,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: super [nd_args]");
         ANN("example: super 1");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_SUPER, "arguments");
         return;
 
       case NODE_ZSUPER:
@@ -589,7 +592,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         return;
 
       case NODE_HASH:
-        if (!node->nd_brace) {
+        if (!RNODE_HASH(node)->nd_brace) {
             ANN("keyword arguments");
             ANN("format: [nd_head]");
             ANN("example: a: 1, b: 2");
@@ -600,13 +603,13 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
             ANN("example: { 1 => 2, 3 => 4 }");
         }
         F_CUSTOM1(nd_brace, "keyword arguments or hash literal") {
-            switch (node->nd_brace) {
+            switch (RNODE_HASH(node)->nd_brace) {
               case 0: A("0 (keyword argument)"); break;
               case 1: A("1 (hash literal)"); break;
             }
         }
         LAST_NODE;
-        F_NODE(nd_head, "contents");
+        F_NODE(nd_head, RNODE_HASH, "contents");
         return;
 
       case NODE_YIELD:
@@ -614,52 +617,52 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: yield [nd_head]");
         ANN("example: yield 1");
         LAST_NODE;
-        F_NODE(nd_head, "arguments");
+        F_NODE(nd_head, RNODE_YIELD, "arguments");
         return;
 
       case NODE_LVAR:
         ANN("local variable reference");
         ANN("format: [nd_vid](lvar)");
         ANN("example: x");
-        F_ID(nd_vid, "local variable");
+        F_ID(nd_vid, RNODE_LVAR, "local variable");
         return;
       case NODE_DVAR:
         ANN("dynamic variable reference");
         ANN("format: [nd_vid](dvar)");
         ANN("example: 1.times { x = 1; x }");
-        F_ID(nd_vid, "local variable");
+        F_ID(nd_vid, RNODE_DVAR, "local variable");
         return;
       case NODE_IVAR:
         ANN("instance variable reference");
         ANN("format: [nd_vid](ivar)");
         ANN("example: @x");
-        F_ID(nd_vid, "instance variable");
+        F_ID(nd_vid, RNODE_IVAR, "instance variable");
         return;
       case NODE_CONST:
         ANN("constant reference");
         ANN("format: [nd_vid](constant)");
         ANN("example: X");
-        F_ID(nd_vid, "constant");
+        F_ID(nd_vid, RNODE_CONST, "constant");
         return;
       case NODE_CVAR:
         ANN("class variable reference");
         ANN("format: [nd_vid](cvar)");
         ANN("example: @@x");
-        F_ID(nd_vid, "class variable");
+        F_ID(nd_vid, RNODE_CVAR, "class variable");
         return;
 
       case NODE_GVAR:
         ANN("global variable reference");
         ANN("format: [nd_vid](gvar)");
         ANN("example: $x");
-        F_ID(nd_vid, "global variable");
+        F_ID(nd_vid, RNODE_GVAR, "global variable");
         return;
 
       case NODE_NTH_REF:
         ANN("nth special variable reference");
         ANN("format: $[nd_nth]");
         ANN("example: $1, $2, ..");
-        F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(node->nd_nth); }
+        F_CUSTOM1(nd_nth, "variable") { A("$"); A_LONG(RNODE_NTH_REF(node)->nd_nth); }
         return;
 
       case NODE_BACK_REF:
@@ -668,7 +671,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("example: $&, $`, $', $+");
         F_CUSTOM1(nd_nth, "variable") {
             char name[3] = "$ ";
-            name[1] = (char)node->nd_nth;
+            name[1] = (char)RNODE_BACK_REF(node)->nd_nth;
             A(name);
         }
         return;
@@ -677,19 +680,19 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("match expression (against $_ implicitly)");
         ANN("format: [nd_lit] (in condition)");
         ANN("example: if /foo/; foo; end");
-        F_LIT(nd_lit, "regexp");
+        F_LIT(nd_lit, RNODE_MATCH, "regexp");
         return;
 
       case NODE_MATCH2:
         ANN("match expression (regexp first)");
         ANN("format: [nd_recv] =~ [nd_value]");
         ANN("example: /foo/ =~ 'foo'");
-        F_NODE(nd_recv, "regexp (receiver)");
-        if (!node->nd_args) LAST_NODE;
-        F_NODE(nd_value, "string (argument)");
-        if (node->nd_args) {
+        F_NODE(nd_recv, RNODE_MATCH2, "regexp (receiver)");
+        if (!RNODE_MATCH2(node)->nd_args) LAST_NODE;
+        F_NODE(nd_value, RNODE_MATCH2, "string (argument)");
+        if (RNODE_MATCH2(node)->nd_args) {
             LAST_NODE;
-            F_NODE(nd_args, "named captures");
+            F_NODE(nd_args, RNODE_MATCH2, "named captures");
         }
         return;
 
@@ -697,9 +700,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("match expression (regexp second)");
         ANN("format: [nd_recv] =~ [nd_value]");
         ANN("example: 'foo' =~ /foo/");
-        F_NODE(nd_recv, "string (receiver)");
+        F_NODE(nd_recv, RNODE_MATCH3, "string (receiver)");
         LAST_NODE;
-        F_NODE(nd_value, "regexp (argument)");
+        F_NODE(nd_value, RNODE_MATCH3, "regexp (argument)");
         return;
 
       case NODE_LIT:
@@ -717,7 +720,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_lit]");
         ANN("example: `foo`");
       lit:
-        F_LIT(nd_lit, "literal");
+        F_LIT(nd_lit, RNODE_LIT, "literal");
         return;
 
       case NODE_ONCE:
@@ -725,8 +728,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_body]");
         ANN("example: /foo#{ bar }baz/o");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_ONCE, "body");
         return;
+
       case NODE_DSTR:
         ANN("string literal with interpolation");
         ANN("format: [nd_lit]");
@@ -747,11 +751,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_lit]");
         ANN("example: :\"foo#{ bar }baz\"");
       dlit:
-        F_LIT(nd_lit, "preceding string");
-        if (!node->nd_next) return;
-        F_NODE(nd_next->nd_head, "interpolation");
+        F_LIT(nd_lit, RNODE_DSTR, "preceding string");
+        if (!RNODE_DSTR(node)->nd_next) return;
+        F_NODE(nd_next->nd_head, RNODE_DSTR, "interpolation");
         LAST_NODE;
-        F_NODE(nd_next->nd_next, "tailing strings");
+        F_NODE(nd_next->nd_next, RNODE_DSTR, "tailing strings");
         return;
 
       case NODE_EVSTR:
@@ -759,25 +763,25 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: \"..#{ [nd_body] }..\"");
         ANN("example: \"foo#{ bar }baz\"");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_EVSTR, "body");
         return;
 
       case NODE_ARGSCAT:
         ANN("splat argument following arguments");
         ANN("format: ..(*[nd_head], [nd_body..])");
         ANN("example: foo(*ary, post_arg1, post_arg2)");
-        F_NODE(nd_head, "preceding array");
+        F_NODE(nd_head, RNODE_ARGSCAT, "preceding array");
         LAST_NODE;
-        F_NODE(nd_body, "following array");
+        F_NODE(nd_body, RNODE_ARGSCAT, "following array");
         return;
 
       case NODE_ARGSPUSH:
         ANN("splat argument following one argument");
         ANN("format: ..(*[nd_head], [nd_body])");
         ANN("example: foo(*ary, post_arg)");
-        F_NODE(nd_head, "preceding array");
+        F_NODE(nd_head, RNODE_ARGSPUSH, "preceding array");
         LAST_NODE;
-        F_NODE(nd_body, "following element");
+        F_NODE(nd_body, RNODE_ARGSPUSH, "following element");
         return;
 
       case NODE_SPLAT:
@@ -785,52 +789,52 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: *[nd_head]");
         ANN("example: foo(*ary)");
         LAST_NODE;
-        F_NODE(nd_head, "splat'ed array");
+        F_NODE(nd_head, RNODE_SPLAT, "splat'ed array");
         return;
 
       case NODE_BLOCK_PASS:
         ANN("arguments with block argument");
         ANN("format: ..([nd_head], &[nd_body])");
         ANN("example: foo(x, &blk)");
-        F_NODE(nd_head, "other arguments");
+        F_NODE(nd_head, RNODE_BLOCK_PASS, "other arguments");
         LAST_NODE;
-        F_NODE(nd_body, "block argument");
+        F_NODE(nd_body, RNODE_BLOCK_PASS, "block argument");
         return;
 
       case NODE_DEFN:
         ANN("method definition");
         ANN("format: def [nd_mid] [nd_defn]; end");
         ANN("example: def foo; bar; end");
-        F_ID(nd_mid, "method name");
+        F_ID(nd_mid, RNODE_DEFN, "method name");
         LAST_NODE;
-        F_NODE(nd_defn, "method definition");
+        F_NODE(nd_defn, RNODE_DEFN, "method definition");
         return;
 
       case NODE_DEFS:
         ANN("singleton method definition");
         ANN("format: def [nd_recv].[nd_mid] [nd_defn]; end");
         ANN("example: def obj.foo; bar; end");
-        F_NODE(nd_recv, "receiver");
-        F_ID(nd_mid, "method name");
+        F_NODE(nd_recv, RNODE_DEFS, "receiver");
+        F_ID(nd_mid, RNODE_DEFS, "method name");
         LAST_NODE;
-        F_NODE(nd_defn, "method definition");
+        F_NODE(nd_defn, RNODE_DEFS, "method definition");
         return;
 
       case NODE_ALIAS:
         ANN("method alias statement");
         ANN("format: alias [nd_1st] [nd_2nd]");
         ANN("example: alias bar foo");
-        F_NODE(nd_1st, "new name");
+        F_NODE(nd_1st, RNODE_ALIAS, "new name");
         LAST_NODE;
-        F_NODE(nd_2nd, "old name");
+        F_NODE(nd_2nd, RNODE_ALIAS, "old name");
         return;
 
       case NODE_VALIAS:
         ANN("global variable alias statement");
         ANN("format: alias [nd_alias](gvar) [nd_orig](gvar)");
         ANN("example: alias $y $x");
-        F_ID(nd_alias, "new name");
-        F_ID(nd_orig, "old name");
+        F_ID(nd_alias, RNODE_VALIAS, "new name");
+        F_ID(nd_orig, RNODE_VALIAS, "old name");
         return;
 
       case NODE_UNDEF:
@@ -838,51 +842,51 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: undef [nd_undef]");
         ANN("example: undef foo");
         LAST_NODE;
-        F_NODE(nd_undef, "old name");
+        F_NODE(nd_undef, RNODE_UNDEF, "old name");
         return;
 
       case NODE_CLASS:
         ANN("class definition");
         ANN("format: class [nd_cpath] < [nd_super]; [nd_body]; end");
         ANN("example: class C2 < C; ..; end");
-        F_NODE(nd_cpath, "class path");
-        F_NODE(nd_super, "superclass");
+        F_NODE(nd_cpath, RNODE_CLASS, "class path");
+        F_NODE(nd_super, RNODE_CLASS, "superclass");
         LAST_NODE;
-        F_NODE(nd_body, "class definition");
+        F_NODE(nd_body, RNODE_CLASS, "class definition");
         return;
 
       case NODE_MODULE:
         ANN("module definition");
         ANN("format: module [nd_cpath]; [nd_body]; end");
         ANN("example: module M; ..; end");
-        F_NODE(nd_cpath, "module path");
+        F_NODE(nd_cpath, RNODE_MODULE, "module path");
         LAST_NODE;
-        F_NODE(nd_body, "module definition");
+        F_NODE(nd_body, RNODE_MODULE, "module definition");
         return;
 
       case NODE_SCLASS:
         ANN("singleton class definition");
         ANN("format: class << [nd_recv]; [nd_body]; end");
         ANN("example: class << obj; ..; end");
-        F_NODE(nd_recv, "receiver");
+        F_NODE(nd_recv, RNODE_SCLASS, "receiver");
         LAST_NODE;
-        F_NODE(nd_body, "singleton class definition");
+        F_NODE(nd_body, RNODE_SCLASS, "singleton class definition");
         return;
 
       case NODE_COLON2:
         ANN("scoped constant reference");
         ANN("format: [nd_head]::[nd_mid]");
         ANN("example: M::C");
-        F_ID(nd_mid, "constant name");
+        F_ID(nd_mid, RNODE_COLON2, "constant name");
         LAST_NODE;
-        F_NODE(nd_head, "receiver");
+        F_NODE(nd_head, RNODE_COLON2, "receiver");
         return;
 
       case NODE_COLON3:
         ANN("top-level constant reference");
         ANN("format: ::[nd_mid]");
         ANN("example: ::Object");
-        F_ID(nd_mid, "constant name");
+        F_ID(nd_mid, RNODE_COLON3, "constant name");
         return;
 
       case NODE_DOT2:
@@ -905,9 +909,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: [nd_beg]...[nd_end]");
         ANN("example: if (x==1)...(x==5); foo; end");
       dot:
-        F_NODE(nd_beg, "begin");
+        F_NODE(nd_beg, RNODE_DOT2, "begin");
         LAST_NODE;
-        F_NODE(nd_end, "end");
+        F_NODE(nd_end, RNODE_DOT2, "end");
         return;
 
       case NODE_SELF:
@@ -944,7 +948,7 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("defined? expression");
         ANN("format: defined?([nd_head])");
         ANN("example: defined?(foo)");
-        F_NODE(nd_head, "expr");
+        F_NODE(nd_head, RNODE_DEFINED, "expr");
         return;
 
       case NODE_POSTEXE:
@@ -952,17 +956,17 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: END { [nd_body] }");
         ANN("example: END { foo }");
         LAST_NODE;
-        F_NODE(nd_body, "END clause");
+        F_NODE(nd_body, RNODE_POSTEXE, "END clause");
         return;
 
       case NODE_ATTRASGN:
         ANN("attr assignment");
         ANN("format: [nd_recv].[nd_mid] = [nd_args]");
         ANN("example: struct.field = foo");
-        F_NODE(nd_recv, "receiver");
-        F_ID(nd_mid, "method name");
+        F_NODE(nd_recv, RNODE_ATTRASGN, "receiver");
+        F_ID(nd_mid, RNODE_ATTRASGN, "method name");
         LAST_NODE;
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_ATTRASGN, "arguments");
         return;
 
       case NODE_LAMBDA:
@@ -970,70 +974,70 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         ANN("format: -> [nd_body]");
         ANN("example: -> { foo }");
         LAST_NODE;
-        F_NODE(nd_body, "lambda clause");
+        F_NODE(nd_body, RNODE_LAMBDA, "lambda clause");
         return;
 
       case NODE_OPT_ARG:
         ANN("optional arguments");
         ANN("format: def method_name([nd_body=some], [nd_next..])");
         ANN("example: def foo(a, b=1, c); end");
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_OPT_ARG, "body");
         LAST_NODE;
-        F_NODE(nd_next, "next");
+        F_NODE(nd_next, RNODE_OPT_ARG, "next");
         return;
 
       case NODE_KW_ARG:
         ANN("keyword arguments");
         ANN("format: def method_name([nd_body=some], [nd_next..])");
         ANN("example: def foo(a:1, b:2); end");
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_KW_ARG, "body");
         LAST_NODE;
-        F_NODE(nd_next, "next");
+        F_NODE(nd_next, RNODE_KW_ARG, "next");
         return;
 
       case NODE_POSTARG:
         ANN("post arguments");
         ANN("format: *[nd_1st], [nd_2nd..] = ..");
         ANN("example: a, *rest, z = foo");
-        if (NODE_NAMED_REST_P(node->nd_1st)) {
-            F_NODE(nd_1st, "rest argument");
+        if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) {
+            F_NODE(nd_1st, RNODE_POSTARG, "rest argument");
         }
         else {
             F_MSG(nd_1st, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
         }
         LAST_NODE;
-        F_NODE(nd_2nd, "post arguments");
+        F_NODE(nd_2nd, RNODE_POSTARG, "post arguments");
         return;
 
       case NODE_ARGS:
         ANN("method parameters");
         ANN("format: def method_name(.., [nd_ainfo->nd_optargs], *[nd_ainfo->rest_arg], [nd_ainfo->first_post_arg], .., [nd_ainfo->kw_args], **[nd_ainfo->kw_rest_arg], &[nd_ainfo->block_arg])");
         ANN("example: def foo(a, b, opt1=1, opt2=2, *rest, y, z, kw: 1, **kwrest, &blk); end");
-        F_INT(nd_ainfo->pre_args_num, "count of mandatory (pre-)arguments");
-        F_NODE(nd_ainfo->pre_init, "initialization of (pre-)arguments");
-        F_INT(nd_ainfo->post_args_num, "count of mandatory post-arguments");
-        F_NODE(nd_ainfo->post_init, "initialization of post-arguments");
-        F_ID(nd_ainfo->first_post_arg, "first post argument");
+        F_INT(nd_ainfo->pre_args_num, RNODE_ARGS, "count of mandatory (pre-)arguments");
+        F_NODE(nd_ainfo->pre_init, RNODE_ARGS, "initialization of (pre-)arguments");
+        F_INT(nd_ainfo->post_args_num, RNODE_ARGS, "count of mandatory post-arguments");
+        F_NODE(nd_ainfo->post_init, RNODE_ARGS, "initialization of post-arguments");
+        F_ID(nd_ainfo->first_post_arg, RNODE_ARGS, "first post argument");
         F_CUSTOM1(nd_ainfo->rest_arg, "rest argument") {
-            if (node->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
+            if (RNODE_ARGS(node)->nd_ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA) {
                 A("1 (excessed comma)");
             }
             else {
-                A_ID(node->nd_ainfo->rest_arg);
+                A_ID(RNODE_ARGS(node)->nd_ainfo->rest_arg);
             }
         }
-        F_ID(nd_ainfo->block_arg, "block argument");
-        F_NODE(nd_ainfo->opt_args, "optional arguments");
-        F_NODE(nd_ainfo->kw_args, "keyword arguments");
+        F_ID(nd_ainfo->block_arg, RNODE_ARGS, "block argument");
+        F_NODE(nd_ainfo->opt_args, RNODE_ARGS, "optional arguments");
+        F_NODE(nd_ainfo->kw_args, RNODE_ARGS, "keyword arguments");
         LAST_NODE;
-        F_NODE(nd_ainfo->kw_rest_arg, "keyword rest argument");
+        F_NODE(nd_ainfo->kw_rest_arg, RNODE_ARGS, "keyword rest argument");
         return;
 
       case NODE_SCOPE:
         ANN("new scope");
         ANN("format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body");
         F_CUSTOM1(nd_tbl, "local table") {
-            rb_ast_id_table_t *tbl = node->nd_tbl;
+            rb_ast_id_table_t *tbl = RNODE_SCOPE(node)->nd_tbl;
             int i;
             int size = tbl ? tbl->size : 0;
             if (size == 0) A("(empty)");
@@ -1041,41 +1045,41 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
                 A_ID(tbl->ids[i]); if (i < size - 1) A(",");
             }
         }
-        F_NODE(nd_args, "arguments");
+        F_NODE(nd_args, RNODE_SCOPE, "arguments");
         LAST_NODE;
-        F_NODE(nd_body, "body");
+        F_NODE(nd_body, RNODE_SCOPE, "body");
         return;
 
       case NODE_ARYPTN:
         ANN("array pattern");
         ANN("format: [nd_pconst]([pre_args], ..., *[rest_arg], [post_args], ...)");
-        F_NODE(nd_pconst, "constant");
-        F_NODE(nd_apinfo->pre_args, "pre arguments");
-        if (NODE_NAMED_REST_P(node->nd_apinfo->rest_arg)) {
-            F_NODE(nd_apinfo->rest_arg, "rest argument");
+        F_NODE(nd_pconst, RNODE_ARYPTN, "constant");
+        F_NODE(nd_apinfo->pre_args, RNODE_ARYPTN, "pre arguments");
+        if (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->nd_apinfo->rest_arg)) {
+            F_NODE(nd_apinfo->rest_arg, RNODE_ARYPTN, "rest argument");
         }
         else {
             F_MSG(nd_apinfo->rest_arg, "rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
         }
         LAST_NODE;
-        F_NODE(nd_apinfo->post_args, "post arguments");
+        F_NODE(nd_apinfo->post_args, RNODE_ARYPTN, "post arguments");
         return;
 
       case NODE_FNDPTN:
         ANN("find pattern");
         ANN("format: [nd_pconst](*[pre_rest_arg], args, ..., *[post_rest_arg])");
-        F_NODE(nd_pconst, "constant");
-        if (NODE_NAMED_REST_P(node->nd_fpinfo->pre_rest_arg)) {
-            F_NODE(nd_fpinfo->pre_rest_arg, "pre rest argument");
+        F_NODE(nd_pconst, RNODE_FNDPTN, "constant");
+        if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->nd_fpinfo->pre_rest_arg)) {
+            F_NODE(nd_fpinfo->pre_rest_arg, RNODE_FNDPTN, "pre rest argument");
         }
         else {
             F_MSG(nd_fpinfo->pre_rest_arg, "pre rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
         }
-        F_NODE(nd_fpinfo->args, "arguments");
+        F_NODE(nd_fpinfo->args, RNODE_FNDPTN, "arguments");
 
         LAST_NODE;
-        if (NODE_NAMED_REST_P(node->nd_fpinfo->post_rest_arg)) {
-            F_NODE(nd_fpinfo->post_rest_arg, "post rest argument");
+        if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->nd_fpinfo->post_rest_arg)) {
+            F_NODE(nd_fpinfo->post_rest_arg, RNODE_FNDPTN, "post rest argument");
         }
         else {
             F_MSG(nd_fpinfo->post_rest_arg, "post rest argument", "NODE_SPECIAL_NO_NAME_REST (rest argument without name)");
@@ -1085,14 +1089,14 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
       case NODE_HSHPTN:
         ANN("hash pattern");
         ANN("format: [nd_pconst]([nd_pkwargs], ..., **[nd_pkwrestarg])");
-        F_NODE(nd_pconst, "constant");
-        F_NODE(nd_pkwargs, "keyword arguments");
+        F_NODE(nd_pconst, RNODE_HSHPTN, "constant");
+        F_NODE(nd_pkwargs, RNODE_HSHPTN, "keyword arguments");
         LAST_NODE;
-        if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
+        if (RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) {
             F_MSG(nd_pkwrestarg, "keyword rest argument", "NODE_SPECIAL_NO_REST_KEYWORD (**nil)");
         }
         else {
-            F_NODE(nd_pkwrestarg, "keyword rest argument");
+            F_NODE(nd_pkwrestarg, RNODE_HSHPTN, "keyword rest argument");
         }
         return;
       case NODE_ERROR:
@@ -1100,6 +1104,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
         return;
 
       case NODE_ARGS_AUX:
+      case NODE_DEF_TEMP:
+      case NODE_DEF_TEMP2:
+      case NODE_RIPPER:
+      case NODE_RIPPER_VALUES:
       case NODE_LAST:
         break;
     }
diff --git a/parse.y b/parse.y
index a011571..b24852c 100644 (file)
--- a/parse.y
+++ b/parse.y
@@ -852,8 +852,7 @@ static void token_info_drop(struct parser_params *p, const char *token, rb_code_
 #define token_column           ((int)(p->lex.ptok - p->lex.pbeg))
 
 #define CALL_Q_P(q) ((q) == TOKEN2VAL(tANDDOT))
-#define NODE_CALL_Q(q) (CALL_Q_P(q) ? NODE_QCALL : NODE_CALL)
-#define NEW_QCALL(q,r,m,a,loc) NEW_NODE(NODE_CALL_Q(q),r,m,a,loc)
+#define NEW_QCALL(q,r,m,a,loc) (CALL_Q_P(q) ? NEW_QCALL0(r,m,a,loc) : NEW_CALL(r,m,a,loc))
 
 #define lambda_beginning_p() (p->lex.lpar_beg == p->lex.paren_nest)
 
@@ -878,17 +877,235 @@ add_mark_object(struct parser_params *p, VALUE obj)
     }
     return obj;
 }
+
+static rb_node_ripper_t *rb_node_ripper_new(struct parser_params *p, ID a, VALUE b, VALUE c, const YYLTYPE *loc);
+static rb_node_ripper_values_t *rb_node_ripper_values_new(struct parser_params *p, VALUE a, VALUE b, VALUE c, const YYLTYPE *loc);
+#define NEW_RIPPER(a,b,c,loc) (VALUE)rb_node_ripper_new(p,a,b,c,loc)
+#define NEW_RIPPER_VALUES(a,b,c,loc) (VALUE)rb_node_ripper_values_new(p,a,b,c,loc)
+
 #else
-static NODE* node_newnode_with_locals(struct parser_params *, enum node_type, VALUE, VALUE, const rb_code_location_t*);
+static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_block_t *rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc);
+static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc);
+static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc);
+static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc);
+static rb_node_iter_t *rb_node_iter_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_for_masgn_t *rb_node_for_masgn_new(struct parser_params *p, NODE *nd_var, const YYLTYPE *loc);
+static rb_node_retry_t *rb_node_retry_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_begin_t *rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_rescue_t *rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc);
+static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_ensure_t *rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc);
+static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
+static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
+static rb_node_masgn_t *rb_node_masgn_new(struct parser_params *p, NODE *nd_head, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_lasgn_t *rb_node_lasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_dasgn_t *rb_node_dasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_gasgn_t *rb_node_gasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_iasgn_t *rb_node_iasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_cdecl_t *rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, const YYLTYPE *loc);
+static rb_node_cvasgn_t *rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, rb_node_argscat_t *nd_args, const YYLTYPE *loc);
+static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, rb_node_op_asgn22_t *nd_next, const YYLTYPE *loc);
+static rb_node_op_asgn22_t *rb_node_op_asgn22_new(struct parser_params *p, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc);
+static rb_node_op_asgn_or_t *rb_node_op_asgn_or_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_op_asgn_and_t *rb_node_op_asgn_and_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_op_cdecl_t *rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, const YYLTYPE *loc);
+static rb_node_call_t *rb_node_call_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_opcall_t *rb_node_opcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_fcall_t *rb_node_fcall_new(struct parser_params *p, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_vcall_t *rb_node_vcall_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc);
+static rb_node_qcall_t *rb_node_qcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_super_t *rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_zsuper_t * rb_node_zsuper_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_list_t *rb_node_list_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_list_t *rb_node_list_new2(struct parser_params *p, NODE *nd_head, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_zlist_t *rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_hash_t *rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
+static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_lvar_t *rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_dvar_t *rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_gvar_t *rb_node_gvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_ivar_t *rb_node_ivar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_const_t *rb_node_const_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_cvar_t *rb_node_cvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
+static rb_node_nth_ref_t *rb_node_nth_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc);
+static rb_node_back_ref_t *rb_node_back_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc);
+static rb_node_match2_t *rb_node_match2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_match3_t *rb_node_match3_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc);
+static rb_node_lit_t *rb_node_lit_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc);
+static rb_node_str_t *rb_node_str_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc);
+static rb_node_dstr_t *rb_node_dstr_new0(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_dstr_t *rb_node_dstr_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc);
+static rb_node_xstr_t *rb_node_xstr_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc);
+static rb_node_dxstr_t *rb_node_dxstr_new(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_once_t *rb_node_once_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_args_t *rb_node_args_new(struct parser_params *p, struct rb_args_info *nd_ainfo, const YYLTYPE *loc);
+static rb_node_args_aux_t *rb_node_args_aux_new(struct parser_params *p, ID nd_pid, long nd_plen, const YYLTYPE *loc);
+static rb_node_opt_arg_t *rb_node_opt_arg_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_kw_arg_t *rb_node_kw_arg_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_postarg_t *rb_node_postarg_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
+static rb_node_argscat_t *rb_node_argscat_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_argspush_t *rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_splat_t *rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_block_pass_t *rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_defn_t *rb_node_defn_new(struct parser_params *p, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc);
+static rb_node_defs_t *rb_node_defs_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc);
+static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
+static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc);
+static rb_node_undef_t *rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc);
+static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc);
+static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc);
+static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc);
+static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc);
+static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc);
+static rb_node_self_t *rb_node_self_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_nil_t *rb_node_nil_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_true_t *rb_node_true_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_false_t *rb_node_false_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_errinfo_t *rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_defined_t *rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_dsym_t *rb_node_dsym_new(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_attrasgn_t *rb_node_attrasgn_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_aryptn_t *rb_node_aryptn_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_hshptn_t *rb_node_hshptn_new(struct parser_params *p, NODE *nd_pconst, NODE *nd_pkwargs, NODE *nd_pkwrestarg, const YYLTYPE *loc);
+static rb_node_fndptn_t *rb_node_fndptn_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE *loc);
+
+#define NEW_SCOPE(a,b,loc) (NODE *)rb_node_scope_new(p,a,b,loc)
+#define NEW_SCOPE2(t,a,b,loc) (NODE *)rb_node_scope_new2(p,t,a,b,loc)
+#define NEW_BLOCK(a,loc) (NODE *)rb_node_block_new(p,a,loc)
+#define NEW_IF(c,t,e,loc) (NODE *)rb_node_if_new(p,c,t,e,loc)
+#define NEW_UNLESS(c,t,e,loc) (NODE *)rb_node_unless_new(p,c,t,e,loc)
+#define NEW_CASE(h,b,loc) (NODE *)rb_node_case_new(p,h,b,loc)
+#define NEW_CASE2(b,loc) (NODE *)rb_node_case2_new(p,b,loc)
+#define NEW_CASE3(h,b,loc) (NODE *)rb_node_case3_new(p,h,b,loc)
+#define NEW_WHEN(c,t,e,loc) (NODE *)rb_node_when_new(p,c,t,e,loc)
+#define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc)
+#define NEW_WHILE(c,b,n,loc) (NODE *)rb_node_while_new(p,c,b,n,loc)
+#define NEW_UNTIL(c,b,n,loc) (NODE *)rb_node_until_new(p,c,b,n,loc)
+#define NEW_ITER(a,b,loc) (NODE *)rb_node_iter_new(p,a,b,loc)
+#define NEW_FOR(i,b,loc) (NODE *)rb_node_for_new(p,i,b,loc)
+#define NEW_FOR_MASGN(v,loc) (NODE *)rb_node_for_masgn_new(p,v,loc)
+#define NEW_RETRY(loc) (NODE *)rb_node_retry_new(p,loc)
+#define NEW_BEGIN(b,loc) (NODE *)rb_node_begin_new(p,b,loc)
+#define NEW_RESCUE(b,res,e,loc) (NODE *)rb_node_rescue_new(p,b,res,e,loc)
+#define NEW_RESBODY(a,ex,n,loc) (NODE *)rb_node_resbody_new(p,a,ex,n,loc)
+#define NEW_ENSURE(b,en,loc) (NODE *)rb_node_ensure_new(p,b,en,loc)
+#define NEW_AND(f,s,loc) (NODE *)rb_node_and_new(p,f,s,loc)
+#define NEW_OR(f,s,loc) (NODE *)rb_node_or_new(p,f,s,loc)
+#define NEW_MASGN(l,r,loc)   (NODE *)rb_node_masgn_new(p,l,r,loc)
+#define NEW_LASGN(v,val,loc) (NODE *)rb_node_lasgn_new(p,v,val,loc)
+#define NEW_DASGN(v,val,loc) (NODE *)rb_node_dasgn_new(p,v,val,loc)
+#define NEW_GASGN(v,val,loc) (NODE *)rb_node_gasgn_new(p,v,val,loc)
+#define NEW_IASGN(v,val,loc) (NODE *)rb_node_iasgn_new(p,v,val,loc)
+#define NEW_CDECL(v,val,path,loc) (NODE *)rb_node_cdecl_new(p,v,val,path,loc)
+#define NEW_CVASGN(v,val,loc) (NODE *)rb_node_cvasgn_new(p,v,val,loc)
+#define NEW_OP_ASGN1(r,id,a,loc) (NODE *)rb_node_op_asgn1_new(p,r,id,a,loc)
+#define NEW_OP_ASGN2(r,t,i,o,val,loc) (NODE *)rb_node_op_asgn2_new(p,r,val,NEW_OP_ASGN22(i,o,t,loc),loc)
+#define NEW_OP_ASGN22(i,o,t,loc) rb_node_op_asgn22_new(p,i,o,t,loc)
+#define NEW_OP_ASGN_OR(i,val,loc) (NODE *)rb_node_op_asgn_or_new(p,i,val,loc)
+#define NEW_OP_ASGN_AND(i,val,loc) (NODE *)rb_node_op_asgn_and_new(p,i,val,loc)
+#define NEW_OP_CDECL(v,op,val,loc) (NODE *)rb_node_op_cdecl_new(p,v,val,op,loc)
+#define NEW_CALL(r,m,a,loc) (NODE *)rb_node_call_new(p,r,m,a,loc)
+#define NEW_OPCALL(r,m,a,loc) (NODE *)rb_node_opcall_new(p,r,m,a,loc)
+#define NEW_FCALL(m,a,loc) (NODE *)rb_node_fcall_new(p,m,a,loc)
+#define NEW_VCALL(m,loc) (NODE *)rb_node_vcall_new(p,m,loc)
+#define NEW_QCALL0(r,m,a,loc) (NODE *)rb_node_qcall_new(p,r,m,a,loc)
+#define NEW_SUPER(a,loc) (NODE *)rb_node_super_new(p,a,loc)
+#define NEW_ZSUPER(loc) (NODE *)rb_node_zsuper_new(p,loc)
+#define NEW_LIST(a,loc) (NODE *)rb_node_list_new(p,a,loc)
+#define NEW_LIST2(h,l,n,loc) (NODE *)rb_node_list_new2(p,h,l,n,loc)
+#define NEW_ZLIST(loc) (NODE *)rb_node_zlist_new(p,loc)
+#define NEW_HASH(a,loc) (NODE *)rb_node_hash_new(p,a,loc)
+#define NEW_RETURN(s,loc) (NODE *)rb_node_return_new(p,s,loc)
+#define NEW_YIELD(a,loc) (NODE *)rb_node_yield_new(p,a,loc)
+#define NEW_LVAR(v,loc) (NODE *)rb_node_lvar_new(p,v,loc)
+#define NEW_DVAR(v,loc) (NODE *)rb_node_dvar_new(p,v,loc)
+#define NEW_GVAR(v,loc) (NODE *)rb_node_gvar_new(p,v,loc)
+#define NEW_IVAR(v,loc) (NODE *)rb_node_ivar_new(p,v,loc)
+#define NEW_CONST(v,loc) (NODE *)rb_node_const_new(p,v,loc)
+#define NEW_CVAR(v,loc) (NODE *)rb_node_cvar_new(p,v,loc)
+#define NEW_NTH_REF(n,loc)  (NODE *)rb_node_nth_ref_new(p,n,loc)
+#define NEW_BACK_REF(n,loc) (NODE *)rb_node_back_ref_new(p,n,loc)
+#define NEW_MATCH2(n1,n2,loc) (NODE *)rb_node_match2_new(p,n1,n2,loc)
+#define NEW_MATCH3(r,n2,loc) (NODE *)rb_node_match3_new(p,r,n2,loc)
+#define NEW_LIT(l,loc) (NODE *)rb_node_lit_new(p,l,loc)
+#define NEW_STR(s,loc) (NODE *)rb_node_str_new(p,s,loc)
+#define NEW_DSTR0(s,l,n,loc) (NODE *)rb_node_dstr_new0(p,s,l,n,loc)
+#define NEW_DSTR(s,loc) (NODE *)rb_node_dstr_new(p,s,loc)
+#define NEW_XSTR(s,loc) (NODE *)rb_node_xstr_new(p,s,loc)
+#define NEW_DXSTR(s,l,n,loc) (NODE *)rb_node_dxstr_new(p,s,l,n,loc)
+#define NEW_EVSTR(n,loc) (NODE *)rb_node_evstr_new(p,n,loc)
+#define NEW_ONCE(b,loc) (NODE *)rb_node_once_new(p,b,loc)
+#define NEW_ARGS(a,loc) (NODE *)rb_node_args_new(p,a,loc)
+#define NEW_ARGS_AUX(r,b,loc) (NODE *)rb_node_args_aux_new(p,r,b,loc)
+#define NEW_OPT_ARG(v,loc) (NODE *)rb_node_opt_arg_new(p,v,loc)
+#define NEW_KW_ARG(v,loc) (NODE *)rb_node_kw_arg_new(p,v,loc)
+#define NEW_POSTARG(i,v,loc) (NODE *)rb_node_postarg_new(p,i,v,loc)
+#define NEW_ARGSCAT(a,b,loc) (NODE *)rb_node_argscat_new(p,a,b,loc)
+#define NEW_ARGSPUSH(a,b,loc) (NODE *)rb_node_argspush_new(p,a,b,loc)
+#define NEW_SPLAT(a,loc) (NODE *)rb_node_splat_new(p,a,loc)
+#define NEW_BLOCK_PASS(b,loc) (NODE *)rb_node_block_pass_new(p,b,loc)
+#define NEW_DEFN(i,s,loc) (NODE *)rb_node_defn_new(p,i,s,loc)
+#define NEW_DEFS(r,i,s,loc) (NODE *)rb_node_defs_new(p,r,i,s,loc)
+#define NEW_ALIAS(n,o,loc) (NODE *)rb_node_alias_new(p,n,o,loc)
+#define NEW_VALIAS(n,o,loc) (NODE *)rb_node_valias_new(p,n,o,loc)
+#define NEW_UNDEF(i,loc) (NODE *)rb_node_undef_new(p,i,loc)
+#define NEW_CLASS(n,b,s,loc) (NODE *)rb_node_class_new(p,n,b,s,loc)
+#define NEW_MODULE(n,b,loc) (NODE *)rb_node_module_new(p,n,b,loc)
+#define NEW_SCLASS(r,b,loc) (NODE *)rb_node_sclass_new(p,r,b,loc)
+#define NEW_COLON2(c,i,loc) (NODE *)rb_node_colon2_new(p,c,i,loc)
+#define NEW_COLON3(i,loc) (NODE *)rb_node_colon3_new(p,i,loc)
+#define NEW_DOT2(b,e,loc) (NODE *)rb_node_dot2_new(p,b,e,loc)
+#define NEW_DOT3(b,e,loc) (NODE *)rb_node_dot3_new(p,b,e,loc)
+#define NEW_SELF(loc) (NODE *)rb_node_self_new(p,loc)
+#define NEW_NIL(loc) (NODE *)rb_node_nil_new(p,loc)
+#define NEW_TRUE(loc) (NODE *)rb_node_true_new(p,loc)
+#define NEW_FALSE(loc) (NODE *)rb_node_false_new(p,loc)
+#define NEW_ERRINFO(loc) (NODE *)rb_node_errinfo_new(p,loc)
+#define NEW_DEFINED(e,loc) (NODE *)rb_node_defined_new(p,e,loc)
+#define NEW_POSTEXE(b,loc) (NODE *)rb_node_postexe_new(p,b,loc)
+#define NEW_DSYM(s,l,n,loc) (NODE *)rb_node_dsym_new(p,s,l,n,loc)
+#define NEW_ATTRASGN(r,m,a,loc) (NODE *)rb_node_attrasgn_new(p,r,m,a,loc)
+#define NEW_LAMBDA(a,b,loc) (NODE *)rb_node_lambda_new(p,a,b,loc)
+#define NEW_ARYPTN(loc) (NODE *)rb_node_aryptn_new(p,loc)
+#define NEW_HSHPTN(c,kw,kwrest,loc) (NODE *)rb_node_hshptn_new(p,c,kw,kwrest,loc)
+#define NEW_FNDPTN(loc) (NODE *)rb_node_fndptn_new(p,loc)
+#define NEW_ERROR(loc) (NODE *)rb_node_error_new(p,loc)
+
 #endif
 
-static NODE* node_newnode(struct parser_params *, enum node_type, VALUE, VALUE, VALUE, const rb_code_location_t*);
-#define rb_node_newnode(type, a1, a2, a3, loc) node_newnode(p, (type), (a1), (a2), (a3), (loc))
+static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
+static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
+static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_def_temp_t *rb_node_def_temp_new(struct parser_params *p, ID nd_vid, ID nd_mid, rb_node_def_temp2_t *nd_next, const YYLTYPE *loc);
+static rb_node_def_temp2_t *rb_node_def_temp2_new(struct parser_params *p, NODE *nd_head, long nd_nth, VALUE nd_cval);
+
+#define NEW_BREAK(s,loc) (NODE *)rb_node_break_new(p,s,loc)
+#define NEW_NEXT(s,loc) (NODE *)rb_node_next_new(p,s,loc)
+#define NEW_REDO(loc) (NODE *)rb_node_redo_new(p,loc)
+#define NEW_DEF_TEMP(v,m,n,loc) (NODE *)rb_node_def_temp_new(p,v,m,n,loc)
+#define NEW_DEF_TEMP2(h,n,c) rb_node_def_temp2_new(p,h,n,c)
 
 /* Make a new internal node, which should not be appeared in the
  * result AST and does not have node_id and location. */
-static NODE* node_new_internal(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2);
-#define NODE_NEW_INTERNAL(t,a0,a1,a2) node_new_internal(p, (t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2))
+static NODE* node_new_internal(struct parser_params *p, enum node_type type, size_t size, size_t alignment);
+#define NODE_NEW_INTERNAL(node_type, type) (type *)node_new_internal(p, node_type, sizeof(type), RUBY_ALIGNOF(type))
 
 static NODE *nd_set_loc(NODE *nd, const YYLTYPE *loc);
 
@@ -923,7 +1140,7 @@ set_line_body(NODE *body, int line)
 static void
 set_embraced_location(NODE *node, const rb_code_location_t *beg, const rb_code_location_t *end)
 {
-    node->nd_body->nd_loc = code_loc_gen(beg, end);
+    RNODE_ITER(node)->nd_body->nd_loc = code_loc_gen(beg, end);
     nd_set_line(node, beg->end_pos.lineno);
 }
 
@@ -931,7 +1148,7 @@ static NODE *
 last_expr_node(NODE *expr)
 {
     if (nd_type_p(expr, NODE_BLOCK)) {
-        expr = expr->nd_end->nd_head;
+        expr = RNODE_BLOCK(RNODE_BLOCK(expr)->nd_end)->nd_head;
     }
     return expr;
 }
@@ -975,7 +1192,7 @@ static NODE *call_bin_op(struct parser_params*,NODE*,ID,NODE*,const YYLTYPE*,con
 static NODE *call_uni_op(struct parser_params*,NODE*,ID,const YYLTYPE*,const YYLTYPE*);
 static NODE *new_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *args, const YYLTYPE *op_loc, const YYLTYPE *loc);
 static NODE *new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *args, NODE *block, const YYLTYPE *op_loc, const YYLTYPE *loc);
-static NODE *method_add_block(struct parser_params*p, NODE *m, NODE *b, const YYLTYPE *loc) {b->nd_iter = m; b->nd_loc = *loc; return b;}
+static NODE *method_add_block(struct parser_params*p, NODE *m, NODE *b, const YYLTYPE *loc) {RNODE_ITER(b)->nd_iter = m; b->nd_loc = *loc; return b;}
 
 static bool args_info_empty_p(struct rb_args_info *args);
 static NODE *new_args(struct parser_params*,NODE*,NODE*,ID,NODE*,NODE*,const YYLTYPE*);
@@ -1046,17 +1263,13 @@ static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYP
 #define get_value(val) (val)
 #define get_num(num) (num)
 #else  /* RIPPER */
-#define NODE_RIPPER NODE_CDECL
-#define NEW_RIPPER(a,b,c,loc) (VALUE)NEW_CDECL(a,b,c,loc)
-#define NODE_RIPPER2 NODE_OP_CDECL
-#define NEW_RIPPER2(a,b,c,loc) (VALUE)NEW_OP_CDECL(a,c,b,loc)
 
 static inline int ripper_is_node_yylval(struct parser_params *p, VALUE n);
 
 static inline VALUE
 ripper_new_yylval(struct parser_params *p, ID a, VALUE b, VALUE c)
 {
-    if (ripper_is_node_yylval(p, c)) c = RNODE(c)->nd_cval;
+    if (ripper_is_node_yylval(p, c)) c = RNODE_RIPPER(c)->nd_cval;
     add_mark_object(p, b);
     add_mark_object(p, c);
     return NEW_RIPPER(a, b, c, &NULL_LOC);
@@ -1068,7 +1281,7 @@ ripper_new_yylval2(struct parser_params *p, VALUE a, VALUE b, VALUE c)
     add_mark_object(p, a);
     add_mark_object(p, b);
     add_mark_object(p, c);
-    return NEW_RIPPER2(a, b, c, &NULL_LOC);
+    return NEW_RIPPER_VALUES(a, b, c, &NULL_LOC);
 }
 
 static inline int
@@ -1236,8 +1449,8 @@ void ripper_error(struct parser_params *p);
 static inline VALUE
 new_args(struct parser_params *p, VALUE pre_args, VALUE opt_args, VALUE rest_arg, VALUE post_args, VALUE tail, YYLTYPE *loc)
 {
-    NODE *t = (NODE *)tail;
-    VALUE kw_args = t->u1.value, kw_rest_arg = t->u2.value, block = t->u3.value;
+    struct RNode_RIPPER_VALUES *t = RNODE_RIPPER_VALUES(tail);
+    VALUE kw_args = t->nd_val1, kw_rest_arg = t->nd_val2, block = t->nd_val3;
     return params_new(pre_args, opt_args, rest_arg, post_args, kw_args, kw_rest_arg, block);
 }
 
@@ -1256,8 +1469,8 @@ args_with_numbered(struct parser_params *p, VALUE args, int max_numparam)
 static VALUE
 new_array_pattern(struct parser_params *p, VALUE constant, VALUE pre_arg, VALUE aryptn, const YYLTYPE *loc)
 {
-    NODE *t = (NODE *)aryptn;
-    VALUE pre_args = t->u1.value, rest_arg = t->u2.value, post_args = t->u3.value;
+    struct RNode_RIPPER_VALUES *t = RNODE_RIPPER_VALUES(aryptn);
+    VALUE pre_args = t->nd_val1, rest_arg = t->nd_val2, post_args = t->nd_val3;
 
     if (!NIL_P(pre_arg)) {
         if (!NIL_P(pre_args)) {
@@ -1279,8 +1492,8 @@ new_array_pattern_tail(struct parser_params *p, VALUE pre_args, VALUE has_rest,
 static VALUE
 new_find_pattern(struct parser_params *p, VALUE constant, VALUE fndptn, const YYLTYPE *loc)
 {
-    NODE *t = (NODE *)fndptn;
-    VALUE pre_rest_arg = t->u1.value, args = t->u2.value, post_rest_arg = t->u3.value;
+    struct RNode_RIPPER_VALUES *t = RNODE_RIPPER_VALUES(fndptn);
+    VALUE pre_rest_arg = t->nd_val1, args = t->nd_val2, post_rest_arg = t->nd_val3;
 
     return dispatch4(fndptn, constant, pre_rest_arg, args, post_rest_arg);
 }
@@ -1302,8 +1515,8 @@ new_unique_key_hash(struct parser_params *p, VALUE ary, const YYLTYPE *loc)
 static VALUE
 new_hash_pattern(struct parser_params *p, VALUE constant, VALUE hshptn, const YYLTYPE *loc)
 {
-    NODE *t = (NODE *)hshptn;
-    VALUE kw_args = t->u1.value, kw_rest_arg = t->u2.value;
+    struct RNode_RIPPER_VALUES *t = RNODE_RIPPER_VALUES(hshptn);
+    VALUE kw_args = t->nd_val1, kw_rest_arg = t->nd_val2;
     return dispatch3(hshptn, constant, kw_args, kw_rest_arg);
 }
 
@@ -1333,9 +1546,9 @@ set_defun_body(struct parser_params *p, NODE *n, NODE *args, NODE *body, const Y
 {
     body = remove_begin(body);
     reduce_nodes(p, &body);
-    n->nd_defn = NEW_SCOPE(args, body, loc);
+    RNODE_DEFN(n)->nd_defn = NEW_SCOPE(args, body, loc);
     n->nd_loc = *loc;
-    nd_set_line(n->nd_defn, loc->end_pos.lineno);
+    nd_set_line(RNODE_DEFN(n)->nd_defn, loc->end_pos.lineno);
     set_line_body(body, loc->beg_pos.lineno);
     return n;
 }
@@ -1361,9 +1574,10 @@ static void clear_block_exit(struct parser_params *p, bool error);
 static void
 restore_defun(struct parser_params *p, NODE *name)
 {
-    NODE *save = name->nd_next;
+    /* See: def_name action */
+    struct RNode_DEF_TEMP2 *save = RNODE_DEF_TEMP(name)->nd_next;
     YYSTYPE c = {.val = save->nd_cval};
-    p->cur_arg = name->nd_vid;
+    p->cur_arg = RNODE_DEF_TEMP(name)->nd_vid;
     p->ctxt.in_def = c.ctxt.in_def;
     p->ctxt.shareable_constant_value = c.ctxt.shareable_constant_value;
     p->ctxt.in_rescue = c.ctxt.in_rescue;
@@ -1376,9 +1590,9 @@ static void
 endless_method_name(struct parser_params *p, NODE *defn, const YYLTYPE *loc)
 {
 #ifdef RIPPER
-    defn = defn->nd_defn;
+    defn = RNODE_DEFN(defn)->nd_defn;
 #endif
-    ID mid = defn->nd_mid;
+    ID mid = RNODE_DEFN(defn)->nd_mid;
     if (is_attrset_id(mid)) {
         yyerror1(loc, "setter method cannot be defined in an endless method definition");
     }
@@ -1496,8 +1710,9 @@ add_block_exit(struct parser_params *p, NODE *node)
     if (!p->ctxt.in_defined) {
         NODE *exits = p->exits;
         if (exits) {
-            exits->nd_end->nd_next = node;
-            exits->nd_end = node;
+            /* Assume NODE_BREAK, NODE_NEXT, NODE_REDO has empty u3 (nd_next) */
+            RNODE_LIST(RNODE_LIST(exits)->as.nd_end)->nd_next = node;
+            RNODE_LIST(exits)->as.nd_end = node;
         }
     }
     return node;
@@ -1507,8 +1722,11 @@ static NODE *
 init_block_exit(struct parser_params *p)
 {
     NODE *old = p->exits;
-    NODE *exits = NODE_NEW_INTERNAL(NODE_ZLIST, 0, 0, 0);
-    p->exits = exits->nd_end = exits;
+    rb_node_zlist_t *exits = NODE_NEW_INTERNAL(NODE_ZLIST, rb_node_zlist_t); /* This has element */
+    exits->not_used = 0;
+    exits->not_used2 = 0;
+    exits->not_used3 = 0;
+    p->exits = RNODE_LIST(exits)->as.nd_end = (NODE *)exits;
     return old;
 }
 
@@ -1532,7 +1750,7 @@ clear_block_exit(struct parser_params *p, bool error)
     NODE *exits = p->exits;
     if (!exits) return;
     if (error && !compile_for_eval) {
-        for (NODE *e = exits; (e = e->nd_next) != 0; ) {
+        for (NODE *e = exits; (e = RNODE_LIST(e)->nd_next) != 0; ) {
             switch (nd_type(e)) {
               case NODE_BREAK:
                 yyerror1(&e->nd_loc, "Invalid break");
@@ -1549,8 +1767,8 @@ clear_block_exit(struct parser_params *p, bool error)
             }
         }
     }
-    exits->nd_end = exits;
-    exits->nd_next = 0;
+    RNODE_LIST(exits)->as.nd_end = exits;
+    RNODE_LIST(exits)->nd_next = 0;
 }
 
 #define WARN_EOL(tok) \
@@ -1578,26 +1796,26 @@ static int looking_at_eol_p(struct parser_params *p);
 #ifndef RIPPER
     rb_parser_printf(p, "%"PRIsVALUE, rb_id2str($$));
 #else
-    rb_parser_printf(p, "%"PRIsVALUE, RNODE($$)->nd_rval);
+    rb_parser_printf(p, "%"PRIsVALUE, RNODE_RIPPER($$)->nd_rval);
 #endif
 } tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tLABEL tOP_ASGN
 %printer {
 #ifndef RIPPER
-    rb_parser_printf(p, "%+"PRIsVALUE, $$->nd_lit);
+    rb_parser_printf(p, "%+"PRIsVALUE, RNODE_LIT($$)->nd_lit);
 #else
     rb_parser_printf(p, "%+"PRIsVALUE, get_value($$));
 #endif
 } tINTEGER tFLOAT tRATIONAL tIMAGINARY tSTRING_CONTENT tCHAR
 %printer {
 #ifndef RIPPER
-    rb_parser_printf(p, "$%ld", $$->nd_nth);
+    rb_parser_printf(p, "$%ld", RNODE_NTH_REF($$)->nd_nth);
 #else
     rb_parser_printf(p, "%"PRIsVALUE, $$);
 #endif
 } tNTH_REF
 %printer {
 #ifndef RIPPER
-    rb_parser_printf(p, "$%c", (int)$$->nd_nth);
+    rb_parser_printf(p, "$%c", (int)RNODE_BACK_REF($$)->nd_nth);
 #else
     rb_parser_printf(p, "%"PRIsVALUE, $$);
 #endif
@@ -1828,10 +2046,10 @@ program         :  {
                             NODE *node = $2;
                             /* last expression should not be void */
                             if (nd_type_p(node, NODE_BLOCK)) {
-                                while (node->nd_next) {
-                                    node = node->nd_next;
+                                while (RNODE_BLOCK(node)->nd_next) {
+                                    node = RNODE_BLOCK(node)->nd_next;
                                 }
-                                node = node->nd_head;
+                                node = RNODE_BLOCK(node)->nd_head;
                             }
                             node = remove_begin(node);
                             void_expr(p, node);
@@ -1990,7 +2208,7 @@ stmt              : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
                     /*%%%*/
                         char buf[2];
                         buf[0] = '$';
-                        buf[1] = (char)$3->nd_nth;
+                        buf[1] = (char)RNODE_BACK_REF($3)->nd_nth;
                         $$ = NEW_VALIAS($2, rb_intern2(buf, 2), &@$);
                     /*% %*/
                     /*% ripper: var_alias!($2, $3) %*/
@@ -2032,7 +2250,7 @@ stmt              : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
                         clear_block_exit(p, false);
                     /*%%%*/
                         if ($1 && nd_type_p($1, NODE_BEGIN)) {
-                            $$ = NEW_WHILE(cond(p, $3, &@3), $1->nd_body, 0, &@$);
+                            $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$);
                         }
                         else {
                             $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$);
@@ -2045,7 +2263,7 @@ stmt              : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
                         clear_block_exit(p, false);
                     /*%%%*/
                         if ($1 && nd_type_p($1, NODE_BEGIN)) {
-                            $$ = NEW_UNTIL(cond(p, $3, &@3), $1->nd_body, 0, &@$);
+                            $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$);
                         }
                         else {
                             $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$);
@@ -2078,8 +2296,7 @@ stmt              : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
                         p->ctxt = $k_END;
                     /*%%%*/
                         {
-                            NODE *scope = NEW_NODE(
-                                NODE_SCOPE, 0 /* tbl */, $compstmt /* body */, 0 /* args */, &@$);
+                            NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $compstmt /* body */, &@$);
                             $$ = NEW_POSTEXE(scope, &@$);
                         }
                     /*% %*/
@@ -2185,7 +2402,7 @@ command_asgn      : lhs '=' lex_ctxt command_rhs
                 | defn_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt]
                     {
                         endless_method_name(p, $<node>head, &@head);
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFN($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $args, $bodystmt, &@$);
                     /*% %*/
@@ -2196,7 +2413,7 @@ command_asgn      : lhs '=' lex_ctxt command_rhs
                 | defs_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt]
                     {
                         endless_method_name(p, $<node>head, &@head);
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFS($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $args, $bodystmt, &@$);
                     /*%
@@ -2319,16 +2536,15 @@ def_name        : fname
                         ID cur_arg = p->cur_arg;
                         YYSTYPE c = {.ctxt = p->ctxt};
                         numparam_name(p, fname);
-                        NODE *save =
-                            NODE_NEW_INTERNAL(NODE_SELF,
-                                              /*head*/numparam_push(p),
-                                              /*nth*/p->max_numparam,
-                                              /*cval*/c.val);
+                        rb_node_def_temp2_t *save =
+                            NEW_DEF_TEMP2(/*head*/numparam_push(p),
+                                          /*nth*/p->max_numparam,
+                                          /*cval*/c.val);
                         local_push(p, 0);
                         p->cur_arg = 0;
                         p->ctxt.in_def = 1;
                         p->ctxt.in_rescue = before_rescue;
-                        $<node>$ = NEW_NODE(NODE_SELF, /*vid*/cur_arg, /*mid*/fname, /*args*/save, &@$);
+                        $<node>$ = NEW_DEF_TEMP(/*vid*/cur_arg, /*mid*/fname, /*next*/save, &@$);
                     /*%%%*/
                     /*%
                         $$ = NEW_RIPPER(fname, get_value($1), $$, &NULL_LOC);
@@ -2340,7 +2556,7 @@ defn_head : k_def def_name
                     {
                         $$ = $2;
                     /*%%%*/
-                        $$ = NEW_NODE(NODE_DEFN, 0, $$->nd_mid, $$, &@$);
+                        $$ = NEW_DEFN(RNODE_DEF_TEMP($$)->nd_mid, $$, &@$);
                     /*% %*/
                     }
                 ;
@@ -2355,11 +2571,11 @@ defs_head       : k_def singleton dot_or_colon
                         SET_LEX_STATE(EXPR_ENDFN|EXPR_LABEL); /* force for args */
                         $$ = $def_name;
                     /*%%%*/
-                        $$ = NEW_NODE(NODE_DEFS, $singleton, $$->nd_mid, $$, &@$);
+                        $$ = NEW_DEFS($singleton, RNODE_DEF_TEMP($$)->nd_mid, $$, &@$);
                     /*%
                         VALUE ary = rb_ary_new_from_args(3, $singleton, $dot_or_colon, get_value($$));
                         add_mark_object(p, ary);
-                        $<node>$->nd_rval = ary;
+                        RNODE_RIPPER($$)->nd_rval = ary;
                     %*/
                     }
                 ;
@@ -2419,7 +2635,7 @@ fcall             : operation
 command                : fcall command_args       %prec tLOWEST
                     {
                     /*%%%*/
-                        $1->nd_args = $2;
+                        RNODE_FCALL($1)->nd_args = $2;
                         nd_set_last_loc($1, @2.end_pos);
                         $$ = $1;
                     /*% %*/
@@ -2429,7 +2645,7 @@ command           : fcall command_args       %prec tLOWEST
                     {
                     /*%%%*/
                         block_dup_check(p, $2, $3);
-                        $1->nd_args = $2;
+                        RNODE_FCALL($1)->nd_args = $2;
                         $$ = method_add_block(p, $1, $3, &@$);
                         fixpos($$, $1);
                         nd_set_last_loc($1, @2.end_pos);
@@ -2545,7 +2761,7 @@ mlhs_basic        : mlhs_head
                 | mlhs_head mlhs_item
                     {
                     /*%%%*/
-                        $$ = NEW_MASGN(list_append(p, $1,$2), 0, &@$);
+                        $$ = NEW_MASGN(list_append(p, $1, $2), 0, &@$);
                     /*% %*/
                     /*% ripper: mlhs_add!($1, $2) %*/
                     }
@@ -2804,7 +3020,7 @@ cpath             : tCOLON3 cname
                 | cname
                     {
                     /*%%%*/
-                        $$ = NEW_COLON2(0, $$, &@$);
+                        $$ = NEW_COLON2(0, $1, &@$);
                     /*% %*/
                     /*% ripper: const_ref!($1) %*/
                     }
@@ -3131,7 +3347,7 @@ arg               : lhs '=' lex_ctxt arg_rhs
                 | defn_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt]
                     {
                         endless_method_name(p, $<node>head, &@head);
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFN($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $2, $bodystmt, &@$);
                     /*% %*/
@@ -3142,7 +3358,7 @@ arg               : lhs '=' lex_ctxt arg_rhs
                 | defs_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt]
                     {
                         endless_method_name(p, $<node>head, &@head);
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFS($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $args, $bodystmt, &@$);
                     /*%
@@ -3531,7 +3747,7 @@ primary           : literal
                 | tLPAREN_ARG compstmt {SET_LEX_STATE(EXPR_ENDARG);} ')'
                     {
                     /*%%%*/
-                        if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0;
+                        if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
                         $$ = $2;
                     /*% %*/
                     /*% ripper: paren!($2) %*/
@@ -3539,7 +3755,7 @@ primary           : literal
                 | tLPAREN compstmt ')'
                     {
                     /*%%%*/
-                        if (nd_type_p($2, NODE_SELF)) $2->nd_state = 0;
+                        if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
                         $$ = $2;
                     /*% %*/
                     /*% ripper: paren!($2) %*/
@@ -3569,7 +3785,7 @@ primary           : literal
                     {
                     /*%%%*/
                         $$ = new_hash(p, $2, &@$);
-                        $$->nd_brace = TRUE;
+                        RNODE_HASH($$)->nd_brace = TRUE;
                     /*% %*/
                     /*% ripper: hash!($2) %*/
                     }
@@ -3625,7 +3841,7 @@ primary           : literal
                 | method_call brace_block
                     {
                     /*%%%*/
-                        block_dup_check(p, $1->nd_args, $2);
+                        block_dup_check(p, RNODE_FCALL($1)->nd_args, $2);
                         $$ = method_add_block(p, $1, $2, &@$);
                     /*% %*/
                     /*% ripper: method_add_block!($1, $2) %*/
@@ -3731,7 +3947,7 @@ primary           : literal
                          *  e.each{|x| a, = x}
                          */
                         ID id = internal_id(p);
-                        NODE *m = NEW_ARGS_AUX(0, 0, &NULL_LOC);
+                        struct RNode_ARGS_AUX *m = RNODE_ARGS_AUX(NEW_ARGS_AUX(0, 0, &NULL_LOC));
                         NODE *args, *scope, *internal_var = NEW_DVAR(id, &@2);
                         rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1);
                         tbl->ids[0] = id; /* internal id */
@@ -3739,7 +3955,7 @@ primary           : literal
                         switch (nd_type($2)) {
                           case NODE_LASGN:
                           case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */
-                            $2->nd_value = internal_var;
+                            RNODE_LASGN($2)->nd_value = internal_var;
                             id = 0;
                             m->nd_plen = 1;
                             m->nd_next = $2;
@@ -3751,8 +3967,8 @@ primary           : literal
                             m->nd_next = node_assign(p, NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, NO_LEX_CTXT, &@2);
                         }
                         /* {|*internal_id| <m> = internal_id; ... } */
-                        args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2);
-                        scope = NEW_NODE(NODE_SCOPE, tbl, $5, args, &@$);
+                        args = new_args(p, (NODE *)m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2);
+                        scope = NEW_SCOPE2(tbl, args, $5, &@$);
                         $$ = NEW_FOR($4, scope, &@$);
                         fixpos($$, $2);
                     /*% %*/
@@ -3767,7 +3983,7 @@ primary           : literal
                     {
                     /*%%%*/
                         $$ = NEW_CLASS($cpath, $bodystmt, $superclass, &@$);
-                        nd_set_line($$->nd_body, @k_end.end_pos.lineno);
+                        nd_set_line(RNODE_CLASS($$)->nd_body, @k_end.end_pos.lineno);
                         set_line_body($bodystmt, @superclass.end_pos.lineno);
                         nd_set_line($$, @superclass.end_pos.lineno);
                     /*% %*/
@@ -3786,7 +4002,7 @@ primary           : literal
                     {
                     /*%%%*/
                         $$ = NEW_SCLASS($expr, $bodystmt, &@$);
-                        nd_set_line($$->nd_body, @k_end.end_pos.lineno);
+                        nd_set_line(RNODE_SCLASS($$)->nd_body, @k_end.end_pos.lineno);
                         set_line_body($bodystmt, nd_line($expr));
                         fixpos($$, $expr);
                     /*% %*/
@@ -3805,7 +4021,7 @@ primary           : literal
                     {
                     /*%%%*/
                         $$ = NEW_MODULE($cpath, $bodystmt, &@$);
-                        nd_set_line($$->nd_body, @k_end.end_pos.lineno);
+                        nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno);
                         set_line_body($bodystmt, @cpath.end_pos.lineno);
                         nd_set_line($$, @cpath.end_pos.lineno);
                     /*% %*/
@@ -3824,7 +4040,7 @@ primary           : literal
                   bodystmt
                   k_end
                     {
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFN($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $args, $bodystmt, &@$);
                     /*% %*/
@@ -3841,7 +4057,7 @@ primary           : literal
                   bodystmt
                   k_end
                     {
-                        restore_defun(p, $<node>head->nd_defn);
+                        restore_defun(p, RNODE_DEFS($head)->nd_defn);
                     /*%%%*/
                         $$ = set_defun_body(p, $head, $args, $bodystmt, &@$);
                     /*%
@@ -4401,7 +4617,7 @@ lambda            : tLAMBDA[dyna]
                         {
                             YYLTYPE loc = code_loc_gen(&@args, &@body);
                             $$ = NEW_LAMBDA($args, $body, &loc);
-                            nd_set_line($$->nd_body, @body.end_pos.lineno);
+                            nd_set_line(RNODE_LAMBDA($$)->nd_body, @body.end_pos.lineno);
                             nd_set_line($$, @args.end_pos.lineno);
                             nd_set_first_loc($$, @1.beg_pos);
                         }
@@ -4425,7 +4641,7 @@ f_larglist        : '(' f_args opt_bv_decl ')'
                     {
                         p->ctxt.in_argdef = 0;
                     /*%%%*/
-                        if (!args_info_empty_p($1->nd_ainfo))
+                        if (!args_info_empty_p(RNODE_ARGS($1)->nd_ainfo))
                             p->max_numparam = ORDINAL_PARAM;
                     /*% %*/
                         $$ = $1;
@@ -4465,7 +4681,7 @@ block_call        : command do_block
                             compile_error(p, "block given to yield");
                         }
                         else {
-                            block_dup_check(p, $1->nd_args, $2);
+                            block_dup_check(p, RNODE_FCALL($1)->nd_args, $2);
                         }
                         $$ = method_add_block(p, $1, $2, &@$);
                         fixpos($$, $1);
@@ -4499,7 +4715,7 @@ method_call       : fcall paren_args
                     {
                     /*%%%*/
                         $$ = $1;
-                        $$->nd_args = $2;
+                        RNODE_FCALL($$)->nd_args = $2;
                         nd_set_last_loc($1, @2.end_pos);
                     /*% %*/
                     /*% ripper: method_add_arg!(fcall!($1), $2) %*/
@@ -4781,7 +4997,7 @@ p_as              : p_expr tASSOC p_variable
 p_alt          : p_alt '|' p_expr_basic
                     {
                     /*%%%*/
-                        $$ = NEW_NODE(NODE_OR, $1, $3, 0, &@$);
+                        $$ = NEW_OR($1, $3, &@$);
                     /*% %*/
                     /*% ripper: binary!($1, STATIC_ID2SYM(idOr), $3) %*/
                     }
@@ -5051,12 +5267,12 @@ p_kw_label      : tLABEL
                     /*%%%*/
                         if (!$2 || nd_type_p($2, NODE_STR)) {
                             NODE *node = dsym_node(p, $2, &loc);
-                            $$ = SYM2ID(node->nd_lit);
+                            $$ = SYM2ID(RNODE_LIT(node)->nd_lit);
                         }
                     /*%
-                        if (ripper_is_node_yylval(p, $2) && RNODE($2)->nd_cval) {
-                            VALUE label = RNODE($2)->nd_cval;
-                            VALUE rval = RNODE($2)->nd_rval;
+                        if (ripper_is_node_yylval(p, $2) && RNODE_RIPPER($2)->nd_cval) {
+                            VALUE label = RNODE_RIPPER($2)->nd_cval;
+                            VALUE rval = RNODE_RIPPER($2)->nd_rval;
                             $$ = ripper_new_yylval(p, rb_intern_str(label), rval, label);
                             RNODE($$)->nd_loc = loc;
                         }
@@ -5296,7 +5512,7 @@ strings           : string
                         NODE *node = $1;
                         if (!node) {
                             node = NEW_STR(STR_NEW0(), &@$);
-                            RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit);
+                            RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_STR(node)->nd_lit);
                         }
                         else {
                             node = evstr2dstr(p, node);
@@ -5478,9 +5694,9 @@ string_contents : /* none */
                     /*%%%*/
                     /*%
                         if (ripper_is_node_yylval(p, $1) && ripper_is_node_yylval(p, $2) &&
-                            !RNODE($1)->nd_cval) {
-                            RNODE($1)->nd_cval = RNODE($2)->nd_cval;
-                            RNODE($1)->nd_rval = add_mark_object(p, $$);
+                            !RNODE_RIPPER($1)->nd_cval) {
+                            RNODE_RIPPER($1)->nd_cval = RNODE_RIPPER($2)->nd_cval;
+                            RNODE_RIPPER($1)->nd_rval = add_mark_object(p, $$);
                             $$ = $1;
                         }
                     %*/
@@ -5540,12 +5756,12 @@ regexp_contents: /* none */
                     /*%
                         VALUE s1 = 1, s2 = 0, n1 = $1, n2 = $2;
                         if (ripper_is_node_yylval(p, n1)) {
-                            s1 = RNODE(n1)->nd_cval;
-                            n1 = RNODE(n1)->nd_rval;
+                            s1 = RNODE_RIPPER(n1)->nd_cval;
+                            n1 = RNODE_RIPPER(n1)->nd_rval;
                         }
                         if (ripper_is_node_yylval(p, n2)) {
-                            s2 = RNODE(n2)->nd_cval;
-                            n2 = RNODE(n2)->nd_rval;
+                            s2 = RNODE_RIPPER(n2)->nd_cval;
+                            n2 = RNODE_RIPPER(n2)->nd_rval;
                         }
                         $$ = dispatch2(regexp_add, n1, n2);
                         if (!s1 && s2) {
@@ -5655,7 +5871,7 @@ numeric   : simple_numeric
                     {
                     /*%%%*/
                         $$ = $2;
-                        RB_OBJ_WRITE(p->ast, &$$->nd_lit, negate_lit(p, $$->nd_lit));
+                        RB_OBJ_WRITE(p->ast, &RNODE_LIT($$)->nd_lit, negate_lit(p, RNODE_LIT($$)->nd_lit));
                     /*% %*/
                     /*% ripper: unary!(ID2VAL(idUMinus), $2) %*/
                     }
@@ -5805,7 +6021,7 @@ args_tail : f_kwarg ',' f_kwrest opt_f_block_arg
                         add_forwarding_args(p);
                         $$ = new_args_tail(p, Qnone, $1, arg_FWD_BLOCK, &@1);
                     /*%%%*/
-                        ($$->nd_ainfo)->forwarding = 1;
+                        (RNODE_ARGS($$)->nd_ainfo)->forwarding = 1;
                     /*% %*/
                     }
                 ;
@@ -5969,13 +6185,13 @@ f_arg_item      : f_arg_asgn
                         loc.end_pos = @2.beg_pos;
                         arg_var(p, tid);
                         if (dyna_in_block(p)) {
-                            $2->nd_value = NEW_DVAR(tid, &loc);
+                            RNODE_MASGN($2)->nd_value = NEW_DVAR(tid, &loc);
                         }
                         else {
-                            $2->nd_value = NEW_LVAR(tid, &loc);
+                            RNODE_MASGN($2)->nd_value = NEW_LVAR(tid, &loc);
                         }
                         $$ = NEW_ARGS_AUX(tid, 1, &NULL_LOC);
-                        $$->nd_next = $2;
+                        RNODE_ARGS_AUX($$)->nd_next = $2;
                     /*% %*/
                     /*% ripper: mlhs_paren!($2) %*/
                     }
@@ -5987,8 +6203,8 @@ f_arg             : f_arg_item
                     {
                     /*%%%*/
                         $$ = $1;
-                        $$->nd_plen++;
-                        $$->nd_next = block_append(p, $$->nd_next, $3->nd_next);
+                        RNODE_ARGS_AUX($$)->nd_plen++;
+                        RNODE_ARGS_AUX($$)->nd_next = block_append(p, RNODE_ARGS_AUX($$)->nd_next, RNODE_ARGS_AUX($3)->nd_next);
                         rb_discard_node(p, $3);
                     /*% %*/
                     /*% ripper: rb_ary_push($1, get_value($3)) %*/
@@ -6267,11 +6483,11 @@ assocs          : assoc
                             assocs = tail;
                         }
                         else if (tail) {
-                            if (assocs->nd_head &&
-                                !tail->nd_head && nd_type_p(tail->nd_next, NODE_LIST) &&
-                                nd_type_p(tail->nd_next->nd_head, NODE_HASH)) {
+                            if (RNODE_LIST(assocs)->nd_head &&
+                                !RNODE_LIST(tail)->nd_head && nd_type_p(RNODE_LIST(tail)->nd_next, NODE_LIST) &&
+                                nd_type_p(RNODE_LIST(RNODE_LIST(tail)->nd_next)->nd_head, NODE_HASH)) {
                                 /* DSTAR */
-                                tail = tail->nd_next->nd_head->nd_head;
+                                tail = RNODE_HASH(RNODE_LIST(RNODE_LIST(tail)->nd_next)->nd_head)->nd_head;
                             }
                             assocs = list_concat(assocs, tail);
                         }
@@ -6286,7 +6502,7 @@ assoc             : arg_value tASSOC arg_value
                     /*%%%*/
                         if (nd_type_p($1, NODE_STR)) {
                             nd_set_type($1, NODE_LIT);
-                            RB_OBJ_WRITE(p->ast, &$1->nd_lit, rb_fstring($1->nd_lit));
+                            RB_OBJ_WRITE(p->ast, &RNODE_LIT($1)->nd_lit, rb_fstring(RNODE_LIT($1)->nd_lit));
                         }
                         $$ = list_append(p, NEW_LIST($1, &@$), $3);
                     /*% %*/
@@ -6320,7 +6536,7 @@ assoc             : arg_value tASSOC arg_value
                     {
                     /*%%%*/
                         if (nd_type_p($2, NODE_HASH) &&
-                            !($2->nd_head && $2->nd_head->nd_alen)) {
+                            !(RNODE_HASH($2)->nd_head && RNODE_LIST(RNODE_HASH($2)->nd_head)->as.nd_alen)) {
                             static VALUE empty_hash;
                             if (!empty_hash) {
                                 empty_hash = rb_obj_freeze(rb_hash_new());
@@ -6553,7 +6769,7 @@ parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int l
 #else
 #define literal_flush(p, ptr) ((void)(ptr))
 
-#define yylval_rval (*(RB_TYPE_P(yylval.val, T_NODE) ? &yylval.node->nd_rval : &yylval.val))
+#define yylval_rval (*(RB_TYPE_P(yylval.val, T_NODE) ? &RNODE_RIPPER(yylval.node)->nd_rval : &yylval.val))
 
 static int
 ripper_has_scan_event(struct parser_params *p)
@@ -7061,9 +7277,9 @@ yycompile0(VALUE arg)
     else {
         VALUE tokens = p->tokens;
         NODE *prelude;
-        NODE *body = parser_append_options(p, tree->nd_body);
+        NODE *body = parser_append_options(p, RNODE_SCOPE(tree)->nd_body);
         prelude = block_append(p, p->eval_tree_begin, body);
-        tree->nd_body = prelude;
+        RNODE_SCOPE(tree)->nd_body = prelude;
         p->ast->body.frozen_string_literal = p->frozen_string_literal;
         p->ast->body.coverage_enabled = cov;
         if (p->keep_tokens) {
@@ -8072,11 +8288,11 @@ flush_string_content(struct parser_params *p, rb_encoding *enc)
         }
         dispatch_delayed_token(p, tSTRING_CONTENT);
         p->lex.ptok = p->lex.pcur;
-        RNODE(content)->nd_rval = yylval.val;
+        RNODE_RIPPER(content)->nd_rval = yylval.val;
     }
     dispatch_scan_event(p, tSTRING_CONTENT);
     if (yylval.val != content)
-        RNODE(content)->nd_rval = yylval.val;
+        RNODE_RIPPER(content)->nd_rval = yylval.val;
     yylval.val = content;
 }
 #else
@@ -8409,10 +8625,10 @@ heredoc_dedent(struct parser_params *p, NODE *root)
     if (!root) return root;
 
     prev_node = node = str_node = root;
-    if (nd_type_p(root, NODE_LIST)) str_node = root->nd_head;
+    if (nd_type_p(root, NODE_LIST)) str_node = RNODE_LIST(root)->nd_head;
 
     while (str_node) {
-        VALUE lit = str_node->nd_lit;
+        VALUE lit = RNODE_LIT(str_node)->nd_lit;
         if (str_node->flags & NODE_FL_NEWLINE) {
             dedent_string(p, lit, indent);
         }
@@ -8423,22 +8639,22 @@ heredoc_dedent(struct parser_params *p, NODE *root)
             return 0;
         }
         else {
-            NODE *end = node->nd_end;
-            node = prev_node->nd_next = node->nd_next;
+            NODE *end = RNODE_LIST(node)->as.nd_end;
+            node = RNODE_LIST(prev_node)->nd_next = RNODE_LIST(node)->nd_next;
             if (!node) {
                 if (nd_type_p(prev_node, NODE_DSTR))
                     nd_set_type(prev_node, NODE_STR);
                 break;
             }
-            node->nd_end = end;
+            RNODE_LIST(node)->as.nd_end = end;
             goto next_str;
         }
 
         str_node = 0;
-        while ((node = (prev_node = node)->nd_next) != 0) {
+        while ((node = RNODE_LIST(prev_node = node)->nd_next) != 0) {
           next_str:
             if (!nd_type_p(node, NODE_LIST)) break;
-            if ((str_node = node->nd_head) != 0) {
+            if ((str_node = RNODE_LIST(node)->nd_head) != 0) {
                 enum node_type type = nd_type(str_node);
                 if (type == NODE_STR || type == NODE_DSTR) break;
                 prev_lit = 0;
@@ -10766,311 +10982,1516 @@ yylex(YYSTYPE *lval, YYLTYPE *yylloc, struct parser_params *p)
 #define LVAR_USED ((ID)1 << (sizeof(ID) * CHAR_BIT - 1))
 
 static NODE*
-node_new_internal(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
+node_new_internal(struct parser_params *p, enum node_type type, size_t size, size_t alignment)
 {
-    NODE *n = rb_ast_newnode(p->ast, type);
+    NODE *n = rb_ast_newnode(p->ast, type, size, alignment);
 
-    rb_node_init(n, type, a0, a1, a2);
+    rb_node_init(n, type);
     return n;
 }
 
+static NODE *
+nd_set_loc(NODE *nd, const YYLTYPE *loc)
+{
+    nd->nd_loc = *loc;
+    nd_set_line(nd, loc->beg_pos.lineno);
+    return nd;
+}
+
 static NODE*
-node_newnode(struct parser_params *p, enum node_type type, VALUE a0, VALUE a1, VALUE a2, const rb_code_location_t *loc)
+node_newnode(struct parser_params *p, enum node_type type, size_t size, size_t alignment, const rb_code_location_t *loc)
 {
-    NODE *n = node_new_internal(p, type, a0, a1, a2);
+    NODE *n = node_new_internal(p, type, size, alignment);
 
     nd_set_loc(n, loc);
     nd_set_node_id(n, parser_get_node_id(p));
     return n;
 }
 
-static NODE *
-nd_set_loc(NODE *nd, const YYLTYPE *loc)
+#define NODE_NEWNODE(node_type, type, loc) (type *)(node_newnode(p, node_type, sizeof(type), RUBY_ALIGNOF(type), loc))
+
+#ifndef RIPPER
+
+static rb_node_scope_t *
+rb_node_scope_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc)
 {
-    nd->nd_loc = *loc;
-    nd_set_line(nd, loc->beg_pos.lineno);
-    return nd;
+    rb_ast_id_table_t *nd_tbl;
+    nd_tbl = local_tbl(p);
+    rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc);
+    n->nd_tbl = nd_tbl;
+    n->nd_body = nd_body;
+    n->nd_args = nd_args;
+
+    return n;
 }
 
-#ifndef RIPPER
-static enum node_type
-nodetype(NODE *node)                   /* for debug */
+static rb_node_scope_t *
+rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc)
 {
-    return (enum node_type)nd_type(node);
+    rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc);
+    n->nd_tbl = nd_tbl;
+    n->nd_body = nd_body;
+    n->nd_args = nd_args;
+
+    return n;
 }
 
-static int
-nodeline(NODE *node)
+static rb_node_defn_t *
+rb_node_defn_new(struct parser_params *p, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc)
 {
-    return nd_line(node);
+    rb_node_defn_t *n = NODE_NEWNODE(NODE_DEFN, rb_node_defn_t, loc);
+    n->not_used = 0;
+    n->nd_mid = nd_mid;
+    n->nd_defn = nd_defn;
+
+    return n;
 }
 
-static NODE*
-newline_node(NODE *node)
+static rb_node_defs_t *
+rb_node_defs_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc)
 {
-    if (node) {
-        node = remove_begin(node);
-        node->flags |= NODE_FL_NEWLINE;
-    }
-    return node;
+    rb_node_defs_t *n = NODE_NEWNODE(NODE_DEFS, rb_node_defs_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_defn = nd_defn;
+
+    return n;
 }
 
-static void
-fixpos(NODE *node, NODE *orig)
+static rb_node_block_t *
+rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
 {
-    if (!node) return;
-    if (!orig) return;
-    nd_set_line(node, nd_line(orig));
+    rb_node_block_t *n = NODE_NEWNODE(NODE_BLOCK, rb_node_block_t, loc);
+    n->nd_head = nd_head;
+    n->nd_end = 0;
+    n->nd_next = 0;
+
+    return n;
 }
 
-static void
-parser_warning(struct parser_params *p, NODE *node, const char *mesg)
+static rb_node_for_t *
+rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc)
 {
-    rb_compile_warning(p->ruby_sourcefile, nd_line(node), "%s", mesg);
+    rb_node_for_t *n = NODE_NEWNODE(NODE_FOR, rb_node_for_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->nd_iter = nd_iter;
+
+    return n;
 }
 
-static void
-parser_warn(struct parser_params *p, NODE *node, const char *mesg)
+static rb_node_for_masgn_t *
+rb_node_for_masgn_new(struct parser_params *p, NODE *nd_var, const YYLTYPE *loc)
 {
-    rb_compile_warn(p->ruby_sourcefile, nd_line(node), "%s", mesg);
+    rb_node_for_masgn_t *n = NODE_NEWNODE(NODE_FOR_MASGN, rb_node_for_masgn_t, loc);
+    n->nd_var = nd_var;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
 }
 
-static NODE*
-block_append(struct parser_params *p, NODE *head, NODE *tail)
+static rb_node_retry_t *
+rb_node_retry_new(struct parser_params *p, const YYLTYPE *loc)
 {
-    NODE *end, *h = head, *nd;
+    rb_node_retry_t *n = NODE_NEWNODE(NODE_RETRY, rb_node_retry_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
 
-    if (tail == 0) return head;
+    return n;
+}
 
-    if (h == 0) return tail;
-    switch (nd_type(h)) {
-      case NODE_LIT:
-      case NODE_STR:
-      case NODE_SELF:
-      case NODE_TRUE:
-      case NODE_FALSE:
-      case NODE_NIL:
-        parser_warning(p, h, "unused literal ignored");
-        return tail;
-      default:
-        h = end = NEW_BLOCK(head, &head->nd_loc);
-        end->nd_end = end;
-        head = end;
-        break;
-      case NODE_BLOCK:
-        end = h->nd_end;
-        break;
-    }
+static rb_node_begin_t *
+rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_begin_t *n = NODE_NEWNODE(NODE_BEGIN, rb_node_begin_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->not_used2 = 0;
 
-    nd = end->nd_head;
-    switch (nd_type(nd)) {
-      case NODE_RETURN:
-      case NODE_BREAK:
-      case NODE_NEXT:
-      case NODE_REDO:
-      case NODE_RETRY:
-        if (RTEST(ruby_verbose)) {
-            parser_warning(p, tail, "statement not reached");
-        }
-        break;
+    return n;
+}
 
-      default:
-        break;
-    }
+static rb_node_rescue_t *
+rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc)
+{
+    rb_node_rescue_t *n = NODE_NEWNODE(NODE_RESCUE, rb_node_rescue_t, loc);
+    n->nd_head = nd_head;
+    n->nd_resq = nd_resq;
+    n->nd_else = nd_else;
 
-    if (!nd_type_p(tail, NODE_BLOCK)) {
-        tail = NEW_BLOCK(tail, &tail->nd_loc);
-        tail->nd_end = tail;
-    }
-    end->nd_next = tail;
-    h->nd_end = tail->nd_end;
-    nd_set_last_loc(head, nd_last_loc(tail));
-    return head;
+    return n;
 }
 
-/* append item to the list */
-static NODE*
-list_append(struct parser_params *p, NODE *list, NODE *item)
+static rb_node_resbody_t *
+rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_head, const YYLTYPE *loc)
 {
-    NODE *last;
+    rb_node_resbody_t *n = NODE_NEWNODE(NODE_RESBODY, rb_node_resbody_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->nd_args = nd_args;
 
-    if (list == 0) return NEW_LIST(item, &item->nd_loc);
-    if (list->nd_next) {
-        last = list->nd_next->nd_end;
-    }
-    else {
-        last = list;
-    }
+    return n;
+}
 
-    list->nd_alen += 1;
-    last->nd_next = NEW_LIST(item, &item->nd_loc);
-    list->nd_next->nd_end = last->nd_next;
+static rb_node_ensure_t *
+rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc)
+{
+    rb_node_ensure_t *n = NODE_NEWNODE(NODE_ENSURE, rb_node_ensure_t, loc);
+    n->nd_head = nd_head;
+    n->nd_resq = 0;
+    n->nd_ensr = nd_ensr;
 
-    nd_set_last_loc(list, nd_last_loc(item));
+    return n;
+}
 
-    return list;
+static rb_node_and_t *
+rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+{
+    rb_node_and_t *n = NODE_NEWNODE(NODE_AND, rb_node_and_t, loc);
+    n->nd_1st = nd_1st;
+    n->nd_2nd = nd_2nd;
+    n->not_used = 0;
+
+    return n;
 }
 
-/* concat two lists */
-static NODE*
-list_concat(NODE *head, NODE *tail)
+static rb_node_or_t *
+rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
 {
-    NODE *last;
+    rb_node_or_t *n = NODE_NEWNODE(NODE_OR, rb_node_or_t, loc);
+    n->nd_1st = nd_1st;
+    n->nd_2nd = nd_2nd;
+    n->not_used = 0;
 
-    if (head->nd_next) {
-        last = head->nd_next->nd_end;
-    }
-    else {
-        last = head;
-    }
+    return n;
+}
 
-    head->nd_alen += tail->nd_alen;
-    last->nd_next = tail;
-    if (tail->nd_next) {
-        head->nd_next->nd_end = tail->nd_next->nd_end;
-    }
-    else {
-        head->nd_next->nd_end = tail;
-    }
+static rb_node_return_t *
+rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+{
+    rb_node_return_t *n = NODE_NEWNODE(NODE_RETURN, rb_node_return_t, loc);
+    n->nd_stts = nd_stts;
+    n->not_used = 0;
+    n->not_used2 = 0;
 
-    nd_set_last_loc(head, nd_last_loc(tail));
+    return n;
+}
 
-    return head;
+static rb_node_yield_t *
+rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+{
+    rb_node_yield_t *n = NODE_NEWNODE(NODE_YIELD, rb_node_yield_t, loc);
+    n->nd_head = nd_head;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
 }
 
-static int
-literal_concat0(struct parser_params *p, VALUE head, VALUE tail)
+static rb_node_if_t *
+rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc)
 {
-    if (NIL_P(tail)) return 1;
-    if (!rb_enc_compatible(head, tail)) {
-        compile_error(p, "string literal encodings differ (%s / %s)",
-                      rb_enc_name(rb_enc_get(head)),
-                      rb_enc_name(rb_enc_get(tail)));
-        rb_str_resize(head, 0);
-        rb_str_resize(tail, 0);
-        return 0;
-    }
-    rb_str_buf_append(head, tail);
-    return 1;
+    rb_node_if_t *n = NODE_NEWNODE(NODE_IF, rb_node_if_t, loc);
+    n->nd_cond = nd_cond;
+    n->nd_body = nd_body;
+    n->nd_else = nd_else;
+
+    return n;
 }
 
-static VALUE
-string_literal_head(struct parser_params *p, enum node_type htype, NODE *head)
+static rb_node_unless_t *
+rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc)
 {
-    if (htype != NODE_DSTR) return Qfalse;
-    if (head->nd_next) {
-        head = head->nd_next->nd_end->nd_head;
-        if (!head || !nd_type_p(head, NODE_STR)) return Qfalse;
-    }
-    const VALUE lit = head->nd_lit;
-    ASSUME(lit != Qfalse);
-    return lit;
+    rb_node_unless_t *n = NODE_NEWNODE(NODE_UNLESS, rb_node_unless_t, loc);
+    n->nd_cond = nd_cond;
+    n->nd_body = nd_body;
+    n->nd_else = nd_else;
+
+    return n;
 }
 
-/* concat two string literals */
-static NODE *
-literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *loc)
+static rb_node_class_t *
+rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc)
 {
-    enum node_type htype;
-    VALUE lit;
+    /* Keep the order of node creation */
+    NODE *scope = NEW_SCOPE(0, nd_body, loc);
+    rb_node_class_t *n = NODE_NEWNODE(NODE_CLASS, rb_node_class_t, loc);
+    n->nd_cpath = nd_cpath;
+    n->nd_body = scope;
+    n->nd_super = nd_super;
 
-    if (!head) return tail;
-    if (!tail) return head;
+    return n;
+}
 
-    htype = nd_type(head);
-    if (htype == NODE_EVSTR) {
-        head = new_dstr(p, head, loc);
-        htype = NODE_DSTR;
-    }
-    if (p->heredoc_indent > 0) {
-        switch (htype) {
-          case NODE_STR:
-            nd_set_type(head, NODE_DSTR);
-          case NODE_DSTR:
-            return list_append(p, head, tail);
-          default:
-            break;
-        }
-    }
-    switch (nd_type(tail)) {
-      case NODE_STR:
-        if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
-            htype = NODE_STR;
-        }
-        else {
-            lit = head->nd_lit;
-        }
-        if (htype == NODE_STR) {
-            if (!literal_concat0(p, lit, tail->nd_lit)) {
-              error:
-                rb_discard_node(p, head);
-                rb_discard_node(p, tail);
-                return 0;
-            }
-            rb_discard_node(p, tail);
-        }
-        else {
-            list_append(p, head, tail);
-        }
-        break;
+static rb_node_sclass_t *
+rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc)
+{
+    /* Keep the order of node creation */
+    NODE *scope = NEW_SCOPE(0, nd_body, loc);
+    rb_node_sclass_t *n = NODE_NEWNODE(NODE_SCLASS, rb_node_sclass_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_body = scope;
+    n->not_used = 0;
 
-      case NODE_DSTR:
-        if (htype == NODE_STR) {
-            if (!literal_concat0(p, head->nd_lit, tail->nd_lit))
-                goto error;
-            tail->nd_lit = head->nd_lit;
-            rb_discard_node(p, head);
-            head = tail;
-        }
-        else if (NIL_P(tail->nd_lit)) {
-          append:
-            head->nd_alen += tail->nd_alen - 1;
-            if (!head->nd_next) {
-                head->nd_next = tail->nd_next;
-            }
-            else if (tail->nd_next) {
-                head->nd_next->nd_end->nd_next = tail->nd_next;
-                head->nd_next->nd_end = tail->nd_next->nd_end;
-            }
-            rb_discard_node(p, tail);
-        }
-        else if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
-            if (!literal_concat0(p, lit, tail->nd_lit))
-                goto error;
-            tail->nd_lit = Qnil;
-            goto append;
-        }
-        else {
-            list_concat(head, NEW_NODE(NODE_LIST, NEW_STR(tail->nd_lit, loc), tail->nd_alen, tail->nd_next, loc));
-        }
-        break;
+    return n;
+}
 
-      case NODE_EVSTR:
-        if (htype == NODE_STR) {
-            nd_set_type(head, NODE_DSTR);
-            head->nd_alen = 1;
-        }
-        list_append(p, head, tail);
-        break;
-    }
-    return head;
+static rb_node_module_t *
+rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc)
+{
+    /* Keep the order of node creation */
+    NODE *scope = NEW_SCOPE(0, nd_body, loc);
+    rb_node_module_t *n = NODE_NEWNODE(NODE_MODULE, rb_node_module_t, loc);
+    n->nd_cpath = nd_cpath;
+    n->nd_body = scope;
+    n->not_used = 0;
+
+    return n;
 }
 
-static NODE *
-evstr2dstr(struct parser_params *p, NODE *node)
+static rb_node_iter_t *
+rb_node_iter_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc)
 {
-    if (nd_type_p(node, NODE_EVSTR)) {
-        node = new_dstr(p, node, &node->nd_loc);
-    }
-    return node;
+    /* Keep the order of node creation */
+    NODE *scope = NEW_SCOPE(nd_args, nd_body, loc);
+    rb_node_iter_t *n = NODE_NEWNODE(NODE_ITER, rb_node_iter_t, loc);
+    n->not_used = 0;
+    n->nd_body = scope;
+    n->nd_iter = 0;
+
+    return n;
 }
 
-static NODE *
-new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
+static rb_node_lambda_t *
+rb_node_lambda_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, const YYLTYPE *loc)
 {
-    NODE *head = node;
+    /* Keep the order of node creation */
+    NODE *scope = NEW_SCOPE(nd_args, nd_body, loc);
+    rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, loc);
+    n->not_used = 0;
+    n->nd_body = scope;
+    n->not_used2 = 0;
 
-    if (node) {
+    return n;
+}
+
+static rb_node_case_t *
+rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_case_t *n = NODE_NEWNODE(NODE_CASE, rb_node_case_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_case2_t *
+rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_case2_t *n = NODE_NEWNODE(NODE_CASE2, rb_node_case2_t, loc);
+    n->nd_head = 0;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_case3_t *
+rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_case3_t *n = NODE_NEWNODE(NODE_CASE3, rb_node_case3_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_when_t *
+rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_when_t *n = NODE_NEWNODE(NODE_WHEN, rb_node_when_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->nd_next = nd_next;
+
+    return n;
+}
+
+static rb_node_in_t *
+rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_in_t *n = NODE_NEWNODE(NODE_IN, rb_node_in_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->nd_next = nd_next;
+
+    return n;
+}
+
+static rb_node_while_t *
+rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc)
+{
+    rb_node_while_t *n = NODE_NEWNODE(NODE_WHILE, rb_node_while_t, loc);
+    n->nd_cond = nd_cond;
+    n->nd_body = nd_body;
+    n->nd_state = nd_state;
+
+    return n;
+}
+
+static rb_node_until_t *
+rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc)
+{
+    rb_node_until_t *n = NODE_NEWNODE(NODE_UNTIL, rb_node_until_t, loc);
+    n->nd_cond = nd_cond;
+    n->nd_body = nd_body;
+    n->nd_state = nd_state;
+
+    return n;
+}
+
+static rb_node_colon2_t *
+rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc)
+{
+    rb_node_colon2_t *n = NODE_NEWNODE(NODE_COLON2, rb_node_colon2_t, loc);
+    n->nd_head = nd_head;
+    n->nd_mid = nd_mid;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_colon3_t *
+rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc)
+{
+    rb_node_colon3_t *n = NODE_NEWNODE(NODE_COLON3, rb_node_colon3_t, loc);
+    n->not_used = 0;
+    n->nd_mid = nd_mid;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_dot2_t *
+rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc)
+{
+    rb_node_dot2_t *n = NODE_NEWNODE(NODE_DOT2, rb_node_dot2_t, loc);
+    n->nd_beg = nd_beg;
+    n->nd_end = nd_end;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_dot3_t *
+rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc)
+{
+    rb_node_dot3_t *n = NODE_NEWNODE(NODE_DOT3, rb_node_dot3_t, loc);
+    n->nd_beg = nd_beg;
+    n->nd_end = nd_end;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_self_t *
+rb_node_self_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_self_t *n = NODE_NEWNODE(NODE_SELF, rb_node_self_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->nd_state = 1;
+
+    return n;
+}
+
+static rb_node_nil_t *
+rb_node_nil_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_nil_t *n = NODE_NEWNODE(NODE_NIL, rb_node_nil_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_true_t *
+rb_node_true_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_true_t *n = NODE_NEWNODE(NODE_TRUE, rb_node_true_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_false_t *
+rb_node_false_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_false_t *n = NODE_NEWNODE(NODE_FALSE, rb_node_false_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_super_t *
+rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_super_t *n = NODE_NEWNODE(NODE_SUPER, rb_node_super_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_zsuper_t *
+rb_node_zsuper_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_zsuper_t *n = NODE_NEWNODE(NODE_ZSUPER, rb_node_zsuper_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_match2_t *
+rb_node_match2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_match2_t *n = NODE_NEWNODE(NODE_MATCH2, rb_node_match2_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_value = nd_value;
+    n->nd_args = 0;
+
+    return n;
+}
+
+static rb_node_match3_t *
+rb_node_match3_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_match3_t *n = NODE_NEWNODE(NODE_MATCH3, rb_node_match3_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+/* TODO: Use union for NODE_LIST2 */
+static rb_node_list_t *
+rb_node_list_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+{
+    rb_node_list_t *n = NODE_NEWNODE(NODE_LIST, rb_node_list_t, loc);
+    n->nd_head = nd_head;
+    n->as.nd_alen = 1;
+    n->nd_next = 0;
+
+    return n;
+}
+
+static rb_node_list_t *
+rb_node_list_new2(struct parser_params *p, NODE *nd_head, long nd_alen, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_list_t *n = NODE_NEWNODE(NODE_LIST, rb_node_list_t, loc);
+    n->nd_head = nd_head;
+    n->as.nd_alen = nd_alen;
+    n->nd_next = nd_next;
+
+    return n;
+}
+
+static rb_node_zlist_t *
+rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_zlist_t *n = NODE_NEWNODE(NODE_ZLIST, rb_node_zlist_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_hash_t *
+rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+{
+    rb_node_hash_t *n = NODE_NEWNODE(NODE_HASH, rb_node_hash_t, loc);
+    n->nd_head = nd_head;
+    n->nd_brace = 0;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_masgn_t *
+rb_node_masgn_new(struct parser_params *p, NODE *nd_head, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_masgn_t *n = NODE_NEWNODE(NODE_MASGN, rb_node_masgn_t, loc);
+    n->nd_head = nd_head;
+    n->nd_value = 0;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_gasgn_t *
+rb_node_gasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_gasgn_t *n = NODE_NEWNODE(NODE_GASGN, rb_node_gasgn_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_lasgn_t *
+rb_node_lasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_lasgn_t *n = NODE_NEWNODE(NODE_LASGN, rb_node_lasgn_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_dasgn_t *
+rb_node_dasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_dasgn_t *n = NODE_NEWNODE(NODE_DASGN, rb_node_dasgn_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_iasgn_t *
+rb_node_iasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_iasgn_t *n = NODE_NEWNODE(NODE_IASGN, rb_node_iasgn_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_cvasgn_t *
+rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_cvasgn_t *n = NODE_NEWNODE(NODE_CVASGN, rb_node_cvasgn_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_op_asgn1_t *
+rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, rb_node_argscat_t *nd_args, const YYLTYPE *loc)
+{
+    rb_node_op_asgn1_t *n = NODE_NEWNODE(NODE_OP_ASGN1, rb_node_op_asgn1_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_op_asgn2_t *
+rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, rb_node_op_asgn22_t *nd_next, const YYLTYPE *loc)
+{
+    rb_node_op_asgn2_t *n = NODE_NEWNODE(NODE_OP_ASGN2, rb_node_op_asgn2_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_value = nd_value;
+    n->nd_next = nd_next;
+
+    return n;
+}
+
+static rb_node_op_asgn22_t *
+rb_node_op_asgn22_new(struct parser_params *p, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc)
+{
+    rb_node_op_asgn22_t *n = NODE_NEWNODE(NODE_OP_ASGN2, rb_node_op_asgn22_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_mid = nd_mid;
+    n->nd_aid = nd_aid;
+
+    return n;
+}
+
+static rb_node_op_asgn_or_t *
+rb_node_op_asgn_or_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_op_asgn_or_t *n = NODE_NEWNODE(NODE_OP_ASGN_OR, rb_node_op_asgn_or_t, loc);
+    n->nd_head = nd_head;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_op_asgn_and_t *
+rb_node_op_asgn_and_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc)
+{
+    rb_node_op_asgn_and_t *n = NODE_NEWNODE(NODE_OP_ASGN_AND, rb_node_op_asgn_and_t, loc);
+    n->nd_head = nd_head;
+    n->nd_value = nd_value;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_gvar_t *
+rb_node_gvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_gvar_t *n = NODE_NEWNODE(NODE_GVAR, rb_node_gvar_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_lvar_t *
+rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_lvar_t *n = NODE_NEWNODE(NODE_LVAR, rb_node_lvar_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_dvar_t *
+rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_dvar_t *n = NODE_NEWNODE(NODE_DVAR, rb_node_dvar_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_ivar_t *
+rb_node_ivar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_ivar_t *n = NODE_NEWNODE(NODE_IVAR, rb_node_ivar_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_const_t *
+rb_node_const_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_const_t *n = NODE_NEWNODE(NODE_CONST, rb_node_const_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_cvar_t *
+rb_node_cvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc)
+{
+    rb_node_cvar_t *n = NODE_NEWNODE(NODE_CVAR, rb_node_cvar_t, loc);
+    n->nd_vid = nd_vid;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_nth_ref_t *
+rb_node_nth_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc)
+{
+    rb_node_nth_ref_t *n = NODE_NEWNODE(NODE_NTH_REF, rb_node_nth_ref_t, loc);
+    n->not_used = 0;
+    n->nd_nth = nd_nth;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_back_ref_t *
+rb_node_back_ref_new(struct parser_params *p, long nd_nth, const YYLTYPE *loc)
+{
+    rb_node_back_ref_t *n = NODE_NEWNODE(NODE_BACK_REF, rb_node_back_ref_t, loc);
+    n->not_used = 0;
+    n->nd_nth = nd_nth;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_lit_t *
+rb_node_lit_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc)
+{
+    rb_node_lit_t *n = NODE_NEWNODE(NODE_LIT, rb_node_lit_t, loc);
+    n->nd_lit = nd_lit;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_str_t *
+rb_node_str_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc)
+{
+    rb_node_str_t *n = NODE_NEWNODE(NODE_STR, rb_node_str_t, loc);
+    n->nd_lit = nd_lit;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+/* TODO; Use union for NODE_DSTR2 */
+static rb_node_dstr_t *
+rb_node_dstr_new0(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_dstr_t *n = NODE_NEWNODE(NODE_DSTR, rb_node_dstr_t, loc);
+    n->nd_lit = nd_lit;
+    n->as.nd_alen = nd_alen;
+    n->nd_next = (rb_node_list_t *)nd_next;
+
+    return n;
+}
+
+static rb_node_dstr_t *
+rb_node_dstr_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc)
+{
+    return rb_node_dstr_new0(p, nd_lit, 1, 0, loc);
+}
+
+static rb_node_xstr_t *
+rb_node_xstr_new(struct parser_params *p, VALUE nd_lit, const YYLTYPE *loc)
+{
+    rb_node_xstr_t *n = NODE_NEWNODE(NODE_XSTR, rb_node_xstr_t, loc);
+    n->nd_lit = nd_lit;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_dxstr_t *
+rb_node_dxstr_new(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_dxstr_t *n = NODE_NEWNODE(NODE_DXSTR, rb_node_dxstr_t, loc);
+    n->nd_lit = nd_lit;
+    n->nd_alen = nd_alen;
+    n->nd_next = (rb_node_list_t *)nd_next;
+
+    return n;
+}
+
+static rb_node_dsym_t *
+rb_node_dsym_new(struct parser_params *p, VALUE nd_lit, long nd_alen, NODE *nd_next, const YYLTYPE *loc)
+{
+    rb_node_dsym_t *n = NODE_NEWNODE(NODE_DSYM, rb_node_dsym_t, loc);
+    n->nd_lit = nd_lit;
+    n->nd_alen = nd_alen;
+    n->nd_next = (rb_node_list_t *)nd_next;
+
+    return n;
+}
+
+static rb_node_evstr_t *
+rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_evstr_t *n = NODE_NEWNODE(NODE_EVSTR, rb_node_evstr_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_call_t *
+rb_node_call_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_call_t *n = NODE_NEWNODE(NODE_CALL, rb_node_call_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_opcall_t *
+rb_node_opcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_opcall_t *n = NODE_NEWNODE(NODE_OPCALL, rb_node_opcall_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_fcall_t *
+rb_node_fcall_new(struct parser_params *p, ID nd_mid, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_fcall_t *n = NODE_NEWNODE(NODE_FCALL, rb_node_fcall_t, loc);
+    n->not_used = 0;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_qcall_t *
+rb_node_qcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_qcall_t *n = NODE_NEWNODE(NODE_QCALL, rb_node_qcall_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_vcall_t *
+rb_node_vcall_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc)
+{
+    rb_node_vcall_t *n = NODE_NEWNODE(NODE_VCALL, rb_node_vcall_t, loc);
+    n->not_used = 0;
+    n->nd_mid = nd_mid;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_once_t *
+rb_node_once_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_once_t *n = NODE_NEWNODE(NODE_ONCE, rb_node_once_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_args_t *
+rb_node_args_new(struct parser_params *p, struct rb_args_info *nd_ainfo, const YYLTYPE *loc)
+{
+    rb_node_args_t *n = NODE_NEWNODE(NODE_ARGS, rb_node_args_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->nd_ainfo = nd_ainfo;
+
+    return n;
+}
+
+static rb_node_args_aux_t *
+rb_node_args_aux_new(struct parser_params *p, ID nd_pid, long nd_plen, const YYLTYPE *loc)
+{
+    rb_node_args_aux_t *n = NODE_NEWNODE(NODE_ARGS_AUX, rb_node_args_aux_t, loc);
+    n->nd_pid = nd_pid;
+    n->nd_plen = nd_plen;
+    n->nd_next = 0;
+
+    return n;
+}
+
+static rb_node_opt_arg_t *
+rb_node_opt_arg_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_opt_arg_t *n = NODE_NEWNODE(NODE_OPT_ARG, rb_node_opt_arg_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->nd_next = 0;
+
+    return n;
+}
+
+static rb_node_kw_arg_t *
+rb_node_kw_arg_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_kw_arg_t *n = NODE_NEWNODE(NODE_KW_ARG, rb_node_kw_arg_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->nd_next = 0;
+
+    return n;
+}
+
+static rb_node_postarg_t *
+rb_node_postarg_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+{
+    rb_node_postarg_t *n = NODE_NEWNODE(NODE_POSTARG, rb_node_postarg_t, loc);
+    n->nd_1st = nd_1st;
+    n->nd_2nd = nd_2nd;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_argscat_t *
+rb_node_argscat_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_argscat_t *n = NODE_NEWNODE(NODE_ARGSCAT, rb_node_argscat_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_argspush_t *
+rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_argspush_t *n = NODE_NEWNODE(NODE_ARGSPUSH, rb_node_argspush_t, loc);
+    n->nd_head = nd_head;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_splat_t *
+rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+{
+    rb_node_splat_t *n = NODE_NEWNODE(NODE_SPLAT, rb_node_splat_t, loc);
+    n->nd_head = nd_head;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_block_pass_t *
+rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_block_pass_t *n = NODE_NEWNODE(NODE_BLOCK_PASS, rb_node_block_pass_t, loc);
+    n->nd_head = 0;
+    n->nd_body = nd_body;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_alias_t *
+rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+{
+    rb_node_alias_t *n = NODE_NEWNODE(NODE_ALIAS, rb_node_alias_t, loc);
+    n->nd_1st = nd_1st;
+    n->nd_2nd = nd_2nd;
+    n->not_used = 0;
+
+    return n;
+}
+
+static rb_node_valias_t *
+rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc)
+{
+    rb_node_valias_t *n = NODE_NEWNODE(NODE_VALIAS, rb_node_valias_t, loc);
+    n->nd_alias = nd_alias;
+    n->nd_orig = nd_orig;
+    n->not_used = 0;
+
+    return n;
+}
+
+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->not_used = 0;
+    n->nd_undef = nd_undef;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_errinfo_t *
+rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_errinfo_t *n = NODE_NEWNODE(NODE_ERRINFO, rb_node_errinfo_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_defined_t *
+rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+{
+    rb_node_defined_t *n = NODE_NEWNODE(NODE_DEFINED, rb_node_defined_t, loc);
+    n->nd_head = nd_head;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_postexe_t *
+rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+{
+    rb_node_postexe_t *n = NODE_NEWNODE(NODE_POSTEXE, rb_node_postexe_t, loc);
+    n->not_used = 0;
+    n->nd_body = nd_body;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_attrasgn_t *
+rb_node_attrasgn_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc)
+{
+    rb_node_attrasgn_t *n = NODE_NEWNODE(NODE_ATTRASGN, rb_node_attrasgn_t, loc);
+    n->nd_recv = nd_recv;
+    n->nd_mid = nd_mid;
+    n->nd_args = nd_args;
+
+    return n;
+}
+
+static rb_node_aryptn_t *
+rb_node_aryptn_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_aryptn_t *n = NODE_NEWNODE(NODE_ARYPTN, rb_node_aryptn_t, loc);
+    n->nd_pconst = 0;
+    n->not_used = 0;
+    n->nd_apinfo = 0;
+
+    return n;
+}
+
+static rb_node_hshptn_t *
+rb_node_hshptn_new(struct parser_params *p, NODE *nd_pconst, NODE *nd_pkwargs, NODE *nd_pkwrestarg, const YYLTYPE *loc)
+{
+    rb_node_hshptn_t *n = NODE_NEWNODE(NODE_HSHPTN, rb_node_hshptn_t, loc);
+    n->nd_pconst = nd_pconst;
+    n->nd_pkwargs = nd_pkwargs;
+    n->nd_pkwrestarg = nd_pkwrestarg;
+
+    return n;
+}
+
+static rb_node_fndptn_t *
+rb_node_fndptn_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_fndptn_t *n = NODE_NEWNODE(NODE_FNDPTN, rb_node_fndptn_t, loc);
+    n->nd_pconst = 0;
+    n->not_used = 0;
+    n->nd_fpinfo = 0;
+
+    return n;
+}
+
+static rb_node_cdecl_t *
+rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, const YYLTYPE *loc)
+{
+    rb_node_cdecl_t *n = NODE_NEWNODE(NODE_CDECL, rb_node_cdecl_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_value = nd_value;
+    n->nd_else = nd_else;
+
+    return n;
+}
+
+static rb_node_op_cdecl_t *
+rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, const YYLTYPE *loc)
+{
+    rb_node_op_cdecl_t *n = NODE_NEWNODE(NODE_OP_CDECL, rb_node_op_cdecl_t, loc);
+    n->nd_head = nd_head;
+    n->nd_value = nd_value;
+    n->nd_aid = nd_aid;
+
+    return n;
+}
+
+static rb_node_error_t *
+rb_node_error_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_error_t *n = NODE_NEWNODE(NODE_ERROR, rb_node_error_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+#else
+
+static rb_node_ripper_t *
+rb_node_ripper_new(struct parser_params *p, ID nd_vid, VALUE nd_rval, VALUE nd_cval, const YYLTYPE *loc)
+{
+    rb_node_ripper_t *n = NODE_NEWNODE(NODE_RIPPER, rb_node_ripper_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_rval = nd_rval;
+    n->nd_cval = nd_cval;
+
+    return n;
+}
+
+static rb_node_ripper_values_t *
+rb_node_ripper_values_new(struct parser_params *p, VALUE nd_val1, VALUE nd_val2, VALUE nd_val3, const YYLTYPE *loc)
+{
+    rb_node_ripper_values_t *n = NODE_NEWNODE(NODE_RIPPER_VALUES, rb_node_ripper_values_t, loc);
+    n->nd_val1 = nd_val1;
+    n->nd_val2 = nd_val2;
+    n->nd_val3 = nd_val3;
+
+    return n;
+}
+
+#endif
+
+static rb_node_break_t *
+rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+{
+    rb_node_break_t *n = NODE_NEWNODE(NODE_BREAK, rb_node_break_t, loc);
+    n->nd_stts = nd_stts;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_next_t *
+rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+{
+    rb_node_next_t *n = NODE_NEWNODE(NODE_NEXT, rb_node_next_t, loc);
+    n->nd_stts = nd_stts;
+    n->not_used = 0;
+    n->not_used2 = 0;
+
+    return n;
+}
+
+static rb_node_redo_t *
+rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc)
+{
+    rb_node_redo_t *n = NODE_NEWNODE(NODE_REDO, rb_node_redo_t, loc);
+    n->not_used = 0;
+    n->not_used2 = 0;
+    n->not_used3 = 0;
+
+    return n;
+}
+
+static rb_node_def_temp_t *
+rb_node_def_temp_new(struct parser_params *p, ID nd_vid, ID nd_mid, rb_node_def_temp2_t *nd_next, const YYLTYPE *loc)
+{
+    rb_node_def_temp_t *n = NODE_NEWNODE(NODE_DEF_TEMP, rb_node_def_temp_t, loc);
+    n->nd_vid = nd_vid;
+    n->nd_mid = nd_mid;
+    n->nd_next = nd_next;
+
+    return n;
+}
+
+static rb_node_def_temp2_t *
+rb_node_def_temp2_new(struct parser_params *p, NODE *nd_head, long nd_nth, VALUE nd_cval)
+{
+    rb_node_def_temp2_t *n = NODE_NEW_INTERNAL(NODE_DEF_TEMP2, rb_node_def_temp2_t);
+    n->nd_head = nd_head;
+    n->nd_nth = nd_nth;
+    n->nd_cval = nd_cval;
+
+    return n;
+}
+
+#ifndef RIPPER
+static enum node_type
+nodetype(NODE *node)                   /* for debug */
+{
+    return (enum node_type)nd_type(node);
+}
+
+static int
+nodeline(NODE *node)
+{
+    return nd_line(node);
+}
+
+static NODE*
+newline_node(NODE *node)
+{
+    if (node) {
+        node = remove_begin(node);
+        node->flags |= NODE_FL_NEWLINE;
+    }
+    return node;
+}
+
+static void
+fixpos(NODE *node, NODE *orig)
+{
+    if (!node) return;
+    if (!orig) return;
+    nd_set_line(node, nd_line(orig));
+}
+
+static void
+parser_warning(struct parser_params *p, NODE *node, const char *mesg)
+{
+    rb_compile_warning(p->ruby_sourcefile, nd_line(node), "%s", mesg);
+}
+
+static void
+parser_warn(struct parser_params *p, NODE *node, const char *mesg)
+{
+    rb_compile_warn(p->ruby_sourcefile, nd_line(node), "%s", mesg);
+}
+
+static NODE*
+block_append(struct parser_params *p, NODE *head, NODE *tail)
+{
+    NODE *end, *h = head, *nd;
+
+    if (tail == 0) return head;
+
+    if (h == 0) return tail;
+    switch (nd_type(h)) {
+      case NODE_LIT:
+      case NODE_STR:
+      case NODE_SELF:
+      case NODE_TRUE:
+      case NODE_FALSE:
+      case NODE_NIL:
+        parser_warning(p, h, "unused literal ignored");
+        return tail;
+      default:
+        h = end = NEW_BLOCK(head, &head->nd_loc);
+        RNODE_BLOCK(end)->nd_end = end;
+        head = end;
+        break;
+      case NODE_BLOCK:
+        end = RNODE_BLOCK(h)->nd_end;
+        break;
+    }
+
+    nd = RNODE_BLOCK(end)->nd_head;
+    switch (nd_type(nd)) {
+      case NODE_RETURN:
+      case NODE_BREAK:
+      case NODE_NEXT:
+      case NODE_REDO:
+      case NODE_RETRY:
+        if (RTEST(ruby_verbose)) {
+            parser_warning(p, tail, "statement not reached");
+        }
+        break;
+
+      default:
+        break;
+    }
+
+    if (!nd_type_p(tail, NODE_BLOCK)) {
+        tail = NEW_BLOCK(tail, &tail->nd_loc);
+        RNODE_BLOCK(tail)->nd_end = tail;
+    }
+    RNODE_BLOCK(end)->nd_next = tail;
+    RNODE_BLOCK(h)->nd_end = RNODE_BLOCK(tail)->nd_end;
+    nd_set_last_loc(head, nd_last_loc(tail));
+    return head;
+}
+
+/* append item to the list */
+static NODE*
+list_append(struct parser_params *p, NODE *list, NODE *item)
+{
+    NODE *last;
+
+    if (list == 0) return NEW_LIST(item, &item->nd_loc);
+    if (RNODE_LIST(list)->nd_next) {
+        last = RNODE_LIST(RNODE_LIST(list)->nd_next)->as.nd_end;
+    }
+    else {
+        last = list;
+    }
+
+    RNODE_LIST(list)->as.nd_alen += 1;
+    RNODE_LIST(last)->nd_next = NEW_LIST(item, &item->nd_loc);
+    RNODE_LIST(RNODE_LIST(list)->nd_next)->as.nd_end = RNODE_LIST(last)->nd_next;
+
+    nd_set_last_loc(list, nd_last_loc(item));
+
+    return list;
+}
+
+/* concat two lists */
+static NODE*
+list_concat(NODE *head, NODE *tail)
+{
+    NODE *last;
+
+    if (RNODE_LIST(head)->nd_next) {
+        last = RNODE_LIST(RNODE_LIST(head)->nd_next)->as.nd_end;
+    }
+    else {
+        last = head;
+    }
+
+    RNODE_LIST(head)->as.nd_alen += RNODE_LIST(tail)->as.nd_alen;
+    RNODE_LIST(last)->nd_next = tail;
+    if (RNODE_LIST(tail)->nd_next) {
+        RNODE_LIST(RNODE_LIST(head)->nd_next)->as.nd_end = RNODE_LIST(RNODE_LIST(tail)->nd_next)->as.nd_end;
+    }
+    else {
+        RNODE_LIST(RNODE_LIST(head)->nd_next)->as.nd_end = tail;
+    }
+
+    nd_set_last_loc(head, nd_last_loc(tail));
+
+    return head;
+}
+
+static int
+literal_concat0(struct parser_params *p, VALUE head, VALUE tail)
+{
+    if (NIL_P(tail)) return 1;
+    if (!rb_enc_compatible(head, tail)) {
+        compile_error(p, "string literal encodings differ (%s / %s)",
+                      rb_enc_name(rb_enc_get(head)),
+                      rb_enc_name(rb_enc_get(tail)));
+        rb_str_resize(head, 0);
+        rb_str_resize(tail, 0);
+        return 0;
+    }
+    rb_str_buf_append(head, tail);
+    return 1;
+}
+
+static VALUE
+string_literal_head(struct parser_params *p, enum node_type htype, NODE *head)
+{
+    if (htype != NODE_DSTR) return Qfalse;
+    if (RNODE_DSTR(head)->nd_next) {
+        head = RNODE_LIST(RNODE_LIST(RNODE_DSTR(head)->nd_next)->as.nd_end)->nd_head;
+        if (!head || !nd_type_p(head, NODE_STR)) return Qfalse;
+    }
+    const VALUE lit = RNODE_DSTR(head)->nd_lit;
+    ASSUME(lit != Qfalse);
+    return lit;
+}
+
+/* concat two string literals */
+static NODE *
+literal_concat(struct parser_params *p, NODE *head, NODE *tail, const YYLTYPE *loc)
+{
+    enum node_type htype;
+    VALUE lit;
+
+    if (!head) return tail;
+    if (!tail) return head;
+
+    htype = nd_type(head);
+    if (htype == NODE_EVSTR) {
+        head = new_dstr(p, head, loc);
+        htype = NODE_DSTR;
+    }
+    if (p->heredoc_indent > 0) {
+        switch (htype) {
+          case NODE_STR:
+            nd_set_type(head, NODE_DSTR);
+          case NODE_DSTR:
+            return list_append(p, head, tail);
+          default:
+            break;
+        }
+    }
+    switch (nd_type(tail)) {
+      case NODE_STR:
+        if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
+            htype = NODE_STR;
+        }
+        else {
+            lit = RNODE_DSTR(head)->nd_lit;
+        }
+        if (htype == NODE_STR) {
+            if (!literal_concat0(p, lit, RNODE_STR(tail)->nd_lit)) {
+              error:
+                rb_discard_node(p, head);
+                rb_discard_node(p, tail);
+                return 0;
+            }
+            rb_discard_node(p, tail);
+        }
+        else {
+            list_append(p, head, tail);
+        }
+        break;
+
+      case NODE_DSTR:
+        if (htype == NODE_STR) {
+            if (!literal_concat0(p, RNODE_STR(head)->nd_lit, RNODE_DSTR(tail)->nd_lit))
+                goto error;
+            RNODE_DSTR(tail)->nd_lit = RNODE_STR(head)->nd_lit;
+            rb_discard_node(p, head);
+            head = tail;
+        }
+        else if (NIL_P(RNODE_DSTR(tail)->nd_lit)) {
+          append:
+            RNODE_DSTR(head)->as.nd_alen += RNODE_DSTR(tail)->as.nd_alen - 1;
+            if (!RNODE_DSTR(head)->nd_next) {
+                RNODE_DSTR(head)->nd_next = RNODE_DSTR(tail)->nd_next;
+            }
+            else if (RNODE_DSTR(tail)->nd_next) {
+                RNODE_DSTR(RNODE_DSTR(RNODE_DSTR(head)->nd_next)->as.nd_end)->nd_next = RNODE_DSTR(tail)->nd_next;
+                RNODE_DSTR(RNODE_DSTR(head)->nd_next)->as.nd_end = RNODE_DSTR(RNODE_DSTR(tail)->nd_next)->as.nd_end;
+            }
+            rb_discard_node(p, tail);
+        }
+        else if ((lit = string_literal_head(p, htype, head)) != Qfalse) {
+            if (!literal_concat0(p, lit, RNODE_DSTR(tail)->nd_lit))
+                goto error;
+            RNODE_DSTR(tail)->nd_lit = Qnil;
+            goto append;
+        }
+        else {
+            list_concat(head, NEW_LIST2(NEW_STR(RNODE_DSTR(tail)->nd_lit, loc), RNODE_DSTR(tail)->as.nd_alen, (NODE *)RNODE_DSTR(tail)->nd_next, loc));
+        }
+        break;
+
+      case NODE_EVSTR:
+        if (htype == NODE_STR) {
+            nd_set_type(head, NODE_DSTR);
+            RNODE_DSTR(head)->as.nd_alen = 1;
+        }
+        list_append(p, head, tail);
+        break;
+    }
+    return head;
+}
+
+static NODE *
+evstr2dstr(struct parser_params *p, NODE *node)
+{
+    if (nd_type_p(node, NODE_EVSTR)) {
+        node = new_dstr(p, node, &node->nd_loc);
+    }
+    return node;
+}
+
+static NODE *
+new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
+{
+    NODE *head = node;
+
+    if (node) {
         switch (nd_type(node)) {
           case NODE_STR:
             nd_set_type(node, NODE_DSTR);
@@ -11134,7 +12555,7 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a
     return ret;
 }
 
-#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? (node)->nd_body : node)
+#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? RNODE_ONCE(node)->nd_body : node)
 
 static NODE*
 last_expr_once_body(NODE *node)
@@ -11164,10 +12585,10 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo
             }
 
           case NODE_LIT:
-            if (RB_TYPE_P(n->nd_lit, T_REGEXP)) {
-                const VALUE lit = n->nd_lit;
+            if (RB_TYPE_P(RNODE_LIT(n)->nd_lit, T_REGEXP)) {
+                const VALUE lit = RNODE_LIT(n)->nd_lit;
                 NODE *match = NEW_MATCH2(node1, node2, loc);
-                match->nd_args = reg_named_capture_assign(p, lit, loc);
+                RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc);
                 nd_set_line(match, line);
                 return match;
             }
@@ -11179,7 +12600,7 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo
 
         switch (nd_type(n)) {
           case NODE_LIT:
-            if (!RB_TYPE_P(n->nd_lit, T_REGEXP)) break;
+            if (!RB_TYPE_P(RNODE_LIT(n)->nd_lit, T_REGEXP)) break;
             /* fallthru */
           case NODE_DREGX:
             match3 = NEW_MATCH3(node2, node1, loc);
@@ -11252,7 +12673,7 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
         return NEW_LIT(INT2FIX(p->tokline), loc);
       case keyword__ENCODING__:
         node = NEW_LIT(rb_enc_from_encoding(p->enc), loc);
-        RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(node)->nd_lit);
         return node;
 
     }
@@ -11311,11 +12732,11 @@ opt_arg_append(NODE *opt_list, NODE *opt)
     NODE *opts = opt_list;
     opts->nd_loc.end_pos = opt->nd_loc.end_pos;
 
-    while (opts->nd_next) {
-        opts = opts->nd_next;
+    while (RNODE_OPT_ARG(opts)->nd_next) {
+        opts = RNODE_OPT_ARG(opts)->nd_next;
         opts->nd_loc.end_pos = opt->nd_loc.end_pos;
     }
-    opts->nd_next = opt;
+    RNODE_OPT_ARG(opts)->nd_next = opt;
 
     return opt_list;
 }
@@ -11345,7 +12766,7 @@ symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol)
         break;
       case NODE_STR:
         nd_set_type(symbol, NODE_LIT);
-        RB_OBJ_WRITTEN(p->ast, Qnil, symbol->nd_lit = rb_str_intern(symbol->nd_lit));
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_STR(symbol)->nd_lit = rb_str_intern(RNODE_STR(symbol)->nd_lit));
         break;
       default:
         compile_error(p, "unexpected node as symbol: %s", ruby_node_name(type));
@@ -11356,64 +12777,65 @@ symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol)
 static NODE *
 new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc)
 {
-    NODE *list, *prev;
+    struct RNode_LIST *list;
+    NODE *prev;
     VALUE lit;
 
     if (!node) {
         node = NEW_LIT(reg_compile(p, STR_NEW0(), options), loc);
-        RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(node)->nd_lit);
         return node;
     }
     switch (nd_type(node)) {
       case NODE_STR:
         {
-            VALUE src = node->nd_lit;
+            VALUE src = RNODE_STR(node)->nd_lit;
             nd_set_type(node, NODE_LIT);
             nd_set_loc(node, loc);
-            RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit = reg_compile(p, src, options));
+            RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_STR(node)->nd_lit = reg_compile(p, src, options));
         }
         break;
       default:
         lit = STR_NEW0();
-        node = NEW_NODE(NODE_DSTR, lit, 1, NEW_LIST(node, loc), loc);
+        node = NEW_DSTR0(lit, 1, NEW_LIST(node, loc), loc);
         RB_OBJ_WRITTEN(p->ast, Qnil, lit);
         /* fall through */
       case NODE_DSTR:
         nd_set_type(node, NODE_DREGX);
         nd_set_loc(node, loc);
-        node->nd_cflag = options & RE_OPTION_MASK;
-        if (!NIL_P(node->nd_lit)) reg_fragment_check(p, node->nd_lit, options);
-        for (list = (prev = node)->nd_next; list; list = list->nd_next) {
+        RNODE_DREGX(node)->nd_cflag = options & RE_OPTION_MASK;
+        if (!NIL_P(RNODE_DREGX(node)->nd_lit)) reg_fragment_check(p, RNODE_DREGX(node)->nd_lit, options);
+        for (list = RNODE_DREGX(prev = node)->nd_next; list; list = RNODE_LIST(list->nd_next)) {
             NODE *frag = list->nd_head;
             enum node_type type = nd_type(frag);
-            if (type == NODE_STR || (type == NODE_DSTR && !frag->nd_next)) {
-                VALUE tail = frag->nd_lit;
-                if (reg_fragment_check(p, tail, options) && prev && !NIL_P(prev->nd_lit)) {
-                    VALUE lit = prev == node ? prev->nd_lit : prev->nd_head->nd_lit;
+            if (type == NODE_STR || (type == NODE_DSTR && !RNODE_DSTR(frag)->nd_next)) {
+                VALUE tail = RNODE_STR(frag)->nd_lit;
+                if (reg_fragment_check(p, tail, options) && prev && !NIL_P(RNODE_DREGX(prev)->nd_lit)) {
+                    VALUE lit = prev == node ? RNODE_DREGX(prev)->nd_lit : RNODE_LIT(RNODE_LIST(prev)->nd_head)->nd_lit;
                     if (!literal_concat0(p, lit, tail)) {
                         return NEW_NIL(loc); /* dummy node on error */
                     }
                     rb_str_resize(tail, 0);
-                    prev->nd_next = list->nd_next;
+                    RNODE_LIST(prev)->nd_next = list->nd_next;
                     rb_discard_node(p, list->nd_head);
-                    rb_discard_node(p, list);
-                    list = prev;
+                    rb_discard_node(p, (NODE *)list);
+                    list = RNODE_LIST(prev);
                 }
                 else {
-                    prev = list;
+                    prev = (NODE *)list;
                 }
             }
             else {
                 prev = 0;
             }
         }
-        if (!node->nd_next) {
-            VALUE src = node->nd_lit;
+        if (!RNODE_DREGX(node)->nd_next) {
+            VALUE src = RNODE_DREGX(node)->nd_lit;
             nd_set_type(node, NODE_LIT);
-            RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit = reg_compile(p, src, options));
+            RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_DREGX(node)->nd_lit = reg_compile(p, src, options));
         }
         if (options & RE_OPTION_ONCE) {
-            node = NEW_NODE(NODE_ONCE, 0, node, 0, loc);
+            node = NEW_ONCE(node, loc);
         }
         break;
     }
@@ -11446,7 +12868,7 @@ new_xstring(struct parser_params *p, NODE *node, const YYLTYPE *loc)
         nd_set_loc(node, loc);
         break;
       default:
-        node = NEW_NODE(NODE_DXSTR, Qnil, 1, NEW_LIST(node, loc), loc);
+        node = NEW_DXSTR(Qnil, 1, NEW_LIST(node, loc), loc);
         break;
     }
     return node;
@@ -11462,7 +12884,7 @@ check_literal_when(struct parser_params *p, NODE *arg, const YYLTYPE *loc)
     lit = rb_node_case_when_optimizable_literal(arg);
     if (UNDEF_P(lit)) return;
     if (nd_type_p(arg, NODE_STR)) {
-        RB_OBJ_WRITTEN(p->ast, Qnil, arg->nd_lit = lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_STR(arg)->nd_lit = lit);
     }
 
     if (NIL_P(p->case_labels)) {
@@ -11506,12 +12928,12 @@ new_regexp(struct parser_params *p, VALUE re, VALUE opt, const YYLTYPE *loc)
     VALUE src = 0, err = 0;
     int options = 0;
     if (ripper_is_node_yylval(p, re)) {
-        src = RNODE(re)->nd_cval;
-        re = RNODE(re)->nd_rval;
+        src = RNODE_RIPPER(re)->nd_cval;
+        re = RNODE_RIPPER(re)->nd_rval;
     }
     if (ripper_is_node_yylval(p, opt)) {
-        options = (int)RNODE(opt)->nd_tag;
-        opt = RNODE(opt)->nd_rval;
+        options = (int)RNODE_RIPPER(opt)->nd_vid;
+        opt = RNODE_RIPPER(opt)->nd_rval;
     }
     if (src && NIL_P(parser_reg_compile(p, src, options, &err))) {
         compile_error(p, "%"PRIsVALUE, err);
@@ -11879,10 +13301,10 @@ rb_backref_error(struct parser_params *p, NODE *node)
 {
     switch (nd_type(node)) {
       case NODE_NTH_REF:
-        compile_error(p, "Can't set variable $%ld", node->nd_nth);
+        compile_error(p, "Can't set variable $%ld", RNODE_NTH_REF(node)->nd_nth);
         break;
       case NODE_BACK_REF:
-        compile_error(p, "Can't set variable $%c", (int)node->nd_nth);
+        compile_error(p, "Can't set variable $%c", (int)RNODE_BACK_REF(node)->nd_nth);
         break;
     }
 }
@@ -11891,7 +13313,7 @@ static VALUE
 backref_error(struct parser_params *p, NODE *ref, VALUE expr)
 {
     VALUE mesg = rb_str_new_cstr("Can't set variable ");
-    rb_str_append(mesg, ref->nd_cval);
+    rb_str_append(mesg, RNODE_RIPPER(ref)->nd_cval);
     return dispatch2(assign_error, mesg, expr);
 }
 #endif
@@ -11905,18 +13327,18 @@ arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc
       case NODE_LIST:
         return list_append(p, node1, node2);
       case NODE_BLOCK_PASS:
-        node1->nd_head = arg_append(p, node1->nd_head, node2, loc);
-        node1->nd_loc.end_pos = node1->nd_head->nd_loc.end_pos;
+        RNODE_BLOCK_PASS(node1)->nd_head = arg_append(p, RNODE_BLOCK_PASS(node1)->nd_head, node2, loc);
+        node1->nd_loc.end_pos = RNODE_BLOCK_PASS(node1)->nd_head->nd_loc.end_pos;
         return node1;
       case NODE_ARGSPUSH:
-        node1->nd_body = list_append(p, NEW_LIST(node1->nd_body, &node1->nd_body->nd_loc), node2);
-        node1->nd_loc.end_pos = node1->nd_body->nd_loc.end_pos;
+        RNODE_ARGSPUSH(node1)->nd_body = list_append(p, NEW_LIST(RNODE_ARGSPUSH(node1)->nd_body, &RNODE_ARGSPUSH(node1)->nd_body->nd_loc), node2);
+        node1->nd_loc.end_pos = RNODE_ARGSPUSH(node1)->nd_body->nd_loc.end_pos;
         nd_set_type(node1, NODE_ARGSCAT);
         return node1;
       case NODE_ARGSCAT:
-        if (!nd_type_p(node1->nd_body, NODE_LIST)) break;
-        node1->nd_body = list_append(p, node1->nd_body, node2);
-        node1->nd_loc.end_pos = node1->nd_body->nd_loc.end_pos;
+        if (!nd_type_p(RNODE_ARGSCAT(node1)->nd_body, NODE_LIST)) break;
+        RNODE_ARGSCAT(node1)->nd_body = list_append(p, RNODE_ARGSCAT(node1)->nd_body, node2);
+        node1->nd_loc.end_pos = RNODE_ARGSCAT(node1)->nd_body->nd_loc.end_pos;
         return node1;
     }
     return NEW_ARGSPUSH(node1, node2, loc);
@@ -11928,20 +13350,20 @@ arg_concat(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc
     if (!node2) return node1;
     switch (nd_type(node1)) {
       case NODE_BLOCK_PASS:
-        if (node1->nd_head)
-            node1->nd_head = arg_concat(p, node1->nd_head, node2, loc);
+        if (RNODE_BLOCK_PASS(node1)->nd_head)
+            RNODE_BLOCK_PASS(node1)->nd_head = arg_concat(p, RNODE_BLOCK_PASS(node1)->nd_head, node2, loc);
         else
-            node1->nd_head = NEW_LIST(node2, loc);
+            RNODE_LIST(node1)->nd_head = NEW_LIST(node2, loc);
         return node1;
       case NODE_ARGSPUSH:
         if (!nd_type_p(node2, NODE_LIST)) break;
-        node1->nd_body = list_concat(NEW_LIST(node1->nd_body, loc), node2);
+        RNODE_ARGSPUSH(node1)->nd_body = list_concat(NEW_LIST(RNODE_ARGSPUSH(node1)->nd_body, loc), node2);
         nd_set_type(node1, NODE_ARGSCAT);
         return node1;
       case NODE_ARGSCAT:
         if (!nd_type_p(node2, NODE_LIST) ||
-            !nd_type_p(node1->nd_body, NODE_LIST)) break;
-        node1->nd_body = list_concat(node1->nd_body, node2);
+            !nd_type_p(RNODE_ARGSCAT(node1)->nd_body, NODE_LIST)) break;
+        RNODE_ARGSCAT(node1)->nd_body = list_concat(RNODE_ARGSCAT(node1)->nd_body, node2);
         return node1;
     }
     return NEW_ARGSCAT(node1, node2, loc);
@@ -11970,7 +13392,7 @@ rest_arg_append(struct parser_params *p, NODE *args, NODE *rest_arg, const YYLTY
 static NODE *
 splat_array(NODE* node)
 {
-    if (nd_type_p(node, NODE_SPLAT)) node = node->nd_head;
+    if (nd_type_p(node, NODE_SPLAT)) node = RNODE_SPLAT(node)->nd_head;
     if (nd_type_p(node, NODE_LIST)) return node;
     return 0;
 }
@@ -11982,12 +13404,12 @@ mark_lvar_used(struct parser_params *p, NODE *rhs)
     if (!rhs) return;
     switch (nd_type(rhs)) {
       case NODE_LASGN:
-        if (local_id_ref(p, rhs->nd_vid, &vidp)) {
+        if (local_id_ref(p, RNODE_LASGN(rhs)->nd_vid, &vidp)) {
             if (vidp) *vidp |= LVAR_USED;
         }
         break;
       case NODE_DASGN:
-        if (dvar_defined_ref(p, rhs->nd_vid, &vidp)) {
+        if (dvar_defined_ref(p, RNODE_DASGN(rhs)->nd_vid, &vidp)) {
             if (vidp) *vidp |= LVAR_USED;
         }
         break;
@@ -12008,18 +13430,18 @@ const_decl_path(struct parser_params *p, NODE **dest)
     if (!nd_type_p(n, NODE_CALL)) {
         const YYLTYPE *loc = &n->nd_loc;
         VALUE path;
-        if (n->nd_vid) {
-             path = rb_id2str(n->nd_vid);
+        if (RNODE_DASGN(n)->nd_vid) {
+             path = rb_id2str(RNODE_DASGN(n)->nd_vid);
         }
         else {
-            n = n->nd_else;
+            n = RNODE_CDECL(n)->nd_else;
             path = rb_ary_new();
-            for (; n && nd_type_p(n, NODE_COLON2); n = n->nd_head) {
-                rb_ary_push(path, rb_id2str(n->nd_mid));
+            for (; n && nd_type_p(n, NODE_COLON2); n = RNODE_COLON2(n)->nd_head) {
+                rb_ary_push(path, rb_id2str(RNODE_COLON2(n)->nd_mid));
             }
             if (n && nd_type_p(n, NODE_CONST)) {
                 // Const::Name
-                rb_ary_push(path, rb_id2str(n->nd_vid));
+                rb_ary_push(path, rb_id2str(RNODE_CONST(n)->nd_vid));
             }
             else if (n && nd_type_p(n, NODE_COLON3)) {
                 // ::Const::Name
@@ -12033,7 +13455,7 @@ const_decl_path(struct parser_params *p, NODE **dest)
             path = rb_fstring(path);
         }
         *dest = n = NEW_LIT(path, loc);
-        RB_OBJ_WRITTEN(p->ast, Qnil, n->nd_lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
     }
     return n;
 }
@@ -12077,7 +13499,7 @@ shareable_literal_value(struct parser_params *p, NODE *node)
       case NODE_NIL:
         return Qnil;
       case NODE_LIT:
-        return node->nd_lit;
+        return RNODE_LIT(node)->nd_lit;
       default:
         return Qundef;
     }
@@ -12111,26 +13533,26 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
         return value;
 
       case NODE_STR:
-        lit = rb_fstring(value->nd_lit);
+        lit = rb_fstring(RNODE_STR(value)->nd_lit);
         nd_set_type(value, NODE_LIT);
-        RB_OBJ_WRITE(p->ast, &value->nd_lit, lit);
+        RB_OBJ_WRITE(p->ast, &RNODE_STR(value)->nd_lit, lit);
         return value;
 
       case NODE_ZLIST:
         lit = rb_ary_new();
         OBJ_FREEZE_RAW(lit);
         NODE *n = NEW_LIT(lit, loc);
-        RB_OBJ_WRITTEN(p->ast, Qnil, n->nd_lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(n)->nd_lit);
         return n;
 
       case NODE_LIST:
         lit = rb_ary_new();
-        for (NODE *n = value; n; n = n->nd_next) {
-            NODE *elt = n->nd_head;
+        for (NODE *n = value; n; n = RNODE_LIST(n)->nd_next) {
+            NODE *elt = RNODE_LIST(n)->nd_head;
             if (elt) {
                 elt = shareable_literal_constant_next(elt);
                 if (elt) {
-                    n->nd_head = elt;
+                    RNODE_LIST(n)->nd_head = elt;
                 }
                 else if (RTEST(lit)) {
                     rb_ary_clear(lit);
@@ -12151,15 +13573,15 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
         break;
 
       case NODE_HASH:
-        if (!value->nd_brace) return 0;
+        if (!RNODE_HASH(value)->nd_brace) return 0;
         lit = rb_hash_new();
-        for (NODE *n = value->nd_head; n; n = n->nd_next->nd_next) {
-            NODE *key = n->nd_head;
-            NODE *val = n->nd_next->nd_head;
+        for (NODE *n = RNODE_HASH(value)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
+            NODE *key = RNODE_LIST(n)->nd_head;
+            NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
             if (key) {
                 key = shareable_literal_constant_next(key);
                 if (key) {
-                    n->nd_head = key;
+                    RNODE_LIST(n)->nd_head = key;
                 }
                 else if (RTEST(lit)) {
                     rb_hash_clear(lit);
@@ -12169,7 +13591,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
             if (val) {
                 val = shareable_literal_constant_next(val);
                 if (val) {
-                    n->nd_next->nd_head = val;
+                    RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head = val;
                 }
                 else if (RTEST(lit)) {
                     rb_hash_clear(lit);
@@ -12207,7 +13629,7 @@ shareable_literal_constant(struct parser_params *p, enum shareability shareable,
     }
     else {
         value = NEW_LIT(rb_ractor_make_shareable(lit), loc);
-        RB_OBJ_WRITTEN(p->ast, Qnil, value->nd_lit);
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_LIT(value)->nd_lit);
     }
 
     return value;
@@ -12261,12 +13683,12 @@ node_assign(struct parser_params *p, NODE *lhs, NODE *rhs, struct lex_context ct
       case NODE_DASGN:
       case NODE_MASGN:
       case NODE_CVASGN:
-        lhs->nd_value = rhs;
+        RNODE_GASGN(lhs)->nd_value = rhs;
         nd_set_loc(lhs, loc);
         break;
 
       case NODE_ATTRASGN:
-        lhs->nd_args = arg_append(p, lhs->nd_args, rhs, loc);
+        RNODE_ATTRASGN(lhs)->nd_args = arg_append(p, RNODE_ATTRASGN(lhs)->nd_args, rhs, loc);
         nd_set_loc(lhs, loc);
         break;
 
@@ -12296,44 +13718,44 @@ value_expr_check(struct parser_params *p, NODE *node)
             return void_node ? void_node : node;
 
           case NODE_CASE3:
-            if (!node->nd_body || !nd_type_p(node->nd_body, NODE_IN)) {
+            if (!RNODE_CASE3(node)->nd_body || !nd_type_p(RNODE_CASE3(node)->nd_body, NODE_IN)) {
                 compile_error(p, "unexpected node");
                 return NULL;
             }
-            if (node->nd_body->nd_body) {
+            if (RNODE_IN(RNODE_CASE3(node)->nd_body)->nd_body) {
                 return NULL;
             }
             /* single line pattern matching with "=>" operator */
             return void_node ? void_node : node;
 
           case NODE_BLOCK:
-            while (node->nd_next) {
-                node = node->nd_next;
+            while (RNODE_BLOCK(node)->nd_next) {
+                node = RNODE_BLOCK(node)->nd_next;
             }
-            node = node->nd_head;
+            node = RNODE_BLOCK(node)->nd_head;
             break;
 
           case NODE_BEGIN:
-            node = node->nd_body;
+            node = RNODE_BEGIN(node)->nd_body;
             break;
 
           case NODE_IF:
           case NODE_UNLESS:
-            if (!node->nd_body) {
+            if (!RNODE_IF(node)->nd_body) {
                 return NULL;
             }
-            else if (!node->nd_else) {
+            else if (!RNODE_IF(node)->nd_else) {
                 return NULL;
             }
-            vn = value_expr_check(p, node->nd_body);
+            vn = value_expr_check(p, RNODE_IF(node)->nd_body);
             if (!vn) return NULL;
             if (!void_node) void_node = vn;
-            node = node->nd_else;
+            node = RNODE_IF(node)->nd_else;
             break;
 
           case NODE_AND:
           case NODE_OR:
-            node = node->nd_1st;
+            node = RNODE_AND(node)->nd_1st;
             break;
 
           case NODE_LASGN:
@@ -12372,7 +13794,7 @@ void_expr(struct parser_params *p, NODE *node)
     if (!node || !(node = nd_once_body(node))) return;
     switch (nd_type(node)) {
       case NODE_OPCALL:
-        switch (node->nd_mid) {
+        switch (RNODE_OPCALL(node)->nd_mid) {
           case '+':
           case '-':
           case '*':
@@ -12391,7 +13813,7 @@ void_expr(struct parser_params *p, NODE *node)
           case tLEQ:
           case tEQ:
           case tNEQ:
-            useless = rb_id2name(node->nd_mid);
+            useless = rb_id2name(RNODE_OPCALL(node)->nd_mid);
             break;
         }
         break;
@@ -12454,9 +13876,9 @@ void_stmts(struct parser_params *p, NODE *node)
     if (!node) return n;
     if (!nd_type_p(node, NODE_BLOCK)) return n;
 
-    while (node->nd_next) {
-        void_expr(p, node->nd_head);
-        node = node->nd_next;
+    while (RNODE_BLOCK(node)->nd_next) {
+        void_expr(p, RNODE_BLOCK(node)->nd_head);
+        node = RNODE_BLOCK(node)->nd_next;
     }
     return n;
 }
@@ -12465,8 +13887,8 @@ static NODE *
 remove_begin(NODE *node)
 {
     NODE **n = &node, *n1 = node;
-    while (n1 && nd_type_p(n1, NODE_BEGIN) && n1->nd_body) {
-        *n = n1 = n1->nd_body;
+    while (n1 && nd_type_p(n1, NODE_BEGIN) && RNODE_BEGIN(n1)->nd_body) {
+        *n = n1 = RNODE_BEGIN(n1)->nd_body;
     }
     return node;
 }
@@ -12476,7 +13898,7 @@ remove_begin_all(NODE *node)
 {
     NODE **n = &node, *n1 = node;
     while (n1 && nd_type_p(n1, NODE_BEGIN)) {
-        *n = n1 = n1->nd_body;
+        *n = n1 = RNODE_BEGIN(n1)->nd_body;
     }
     return node;
 }
@@ -12490,10 +13912,10 @@ reduce_nodes(struct parser_params *p, NODE **body)
         *body = NEW_NIL(&NULL_LOC);
         return;
     }
-#define subnodes(n1, n2) \
-    ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
-     (!node->n2) ? (body = &node->n1, 1) : \
-     (reduce_nodes(p, &node->n1), body = &node->n2, 1))
+#define subnodes(type, n1, n2) \
+    ((!type(node)->n1) ? (type(node)->n2 ? (body = &type(node)->n2, 1) : 0) : \
+     (!type(node)->n2) ? (body = &type(node)->n1, 1) : \
+     (reduce_nodes(p, &type(node)->n1), body = &type(node)->n2, 1))
 
     while (node) {
         int newline = (int)(node->flags & NODE_FL_NEWLINE);
@@ -12503,36 +13925,36 @@ reduce_nodes(struct parser_params *p, NODE **body)
             *body = 0;
             return;
           case NODE_RETURN:
-            *body = node = node->nd_stts;
+            *body = node = RNODE_RETURN(node)->nd_stts;
             if (newline && node) node->flags |= NODE_FL_NEWLINE;
             continue;
           case NODE_BEGIN:
-            *body = node = node->nd_body;
+            *body = node = RNODE_BEGIN(node)->nd_body;
             if (newline && node) node->flags |= NODE_FL_NEWLINE;
             continue;
           case NODE_BLOCK:
-            body = &node->nd_end->nd_head;
+            body = &RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head;
             break;
           case NODE_IF:
           case NODE_UNLESS:
-            if (subnodes(nd_body, nd_else)) break;
+            if (subnodes(RNODE_IF, nd_body, nd_else)) break;
             return;
           case NODE_CASE:
-            body = &node->nd_body;
+            body = &RNODE_CASE(node)->nd_body;
             break;
           case NODE_WHEN:
-            if (!subnodes(nd_body, nd_next)) goto end;
+            if (!subnodes(RNODE_WHEN, nd_body, nd_next)) goto end;
             break;
           case NODE_ENSURE:
-            if (!subnodes(nd_head, nd_resq)) goto end;
+            if (!subnodes(RNODE_ENSURE, nd_head, nd_resq)) goto end;
             break;
           case NODE_RESCUE:
             newline = 0; // RESBODY should not be a NEWLINE
-            if (node->nd_else) {
-                body = &node->nd_resq;
+            if (RNODE_RESCUE(node)->nd_else) {
+                body = &RNODE_RESCUE(node)->nd_resq;
                 break;
             }
-            if (!subnodes(nd_head, nd_resq)) goto end;
+            if (!subnodes(RNODE_RESCUE, nd_head, nd_resq)) goto end;
             break;
           default:
             return;
@@ -12550,11 +13972,11 @@ is_static_content(NODE *node)
     if (!node) return 1;
     switch (nd_type(node)) {
       case NODE_HASH:
-        if (!(node = node->nd_head)) break;
+        if (!(node = RNODE_HASH(node)->nd_head)) break;
       case NODE_LIST:
         do {
-            if (!is_static_content(node->nd_head)) return 0;
-        } while ((node = node->nd_next) != 0);
+            if (!is_static_content(RNODE_LIST(node)->nd_head)) return 0;
+        } while ((node = RNODE_LIST(node)->nd_next) != 0);
       case NODE_LIT:
       case NODE_STR:
       case NODE_NIL:
@@ -12583,10 +14005,10 @@ assign_in_cond(struct parser_params *p, NODE *node)
         return 0;
     }
 
-    if (!node->nd_value) return 1;
-    if (is_static_content(node->nd_value)) {
+    if (!RNODE_MASGN(node)->nd_value) return 1;
+    if (is_static_content(RNODE_MASGN(node)->nd_value)) {
         /* reports always */
-        parser_warn(p, node->nd_value, "found `= literal' in conditional, should be ==");
+        parser_warn(p, RNODE_MASGN(node)->nd_value, "found `= literal' in conditional, should be ==");
     }
     return 1;
 }
@@ -12615,7 +14037,7 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc)
 
     type = nd_type(node);
     value_expr(node);
-    if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
+    if (type == NODE_LIT && FIXNUM_P(RNODE_LIT(node)->nd_lit)) {
         if (!e_option_supplied(p)) parser_warn(p, node, "integer literal in flip-flop");
         ID lineno = rb_intern("$.");
         return NEW_CALL(node, tEQ, NEW_LIST(NEW_GVAR(lineno, loc), loc), loc);
@@ -12643,19 +14065,19 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
         return NEW_MATCH2(node, NEW_GVAR(idLASTLINE, loc), loc);
 
       case NODE_BLOCK:
-        node->nd_end->nd_head = cond0(p, node->nd_end->nd_head, type, loc);
+        RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head = cond0(p, RNODE_BLOCK(RNODE_BLOCK(node)->nd_end)->nd_head, type, loc);
         break;
 
       case NODE_AND:
       case NODE_OR:
-        node->nd_1st = cond0(p, node->nd_1st, COND_IN_COND, loc);
-        node->nd_2nd = cond0(p, node->nd_2nd, COND_IN_COND, loc);
+        RNODE_AND(node)->nd_1st = cond0(p, RNODE_AND(node)->nd_1st, COND_IN_COND, loc);
+        RNODE_AND(node)->nd_2nd = cond0(p, RNODE_AND(node)->nd_2nd, COND_IN_COND, loc);
         break;
 
       case NODE_DOT2:
       case NODE_DOT3:
-        node->nd_beg = range_op(p, node->nd_beg, loc);
-        node->nd_end = range_op(p, node->nd_end, loc);
+        RNODE_DOT2(node)->nd_beg = range_op(p, RNODE_DOT2(node)->nd_beg, loc);
+        RNODE_DOT2(node)->nd_end = range_op(p, RNODE_DOT2(node)->nd_end, loc);
         if (nd_type_p(node, NODE_DOT2)) nd_set_type(node,NODE_FLIP2);
         else if (nd_type_p(node, NODE_DOT3)) nd_set_type(node, NODE_FLIP3);
         break;
@@ -12666,15 +14088,15 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
         break;
 
       case NODE_LIT:
-        if (RB_TYPE_P(node->nd_lit, T_REGEXP)) {
+        if (RB_TYPE_P(RNODE_LIT(node)->nd_lit, T_REGEXP)) {
             if (!e_option_supplied(p)) SWITCH_BY_COND_TYPE(type, warn, "regex ")
             nd_set_type(node, NODE_MATCH);
         }
-        else if (node->nd_lit == Qtrue ||
-                 node->nd_lit == Qfalse) {
+        else if (RNODE_LIT(node)->nd_lit == Qtrue ||
+                 RNODE_LIT(node)->nd_lit == Qfalse) {
             /* booleans are OK, e.g., while true */
         }
-        else if (SYMBOL_P(node->nd_lit)) {
+        else if (SYMBOL_P(RNODE_LIT(node)->nd_lit)) {
             goto warn_symbol;
         }
         else {
@@ -12723,6 +14145,8 @@ new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYL
     return newline_node(NEW_UNLESS(cc, left, right, loc));
 }
 
+#define NEW_AND_OR(type, f, s, loc) (type == NODE_AND ? NEW_AND(f,s,loc) : NEW_OR(f,s,loc))
+
 static NODE*
 logop(struct parser_params *p, ID id, NODE *left, NODE *right,
           const YYLTYPE *op_loc, const YYLTYPE *loc)
@@ -12732,19 +14156,21 @@ logop(struct parser_params *p, ID id, NODE *left, NODE *right,
     value_expr(left);
     if (left && nd_type_p(left, type)) {
         NODE *node = left, *second;
-        while ((second = node->nd_2nd) != 0 && nd_type_p(second, type)) {
+        while ((second = RNODE_AND(node)->nd_2nd) != 0 && nd_type_p(second, type)) {
             node = second;
         }
-        node->nd_2nd = NEW_NODE(type, second, right, 0, loc);
-        nd_set_line(node->nd_2nd, op_loc->beg_pos.lineno);
+        RNODE_AND(node)->nd_2nd = NEW_AND_OR(type, second, right, loc);
+        nd_set_line(RNODE_AND(node)->nd_2nd, op_loc->beg_pos.lineno);
         left->nd_loc.end_pos = loc->end_pos;
         return left;
     }
-    op = NEW_NODE(type, left, right, 0, loc);
+    op = NEW_AND_OR(type, left, right, loc);
     nd_set_line(op, op_loc->beg_pos.lineno);
     return op;
 }
 
+#undef NEW_AND_OR
+
 static void
 no_blockarg(struct parser_params *p, NODE *node)
 {
@@ -12759,8 +14185,8 @@ ret_args(struct parser_params *p, NODE *node)
     if (node) {
         no_blockarg(p, node);
         if (nd_type_p(node, NODE_LIST)) {
-            if (node->nd_next == 0) {
-                node = node->nd_head;
+            if (RNODE_LIST(node)->nd_next == 0) {
+                node = RNODE_LIST(node)->nd_head;
             }
             else {
                 nd_set_type(node, NODE_VALUES);
@@ -12821,7 +14247,7 @@ arg_blk_pass(NODE *node1, NODE *node2)
 {
     if (node2) {
         if (!node1) return node2;
-        node2->nd_head = node1;
+        RNODE_BLOCK_PASS(node2)->nd_head = node1;
         nd_set_first_lineno(node2, nd_first_lineno(node1));
         nd_set_first_column(node2, nd_first_column(node1));
         return node2;
@@ -12846,7 +14272,7 @@ static NODE*
 new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, NODE *post_args, NODE *tail, const YYLTYPE *loc)
 {
     int saved_line = p->ruby_sourceline;
-    struct rb_args_info *args = tail->nd_ainfo;
+    struct rb_args_info *args = RNODE_ARGS(tail)->nd_ainfo;
 
     if (args->forwarding) {
         if (rest_arg) {
@@ -12856,12 +14282,12 @@ new_args(struct parser_params *p, NODE *pre_args, NODE *opt_args, ID rest_arg, N
         rest_arg = idFWD_REST;
     }
 
-    args->pre_args_num   = pre_args ? rb_long2int(pre_args->nd_plen) : 0;
-    args->pre_init       = pre_args ? pre_args->nd_next : 0;
+    args->pre_args_num   = pre_args ? rb_long2int(RNODE_ARGS_AUX(pre_args)->nd_plen) : 0;
+    args->pre_init       = pre_args ? RNODE_ARGS_AUX(pre_args)->nd_next : 0;
 
-    args->post_args_num  = post_args ? rb_long2int(post_args->nd_plen) : 0;
-    args->post_init      = post_args ? post_args->nd_next : 0;
-    args->first_post_arg = post_args ? post_args->nd_pid : 0;
+    args->post_args_num  = post_args ? rb_long2int(RNODE_ARGS_AUX(post_args)->nd_plen) : 0;
+    args->post_init      = post_args ? RNODE_ARGS_AUX(post_args)->nd_next : 0;
+    args->first_post_arg = post_args ? RNODE_ARGS_AUX(post_args)->nd_pid : 0;
 
     args->rest_arg       = rest_arg;
 
@@ -12883,9 +14309,9 @@ static NODE*
 new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block, const YYLTYPE *kw_rest_loc)
 {
     int saved_line = p->ruby_sourceline;
-    NODE *node = NEW_NODE(NODE_ARGS, 0, 0, 0, &NULL_LOC);
+    NODE *node = NEW_ARGS(0, &NULL_LOC);
     struct rb_args_info *args = ZALLOC(struct rb_args_info);
-    node->nd_ainfo = args;
+    RNODE_ARGS(node)->nd_ainfo = args;
     if (p->error_p) return node;
 
     args->block_arg      = block;
@@ -12906,15 +14332,15 @@ new_args_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, ID block,
         vtable_pop(vtargs, !!block + !!kw_rest_arg);
         required_kw_vars = kw_vars = &vtargs->tbl[vtargs->pos];
         while (kwn) {
-            if (!NODE_REQUIRED_KEYWORD_P(kwn->nd_body))
+            if (!NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(RNODE_KW_ARG(kwn)->nd_body)))
                 --kw_vars;
             --required_kw_vars;
-            kwn = kwn->nd_next;
+            kwn = RNODE_KW_ARG(kwn)->nd_next;
         }
 
-        for (kwn = kw_args; kwn; kwn = kwn->nd_next) {
-            ID vid = kwn->nd_body->nd_vid;
-            if (NODE_REQUIRED_KEYWORD_P(kwn->nd_body)) {
+        for (kwn = kw_args; kwn; kwn = RNODE_KW_ARG(kwn)->nd_next) {
+            ID vid = RNODE_LASGN(RNODE_KW_ARG(kwn)->nd_body)->nd_vid;
+            if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(RNODE_KW_ARG(kwn)->nd_body))) {
                 *required_kw_vars++ = vid;
             }
             else {
@@ -12948,7 +14374,7 @@ args_with_numbered(struct parser_params *p, NODE *args, int max_numparam)
             args = new_args_tail(p, 0, 0, 0, 0);
             nd_set_loc(args, &loc);
         }
-        args->nd_ainfo->pre_args_num = max_numparam;
+        RNODE_ARGS(args)->nd_ainfo->pre_args_num = max_numparam;
     }
     return args;
 }
@@ -12956,9 +14382,9 @@ args_with_numbered(struct parser_params *p, NODE *args, int max_numparam)
 static NODE*
 new_array_pattern(struct parser_params *p, NODE *constant, NODE *pre_arg, NODE *aryptn, const YYLTYPE *loc)
 {
-    struct rb_ary_pattern_info *apinfo = aryptn->nd_apinfo;
+    struct rb_ary_pattern_info *apinfo = RNODE_ARYPTN(aryptn)->nd_apinfo;
 
-    aryptn->nd_pconst = constant;
+    RNODE_ARYPTN(aryptn)->nd_pconst = constant;
 
     if (pre_arg) {
         NODE *pre_args = NEW_LIST(pre_arg, loc);
@@ -12976,9 +14402,9 @@ static NODE*
 new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc)
 {
     int saved_line = p->ruby_sourceline;
-    NODE *node = NEW_NODE(NODE_ARYPTN, 0, 0, 0, loc);
+    NODE *node = NEW_ARYPTN(loc);
     struct rb_ary_pattern_info *apinfo = ZALLOC(struct rb_ary_pattern_info);
-    node->nd_apinfo = apinfo;
+    RNODE_ARYPTN(node)->nd_apinfo = apinfo;
 
     apinfo->pre_args = pre_args;
 
@@ -12998,7 +14424,7 @@ new_array_pattern_tail(struct parser_params *p, NODE *pre_args, int has_rest, NO
 static NODE*
 new_find_pattern(struct parser_params *p, NODE *constant, NODE *fndptn, const YYLTYPE *loc)
 {
-    fndptn->nd_pconst = constant;
+    RNODE_FNDPTN(fndptn)->nd_pconst = constant;
 
     return fndptn;
 }
@@ -13007,9 +14433,9 @@ static NODE*
 new_find_pattern_tail(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc)
 {
     int saved_line = p->ruby_sourceline;
-    NODE *node = NEW_NODE(NODE_FNDPTN, 0, 0, 0, loc);
+    NODE *node = NEW_FNDPTN(loc);
     struct rb_fnd_pattern_info *fpinfo = ZALLOC(struct rb_fnd_pattern_info);
-    node->nd_fpinfo = fpinfo;
+    RNODE_FNDPTN(node)->nd_fpinfo = fpinfo;
 
     fpinfo->pre_rest_arg = pre_rest_arg ? pre_rest_arg : NODE_SPECIAL_NO_NAME_REST;
     fpinfo->args = args;
@@ -13022,7 +14448,7 @@ new_find_pattern_tail(struct parser_params *p, NODE *pre_rest_arg, NODE *args, N
 static NODE*
 new_hash_pattern(struct parser_params *p, NODE *constant, NODE *hshptn, const YYLTYPE *loc)
 {
-    hshptn->nd_pconst = constant;
+    RNODE_HSHPTN(hshptn)->nd_pconst = constant;
     return hshptn;
 }
 
@@ -13042,7 +14468,7 @@ new_hash_pattern_tail(struct parser_params *p, NODE *kw_args, ID kw_rest_arg, co
         kw_rest_arg_node = NULL;
     }
 
-    node = NEW_NODE(NODE_HSHPTN, 0, kw_args, kw_rest_arg_node, loc);
+    node = NEW_HSHPTN(0, kw_args, kw_rest_arg_node, loc);
 
     p->ruby_sourceline = saved_line;
     return node;
@@ -13063,13 +14489,13 @@ dsym_node(struct parser_params *p, NODE *node, const YYLTYPE *loc)
         nd_set_loc(node, loc);
         break;
       case NODE_STR:
-        lit = node->nd_lit;
-        RB_OBJ_WRITTEN(p->ast, Qnil, node->nd_lit = ID2SYM(rb_intern_str(lit)));
+        lit = RNODE_STR(node)->nd_lit;
+        RB_OBJ_WRITTEN(p->ast, Qnil, RNODE_STR(node)->nd_lit = ID2SYM(rb_intern_str(lit)));
         nd_set_type(node, NODE_LIT);
         nd_set_loc(node, loc);
         break;
       default:
-        node = NEW_NODE(NODE_DSYM, Qnil, 1, NEW_LIST(node, loc), loc);
+        node = NEW_DSYM(Qnil, 1, NEW_LIST(node, loc), loc);
         break;
     }
     return node;
@@ -13080,9 +14506,9 @@ append_literal_keys(st_data_t k, st_data_t v, st_data_t h)
 {
     NODE *node = (NODE *)v;
     NODE **result = (NODE **)h;
-    node->nd_alen = 2;
-    node->nd_next->nd_end = node->nd_next;
-    node->nd_next->nd_next = 0;
+    RNODE_LIST(node)->as.nd_alen = 2;
+    RNODE_LIST(RNODE_LIST(node)->nd_next)->as.nd_end = RNODE_LIST(node)->nd_next;
+    RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next = 0;
     if (*result)
         list_concat(*result, node);
     else
@@ -13098,28 +14524,28 @@ remove_duplicate_keys(struct parser_params *p, NODE *hash)
         literal_hash,
     };
 
-    st_table *literal_keys = st_init_table_with_size(&literal_type, hash->nd_alen / 2);
+    st_table *literal_keys = st_init_table_with_size(&literal_type, RNODE_LIST(hash)->as.nd_alen / 2);
     NODE *result = 0;
     NODE *last_expr = 0;
     rb_code_location_t loc = hash->nd_loc;
-    while (hash && hash->nd_head && hash->nd_next) {
-        NODE *head = hash->nd_head;
-        NODE *value = hash->nd_next;
-        NODE *next = value->nd_next;
+    while (hash && RNODE_LIST(hash)->nd_head && RNODE_LIST(hash)->nd_next) {
+        NODE *head = RNODE_LIST(hash)->nd_head;
+        NODE *value = RNODE_LIST(hash)->nd_next;
+        NODE *next = RNODE_LIST(value)->nd_next;
         st_data_t key = (st_data_t)head;
         st_data_t data;
-        value->nd_next = 0;
+        RNODE_LIST(value)->nd_next = 0;
         if (nd_type_p(head, NODE_LIT) &&
-            st_delete(literal_keys, (key = (st_data_t)head->nd_lit, &key), &data)) {
-            NODE *dup_value = ((NODE *)data)->nd_next;
+            st_delete(literal_keys, (key = (st_data_t)RNODE_LIT(head)->nd_lit, &key), &data)) {
+            NODE *dup_value = (RNODE_LIST((NODE *)data))->nd_next;
             rb_compile_warn(p->ruby_sourcefile, nd_line((NODE *)data),
                             "key %+"PRIsVALUE" is duplicated and overwritten on line %d",
-                            head->nd_lit, nd_line(head));
+                            RNODE_LIT(head)->nd_lit, nd_line(head));
             if (dup_value == last_expr) {
-                value->nd_head = block_append(p, dup_value->nd_head, value->nd_head);
+                RNODE_LIST(value)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(value)->nd_head);
             }
             else {
-                last_expr->nd_head = block_append(p, dup_value->nd_head, last_expr->nd_head);
+                RNODE_LIST(last_expr)->nd_head = block_append(p, RNODE_LIST(dup_value)->nd_head, RNODE_LIST(last_expr)->nd_head);
             }
         }
         st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
@@ -13186,7 +14612,7 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
     NODE *asgn;
 
     if (lhs) {
-        ID vid = lhs->nd_vid;
+        ID vid = RNODE_LASGN(lhs)->nd_vid;
         YYLTYPE lhs_loc = lhs->nd_loc;
         int shareable = ctxt.shareable_constant_value;
         if (shareable) {
@@ -13202,7 +14628,7 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
         }
         if (op == tOROP) {
             rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
-            lhs->nd_value = rhs;
+            RNODE_LASGN(lhs)->nd_value = rhs;
             nd_set_loc(lhs, loc);
             asgn = NEW_OP_ASGN_OR(gettable(p, vid, &lhs_loc), lhs, loc);
         }
@@ -13210,7 +14636,7 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
             if (shareable) {
                 rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
             }
-            lhs->nd_value = rhs;
+            RNODE_LASGN(lhs)->nd_value = rhs;
             nd_set_loc(lhs, loc);
             asgn = NEW_OP_ASGN_AND(gettable(p, vid, &lhs_loc), lhs, loc);
         }
@@ -13220,7 +14646,7 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
             if (shareable) {
                 rhs = shareable_constant_value(p, shareable, lhs, rhs, &rhs->nd_loc);
             }
-            asgn->nd_value = rhs;
+            RNODE_LASGN(asgn)->nd_value = rhs;
             nd_set_loc(asgn, loc);
         }
     }
@@ -13243,7 +14669,7 @@ new_ary_op_assign(struct parser_params *p, NODE *ary,
     else {
         args = arg_concat(p, args, rhs, loc);
     }
-    asgn = NEW_OP_ASGN1(ary, op, args, loc);
+    asgn = NEW_OP_ASGN1(ary, op, (rb_node_argscat_t *)args, loc);
     fixpos(asgn, ary);
     return asgn;
 }
@@ -13447,17 +14873,6 @@ local_tbl(struct parser_params *p)
     return tbl;
 }
 
-static NODE*
-node_newnode_with_locals(struct parser_params *p, enum node_type type, VALUE a1, VALUE a2, const rb_code_location_t *loc)
-{
-    rb_ast_id_table_t *a0;
-    NODE *n;
-
-    a0 = local_tbl(p);
-    n = NEW_NODE(type, a0, a1, a2, loc);
-    return n;
-}
-
 #endif
 
 static void
@@ -13801,7 +15216,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
     onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
 
     if (!arg.succ_block) return 0;
-    return arg.succ_block->nd_next;
+    return RNODE_BLOCK(arg.succ_block)->nd_next;
 }
 #endif
 
@@ -13863,7 +15278,7 @@ parser_reg_compile(struct parser_params* p, VALUE str, int options, VALUE *errms
 {
     VALUE err = rb_errinfo();
     VALUE re;
-    str = ripper_is_node_yylval(p, str) ? RNODE(str)->nd_cval : str;
+    str = ripper_is_node_yylval(p, str) ? RNODE_RIPPER(str)->nd_cval : str;
     int c = rb_reg_fragment_setenc(p, str, options);
     if (c) reg_fragment_enc_error(p, str, c);
     re = rb_parser_reg_compile(p, str, options);
dissimilarity index 90%
index c21fee6..2955720 100644 (file)
-#ifndef RUBY_PARSER_NODE_H
-#define RUBY_PARSER_NODE_H 1
-/*
- * This is a header file used by only "parse.y"
- */
-#include "rubyparser.h"
-#include "internal/compilers.h"
-
-#if defined(__cplusplus)
-extern "C" {
-#if 0
-} /* satisfy cc-mode */
-#endif
-#endif
-
-static inline rb_code_location_t
-code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
-{
-    rb_code_location_t loc;
-    loc.beg_pos = loc1->beg_pos;
-    loc.end_pos = loc2->end_pos;
-    return loc;
-}
-
-#define RNODE(obj)  ((struct RNode *)(obj))
-
-
-#define NEW_NODE(t,a0,a1,a2,loc) rb_node_newnode((t),(VALUE)(a0),(VALUE)(a1),(VALUE)(a2),loc)
-#define NEW_NODE_WITH_LOCALS(t,a1,a2,loc) node_newnode_with_locals(p, (t),(VALUE)(a1),(VALUE)(a2),loc)
-
-#define NEW_DEFN(i,a,d,loc) NEW_NODE(NODE_DEFN,0,i,NEW_SCOPE(a,d,loc),loc)
-#define NEW_DEFS(r,i,a,d,loc) NEW_NODE(NODE_DEFS,r,i,NEW_SCOPE(a,d,loc),loc)
-#define NEW_SCOPE(a,b,loc) NEW_NODE_WITH_LOCALS(NODE_SCOPE,b,a,loc)
-#define NEW_BLOCK(a,loc) NEW_NODE(NODE_BLOCK,a,0,0,loc)
-#define NEW_IF(c,t,e,loc) NEW_NODE(NODE_IF,c,t,e,loc)
-#define NEW_UNLESS(c,t,e,loc) NEW_NODE(NODE_UNLESS,c,t,e,loc)
-#define NEW_CASE(h,b,loc) NEW_NODE(NODE_CASE,h,b,0,loc)
-#define NEW_CASE2(b,loc) NEW_NODE(NODE_CASE2,0,b,0,loc)
-#define NEW_CASE3(h,b,loc) NEW_NODE(NODE_CASE3,h,b,0,loc)
-#define NEW_WHEN(c,t,e,loc) NEW_NODE(NODE_WHEN,c,t,e,loc)
-#define NEW_IN(c,t,e,loc) NEW_NODE(NODE_IN,c,t,e,loc)
-#define NEW_WHILE(c,b,n,loc) NEW_NODE(NODE_WHILE,c,b,n,loc)
-#define NEW_UNTIL(c,b,n,loc) NEW_NODE(NODE_UNTIL,c,b,n,loc)
-#define NEW_FOR(i,b,loc) NEW_NODE(NODE_FOR,0,b,i,loc)
-#define NEW_FOR_MASGN(v,loc) NEW_NODE(NODE_FOR_MASGN,v,0,0,loc)
-#define NEW_ITER(a,b,loc) NEW_NODE(NODE_ITER,0,NEW_SCOPE(a,b,loc),0,loc)
-#define NEW_LAMBDA(a,b,loc) NEW_NODE(NODE_LAMBDA,0,NEW_SCOPE(a,b,loc),0,loc)
-#define NEW_BREAK(s,loc) NEW_NODE(NODE_BREAK,s,0,0,loc)
-#define NEW_NEXT(s,loc) NEW_NODE(NODE_NEXT,s,0,0,loc)
-#define NEW_REDO(loc) NEW_NODE(NODE_REDO,0,0,0,loc)
-#define NEW_RETRY(loc) NEW_NODE(NODE_RETRY,0,0,0,loc)
-#define NEW_BEGIN(b,loc) NEW_NODE(NODE_BEGIN,0,b,0,loc)
-#define NEW_RESCUE(b,res,e,loc) NEW_NODE(NODE_RESCUE,b,res,e,loc)
-#define NEW_RESBODY(a,ex,n,loc) NEW_NODE(NODE_RESBODY,n,ex,a,loc)
-#define NEW_ENSURE(b,en,loc) NEW_NODE(NODE_ENSURE,b,0,en,loc)
-#define NEW_RETURN(s,loc) NEW_NODE(NODE_RETURN,s,0,0,loc)
-#define NEW_YIELD(a,loc) NEW_NODE(NODE_YIELD,a,0,0,loc)
-#define NEW_LIST(a,loc) NEW_NODE(NODE_LIST,a,1,0,loc)
-#define NEW_ZLIST(loc) NEW_NODE(NODE_ZLIST,0,0,0,loc)
-#define NEW_HASH(a,loc)  NEW_NODE(NODE_HASH,a,0,0,loc)
-#define NEW_MASGN(l,r,loc)   NEW_NODE(NODE_MASGN,l,0,r,loc)
-#define NEW_GASGN(v,val,loc) NEW_NODE(NODE_GASGN,v,val,0,loc)
-#define NEW_LASGN(v,val,loc) NEW_NODE(NODE_LASGN,v,val,0,loc)
-#define NEW_DASGN(v,val,loc) NEW_NODE(NODE_DASGN,v,val,0,loc)
-#define NEW_IASGN(v,val,loc) NEW_NODE(NODE_IASGN,v,val,0,loc)
-#define NEW_CDECL(v,val,path,loc) NEW_NODE(NODE_CDECL,v,val,path,loc)
-#define NEW_CVASGN(v,val,loc) NEW_NODE(NODE_CVASGN,v,val,0,loc)
-#define NEW_OP_ASGN1(p,id,a,loc) NEW_NODE(NODE_OP_ASGN1,p,id,a,loc)
-#define NEW_OP_ASGN2(r,t,i,o,val,loc) NEW_NODE(NODE_OP_ASGN2,r,val,NEW_OP_ASGN22(i,o,t,loc),loc)
-#define NEW_OP_ASGN22(i,o,t,loc) NEW_NODE(NODE_OP_ASGN2,i,o,t,loc)
-#define NEW_OP_ASGN_OR(i,val,loc) NEW_NODE(NODE_OP_ASGN_OR,i,val,0,loc)
-#define NEW_OP_ASGN_AND(i,val,loc) NEW_NODE(NODE_OP_ASGN_AND,i,val,0,loc)
-#define NEW_OP_CDECL(v,op,val,loc) NEW_NODE(NODE_OP_CDECL,v,val,op,loc)
-#define NEW_GVAR(v,loc) NEW_NODE(NODE_GVAR,v,0,0,loc)
-#define NEW_LVAR(v,loc) NEW_NODE(NODE_LVAR,v,0,0,loc)
-#define NEW_DVAR(v,loc) NEW_NODE(NODE_DVAR,v,0,0,loc)
-#define NEW_IVAR(v,loc) NEW_NODE(NODE_IVAR,v,0,0,loc)
-#define NEW_CONST(v,loc) NEW_NODE(NODE_CONST,v,0,0,loc)
-#define NEW_CVAR(v,loc) NEW_NODE(NODE_CVAR,v,0,0,loc)
-#define NEW_NTH_REF(n,loc)  NEW_NODE(NODE_NTH_REF,0,n,0,loc)
-#define NEW_BACK_REF(n,loc) NEW_NODE(NODE_BACK_REF,0,n,0,loc)
-#define NEW_MATCH(c,loc) NEW_NODE(NODE_MATCH,c,0,0,loc)
-#define NEW_MATCH2(n1,n2,loc) NEW_NODE(NODE_MATCH2,n1,n2,0,loc)
-#define NEW_MATCH3(r,n2,loc) NEW_NODE(NODE_MATCH3,r,n2,0,loc)
-#define NEW_LIT(l,loc) NEW_NODE(NODE_LIT,l,0,0,loc)
-#define NEW_STR(s,loc) NEW_NODE(NODE_STR,s,0,0,loc)
-#define NEW_DSTR(s,loc) NEW_NODE(NODE_DSTR,s,1,0,loc)
-#define NEW_XSTR(s,loc) NEW_NODE(NODE_XSTR,s,0,0,loc)
-#define NEW_DXSTR(s,loc) NEW_NODE(NODE_DXSTR,s,0,0,loc)
-#define NEW_DSYM(s,loc) NEW_NODE(NODE_DSYM,s,0,0,loc)
-#define NEW_EVSTR(n,loc) NEW_NODE(NODE_EVSTR,0,(n),0,loc)
-#define NEW_CALL(r,m,a,loc) NEW_NODE(NODE_CALL,r,m,a,loc)
-#define NEW_OPCALL(r,m,a,loc) NEW_NODE(NODE_OPCALL,r,m,a,loc)
-#define NEW_FCALL(m,a,loc) NEW_NODE(NODE_FCALL,0,m,a,loc)
-#define NEW_VCALL(m,loc) NEW_NODE(NODE_VCALL,0,m,0,loc)
-#define NEW_SUPER(a,loc) NEW_NODE(NODE_SUPER,0,0,a,loc)
-#define NEW_ZSUPER(loc) NEW_NODE(NODE_ZSUPER,0,0,0,loc)
-#define NEW_ARGS_AUX(r,b,loc) NEW_NODE(NODE_ARGS_AUX,r,b,0,loc)
-#define NEW_OPT_ARG(v,loc) NEW_NODE(NODE_OPT_ARG,0,v,0,loc)
-#define NEW_KW_ARG(v,loc) NEW_NODE(NODE_KW_ARG,0,v,0,loc)
-#define NEW_POSTARG(i,v,loc) NEW_NODE(NODE_POSTARG,i,v,0,loc)
-#define NEW_ARGSCAT(a,b,loc) NEW_NODE(NODE_ARGSCAT,a,b,0,loc)
-#define NEW_ARGSPUSH(a,b,loc) NEW_NODE(NODE_ARGSPUSH,a,b,0,loc)
-#define NEW_SPLAT(a,loc) NEW_NODE(NODE_SPLAT,a,0,0,loc)
-#define NEW_BLOCK_PASS(b,loc) NEW_NODE(NODE_BLOCK_PASS,0,b,0,loc)
-#define NEW_ALIAS(n,o,loc) NEW_NODE(NODE_ALIAS,n,o,0,loc)
-#define NEW_VALIAS(n,o,loc) NEW_NODE(NODE_VALIAS,n,o,0,loc)
-#define NEW_UNDEF(i,loc) NEW_NODE(NODE_UNDEF,0,i,0,loc)
-#define NEW_CLASS(n,b,s,loc) NEW_NODE(NODE_CLASS,n,NEW_SCOPE(0,b,loc),(s),loc)
-#define NEW_SCLASS(r,b,loc) NEW_NODE(NODE_SCLASS,r,NEW_SCOPE(0,b,loc),0,loc)
-#define NEW_MODULE(n,b,loc) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b,loc),0,loc)
-#define NEW_COLON2(c,i,loc) NEW_NODE(NODE_COLON2,c,i,0,loc)
-#define NEW_COLON3(i,loc) NEW_NODE(NODE_COLON3,0,i,0,loc)
-#define NEW_DOT2(b,e,loc) NEW_NODE(NODE_DOT2,b,e,0,loc)
-#define NEW_DOT3(b,e,loc) NEW_NODE(NODE_DOT3,b,e,0,loc)
-#define NEW_SELF(loc) NEW_NODE(NODE_SELF,0,0,1,loc)
-#define NEW_NIL(loc) NEW_NODE(NODE_NIL,0,0,0,loc)
-#define NEW_TRUE(loc) NEW_NODE(NODE_TRUE,0,0,0,loc)
-#define NEW_FALSE(loc) NEW_NODE(NODE_FALSE,0,0,0,loc)
-#define NEW_ERRINFO(loc) NEW_NODE(NODE_ERRINFO,0,0,0,loc)
-#define NEW_DEFINED(e,loc) NEW_NODE(NODE_DEFINED,e,0,0,loc)
-#define NEW_POSTEXE(b,loc) NEW_NODE(NODE_POSTEXE,0,b,0,loc)
-#define NEW_ATTRASGN(r,m,a,loc) NEW_NODE(NODE_ATTRASGN,r,m,a,loc)
-#define NEW_ERROR(loc) NEW_NODE(NODE_ERROR,0,0,0,loc)
-
-#if defined(__cplusplus)
-#if 0
-{ /* satisfy cc-mode */
-#endif
-}  /* extern "C" { */
-#endif
-
-#endif /* RUBY_PARSER_NODE_H */
+#ifndef RUBY_PARSER_NODE_H
+#define RUBY_PARSER_NODE_H 1
+/*
+ * This is a header file used by only "parse.y"
+ */
+#include "rubyparser.h"
+#include "internal/compilers.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#if 0
+} /* satisfy cc-mode */
+#endif
+#endif
+
+static inline rb_code_location_t
+code_loc_gen(const rb_code_location_t *loc1, const rb_code_location_t *loc2)
+{
+    rb_code_location_t loc;
+    loc.beg_pos = loc1->beg_pos;
+    loc.end_pos = loc2->end_pos;
+    return loc;
+}
+
+#if defined(__cplusplus)
+#if 0
+{ /* satisfy cc-mode */
+#endif
+}  /* extern "C" { */
+#endif
+
+#endif /* RUBY_PARSER_NODE_H */
index da89968..b239494 100644 (file)
@@ -356,7 +356,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_lo
     onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
 
     if (!arg.succ_block) return 0;
-    return arg.succ_block->nd_next;
+    return RNODE_BLOCK(arg.succ_block)->nd_next;
 }
 
 static VALUE
index 5aa0e86..b43823a 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <stdarg.h> /* for va_list */
+#include <assert.h>
 
 #ifdef UNIVERSAL_PARSER
 
@@ -130,79 +131,13 @@ enum node_type {
     NODE_HSHPTN,
     NODE_FNDPTN,
     NODE_ERROR,
+    NODE_DEF_TEMP,
+    NODE_DEF_TEMP2,
+    NODE_RIPPER,
+    NODE_RIPPER_VALUES,
     NODE_LAST
 };
 
-
-#define nd_head  u1.node
-#define nd_alen  u2.argc
-#define nd_next  u3.node
-
-#define nd_cond  u1.node
-#define nd_body  u2.node
-#define nd_else  u3.node
-
-#define nd_resq  u2.node
-#define nd_ensr  u3.node
-
-#define nd_1st   u1.node
-#define nd_2nd   u2.node
-
-#define nd_stts  u1.node
-
-#define nd_vid   u1.id
-
-#define nd_var   u1.node
-#define nd_iter  u3.node
-
-#define nd_value u2.node
-#define nd_aid   u3.id
-
-#define nd_lit   u1.value
-
-#define nd_recv  u1.node
-#define nd_mid   u2.id
-#define nd_args  u3.node
-#define nd_ainfo u3.args
-
-#define nd_defn  u3.node
-
-#define nd_cpath u1.node
-#define nd_super u3.node
-
-#define nd_beg   u1.node
-#define nd_end   u2.node
-#define nd_state u3.state
-
-#define nd_nth   u2.argc
-
-#define nd_alias  u1.id
-#define nd_orig   u2.id
-#define nd_undef  u2.node
-
-#define nd_brace u2.argc
-
-#define nd_pconst     u1.node
-#define nd_pkwargs    u2.node
-#define nd_pkwrestarg u3.node
-
-#define nd_apinfo u3.apinfo
-
-#define nd_fpinfo u3.fpinfo
-
-// for NODE_SCOPE
-#define nd_tbl   u1.tbl
-
-// for NODE_ARGS_AUX
-#define nd_pid   u1.id
-#define nd_plen  u2.argc
-#define nd_cflag u2.id
-
-// for ripper
-#define nd_cval  u3.value
-#define nd_rval  u2.value
-#define nd_tag   u1.id
-
 #ifndef FLEX_ARY_LEN
 /* From internal/compilers.h */
 /* A macro for defining a flexible array, like: VALUE ary[FLEX_ARY_LEN]; */
@@ -230,33 +165,1037 @@ typedef struct rb_code_location_struct {
     rb_code_position_t end_pos;
 } rb_code_location_t;
 
+/* Header part of AST Node */
 typedef struct RNode {
     VALUE flags;
-    union {
-        struct RNode *node;
-        ID id;
-        VALUE value;
-        rb_ast_id_table_t *tbl;
-    } u1;
-    union {
-        struct RNode *node;
-        ID id;
-        long argc;
-        VALUE value;
-    } u2;
-    union {
-        struct RNode *node;
-        ID id;
-        long state;
-        struct rb_args_info *args;
-        struct rb_ary_pattern_info *apinfo;
-        struct rb_fnd_pattern_info *fpinfo;
-        VALUE value;
-    } u3;
     rb_code_location_t nd_loc;
     int node_id;
 } NODE;
 
+typedef struct RNode_SCOPE {
+    NODE node;
+
+    rb_ast_id_table_t *nd_tbl;
+    struct RNode *nd_body;
+    struct RNode *nd_args;
+} rb_node_scope_t;
+
+typedef struct RNode_BLOCK {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_end;
+    struct RNode *nd_next;
+} rb_node_block_t;
+
+typedef struct RNode_IF {
+    NODE node;
+
+    struct RNode *nd_cond;
+    struct RNode *nd_body;
+    struct RNode *nd_else;
+} rb_node_if_t;
+
+typedef struct RNode_UNLESS {
+    NODE node;
+
+    struct RNode *nd_cond;
+    struct RNode *nd_body;
+    struct RNode *nd_else;
+} rb_node_unless_t;
+
+typedef struct RNode_CASE {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_case_t;
+
+typedef struct RNode_CASE2 {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_case2_t;
+
+typedef struct RNode_CASE3 {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_case3_t;
+
+typedef struct RNode_WHEN {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    struct RNode *nd_next;
+} rb_node_when_t;
+
+typedef struct RNode_IN {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    struct RNode *nd_next;
+} rb_node_in_t;
+
+/* RNode_WHILE and RNode_UNTIL should be same structure */
+typedef struct RNode_WHILE {
+    NODE node;
+
+    struct RNode *nd_cond;
+    struct RNode *nd_body;
+    long nd_state;
+} rb_node_while_t;
+
+typedef struct RNode_UNTIL {
+    NODE node;
+
+    struct RNode *nd_cond;
+    struct RNode *nd_body;
+    long nd_state;
+} rb_node_until_t;
+
+/* RNode_ITER and RNode_FOR should be same structure */
+typedef struct RNode_ITER {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    struct RNode *nd_iter;
+} rb_node_iter_t;
+
+typedef struct RNode_FOR {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    struct RNode *nd_iter;
+} rb_node_for_t;
+
+typedef struct RNode_FOR_MASGN {
+    NODE node;
+
+    struct RNode *nd_var;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_for_masgn_t;
+
+/* RNode_BREAK, RNode_NEXT and RNode_RETURN should be same structure */
+typedef struct RNode_BREAK {
+    NODE node;
+
+    struct RNode *nd_stts;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_break_t;
+
+typedef struct RNode_NEXT {
+    NODE node;
+
+    struct RNode *nd_stts;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_next_t;
+
+typedef struct RNode_REDO {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_redo_t;
+
+typedef struct RNode_RETRY {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_retry_t;
+
+typedef struct RNode_BEGIN {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    VALUE not_used2;
+} rb_node_begin_t;
+
+typedef struct RNode_RESCUE {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_resq;
+    struct RNode *nd_else;
+} rb_node_rescue_t;
+
+typedef struct RNode_RESBODY {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    struct RNode *nd_args;
+} rb_node_resbody_t;
+
+typedef struct RNode_ENSURE {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_resq; /* Maybe not used other than reduce_nodes */
+    struct RNode *nd_ensr;
+} rb_node_ensure_t;
+
+/* RNode_AND and RNode_OR should be same structure */
+typedef struct RNode_AND {
+    NODE node;
+
+    struct RNode *nd_1st;
+    struct RNode *nd_2nd;
+    VALUE not_used;
+} rb_node_and_t;
+
+typedef struct RNode_OR {
+    NODE node;
+
+    struct RNode *nd_1st;
+    struct RNode *nd_2nd;
+    VALUE not_used;
+} rb_node_or_t;
+
+typedef struct RNode_MASGN {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_value;
+    struct RNode *nd_args;
+} rb_node_masgn_t;
+
+/* RNode_LASGN, RNode_DASGN, RNode_IASGN, RNode_CVASGN and RNode_GASGN should be same structure */
+typedef struct RNode_LASGN {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_lasgn_t;
+
+typedef struct RNode_DASGN {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_dasgn_t;
+
+typedef struct RNode_GASGN {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_gasgn_t;
+
+typedef struct RNode_IASGN {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_iasgn_t;
+
+typedef struct RNode_CDECL {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    struct RNode *nd_else;
+} rb_node_cdecl_t;
+
+typedef struct RNode_CVASGN {
+    NODE node;
+
+    ID nd_vid;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_cvasgn_t;
+
+typedef struct RNode_OP_ASGN1 {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode_ARGSCAT *nd_args;
+} rb_node_op_asgn1_t;
+
+typedef struct RNode_OP_ASGN2 {
+    NODE node;
+
+    struct RNode *nd_recv;
+    struct RNode *nd_value;
+    struct RNode_OP_ASGN22 *nd_next;
+} rb_node_op_asgn2_t;
+
+typedef struct RNode_OP_ASGN22 {
+    NODE node;
+
+    ID nd_vid;
+    ID nd_mid;
+    bool nd_aid;
+} rb_node_op_asgn22_t;
+
+typedef struct RNode_OP_ASGN_AND {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_op_asgn_and_t;
+
+typedef struct RNode_OP_ASGN_OR {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_op_asgn_or_t;
+
+typedef struct RNode_OP_CDECL {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_value;
+    ID nd_aid;
+} rb_node_op_cdecl_t;
+
+/* RNode_CALL, RNode_OPCALL and RNode_QCALL should be same structure */
+typedef struct RNode_CALL {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode *nd_args;
+} rb_node_call_t;
+
+typedef struct RNode_OPCALL {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode *nd_args;
+} rb_node_opcall_t;
+
+typedef struct RNode_FCALL {
+    NODE node;
+
+    VALUE not_used;
+    ID nd_mid;
+    struct RNode *nd_args;
+} rb_node_fcall_t;
+
+typedef struct RNode_VCALL {
+    NODE node;
+
+    VALUE not_used;
+    ID nd_mid;
+    VALUE not_used2;
+} rb_node_vcall_t;
+
+typedef struct RNode_QCALL {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode *nd_args;
+} rb_node_qcall_t;
+
+typedef struct RNode_SUPER {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    struct RNode *nd_args;
+} rb_node_super_t;
+
+typedef struct RNode_ZSUPER {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_zsuper_t;
+
+/*
+
+  Structure of LIST:
+
+  LIST                     +--> LIST
+   * head --> element      |     * head
+   * alen (length of list) |     * nd_end (point to the last LIST)
+   * next -----------------+     * next
+
+
+  RNode_LIST and RNode_VALUES should be same structure
+*/
+typedef struct RNode_LIST {
+    NODE node;
+
+    struct RNode *nd_head; /* element */
+    union {
+        long nd_alen;
+        struct RNode *nd_end; /* Second list node has this structure */
+    } as;
+    struct RNode *nd_next; /* next list node */
+} rb_node_list_t;
+
+typedef struct RNode_ZLIST {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2; /* Used by p->exits */
+    VALUE not_used3; /* Used by p->exits */
+} rb_node_zlist_t;
+
+typedef struct RNode_VALUES {
+    NODE node;
+
+    struct RNode *nd_head;
+    long nd_alen;
+    struct RNode *nd_next;
+} rb_node_values_t;
+
+typedef struct RNode_HASH {
+    NODE node;
+
+    struct RNode *nd_head;
+    long nd_brace;
+    VALUE not_used;
+} rb_node_hash_t;
+
+typedef struct RNode_RETURN {
+    NODE node;
+
+    struct RNode *nd_stts;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_return_t;
+
+typedef struct RNode_YIELD {
+    NODE node;
+
+    struct RNode *nd_head;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_yield_t;
+
+/* RNode_LVAR and RNode_DVAR should be same structure */
+typedef struct RNode_LVAR {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_lvar_t;
+
+typedef struct RNode_DVAR {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_dvar_t;
+
+/* RNode_GVAR, RNode_IVAR, RNode_CONST and RNode_CVAR should be same structure */
+typedef struct RNode_GVAR {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_gvar_t;
+
+typedef struct RNode_IVAR {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_ivar_t;
+
+typedef struct RNode_CONST {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_const_t;
+
+typedef struct RNode_CVAR {
+    NODE node;
+
+    ID nd_vid;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_cvar_t;
+
+typedef struct RNode_NTH_REF {
+    NODE node;
+
+    VALUE not_used;
+    long nd_nth;
+    VALUE not_used2;
+} rb_node_nth_ref_t;
+
+typedef struct RNode_BACK_REF {
+    NODE node;
+
+    VALUE not_used;
+    long nd_nth;
+    VALUE not_used2;
+} rb_node_back_ref_t;
+
+/* RNode_MATCH, RNode_LIT, RNode_STR and RNode_XSTR should be same structure */
+typedef struct RNode_MATCH {
+    NODE node;
+
+    VALUE nd_lit;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_match_t;
+
+typedef struct RNode_MATCH2 {
+    NODE node;
+
+    struct RNode *nd_recv;
+    struct RNode *nd_value;
+    struct RNode *nd_args;
+} rb_node_match2_t;
+
+typedef struct RNode_MATCH3 {
+    NODE node;
+
+    struct RNode *nd_recv;
+    struct RNode *nd_value;
+    VALUE not_used;
+} rb_node_match3_t;
+
+typedef struct RNode_LIT {
+    NODE node;
+
+    VALUE nd_lit;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_lit_t;
+
+typedef struct RNode_STR {
+    NODE node;
+
+    VALUE nd_lit;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_str_t;
+
+/* RNode_DSTR, RNode_DXSTR and RNode_DSYM should be same structure */
+typedef struct RNode_DSTR {
+    NODE node;
+
+    VALUE nd_lit;
+    union {
+        long nd_alen;
+        struct RNode *nd_end; /* Second dstr node has this structure. See also RNode_LIST */
+    } as;
+    struct RNode_LIST *nd_next;
+} rb_node_dstr_t;
+
+typedef struct RNode_XSTR {
+    NODE node;
+
+    VALUE nd_lit;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_xstr_t;
+
+typedef struct RNode_DXSTR {
+    NODE node;
+
+    VALUE nd_lit;
+    long nd_alen;
+    struct RNode_LIST *nd_next;
+} rb_node_dxstr_t;
+
+typedef struct RNode_EVSTR {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    VALUE not_used2;
+} rb_node_evstr_t;
+
+typedef struct RNode_DREGX {
+    NODE node;
+
+    VALUE nd_lit;
+    ID nd_cflag;
+    struct RNode_LIST *nd_next;
+} rb_node_dregx_t;
+
+typedef struct RNode_ONCE {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    VALUE not_used2;
+} rb_node_once_t;
+
+typedef struct RNode_ARGS {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    struct rb_args_info *nd_ainfo;
+} rb_node_args_t;
+
+typedef struct RNode_ARGS_AUX {
+    NODE node;
+
+    ID nd_pid;
+    long nd_plen;
+    struct RNode *nd_next;
+} rb_node_args_aux_t;
+
+typedef struct RNode_OPT_ARG {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    struct RNode *nd_next;
+} rb_node_opt_arg_t;
+
+typedef struct RNode_KW_ARG {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    struct RNode *nd_next;
+} rb_node_kw_arg_t;
+
+typedef struct RNode_POSTARG {
+    NODE node;
+
+    struct RNode *nd_1st;
+    struct RNode *nd_2nd;
+    VALUE not_used;
+} rb_node_postarg_t;
+
+typedef struct RNode_ARGSCAT {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_argscat_t;
+
+typedef struct RNode_ARGSPUSH {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_argspush_t;
+
+typedef struct RNode_SPLAT {
+    NODE node;
+
+    struct RNode *nd_head;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_splat_t;
+
+typedef struct RNode_BLOCK_PASS {
+    NODE node;
+
+    struct RNode *nd_head;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_block_pass_t;
+
+typedef struct RNode_DEFN {
+    NODE node;
+
+    VALUE not_used;
+    ID nd_mid;
+    struct RNode *nd_defn;
+} rb_node_defn_t;
+
+typedef struct RNode_DEFS {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode *nd_defn;
+} rb_node_defs_t;
+
+typedef struct RNode_DEF_TEMP {
+    NODE node;
+
+    ID nd_vid;
+    ID nd_mid;
+    struct RNode_DEF_TEMP2 *nd_next;
+} rb_node_def_temp_t;
+
+typedef struct RNode_DEF_TEMP2 {
+    NODE node;
+
+    struct RNode *nd_head;
+    long nd_nth;
+    VALUE nd_cval;
+} rb_node_def_temp2_t;
+
+typedef struct RNode_ALIAS {
+    NODE node;
+
+    struct RNode *nd_1st;
+    struct RNode *nd_2nd;
+    VALUE not_used;
+} rb_node_alias_t;
+
+typedef struct RNode_VALIAS {
+    NODE node;
+
+    ID nd_alias;
+    ID nd_orig;
+    VALUE not_used;
+} rb_node_valias_t;
+
+typedef struct RNode_UNDEF {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_undef;
+    VALUE not_used2;
+} rb_node_undef_t;
+
+typedef struct RNode_CLASS {
+    NODE node;
+
+    struct RNode *nd_cpath;
+    struct RNode *nd_body;
+    struct RNode *nd_super;
+} rb_node_class_t;
+
+typedef struct RNode_MODULE {
+    NODE node;
+
+    struct RNode *nd_cpath;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_module_t;
+
+typedef struct RNode_SCLASS {
+    NODE node;
+
+    struct RNode *nd_recv;
+    struct RNode *nd_body;
+    VALUE not_used;
+} rb_node_sclass_t;
+
+typedef struct RNode_COLON2 {
+    NODE node;
+
+    struct RNode *nd_head;
+    ID nd_mid;
+    VALUE not_used;
+} rb_node_colon2_t;
+
+typedef struct RNode_COLON3 {
+    NODE node;
+
+    VALUE not_used;
+    ID nd_mid;
+    VALUE not_used2;
+} rb_node_colon3_t;
+
+/* RNode_DOT2, RNode_DOT3, RNode_FLIP2 and RNode_FLIP3 should be same structure */
+typedef struct RNode_DOT2 {
+    NODE node;
+
+    struct RNode *nd_beg;
+    struct RNode *nd_end;
+    VALUE not_used;
+} rb_node_dot2_t;
+
+typedef struct RNode_DOT3 {
+    NODE node;
+
+    struct RNode *nd_beg;
+    struct RNode *nd_end;
+    VALUE not_used;
+} rb_node_dot3_t;
+
+typedef struct RNode_FLIP2 {
+    NODE node;
+
+    struct RNode *nd_beg;
+    struct RNode *nd_end;
+    VALUE not_used;
+} rb_node_flip2_t;
+
+typedef struct RNode_FLIP3 {
+    NODE node;
+
+    struct RNode *nd_beg;
+    struct RNode *nd_end;
+    VALUE not_used;
+} rb_node_flip3_t;
+
+typedef struct RNode_SELF {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    long nd_state; /* Default 1. See NEW_SELF. */
+} rb_node_self_t;
+
+typedef struct RNode_NIL {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_nil_t;
+
+typedef struct RNode_TRUE {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_true_t;
+
+typedef struct RNode_FALSE {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_false_t;
+
+typedef struct RNode_ERRINFO {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_errinfo_t;
+
+typedef struct RNode_DEFINED {
+    NODE node;
+
+    struct RNode *nd_head;
+    VALUE not_used;
+    VALUE not_used2;
+} rb_node_defined_t;
+
+typedef struct RNode_POSTEXE {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    VALUE not_used2;
+} rb_node_postexe_t;
+
+typedef struct RNode_DSYM {
+    NODE node;
+
+    VALUE nd_lit;
+    long nd_alen;
+    struct RNode_LIST *nd_next;
+} rb_node_dsym_t;
+
+typedef struct RNode_ATTRASGN {
+    NODE node;
+
+    struct RNode *nd_recv;
+    ID nd_mid;
+    struct RNode *nd_args;
+} rb_node_attrasgn_t;
+
+typedef struct RNode_LAMBDA {
+    NODE node;
+
+    VALUE not_used;
+    struct RNode *nd_body;
+    VALUE not_used2;
+} rb_node_lambda_t;
+
+typedef struct RNode_ARYPTN {
+    NODE node;
+
+    struct RNode *nd_pconst;
+    VALUE not_used;
+    struct rb_ary_pattern_info *nd_apinfo;
+} rb_node_aryptn_t;
+
+typedef struct RNode_HSHPTN {
+    NODE node;
+
+    struct RNode *nd_pconst;
+    struct RNode *nd_pkwargs;
+    struct RNode *nd_pkwrestarg;
+} rb_node_hshptn_t;
+
+typedef struct RNode_FNDPTN {
+    NODE node;
+
+    struct RNode *nd_pconst;
+    VALUE not_used;
+    struct rb_fnd_pattern_info *nd_fpinfo;
+} rb_node_fndptn_t;
+
+typedef struct RNode_ERROR {
+    NODE node;
+
+    VALUE not_used;
+    VALUE not_used2;
+    VALUE not_used3;
+} rb_node_error_t;
+
+#define RNODE(obj)  ((struct RNode *)(obj))
+
+#define RNODE_SCOPE(node) ((struct RNode_SCOPE *)(node))
+#define RNODE_BLOCK(node) ((struct RNode_BLOCK *)(node))
+#define RNODE_IF(node) ((struct RNode_IF *)(node))
+#define RNODE_UNLESS(node) ((struct RNode_UNLESS *)(node))
+#define RNODE_CASE(node) ((struct RNode_CASE *)(node))
+#define RNODE_CASE2(node) ((struct RNode_CASE2 *)(node))
+#define RNODE_CASE3(node) ((struct RNode_CASE3 *)(node))
+#define RNODE_WHEN(node) ((struct RNode_WHEN *)(node))
+#define RNODE_IN(node) ((struct RNode_IN *)(node))
+#define RNODE_WHILE(node) ((struct RNode_WHILE *)(node))
+#define RNODE_UNTIL(node) ((struct RNode_UNTIL *)(node))
+#define RNODE_ITER(node) ((struct RNode_ITER *)(node))
+#define RNODE_FOR(node) ((struct RNode_FOR *)(node))
+#define RNODE_FOR_MASGN(node) ((struct RNode_FOR_MASGN *)(node))
+#define RNODE_BREAK(node) ((struct RNode_BREAK *)(node))
+#define RNODE_NEXT(node) ((struct RNode_NEXT *)(node))
+#define RNODE_REDO(node) ((struct RNode_REDO *)(node))
+#define RNODE_RETRY(node) ((struct RNode_RETRY *)(node))
+#define RNODE_BEGIN(node) ((struct RNode_BEGIN *)(node))
+#define RNODE_RESCUE(node) ((struct RNode_RESCUE *)(node))
+#define RNODE_RESBODY(node) ((struct RNode_RESBODY *)(node))
+#define RNODE_ENSURE(node) ((struct RNode_ENSURE *)(node))
+#define RNODE_AND(node) ((struct RNode_AND *)(node))
+#define RNODE_OR(node) ((struct RNode_OR *)(node))
+#define RNODE_MASGN(node) ((struct RNode_MASGN *)(node))
+#define RNODE_LASGN(node) ((struct RNode_LASGN *)(node))
+#define RNODE_DASGN(node) ((struct RNode_DASGN *)(node))
+#define RNODE_GASGN(node) ((struct RNode_GASGN *)(node))
+#define RNODE_IASGN(node) ((struct RNode_IASGN *)(node))
+#define RNODE_CDECL(node) ((struct RNode_CDECL *)(node))
+#define RNODE_CVASGN(node) ((struct RNode_CVASGN *)(node))
+#define RNODE_OP_ASGN1(node) ((struct RNode_OP_ASGN1 *)(node))
+#define RNODE_OP_ASGN2(node) ((struct RNode_OP_ASGN2 *)(node))
+#define RNODE_OP_ASGN22(node) ((struct RNode_OP_ASGN22 *)(node))
+#define RNODE_OP_ASGN_AND(node) ((struct RNode_OP_ASGN_AND *)(node))
+#define RNODE_OP_ASGN_OR(node) ((struct RNode_OP_ASGN_OR *)(node))
+#define RNODE_OP_CDECL(node) ((struct RNode_OP_CDECL *)(node))
+#define RNODE_CALL(node) ((struct RNode_CALL *)(node))
+#define RNODE_OPCALL(node) ((struct RNode_OPCALL *)(node))
+#define RNODE_FCALL(node) ((struct RNode_FCALL *)(node))
+#define RNODE_VCALL(node) ((struct RNode_VCALL *)(node))
+#define RNODE_QCALL(node) ((struct RNode_QCALL *)(node))
+#define RNODE_SUPER(node) ((struct RNode_SUPER *)(node))
+#define RNODE_ZSUPER(node) ((struct RNode_ZSUPER *)(node))
+#define RNODE_LIST(node) ((struct RNode_LIST *)(node))
+#define RNODE_ZLIST(node) ((struct RNode_ZLIST *)(node))
+#define RNODE_VALUES(node) ((struct RNode_VALUES *)(node))
+#define RNODE_HASH(node) ((struct RNode_HASH *)(node))
+#define RNODE_RETURN(node) ((struct RNode_RETURN *)(node))
+#define RNODE_YIELD(node) ((struct RNode_YIELD *)(node))
+#define RNODE_LVAR(node) ((struct RNode_LVAR *)(node))
+#define RNODE_DVAR(node) ((struct RNode_DVAR *)(node))
+#define RNODE_GVAR(node) ((struct RNode_GVAR *)(node))
+#define RNODE_IVAR(node) ((struct RNode_IVAR *)(node))
+#define RNODE_CONST(node) ((struct RNode_CONST *)(node))
+#define RNODE_CVAR(node) ((struct RNode_CVAR *)(node))
+#define RNODE_NTH_REF(node) ((struct RNode_NTH_REF *)(node))
+#define RNODE_BACK_REF(node) ((struct RNode_BACK_REF *)(node))
+#define RNODE_MATCH(node) ((struct RNode_MATCH *)(node))
+#define RNODE_MATCH2(node) ((struct RNode_MATCH2 *)(node))
+#define RNODE_MATCH3(node) ((struct RNode_MATCH3 *)(node))
+#define RNODE_LIT(node) ((struct RNode_LIT *)(node))
+#define RNODE_STR(node) ((struct RNode_STR *)(node))
+#define RNODE_DSTR(node) ((struct RNode_DSTR *)(node))
+#define RNODE_XSTR(node) ((struct RNode_XSTR *)(node))
+#define RNODE_DXSTR(node) ((struct RNode_DXSTR *)(node))
+#define RNODE_EVSTR(node) ((struct RNode_EVSTR *)(node))
+#define RNODE_DREGX(node) ((struct RNode_DREGX *)(node))
+#define RNODE_ONCE(node) ((struct RNode_ONCE *)(node))
+#define RNODE_ARGS(node) ((struct RNode_ARGS *)(node))
+#define RNODE_ARGS_AUX(node) ((struct RNode_ARGS_AUX *)(node))
+#define RNODE_OPT_ARG(node) ((struct RNode_OPT_ARG *)(node))
+#define RNODE_KW_ARG(node) ((struct RNode_KW_ARG *)(node))
+#define RNODE_POSTARG(node) ((struct RNode_POSTARG *)(node))
+#define RNODE_ARGSCAT(node) ((struct RNode_ARGSCAT *)(node))
+#define RNODE_ARGSPUSH(node) ((struct RNode_ARGSPUSH *)(node))
+#define RNODE_SPLAT(node) ((struct RNode_SPLAT *)(node))
+#define RNODE_BLOCK_PASS(node) ((struct RNode_BLOCK_PASS *)(node))
+#define RNODE_DEFN(node) ((struct RNode_DEFN *)(node))
+#define RNODE_DEFS(node) ((struct RNode_DEFS *)(node))
+#define RNODE_DEF_TEMP(node) ((struct RNode_DEF_TEMP *)(node))
+#define RNODE_DEF_TEMP2(node) ((struct RNode_DEF_TEMP2 *)(node))
+#define RNODE_ALIAS(node) ((struct RNode_ALIAS *)(node))
+#define RNODE_VALIAS(node) ((struct RNode_VALIAS *)(node))
+#define RNODE_UNDEF(node) ((struct RNode_UNDEF *)(node))
+#define RNODE_CLASS(node) ((struct RNode_CLASS *)(node))
+#define RNODE_MODULE(node) ((struct RNode_MODULE *)(node))
+#define RNODE_SCLASS(node) ((struct RNode_SCLASS *)(node))
+#define RNODE_COLON2(node) ((struct RNode_COLON2 *)(node))
+#define RNODE_COLON3(node) ((struct RNode_COLON3 *)(node))
+#define RNODE_DOT2(node) ((struct RNode_DOT2 *)(node))
+#define RNODE_DOT3(node) ((struct RNode_DOT3 *)(node))
+#define RNODE_FLIP2(node) ((struct RNode_FLIP2 *)(node))
+#define RNODE_FLIP3(node) ((struct RNode_FLIP3 *)(node))
+#define RNODE_SELF(node) ((struct RNode_SELF *)(node))
+#define RNODE_NIL(node) ((struct RNode_NIL *)(node))
+#define RNODE_TRUE(node) ((struct RNode_TRUE *)(node))
+#define RNODE_FALSE(node) ((struct RNode_FALSE *)(node))
+#define RNODE_ERRINFO(node) ((struct RNode_ERRINFO *)(node))
+#define RNODE_DEFINED(node) ((struct RNode_DEFINED *)(node))
+#define RNODE_POSTEXE(node) ((struct RNode_POSTEXE *)(node))
+#define RNODE_DSYM(node) ((struct RNode_DSYM *)(node))
+#define RNODE_ATTRASGN(node) ((struct RNode_ATTRASGN *)(node))
+#define RNODE_LAMBDA(node) ((struct RNode_LAMBDA *)(node))
+#define RNODE_ARYPTN(node) ((struct RNode_ARYPTN *)(node))
+#define RNODE_HSHPTN(node) ((struct RNode_HSHPTN *)(node))
+#define RNODE_FNDPTN(node) ((struct RNode_FNDPTN *)(node))
+
+#ifdef RIPPER
+typedef struct RNode_RIPPER {
+    NODE node;
+
+    ID nd_vid;
+    VALUE nd_rval;
+    VALUE nd_cval;
+} rb_node_ripper_t;
+
+typedef struct RNode_RIPPER_VALUES {
+    NODE node;
+
+    VALUE nd_val1;
+    VALUE nd_val2;
+    VALUE nd_val3;
+} rb_node_ripper_values_t;
+
+#define RNODE_RIPPER(node) ((struct RNode_RIPPER *)(node))
+#define RNODE_RIPPER_VALUES(node) ((struct RNode_RIPPER_VALUES *)(node))
+#endif
+
 /* FL     : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */
 /* NODE_FL: 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: NODE_FL_NEWLINE,
  *          8..14: nd_type,
@@ -267,7 +1206,7 @@ typedef struct RNode {
 #define NODE_TYPESHIFT 8
 #define NODE_TYPEMASK  (((VALUE)0x7f)<<NODE_TYPESHIFT)
 
-#define nd_type(n) ((int) (((n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
+#define nd_type(n) ((int) ((RNODE(n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
 #define nd_set_type(n,t) \
     rb_node_set_type(n, t)
 #define nd_init_type(n,t) \
diff --git a/vm.c b/vm.c
index e325cf3..ecf8c8b 100644 (file)
--- a/vm.c
+++ b/vm.c
@@ -1384,7 +1384,7 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I
     rb_execution_context_t *ec = GET_EC();
     const rb_iseq_t *base_iseq, *iseq;
     rb_ast_body_t ast;
-    NODE tmp_node;
+    rb_node_scope_t tmp_node;
 
     if (dyncount < 0) return 0;
 
@@ -1396,8 +1396,12 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I
     dyns->size = dyncount;
     MEMCPY(dyns->ids, dynvars, ID, dyncount);
 
-    rb_node_init(&tmp_node, NODE_SCOPE, (VALUE)dyns, 0, 0);
-    ast.root = &tmp_node;
+    rb_node_init(RNODE(&tmp_node), NODE_SCOPE);
+    tmp_node.nd_tbl = dyns;
+    tmp_node.nd_body = 0;
+    tmp_node.nd_args = 0;
+
+    ast.root = RNODE(&tmp_node);
     ast.frozen_string_literal = -1;
     ast.coverage_enabled = -1;
     ast.script_lines = INT2FIX(-1);