When a single quote comes, parse.y will do:
case '\'':
lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
return tSTRING_BEG;
This piece of codes is very same as a part of :'aaa'
NEW_STRTERM
is a macro. It is a wrapper of a macro rb_node_newnode
, which is a wrapper of a function node_newnode
#define NEW_STRTERM(func, term, paren) \
rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)
#define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, type, a1, a2, a3)
static NODE*
node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = (rb_node_newnode)(type, a0, a1, a2);
nd_set_line(n, ruby_sourceline);
return n;
}
The last function node_newnode
calls rb_node_newnode
, that is node_newnode
itself, recursively.
Here is the node_newnode
which macro is expanded:
static NODE*
node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = node_newnode(parser, type, a0, a1, a2);
nd_set_line(n, ruby_sourceline);
return n;
}
It's mysterious. node_newnode
seems infinite recursion without any terminate conditions. Why does it work?
A function type macro is not expanded in this case.
ReplyDeleteI think it is a normal function call.
The function rb_node_newnode is defined in node.h.
Thank you! I rak'd rb_node_newnode to find where is the definition. The perpetrator is gc.c!
ReplyDeleteNODE*
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = (NODE*)rb_newobj();
n->flags |= T_NODE;
nd_set_type(n, type);
n->u1.value = a0;
n->u2.value = a1;
n->u3.value = a2;
return n;
}